@beignet/cli 0.0.48 → 0.0.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +76 -21
  3. package/dist/analysis/contract-factories.d.ts +17 -0
  4. package/dist/analysis/contract-factories.d.ts.map +1 -0
  5. package/dist/analysis/contract-factories.js +176 -0
  6. package/dist/analysis/contract-factories.js.map +1 -0
  7. package/dist/analysis/layers.d.ts +5 -0
  8. package/dist/analysis/layers.d.ts.map +1 -0
  9. package/dist/analysis/layers.js +172 -0
  10. package/dist/analysis/layers.js.map +1 -0
  11. package/dist/analysis/port-wiring.d.ts +23 -0
  12. package/dist/analysis/port-wiring.d.ts.map +1 -0
  13. package/dist/analysis/port-wiring.js +379 -0
  14. package/dist/analysis/port-wiring.js.map +1 -0
  15. package/dist/analysis/source-index.d.ts +5 -0
  16. package/dist/analysis/source-index.d.ts.map +1 -1
  17. package/dist/analysis/source-index.js +171 -42
  18. package/dist/analysis/source-index.js.map +1 -1
  19. package/dist/analysis/workspace.d.ts +10 -4
  20. package/dist/analysis/workspace.d.ts.map +1 -1
  21. package/dist/analysis/workspace.js +66 -6
  22. package/dist/analysis/workspace.js.map +1 -1
  23. package/dist/app-map.d.ts.map +1 -1
  24. package/dist/app-map.js +311 -92
  25. package/dist/app-map.js.map +1 -1
  26. package/dist/check.js +37 -3
  27. package/dist/check.js.map +1 -1
  28. package/dist/explain.js +4 -4
  29. package/dist/explain.js.map +1 -1
  30. package/dist/inspect.d.ts.map +1 -1
  31. package/dist/inspect.js +415 -168
  32. package/dist/inspect.js.map +1 -1
  33. package/dist/lint.d.ts.map +1 -1
  34. package/dist/lint.js +309 -487
  35. package/dist/lint.js.map +1 -1
  36. package/dist/make/inbox.d.ts.map +1 -1
  37. package/dist/make/inbox.js +11 -4
  38. package/dist/make/inbox.js.map +1 -1
  39. package/dist/make/payments.js +2 -2
  40. package/dist/make.d.ts.map +1 -1
  41. package/dist/make.js +144 -8
  42. package/dist/make.js.map +1 -1
  43. package/dist/mcp.d.ts +1 -1
  44. package/dist/mcp.d.ts.map +1 -1
  45. package/dist/mcp.js +19 -19
  46. package/dist/mcp.js.map +1 -1
  47. package/dist/provider-add.d.ts.map +1 -1
  48. package/dist/provider-add.js +142 -7
  49. package/dist/provider-add.js.map +1 -1
  50. package/dist/registry-edits.d.ts +7 -0
  51. package/dist/registry-edits.d.ts.map +1 -1
  52. package/dist/registry-edits.js +237 -53
  53. package/dist/registry-edits.js.map +1 -1
  54. package/dist/templates/agents.d.ts.map +1 -1
  55. package/dist/templates/agents.js +16 -0
  56. package/dist/templates/agents.js.map +1 -1
  57. package/dist/templates/base.d.ts.map +1 -1
  58. package/dist/templates/base.js +9 -1
  59. package/dist/templates/base.js.map +1 -1
  60. package/dist/templates/server.d.ts.map +1 -1
  61. package/dist/templates/server.js +2 -0
  62. package/dist/templates/server.js.map +1 -1
  63. package/dist/templates/shared.d.ts +1 -0
  64. package/dist/templates/shared.d.ts.map +1 -1
  65. package/dist/templates/shared.js +3 -2
  66. package/dist/templates/shared.js.map +1 -1
  67. package/package.json +7 -6
  68. package/skills/app-structure/SKILL.md +46 -5
  69. package/src/analysis/contract-factories.ts +256 -0
  70. package/src/analysis/layers.ts +266 -0
  71. package/src/analysis/port-wiring.ts +506 -0
  72. package/src/analysis/source-index.ts +225 -57
  73. package/src/analysis/workspace.ts +115 -6
  74. package/src/app-map.ts +418 -109
  75. package/src/check.ts +51 -3
  76. package/src/explain.ts +4 -4
  77. package/src/inspect.ts +583 -215
  78. package/src/lint.ts +393 -643
  79. package/src/make/inbox.ts +11 -4
  80. package/src/make/payments.ts +2 -2
  81. package/src/make.ts +225 -8
  82. package/src/mcp.ts +19 -22
  83. package/src/provider-add.ts +186 -7
  84. package/src/registry-edits.ts +313 -63
  85. package/src/templates/agents.ts +16 -0
  86. package/src/templates/base.ts +9 -1
  87. package/src/templates/server.ts +2 -0
  88. package/src/templates/shared.ts +3 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @beignet/cli
