127 lines
4.5 KiB
TypeScript
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);
|
|
});
|
|
});
|