feat(generators): emit feature.manifest.ts + self-asserting bind-production
This commit is contained in:
@@ -120,6 +120,11 @@ export default function generator(plop: PlopTypes.NodePlopAPI): void {
|
||||
path: "packages/{{kebabCase name}}/src/index.ts",
|
||||
templateFile: "templates/feature/src/index.ts.hbs",
|
||||
},
|
||||
{
|
||||
type: "add",
|
||||
path: "packages/{{kebabCase name}}/src/feature.manifest.ts",
|
||||
templateFile: "templates/feature/src/feature.manifest.ts.hbs",
|
||||
},
|
||||
|
||||
// Entities — models + errors
|
||||
{
|
||||
|
||||
@@ -11,6 +11,8 @@ import { {{constantCase name}}_SYMBOLS } from "./symbols";
|
||||
import { {{pascalCase entity}}Repository } from "../infrastructure/repositories/{{kebabCase entity}}.repository";
|
||||
import { get{{pascalCase entity}}UseCase } from "../application/use-cases/get-{{kebabCase entity}}.use-case";
|
||||
import { get{{pascalCase entity}}Controller } from "../interface-adapters/controllers/get-{{kebabCase entity}}.controller";
|
||||
import { assertFeatureConformance } from "@repo/core-shared/conformance";
|
||||
import { {{camelCase name}}Manifest } from "../feature.manifest";
|
||||
|
||||
export function bindProduction{{pascalCase name}}(ctx: BindProductionContext): void {
|
||||
const { config, tracer, logger, bus, queue, realtime, realtimeRegistry } = ctx;
|
||||
@@ -73,4 +75,15 @@ export function bindProduction{{pascalCase name}}(ctx: BindProductionContext): v
|
||||
// <gen:event-handlers>
|
||||
// <gen:jobs>
|
||||
// <gen:realtime-handlers>
|
||||
|
||||
// Boot-time conformance check: refuses to start if any use-case binding
|
||||
// is missing a required brand (withSpan / withCapture / withAudit).
|
||||
assertFeatureConformance(
|
||||
{{camelCase name}}Container,
|
||||
{{camelCase name}}Manifest,
|
||||
{
|
||||
get{{pascalCase entity}}: {{constantCase name}}_SYMBOLS.IGet{{pascalCase entity}}UseCase,
|
||||
},
|
||||
ctx,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { defineFeature } from "@repo/core-shared/conformance";
|
||||
|
||||
/**
|
||||
* The {{camelCase name}} feature's conformance manifest. Drives binding-slot
|
||||
* types in `di/bind-production.ts` and is read by ESLint, the boot
|
||||
* assertion, and the CI drift gate.
|
||||
*
|
||||
* Conventions:
|
||||
* - `mutates: true` for any use case that creates, updates, or deletes state
|
||||
* - `audits` lists every audit event the use case emits (must match calls
|
||||
* to `auditLog.record(...)` in the factory body — ESLint enforces this)
|
||||
* - `publishes` / `consumes` cover cross-feature events through `IEventBus`
|
||||
*/
|
||||
export const {{camelCase name}}Manifest = defineFeature({
|
||||
name: "{{kebabCase name}}",
|
||||
requiredCores: [],
|
||||
useCases: {
|
||||
get{{pascalCase entity}}: {
|
||||
mutates: false,
|
||||
audits: [],
|
||||
publishes: [],
|
||||
consumes: [],
|
||||
},
|
||||
},
|
||||
realtimeChannels: [],
|
||||
jobs: [],
|
||||
} as const);
|
||||
|
||||
export type {{pascalCase name}}Manifest = typeof {{camelCase name}}Manifest;
|
||||
Reference in New Issue
Block a user