2
2
 
3
+ ## 0.0.49
4
+
5
+ ### Patch Changes
6
+
7
+ - e597d53: Require Node.js 22.12 or newer across every Beignet package, generated app,
8
+ and documented workflow.
9
+ - 3049831: Prevent outbox job registries from silently running without a dispatcher by
10
+ wiring generated jobs, reporting incomplete app-port configuration, and
11
+ validating delivery transports before claiming messages. Jobs provider presets
12
+ replace only the marked generated inline fallback.
13
+ - ea4bcf7: Inspect TypeScript module references structurally in architecture lint,
14
+ including require/import variants, transitive feature helpers, configured path
15
+ layouts, and exhaustive feature layer classification.
16
+ - ac46aad: Inspect contracts through import-backed TypeScript syntax and local fluent-builder aliases, align lint and doctor placement diagnostics, and reject non-app roots before `beignet check` runs validation.
17
+ - a06c5b9: Require contracts with query schemas to declare an explicit transport shared by typed clients, servers, and OpenAPI generation. Add deterministic scalar, repeated-array, and flat deep-object transports, migrate CLI generators, and diagnose legacy one-argument query declarations.
18
+ - e597d53: Migrate the Beignet MCP server to the stable TypeScript SDK v2 packages while
19
+ preserving stdio transport and protocol compatibility.
20
+ - 8c0b355: Isolate and safely frame default rate-limit buckets, fail closed for unresolved user scopes, escape Swagger script data, and require an explicit access policy for devtools routes.
21
+ - b2188d8: Align provider production behavior by validating cache TTLs consistently,
22
+ requiring encrypted SMTP transport by default, and streaming unknown-size S3
23
+ uploads through bounded managed multipart uploads with explicit cleanup across
24
+ all failure stages.
25
+
26
+ The S3 provider now requires `@aws-sdk/lib-storage`; the Beignet provider
27
+ preset installs the compatible version automatically.
28
+
29
+ - Updated dependencies [e597d53]
30
+ - Updated dependencies [3049831]
31
+ - Updated dependencies [60edd56]
32
+ - Updated dependencies [a06c5b9]
33
+ - Updated dependencies [8c0b355]
34
+ - Updated dependencies [b2188d8]
35
+ - @beignet/core@0.0.49
36
+
3
37
  ## 0.0.48
4
38
 
5
39
  ### Patch Changes
package/README.md CHANGED
@@ -6,6 +6,9 @@
6
6
 
7
7
  Command-line tools for creating and maintaining Beignet apps.
8
8
 
9
+ Beignet requires Node.js 22.12 or newer. Bun 1.3.14 or newer is supported for
10
+ CLI commands.
11
+
9
12
  The package ships a single `beignet` bin. Generated apps install
10
13
  `@beignet/cli` as a dev dependency and add a `beignet` package script, so the
11
14
  day-to-day form inside an app is:
@@ -362,7 +365,13 @@ server/routes.ts
362
365
  generated route tests pass the same value to `createTestApp(...)`.
363
366
 
364
367
  Route inspection supports contract-group definitions and direct
365
- `defineContract({ method, path })` exports.
368
+ `defineContract({ method, path })` exports. It reads exported declarations and
369
+ fluent contract calls from TypeScript syntax, so nested objects, comments, and
370
+ multiline expressions do not truncate a contract before its method or path.
371
+ Local fluent-builder aliases and named local exports are followed. Factories
372
+ must be value imports from `@beignet/core/contracts`; named aliases and
373
+ namespace imports work, while same-named methods on unrelated objects are
374
+ ignored.
366
375
 
367
376
  The standard app layout includes the files feature generators expect:
368
377
 
@@ -688,7 +697,9 @@ starter, tests, and feature-specific not-found and conflict catalog errors. Use
688
697
  resource.
689
698
 
690
699
  Generated list routes use cursor pagination with `limit`, `cursor`, `name`,
691
- `sortBy`, and `sortDirection` query parameters. The generated use case
700
+ `sortBy`, and `sortDirection` query parameters. Their contract pairs the query
701
+ schema with an explicit transport so the client, server, and OpenAPI document
702
+ use the same URL representation. The generated use case
692
703
  normalizes cursor pages, validates opaque base64url cursors against the selected
693
704
  sort, and passes one repository query object into memory and Drizzle adapters.
694
705
  Adapters filter `name` with case-insensitive contains matching, sort only by
@@ -787,6 +798,20 @@ and `make job` create that outbox path on first use and register the feature's
787
798
  `beignet doctor` reports events and jobs the registry cannot deliver. Keep the
788
799
  route as the durable recovery sweep even when the deferred trigger is present.
