Files
2026-05-27 23:29:53 +01:00

127 lines
4.5 KiB
TypeScript

/**
* Root-export shape snapshot. Pins the canonical exports of
* `@suaveplan/api-plugin-example` so the dual-shape refactor cannot
* accidentally drop or rename a public surface.
*
* Uses TypeScript `typeof` + a structural `Equal<>` helper rather than
* a runtime structural diff so the assertion fires at typecheck time —
* any drift in the exported type's signature breaks the build before
* the test even runs.
*/
import { describe, expect, it } from "@suaveplan/testing/runner";
import * as RootBarrel from "../../src/index.js";
type Equal<A, B> =
(<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2
? true
: false;
// Pin the canonical exports — assigning to a `true` constant means the
// build fails if the structural compatibility breaks.
type _Pin_EXAMPLE_CODES = Equal<
typeof RootBarrel.EXAMPLE_CODES,
{
readonly SUBSCRIPTION_INACTIVE: "PLUGIN.EXAMPLE.SUBSCRIPTION_INACTIVE";
readonly INVOICE_NOT_FOUND: "PLUGIN.EXAMPLE.INVOICE_NOT_FOUND";
readonly INVALID_INVOICE_STATE: "PLUGIN.EXAMPLE.INVALID_INVOICE_STATE";
readonly RESPONSE_VALIDATION_TRIGGER: "PLUGIN.EXAMPLE.RESPONSE_VALIDATION_TRIGGER";
}
>;
const pinExampleCodes: _Pin_EXAMPLE_CODES = true;
type _Pin_examplePluginModule_name = Equal<
typeof RootBarrel.examplePluginModule.name,
"@suaveplan/api-plugin-example"
>;
const pinPluginName: _Pin_examplePluginModule_name = true;
type _Pin_buildRoutes = Equal<
Parameters<typeof RootBarrel.buildRoutes>[0]["ledger"]["nextId"],
() => string
>;
const pinBuildRoutes: _Pin_buildRoutes = true;
describe("root exports preserve existing types and names", () => {
it("exports the canonical EXAMPLE_CODES constants", {
timeout: 5000,
}, () => {
expect(RootBarrel.EXAMPLE_CODES.INVOICE_NOT_FOUND).toBe(
"PLUGIN.EXAMPLE.INVOICE_NOT_FOUND"
);
expect(RootBarrel.EXAMPLE_CODES.SUBSCRIPTION_INACTIVE).toBe(
"PLUGIN.EXAMPLE.SUBSCRIPTION_INACTIVE"
);
expect(RootBarrel.EXAMPLE_CODES.INVALID_INVOICE_STATE).toBe(
"PLUGIN.EXAMPLE.INVALID_INVOICE_STATE"
);
expect(RootBarrel.EXAMPLE_CODES.RESPONSE_VALIDATION_TRIGGER).toBe(
"PLUGIN.EXAMPLE.RESPONSE_VALIDATION_TRIGGER"
);
});
it("exports ExamplePluginError as a public-constructor class", {
timeout: 5000,
}, () => {
const e = new RootBarrel.ExamplePluginError(
RootBarrel.EXAMPLE_CODES.INVOICE_NOT_FOUND,
"msg"
);
expect(e.code).toBe("PLUGIN.EXAMPLE.INVOICE_NOT_FOUND");
});
it("exports examplePluginModule with the canonical name + version", {
timeout: 5000,
}, () => {
expect(RootBarrel.examplePluginModule.name).toBe(
"@suaveplan/api-plugin-example"
);
expect(RootBarrel.examplePluginModule.version).toBe("0.1.0");
});
it("exports buildRoutes + createInMemoryLedger", {
timeout: 5000,
}, () => {
const ledger = RootBarrel.createInMemoryLedger();
const routes = RootBarrel.buildRoutes({
ledger,
publisher: { publish() {} },
});
expect(routes.length).toBeGreaterThan(0);
expect(typeof ledger.nextId).toBe("function");
});
it("exports the canonical event topics and payload schemas", {
timeout: 5000,
}, () => {
expect(RootBarrel.EXAMPLE_INVOICE_CREATED_TOPIC).toBe(
"example.invoice.created"
);
expect(RootBarrel.USERS_USER_DELETED_TOPIC).toBe("users.user.deleted");
expect(RootBarrel.ExampleInvoiceCreatedPayload).toBeDefined();
expect(RootBarrel.UsersUserDeletedPayload).toBeDefined();
});
it("exports the request/response Zod schemas", { timeout: 5000 }, () => {
expect(RootBarrel.CreateInvoiceRequest).toBeDefined();
expect(RootBarrel.CreateInvoiceResponse).toBeDefined();
expect(RootBarrel.InvoiceResponse).toBeDefined();
expect(RootBarrel.PingResponse).toBeDefined();
expect(RootBarrel.StreamChunk).toBeDefined();
});
it("exports instrument helpers", { timeout: 5000 }, () => {
expect(typeof RootBarrel.getExampleInstruments).toBe("function");
expect(typeof RootBarrel.resetExampleInstrumentsForTest).toBe(
"function"
);
});
it("type-level pins satisfy structural equality", {
timeout: 5000,
}, () => {
expect(pinExampleCodes).toBe(true);
expect(pinPluginName).toBe(true);
expect(pinBuildRoutes).toBe(true);
});
});