789
800
 
801
+ `make job` also ensures `jobs: JobDispatcherPort` is declared and bound. When
802
+ the app has no job dispatcher yet, it defers the port and installs an app-owned
803
+ inline dispatcher provider; existing direct wiring and providers such as
804
+ Inngest are preserved. Registry membership alone is not execution wiring.
805
+ Adding the `jobs-inngest` or `jobs-bullmq` preset later replaces only that
806
+ marked generated fallback; an unmarked app-owned inline provider is reported
807
+ as a conflict instead of being removed.
808
+ `beignet doctor` warns when an outbox registry contains jobs but the configured
809
+ ports and port-wiring files do not declare and bind or defer `jobs`. Keep that
810
+ key and the registry's `jobs` entries explicit; doctor reports indeterminate
811
+ registry or port-wiring shapes when they prevent it from verifying required
812
+ wiring, and the generator stops rather than replacing custom spread- or
813
+ helper-based wiring it cannot verify.
814
+
790
815
  Generators wire the provider-backed ports their output depends on. `make
791
816
  event` (and `make resource --events`) wires `eventBus: EventBusPort` with
792
817
  `createMemoryEventBusProvider()` from
@@ -840,6 +865,8 @@ The runner loads `server/outbox.ts` or `paths.outbox`. That module should export
840
865
  `stopOutboxDrainContext(...)`. The context owns app ports and provider
841
866
  lifecycle, so the CLI drain uses the same outbox, event bus, jobs,
842
867
  instrumentation, actor, and tenant decisions as the scheduled drain route.
868
+ The drain validates all transports required by the registry before claiming a
869
+ batch, so missing `eventBus` or `jobs` wiring does not consume attempts.
843
870
 
844
871
  Inspect and recover failed deliveries through the same app-owned operational
845
872
  context:
@@ -1032,11 +1059,12 @@ every edge carries source evidence and confidence.
1032
1059
 
1033
1060
  The JSON app map retains failed local module references as explicit
1034
1061
  `local_import_unresolved` entries instead of silently omitting their edges. It
1035
- also reports `contract_declaration_unresolved` when it finds an exported direct
1036
- `defineContract(...)` declaration whose method or path cannot be derived
1037
- statically. Registration diagnostics identify their declaration through a
1038
- structured `subject.file` and `subject.exportName`; registration status in the
1039
- map uses that identity rather than matching human-readable messages.
1062
+ also reports `contract_declaration_unresolved` when an exported direct or
1063
+ contract-group declaration has a method, path, or group prefix that cannot be
1064
+ derived statically. Registration diagnostics identify their declaration
1065
+ through a structured `subject.file` and `subject.exportName`; registration
1066
+ status in the map uses that identity rather than matching human-readable
1067
+ messages.
1040
1068
 
1041
1069
  `--feature` keeps that feature plus its direct relationships, while `--kind`
1042
1070
  accepts one or a comma-separated list of node kinds. These projections make
@@ -1090,7 +1118,12 @@ in that order. Every step runs even when an earlier one fails, so a single
1090
1118
  run reports everything that needs fixing; the command exits non-zero when any
1091
1119
  step fails. Missing package scripts are reported as skipped, never as
1092
1120
  failures. Failed package-script output retains at most the last 64 KiB of each
1093
- stream.
1121
+ stream. The target package must declare `@beignet/core`, `@beignet/next`, or
1122
+ `@beignet/web` as a runtime dependency. The root must also contain
1123
+ `app-context.ts` or `beignet.config.*`; a canonical app with both `features/`
1124
+ and `server/index.ts` is accepted when `app-context.ts` is missing so doctor
1125
+ can report the drift. Other package roots stop before lint, doctor, or app
1126
+ scripts run.
1094
1127
 
1095
1128
  Use `beignet check --fix` to apply doctor's eligible low-risk fixes
1096
1129
  before checking, and `beignet check --json` for a versioned payload
@@ -1148,14 +1181,30 @@ Run `lint` when you want the CLI to enforce Beignet dependency direction:
1148
1181
  beignet lint
1149
1182
  ```
1150
1183
 
1151
- The command scans static imports and fails when app layers reach into runtime
1152
- or framework layers. It catches domain, use case, workflow, policy, port,
1153
- contract, route, infra, and component files importing things like `infra/`, UI
1154
- components, route handlers, server modules, client modules, provider packages,
1155
- Next.js, React, or database vendors in the wrong direction. It also catches
1156
- feature-specific domain files importing another feature's domain unless the
1157
- target is `features/shared/domain`. Workflow folders include feature-owned
1158
- jobs, listeners, notifications, schedules, and uploads.
1184
+ The command recognizes TypeScript imports and re-exports, `require()`, import
1185
+ assignments, and literal dynamic imports. It fails when app layers reach into
1186
+ runtime or framework layers, including domain, use case, workflow, policy,
1187
+ port, contract, route, schema, seed, agent capability, feature helper, infra,
1188
+ and component files importing `infra/`, UI components, route handlers, server
1189
+ modules, client modules, provider packages, Next.js, React, or database vendors
1190
+ in the wrong direction. Computed `require()` and `import()` expressions inside
1191
+ constrained layers fail because lint cannot verify their destination; use a
1192
+ string-literal specifier or move runtime loading behind an allowed boundary.
1193
+ Client-safe graphs reject Node built-ins whether they use `node:fs` or a bare
1194
+ specifier such as `fs/promises`.
1195
+
1196
+ Local value-import checks follow feature-root and other local helpers.
1197
+ For example, `use-case -> history.ts -> infra` reports the complete chain
1198
+ instead of treating `history.ts` as an unknown layer. Every module inside the
1199
+ configured feature root is classified; allowed feature-root helpers remain
1200
+ helpers, while near-miss canonical names such as `usecases/` report the
1201
+ expected `use-cases/` path. Feature-specific domain files still cannot import
1202
+ another feature's domain unless the target is `features/shared/domain`.
1203
+ Workflow folders include feature-owned jobs, listeners, notifications,
1204
+ schedules, tasks, and uploads. Agent capabilities may adapt use cases but core
1205
+ application layers cannot depend back on those adapters. Seeds may compose
1206
+ factories and app ports, but not concrete infra, providers, UI, or runtime
1207
+ composition.
1159
1208
 
1160
1209
  Local imports are resolved with the app's complete `tsconfig.json`
1161
1210
  configuration before dependency direction is classified. That includes
@@ -1163,10 +1212,10 @@ configuration before dependency direction is classified. That includes
1163
1212
  with multiple targets. The CLI uses TypeScript's config parser and resolver, so
1164
1213
  JSON comments and extended tsconfigs follow the same rules as the compiler.
1165
1214
 
1166
- Import diagnostics include 1-based `line` and `column` positions. Human
1167
- output prints clickable `file.ts:12:3` locations; runtime-boundary
1168
- diagnostics report the chain root file and the full import chain in the
1169
- message instead.
1215
+ Import diagnostics include 1-based `line` and `column` positions and preserve
1216
+ separate occurrences of the same module specifier. Human output prints
1217
+ clickable `file.ts:12:3` locations; transitive and runtime-boundary diagnostics
1218
+ report the chain root file and the full import chain in the message instead.
1170
1219
 
1171
1220
  Use JSON output in CI or custom scripts, or GitHub annotations in workflows:
1172
1221
 
@@ -1186,11 +1235,14 @@ beignet doctor
1186
1235
  Today it detects:
1187
1236
 
1188
1237
  - Contracts without a matching Next.js route handler
1238
+ - Contract query schemas without an explicit second `.query(...)` transport
1189
1239
  - Feature route groups that are not registered in the central route list
1190
1240
  - Feature schedules and tasks that are not registered in `server/schedules.ts`
1191
1241
  or `server/tasks.ts`
1192
1242
  - Feature events with listeners, and feature jobs, that are missing from
1193
1243
  `defineOutboxRegistry({...})` when the app uses outbox delivery
1244
+ - Outbox registries with jobs but no declared and bound or deferred `jobs`
1245
+ application port
1194
1246
  - Feature listeners missing from `server/listeners.ts` or otherwise not
1195
1247
  referenced by `registerListeners(...)`
1196
1248
  - Opted-in runtime manifests that omit generated workflow registries
@@ -1208,6 +1260,9 @@ Today it detects:
1208
1260
  `features/shared/errors.ts`
1209
1261
  - Feature runtime `appError(...)` calls that are not declared on the feature's
1210
1262
  contracts
1263
+ - Feature layers whose normalized name or known alias points at a canonical
1264
+ location, such as `usecases/` instead of `use-cases/` or `events/` instead
1265
+ of `domain/events/`; doctor and lint report the same expected path
1211
1266
  - Authorization metadata whose ability is missing from feature policy coverage
1212
1267
  - Audit-required metadata without feature audit writes or test assertions
1213
1268
  - Mixed `@beignet/*` version ranges in package.json, and mixed installed
@@ -1247,7 +1302,7 @@ Today it detects:
1247
1302
  - Billing entitlement modules that are not wired into infra or server providers
1248
1303
  - Stripe payments configuration paired with local memory payments provider
1249
1304
  wiring
1250
- - Devtools routes that are explicitly enabled without authorization
1305
+ - Devtools routes without authorization or an explicit local-only development opt-in
1251
1306
  - Cron routes that do not use `CRON_SECRET`
1252
1307
  - Installed provider packages without expected environment configuration
1253
1308
  - Better Auth providers without an auth route or trusted-origin configuration
@@ -0,0 +1,17 @@
1
+ import ts from "typescript";
2
+ export type ContractFactoryName = "defineContract" | "defineContractGroup";
3
+ export type ContractFactoryBindings = {
4
+ localNames: Record<ContractFactoryName, Set<string>>;
5
+ namespaceNames: Set<string>;
6
+ };
7
+ export type ContractBindingNames = {
8
+ contracts: Set<string>;
9
+ groups: Set<string>;
10
+ };
11
+ export declare function contractFactoryBindings(sourceFile: ts.SourceFile): ContractFactoryBindings;
12
+ export declare function isImportedContractFactoryCall(call: ts.CallExpression, name: ContractFactoryName, bindings: ContractFactoryBindings): boolean;
13
+ /** Follow imported factories through local group and contract builder aliases. */
14
+ export declare function contractBindingNames(sourceFile: ts.SourceFile, bindings: ContractFactoryBindings): ContractBindingNames;
15
+ /** Determine whether an expression declares a direct or group-built contract. */
16
+ export declare function isImportedContractDeclaration(expression: ts.Expression, bindings: ContractFactoryBindings, names: ContractBindingNames): boolean;
17
+ //# sourceMappingURL=contract-factories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-factories.d.ts","sourceRoot":"","sources":["../../src/analysis/contract-factories.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAI5B,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,GAAG,qBAAqB,CAAC;AAE3E,MAAM,MAAM,uBAAuB,GAAG;IACpC,UAAU,EAAE,MAAM,CAAC,mBAAmB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACrD,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACrB,CAAC;AAkCF,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,EAAE,CAAC,UAAU,GACxB,uBAAuB,CAoCzB;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,EAAE,CAAC,cAAc,EACvB,IAAI,EAAE,mBAAmB,EACzB,QAAQ,EAAE,uBAAuB,GAChC,OAAO,CAaT;AAED,kFAAkF;AAClF,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,EAAE,CAAC,UAAU,EACzB,QAAQ,EAAE,uBAAuB,GAChC,oBAAoB,CAiDtB;AAED,iFAAiF;AACjF,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,EAAE,CAAC,UAAU,EACzB,QAAQ,EAAE,uBAAuB,EACjC,KAAK,EAAE,oBAAoB,GAC1B,OAAO,CAaT"}
@@ -0,0 +1,176 @@
1
+ import ts from "typescript";
2
+ const contractFactoryModule = "@beignet/core/contracts";
3
+ const contractGroupMethods = new Set([
4
+ "defineContractGroup",
5
+ "deprecated",
6
+ "errors",
7
+ "headers",
8
+ "meta",
9
+ "namespace",
10
+ "prefix",
11
+ "responses",
12
+ ]);
13
+ const httpContractMethods = new Set([
14
+ "delete",
15
+ "get",
16
+ "head",
17
+ "options",
18
+ "patch",
19
+ "post",
20
+ "put",
21
+ ]);
22
+ export function contractFactoryBindings(sourceFile) {
23
+ const bindings = {
24
+ localNames: {
25
+ defineContract: new Set(),
26
+ defineContractGroup: new Set(),
27
+ },
28
+ namespaceNames: new Set(),
29
+ };
30
+ for (const statement of sourceFile.statements) {
31
+ if (!ts.isImportDeclaration(statement) ||
32
+ !ts.isStringLiteral(statement.moduleSpecifier) ||
33
+ statement.moduleSpecifier.text !== contractFactoryModule ||
34
+ !statement.importClause ||
35
+ statement.importClause.isTypeOnly) {
36
+ continue;
37
+ }
38
+ const namedBindings = statement.importClause.namedBindings;
39
+ if (namedBindings && ts.isNamespaceImport(namedBindings)) {
40
+ bindings.namespaceNames.add(namedBindings.name.text);
41
+ continue;
42
+ }
43
+ if (!namedBindings || !ts.isNamedImports(namedBindings))
44
+ continue;
45
+ for (const element of namedBindings.elements) {
46
+ if (element.isTypeOnly)
47
+ continue;
48
+ const importedName = (element.propertyName ?? element.name).text;
49
+ if (!isContractFactoryName(importedName))
50
+ continue;
51
+ bindings.localNames[importedName].add(element.name.text);
52
+ }
53
+ }
54
+ return bindings;
55
+ }
56
+ export function isImportedContractFactoryCall(call, name, bindings) {
57
+ const callee = unwrapExpression(call.expression);
58
+ if (ts.isIdentifier(callee)) {
59
+ return bindings.localNames[name].has(callee.text);
60
+ }
61
+ if (!ts.isPropertyAccessExpression(callee) || callee.name.text !== name) {
62
+ return false;
63
+ }
64
+ const receiver = unwrapExpression(callee.expression);
65
+ return (ts.isIdentifier(receiver) && bindings.namespaceNames.has(receiver.text));
66
+ }
67
+ /** Follow imported factories through local group and contract builder aliases. */
68
+ export function contractBindingNames(sourceFile, bindings) {
69
+ const declarations = sourceFile.statements
70
+ .filter(ts.isVariableStatement)
71
+ .flatMap((statement) => [...statement.declarationList.declarations]);
72
+ const names = {
73
+ contracts: new Set(),
74
+ groups: new Set(),
75
+ };
76
+ let changed = true;
77
+ while (changed) {
78
+ changed = false;
79
+ for (const declaration of declarations) {
80
+ if (!ts.isIdentifier(declaration.name) ||
81
+ !declaration.initializer ||
82
+ names.contracts.has(declaration.name.text) ||
83
+ names.groups.has(declaration.name.text)) {
84
+ continue;
85
+ }
86
+ const chain = contractCallChain(declaration.initializer);
87
+ if (!chain)
88
+ continue;
89
+ if (contractFactoryCall(chain, "defineContract", bindings) ||
90
+ (chain.baseIdentifier && names.contracts.has(chain.baseIdentifier))) {
91
+ names.contracts.add(declaration.name.text);
92
+ changed = true;
93
+ continue;
94
+ }
95
+ if (!isContractGroupDerived(chain, bindings, names.groups))
96
+ continue;
97
+ if (chain.calls.some((call) => httpContractMethods.has(call.name))) {
98
+ names.contracts.add(declaration.name.text);
99
+ changed = true;
100
+ continue;
101
+ }
102
+ if (chain.calls.some((call) => !contractGroupMethods.has(call.name))) {
103
+ continue;
104
+ }
105
+ names.groups.add(declaration.name.text);
106
+ changed = true;
107
+ }
108
+ }
109
+ return names;
110
+ }
111
+ /** Determine whether an expression declares a direct or group-built contract. */
112
+ export function isImportedContractDeclaration(expression, bindings, names) {
113
+ const chain = contractCallChain(expression);
114
+ if (!chain)
115
+ return false;
116
+ if (contractFactoryCall(chain, "defineContract", bindings) ||
117
+ (chain.baseIdentifier && names.contracts.has(chain.baseIdentifier))) {
118
+ return true;
119
+ }
120
+ return (isContractGroupDerived(chain, bindings, names.groups) &&
121
+ chain.calls.some((call) => httpContractMethods.has(call.name)));
122
+ }
123
+ function isContractGroupDerived(chain, bindings, groupNames) {
124
+ return Boolean(contractFactoryCall(chain, "defineContractGroup", bindings) ||
125
+ (chain.baseIdentifier && groupNames.has(chain.baseIdentifier)));
126
+ }
127
+ function contractFactoryCall(chain, name, bindings) {
128
+ const calls = chain.rootCall ? [chain.rootCall, ...chain.calls] : chain.calls;
129
+ return calls.find((call) => isImportedContractFactoryCall(call.node, name, bindings));
130
+ }
131
+ function contractCallChain(rawExpression) {
132
+ const calls = [];
133
+ let expression = rawExpression;
134
+ while (true) {
135
+ expression = unwrapExpression(expression);
136
+ if (ts.isPropertyAccessExpression(expression)) {
137
+ expression = expression.expression;
138
+ continue;
139
+ }
140
+ if (ts.isCallExpression(expression)) {
141
+ const callee = unwrapExpression(expression.expression);
142
+ if (ts.isPropertyAccessExpression(callee)) {
143
+ calls.unshift({ name: callee.name.text, node: expression });
144
+ expression = callee.expression;
145
+ continue;
146
+ }
147
+ if (ts.isIdentifier(callee)) {
148
+ return {
149
+ baseIdentifier: callee.text,
150
+ rootCall: { name: callee.text, node: expression },
151
+ calls,
152
+ };
153
+ }
154
+ return undefined;
155
+ }
156
+ if (ts.isIdentifier(expression)) {
157
+ return { baseIdentifier: expression.text, calls };
158
+ }
159
+ return undefined;
160
+ }
161
+ }
162
+ function isContractFactoryName(value) {
163
+ return value === "defineContract" || value === "defineContractGroup";
164
+ }
165
+ function unwrapExpression(expression) {
166
+ let current = expression;
167
+ while (ts.isParenthesizedExpression(current) ||
168
+ ts.isAsExpression(current) ||
169
+ ts.isTypeAssertionExpression(current) ||
170
+ ts.isNonNullExpression(current) ||
171
+ ts.isSatisfiesExpression(current)) {
172
+ current = current.expression;
173
+ }
174
+ return current;
175
+ }
176
+ //# sourceMappingURL=contract-factories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-factories.js","sourceRoot":"","sources":["../../src/analysis/contract-factories.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { type ResolvedBeignetConfig } from "../config.js";
2
+ export type SourceLayer = "app" | "app-context" | "agent-capability" | "client" | "component" | "contract" | "domain" | "feature-helper" | "feature-port" | "infra" | "lib" | "policy" | "port" | "route" | "schema" | "seed" | "server" | "test" | "use-case" | "workflow" | "unknown";
3
+ export declare function classifySourcePath(filePath: string, config: ResolvedBeignetConfig): SourceLayer;
4
+ export declare function canonicalFeatureLayerPath(filePath: string, config: ResolvedBeignetConfig): string | undefined;
5
+ //# sourceMappingURL=layers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layers.d.ts","sourceRoot":"","sources":["../../src/analysis/layers.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,qBAAqB,EAC3B,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,WAAW,GACnB,KAAK,GACL,aAAa,GACb,kBAAkB,GAClB,QAAQ,GACR,WAAW,GACX,UAAU,GACV,QAAQ,GACR,gBAAgB,GAChB,cAAc,GACd,OAAO,GACP,KAAK,GACL,QAAQ,GACR,MAAM,GACN,OAAO,GACP,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,MAAM,GACN,UAAU,GACV,UAAU,GACV,SAAS,CAAC;AA6Cd,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,qBAAqB,GAC5B,WAAW,CAuEb;AAED,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,qBAAqB,GAC5B,MAAM,GAAG,SAAS,CAmCpB"}
@@ -0,0 +1,172 @@
1
+ import path from "node:path";
2
+ import { clientDirPath, directoryPath, normalizePath, } from "../config.js";
3
+ const canonicalFeatureDirectories = {
4
+ client: "client",
5
+ components: "component",
6
+ domain: "domain",
7
+ jobs: "workflow",
8
+ listeners: "workflow",
9
+ notifications: "workflow",
10
+ schedules: "workflow",
11
+ seeds: "seed",
12
+ tasks: "workflow",
13
+ tests: "test",
14
+ uploads: "workflow",
15
+ "use-cases": "use-case",
16
+ };
17
+ const canonicalFeatureRootFiles = {
18
+ "agent-capabilities": "agent-capability",
19
+ contracts: "contract",
20
+ policy: "policy",
21
+ ports: "feature-port",
22
+ routes: "route",
23
+ schemas: "schema",
24
+ };
25
+ const featureDirectoryAliases = {
26
+ command: "tasks",
27
+ commands: "tasks",
28
+ event: "domain/events",
29
+ events: "domain/events",
30
+ job: "jobs",
31
+ listener: "listeners",
32
+ notification: "notifications",
33
+ schedule: "schedules",
34
+ scheduled: "schedules",
35
+ task: "tasks",
36
+ upload: "uploads",
37
+ };
38
+ export function classifySourcePath(filePath, config) {
39
+ const normalizedPath = stripKnownExtension(normalizePath(filePath));
40
+ const featuresPath = directoryPath(config.paths.features);
41
+ const portsDir = directoryPath(path.dirname(config.paths.ports));
42
+ if (isTestPath(normalizedPath) ||
43
+ isUnder(normalizedPath, directoryPath(config.paths.tests))) {
44
+ return "test";
45
+ }
46
+ if (normalizedPath === stripKnownExtension(config.paths.appContext)) {
47
+ return "app-context";
48
+ }
49
+ const featurePath = featureRelativePath(normalizedPath, featuresPath);
50
+ if (featurePath) {
51
+ const layerSegment = featurePath.split("/")[1];
52
+ if (!layerSegment)
53
+ return "feature-helper";
54
+ const convention = featureDirectoryConvention(layerSegment);
55
+ if (convention)
56
+ return convention.layer;
57
+ const rootConvention = featureRootFileConvention(layerSegment);
58
+ if (rootConvention)
59
+ return rootConvention.layer;
60
+ if (layerSegment.endsWith("-contracts"))
61
+ return "contract";
62
+ return "feature-helper";
63
+ }
64
+ if (directoryPath(config.paths.contracts) !== featuresPath &&
65
+ isUnder(normalizedPath, directoryPath(config.paths.contracts))) {
66
+ return "contract";
67
+ }
68
+ if (directoryPath(config.paths.useCases) !== featuresPath &&
69
+ isUnder(normalizedPath, directoryPath(config.paths.useCases))) {
70
+ return "use-case";
71
+ }
72
+ if (directoryPath(config.paths.policies) !== featuresPath &&
73
+ isUnder(normalizedPath, directoryPath(config.paths.policies))) {
74
+ return "policy";
75
+ }
76
+ if (isUnder(normalizedPath, directoryPath(path.dirname(config.paths.server)))) {
77
+ return "server";
78
+ }
79
+ if (isUnder(normalizedPath, directoryPath(path.dirname(config.paths.portWiring)))) {
80
+ return "infra";
81
+ }
82
+ if (isUnder(normalizedPath, portsDir))
83
+ return "port";
84
+ if (isUnder(normalizedPath, clientDirPath(config)))
85
+ return "client";
86
+ if (isUnder(normalizedPath, "components"))
87
+ return "component";
88
+ if (isUnder(normalizedPath, legacySharedDomainPath(config)))
89
+ return "domain";
90
+ if (isUnder(normalizedPath, "lib"))
91
+ return "lib";
92
+ if (isUnder(normalizedPath, directoryPath(path.dirname(config.paths.routes)))) {
93
+ return "app";
94
+ }
95
+ return "unknown";
96
+ }
97
+ export function canonicalFeatureLayerPath(filePath, config) {
98
+ const featuresPath = directoryPath(config.paths.features);
99
+ const relativePath = featureRelativePath(normalizePath(filePath), featuresPath);
100
+ if (!relativePath)
101
+ return undefined;
102
+ const [feature, segment, ...rest] = relativePath.split("/");
103
+ if (!feature || !segment)
104
+ return undefined;
105
+ if (isTestSourceFile(segment, rest) && segment !== "tests") {
106
+ return path.posix.join(featuresPath, feature, "tests", ...(rest.length > 0 ? rest : [segment]));
107
+ }
108
+ if (rest.length > 0) {
109
+ const convention = featureDirectoryConvention(segment);
110
+ if (!convention || convention.path === segment)
111
+ return undefined;
112
+ return path.posix.join(featuresPath, feature, convention.path, ...rest);
113
+ }
114
+ const extension = path.posix.extname(segment);
115
+ const stem = extension ? segment.slice(0, -extension.length) : segment;
116
+ const convention = featureRootFileConvention(stem);
117
+ if (!convention || convention.path === stem)
118
+ return undefined;
119
+ return path.posix.join(featuresPath, feature, `${convention.path}${extension}`);
120
+ }
121
+ function isTestSourceFile(segment, rest) {
122
+ const fileName = rest.at(-1) ?? segment;
123
+ return /\.(?:test|spec)\.(?:ts|tsx|mts|cts)$/.test(fileName);
124
+ }
125
+ function featureDirectoryConvention(segment) {
126
+ const canonical = Object.entries(canonicalFeatureDirectories).find(([candidate]) => normalizeLayerSegment(candidate) === normalizeLayerSegment(segment));
127
+ if (canonical)
128
+ return { path: canonical[0], layer: canonical[1] };
129
+ const alias = featureDirectoryAliases[normalizeLayerSegment(segment)];
130
+ if (!alias)
131
+ return undefined;
132
+ return {
133
+ path: alias,
134
+ layer: alias === "domain/events"
135
+ ? "domain"
136
+ : canonicalFeatureDirectories[alias],
137
+ };
138
+ }
139
+ function featureRootFileConvention(segment) {
140
+ const canonical = Object.entries(canonicalFeatureRootFiles).find(([candidate]) => normalizeLayerSegment(candidate) === normalizeLayerSegment(segment));
141
+ return canonical ? { path: canonical[0], layer: canonical[1] } : undefined;
142
+ }
143
+ function normalizeLayerSegment(segment) {
144
+ return segment.replaceAll("-", "").replaceAll("_", "").toLowerCase();
145
+ }
146
+ function stripKnownExtension(filePath) {
147
+ return filePath.replace(/\.(c|m)?tsx?$/, "");
148
+ }
149
+ function isTestPath(filePath) {
150
+ return (filePath.includes("/tests/") ||
151
+ filePath.endsWith(".test") ||
152
+ filePath.endsWith(".spec"));
153
+ }
154
+ function isUnder(filePath, directory) {
155
+ const normalizedDir = directoryPath(directory);
156
+ if (!normalizedDir || normalizedDir === ".")
157
+ return false;
158
+ return filePath === normalizedDir || filePath.startsWith(`${normalizedDir}/`);
159
+ }
160
+ function featureRelativePath(filePath, featuresPath) {
161
+ if (!isUnder(filePath, featuresPath))
162
+ return undefined;
163
+ return filePath.slice(`${directoryPath(featuresPath)}/`.length);
164
+ }
165
+ function legacySharedDomainPath(config) {
166
+ const featuresDir = directoryPath(config.paths.features);
167
+ const featuresParent = directoryPath(path.dirname(featuresDir));
168
+ if (!featuresParent || featuresParent === ".")
169
+ return "domain";
170
+ return path.join(featuresParent, "domain");
171
+ }
172
+ //# sourceMappingURL=layers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layers.js","sourceRoot":"","sources":["../../src/analysis/layers.ts"],"names":[],"mappings":"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"}