forgeos 0.1.0-alpha.0 → 0.1.0-alpha.2

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 (283) hide show
  1. package/.npmignore +9 -1
  2. package/AGENTS.md +6 -1
  3. package/CHANGELOG.md +30 -0
  4. package/CONTRIBUTING.md +22 -1
  5. package/README.md +30 -3
  6. package/bin/forge.mjs +4 -3
  7. package/package.json +3 -1
  8. package/packages/eslint-plugin-forge/index.ts +15 -15
  9. package/packages/eslint-plugin-forge/package.json +10 -10
  10. package/packages/eslint-plugin-forge/src/check-source.ts +95 -95
  11. package/packages/eslint-plugin-forge/src/load-artifacts.ts +24 -24
  12. package/packages/eslint-plugin-forge/src/rule-no-forge-guard-violation.ts +93 -93
  13. package/src/forge/_generated/actionSubscriptions.json +2 -2
  14. package/src/forge/_generated/actionSubscriptions.ts +3 -3
  15. package/src/forge/_generated/agentAdapterManifest.json +2 -2
  16. package/src/forge/_generated/agentAdapterManifest.ts +3 -3
  17. package/src/forge/_generated/agentContract.json +2 -2
  18. package/src/forge/_generated/agentContract.ts +6786 -2
  19. package/src/forge/_generated/agentQuickstart.md +1 -1
  20. package/src/forge/_generated/aiContext.ts +1 -1
  21. package/src/forge/_generated/aiModels.json +1 -1
  22. package/src/forge/_generated/aiModels.ts +1 -1
  23. package/src/forge/_generated/aiProviders.json +1 -1
  24. package/src/forge/_generated/aiProviders.ts +1 -1
  25. package/src/forge/_generated/aiRegistry.json +2 -2
  26. package/src/forge/_generated/aiRegistry.ts +3 -3
  27. package/src/forge/_generated/api.json +2 -2
  28. package/src/forge/_generated/api.ts +1 -1
  29. package/src/forge/_generated/appGraph.json +2 -2
  30. package/src/forge/_generated/appGraph.ts +1297 -1141
  31. package/src/forge/_generated/appMap.md +1 -1
  32. package/src/forge/_generated/artifactManifest.json +2 -2
  33. package/src/forge/_generated/artifactManifest.ts +2 -2
  34. package/src/forge/_generated/authClaims.json +1 -1
  35. package/src/forge/_generated/authClaims.ts +1 -1
  36. package/src/forge/_generated/authConfig.json +1 -1
  37. package/src/forge/_generated/authConfig.ts +1 -1
  38. package/src/forge/_generated/authContext.ts +1 -1
  39. package/src/forge/_generated/authRegistry.json +1 -1
  40. package/src/forge/_generated/authRegistry.ts +1 -1
  41. package/src/forge/_generated/buildInfo.json +2 -2
  42. package/src/forge/_generated/buildInfo.ts +4 -4
  43. package/src/forge/_generated/capabilityMap.json +2 -2
  44. package/src/forge/_generated/capabilityMap.md +1 -1
  45. package/src/forge/_generated/capabilityMap.ts +2 -2
  46. package/src/forge/_generated/client.ts +1 -1
  47. package/src/forge/_generated/clientApi.ts +1 -1
  48. package/src/forge/_generated/clientManifest.json +2 -2
  49. package/src/forge/_generated/clientManifest.ts +3 -3
  50. package/src/forge/_generated/clientTypes.ts +1 -1
  51. package/src/forge/_generated/configRegistry.json +1 -1
  52. package/src/forge/_generated/configRegistry.ts +1 -1
  53. package/src/forge/_generated/dataGraph.json +2 -2
  54. package/src/forge/_generated/dataGraph.ts +3 -3
  55. package/src/forge/_generated/db.json +1 -1
  56. package/src/forge/_generated/db.ts +1 -1
  57. package/src/forge/_generated/dbSecurityManifest.json +1 -1
  58. package/src/forge/_generated/dbSecurityManifest.ts +1 -1
  59. package/src/forge/_generated/dbSessionContext.json +1 -1
  60. package/src/forge/_generated/dbSessionContext.ts +1 -1
  61. package/src/forge/_generated/deployManifest.json +2 -2
  62. package/src/forge/_generated/deployManifest.ts +7 -7
  63. package/src/forge/_generated/devManifest.json +2 -2
  64. package/src/forge/_generated/devManifest.ts +3 -3
  65. package/src/forge/_generated/envSchema.json +1 -1
  66. package/src/forge/_generated/envSchema.ts +1 -1
  67. package/src/forge/_generated/frontendGraph.json +1 -1
  68. package/src/forge/_generated/frontendGraph.ts +1 -1
  69. package/src/forge/_generated/importGuards.json +2 -2
  70. package/src/forge/_generated/importGuards.ts +35 -1
  71. package/src/forge/_generated/index.ts +1 -1
  72. package/src/forge/_generated/liveProductionManifest.json +1 -1
  73. package/src/forge/_generated/liveProductionManifest.ts +1 -1
  74. package/src/forge/_generated/liveProtocol.json +1 -1
  75. package/src/forge/_generated/liveProtocol.ts +1 -1
  76. package/src/forge/_generated/liveQueryRegistry.json +2 -2
  77. package/src/forge/_generated/liveQueryRegistry.ts +3 -3
  78. package/src/forge/_generated/liveTransportConfig.json +1 -1
  79. package/src/forge/_generated/liveTransportConfig.ts +1 -1
  80. package/src/forge/_generated/makeRegistry.json +2 -2
  81. package/src/forge/_generated/makeRegistry.ts +2 -2
  82. package/src/forge/_generated/makeTemplates.json +1 -1
  83. package/src/forge/_generated/makeTemplates.ts +1 -1
  84. package/src/forge/_generated/mockMap.json +1 -1
  85. package/src/forge/_generated/mockMap.ts +1 -1
  86. package/src/forge/_generated/operationPlaybooks.md +7 -5
  87. package/src/forge/_generated/packageGraph.json +2 -2
  88. package/src/forge/_generated/packageGraph.ts +90964 -14284
  89. package/src/forge/_generated/packageUpgradeRegistry.json +2 -2
  90. package/src/forge/_generated/packageUpgradeRegistry.ts +2 -2
  91. package/src/forge/_generated/permissionMatrix.json +2 -2
  92. package/src/forge/_generated/permissionMatrix.ts +3 -3
  93. package/src/forge/_generated/policyRegistry.json +2 -2
  94. package/src/forge/_generated/policyRegistry.ts +3 -3
  95. package/src/forge/_generated/queryRegistry.json +2 -2
  96. package/src/forge/_generated/queryRegistry.ts +3 -3
  97. package/src/forge/_generated/react.d.ts +1 -1
  98. package/src/forge/_generated/react.ts +1 -1
  99. package/src/forge/_generated/reactManifest.json +2 -2
  100. package/src/forge/_generated/reactManifest.ts +3 -3
  101. package/src/forge/_generated/releaseManifest.json +2 -2
  102. package/src/forge/_generated/releaseManifest.ts +3 -3
  103. package/src/forge/_generated/rlsPolicies.json +1 -1
  104. package/src/forge/_generated/rlsPolicies.sql +1 -1
  105. package/src/forge/_generated/rlsPolicies.ts +1 -1
  106. package/src/forge/_generated/runtimeGraph.json +2 -2
  107. package/src/forge/_generated/runtimeGraph.ts +3 -3
  108. package/src/forge/_generated/runtimeMatrix.json +2 -2
  109. package/src/forge/_generated/runtimeMatrix.ts +106177 -7917
  110. package/src/forge/_generated/runtimeRegistry.ts +1 -1
  111. package/src/forge/_generated/runtimeRules.md +1 -1
  112. package/src/forge/_generated/secretRegistry.json +1 -1
  113. package/src/forge/_generated/secretRegistry.ts +1 -1
  114. package/src/forge/_generated/secretsContext.ts +1 -1
  115. package/src/forge/_generated/serverApi.ts +1 -1
  116. package/src/forge/_generated/sourceMapManifest.json +2 -2
  117. package/src/forge/_generated/sourceMapManifest.ts +2 -2
  118. package/src/forge/_generated/sqlPlan.json +1 -1
  119. package/src/forge/_generated/sqlPlan.ts +1 -1
  120. package/src/forge/_generated/subscriptionManifest.json +2 -2
  121. package/src/forge/_generated/subscriptionManifest.ts +3 -3
  122. package/src/forge/_generated/symbolicationManifest.json +2 -2
  123. package/src/forge/_generated/symbolicationManifest.ts +2 -2
  124. package/src/forge/_generated/telemetryRegistry.json +2 -2
  125. package/src/forge/_generated/telemetryRegistry.ts +3 -3
  126. package/src/forge/_generated/telemetrySinks.json +2 -2
  127. package/src/forge/_generated/telemetrySinks.ts +2 -2
  128. package/src/forge/_generated/tenantScope.json +2 -2
  129. package/src/forge/_generated/tenantScope.ts +3 -3
  130. package/src/forge/_generated/testGraph.json +2 -2
  131. package/src/forge/_generated/testGraph.ts +129 -75
  132. package/src/forge/_generated/testPlanRegistry.json +2 -2
  133. package/src/forge/_generated/testPlanRegistry.ts +2 -2
  134. package/src/forge/_generated/uiRoutes.json +1 -1
  135. package/src/forge/_generated/uiRoutes.ts +1 -1
  136. package/src/forge/_generated/uiScenarios.json +1 -1
  137. package/src/forge/_generated/uiScenarios.ts +1 -1
  138. package/src/forge/_generated/uiTestManifest.json +2 -2
  139. package/src/forge/_generated/uiTestManifest.ts +2 -2
  140. package/src/forge/_generated/workflowRegistry.json +2 -2
  141. package/src/forge/_generated/workflowRegistry.ts +3 -3
  142. package/src/forge/_generated/workflowSubscriptions.json +2 -2
  143. package/src/forge/_generated/workflowSubscriptions.ts +3 -3
  144. package/src/forge/cli/commands.ts +861 -861
  145. package/src/forge/cli/deps.ts +178 -11
  146. package/src/forge/cli/dev.ts +32 -5
  147. package/src/forge/cli/index.ts +7 -7
  148. package/src/forge/cli/main.ts +54 -54
  149. package/src/forge/cli/new.ts +29 -1
  150. package/src/forge/cli/output.ts +97 -97
  151. package/src/forge/cli/parse.ts +679 -673
  152. package/src/forge/cli/version.ts +1 -1
  153. package/src/forge/compiler/agent-contract/build.ts +28 -0
  154. package/src/forge/compiler/agent-contract/types.ts +16 -0
  155. package/src/forge/compiler/app-graph/build.ts +112 -112
  156. package/src/forge/compiler/app-graph/classify.ts +10 -10
  157. package/src/forge/compiler/app-graph/dup-symbol.ts +29 -29
  158. package/src/forge/compiler/app-graph/extract.ts +123 -123
  159. package/src/forge/compiler/app-graph/forge-apis.ts +29 -29
  160. package/src/forge/compiler/app-graph/index.ts +11 -11
  161. package/src/forge/compiler/app-graph/module-graph.ts +316 -316
  162. package/src/forge/compiler/app-graph/parser.ts +119 -119
  163. package/src/forge/compiler/app-graph/symbols.ts +48 -48
  164. package/src/forge/compiler/app-graph/tsconfig-hash.ts +62 -62
  165. package/src/forge/compiler/app-graph/types.ts +43 -43
  166. package/src/forge/compiler/app-graph/versions.ts +14 -14
  167. package/src/forge/compiler/cache/index.ts +17 -17
  168. package/src/forge/compiler/cache/key.ts +46 -46
  169. package/src/forge/compiler/cache/scheduler.ts +72 -72
  170. package/src/forge/compiler/cache/store.ts +78 -78
  171. package/src/forge/compiler/classifier/capabilities.ts +78 -78
  172. package/src/forge/compiler/classifier/classify.ts +113 -113
  173. package/src/forge/compiler/classifier/contexts.ts +188 -188
  174. package/src/forge/compiler/classifier/index.ts +18 -18
  175. package/src/forge/compiler/classifier/runtime-matrix.ts +45 -45
  176. package/src/forge/compiler/classifier/secrets.ts +41 -41
  177. package/src/forge/compiler/classifier/signals.ts +129 -129
  178. package/src/forge/compiler/diagnostics/codes.ts +125 -120
  179. package/src/forge/compiler/diagnostics/create.ts +87 -87
  180. package/src/forge/compiler/diagnostics/index.ts +41 -41
  181. package/src/forge/compiler/emitter/artifact-kind.ts +14 -14
  182. package/src/forge/compiler/emitter/barrel.ts +38 -38
  183. package/src/forge/compiler/emitter/constants.ts +7 -7
  184. package/src/forge/compiler/emitter/emit.ts +234 -237
  185. package/src/forge/compiler/emitter/index.ts +24 -24
  186. package/src/forge/compiler/emitter/lock.ts +61 -61
  187. package/src/forge/compiler/emitter/render.ts +73 -73
  188. package/src/forge/compiler/guards/artifacts.ts +96 -96
  189. package/src/forge/compiler/guards/check-import-guards.ts +106 -106
  190. package/src/forge/compiler/guards/index.ts +11 -11
  191. package/src/forge/compiler/guards/propagate-contexts.ts +57 -57
  192. package/src/forge/compiler/index.ts +17 -17
  193. package/src/forge/compiler/integration/add.ts +493 -493
  194. package/src/forge/compiler/integration/index.ts +17 -17
  195. package/src/forge/compiler/integration/plan.ts +279 -279
  196. package/src/forge/compiler/integration/render.ts +189 -189
  197. package/src/forge/compiler/integration/snapshot.ts +52 -52
  198. package/src/forge/compiler/orchestrator/discover.ts +214 -214
  199. package/src/forge/compiler/orchestrator/guards.ts +5 -5
  200. package/src/forge/compiler/orchestrator/index.ts +27 -27
  201. package/src/forge/compiler/orchestrator/manifest.ts +69 -69
  202. package/src/forge/compiler/orchestrator/orphans.ts +51 -51
  203. package/src/forge/compiler/orchestrator/plan.ts +804 -804
  204. package/src/forge/compiler/orchestrator/run.ts +178 -178
  205. package/src/forge/compiler/orchestrator/serialize.ts +859 -859
  206. package/src/forge/compiler/orchestrator/types.ts +23 -23
  207. package/src/forge/compiler/orchestrator/verify.ts +35 -35
  208. package/src/forge/compiler/package-graph/capabilities-stub.ts +33 -33
  209. package/src/forge/compiler/package-graph/checksum.ts +107 -97
  210. package/src/forge/compiler/package-graph/compiler.ts +444 -363
  211. package/src/forge/compiler/package-graph/constants.ts +4 -4
  212. package/src/forge/compiler/package-graph/exports-discovery.ts +91 -84
  213. package/src/forge/compiler/package-graph/extract-dts.ts +32 -32
  214. package/src/forge/compiler/package-graph/index.ts +24 -24
  215. package/src/forge/compiler/package-graph/jsdoc.ts +50 -50
  216. package/src/forge/compiler/package-graph/oracle.ts +326 -0
  217. package/src/forge/compiler/package-graph/read-file.ts +21 -21
  218. package/src/forge/compiler/package-graph/resolve.ts +131 -127
  219. package/src/forge/compiler/package-manager/adapter.ts +232 -232
  220. package/src/forge/compiler/package-manager/commands.ts +47 -47
  221. package/src/forge/compiler/package-manager/detect.ts +65 -65
  222. package/src/forge/compiler/package-manager/executor.ts +29 -29
  223. package/src/forge/compiler/package-manager/index.ts +22 -22
  224. package/src/forge/compiler/package-manager/parse-spec.ts +16 -16
  225. package/src/forge/compiler/package-manager/version.ts +20 -20
  226. package/src/forge/compiler/primitives/compare.ts +26 -26
  227. package/src/forge/compiler/primitives/hash.ts +42 -33
  228. package/src/forge/compiler/primitives/header.ts +43 -43
  229. package/src/forge/compiler/primitives/index.ts +45 -45
  230. package/src/forge/compiler/primitives/paths.ts +24 -24
  231. package/src/forge/compiler/primitives/serialize.ts +66 -66
  232. package/src/forge/compiler/primitives/sort.ts +87 -87
  233. package/src/forge/compiler/recipes/definitions.ts +269 -269
  234. package/src/forge/compiler/recipes/helpers.ts +37 -37
  235. package/src/forge/compiler/recipes/index.ts +21 -21
  236. package/src/forge/compiler/recipes/registry.ts +87 -87
  237. package/src/forge/compiler/sandbox/artifact-sanitize.ts +26 -26
  238. package/src/forge/compiler/sandbox/backends/child.ts +123 -123
  239. package/src/forge/compiler/sandbox/backends/docker.ts +173 -173
  240. package/src/forge/compiler/sandbox/index.ts +51 -51
  241. package/src/forge/compiler/sandbox/inspect.ts +143 -143
  242. package/src/forge/compiler/sandbox/inspector-entry.ts +115 -115
  243. package/src/forge/compiler/sandbox/limits.ts +31 -31
  244. package/src/forge/compiler/sandbox/scrub-env.ts +60 -60
  245. package/src/forge/compiler/sandbox/secret-scan.ts +54 -54
  246. package/src/forge/compiler/sandbox/serialize.ts +106 -106
  247. package/src/forge/compiler/sandbox/types.ts +7 -7
  248. package/src/forge/compiler/types/app-graph.ts +71 -71
  249. package/src/forge/compiler/types/capability.ts +29 -29
  250. package/src/forge/compiler/types/classification.ts +9 -9
  251. package/src/forge/compiler/types/cli.ts +85 -85
  252. package/src/forge/compiler/types/diagnostic.ts +2 -2
  253. package/src/forge/compiler/types/emit.ts +25 -25
  254. package/src/forge/compiler/types/import-guards.ts +19 -19
  255. package/src/forge/compiler/types/index.ts +98 -98
  256. package/src/forge/compiler/types/integration.ts +25 -25
  257. package/src/forge/compiler/types/json.ts +3 -3
  258. package/src/forge/compiler/types/lock.ts +37 -37
  259. package/src/forge/compiler/types/package-graph.ts +122 -77
  260. package/src/forge/compiler/types/runtime-matrix.ts +16 -16
  261. package/src/forge/compiler/types/runtime.ts +30 -30
  262. package/src/forge/compiler/types/sandbox.ts +24 -24
  263. package/src/forge/dev/server.ts +16 -2
  264. package/src/forge/refactor/index.ts +10 -2
  265. package/src/forge/refactor/runtime-rename.ts +598 -0
  266. package/src/forge/runtime/executor.ts +3 -2
  267. package/src/forge/runtime/live/live-query-runner.ts +2 -1
  268. package/src/forge/runtime/outbox/process.ts +2 -1
  269. package/src/forge/runtime/query/run-query.ts +2 -1
  270. package/src/forge/runtime/runner/run-entry.ts +2 -1
  271. package/src/forge/runtime/telemetry/sinks/posthog.ts +4 -5
  272. package/src/forge/runtime/telemetry/sinks/sentry.ts +4 -5
  273. package/src/forge/runtime/workflows/resolve-step.ts +2 -1
  274. package/src/forge/version.ts +3 -0
  275. package/templates/b2b-support-web/src/actions/captureTicketCreated.ts +7 -2
  276. package/templates/b2b-support-web/src/commands/closeTicket.ts +6 -1
  277. package/templates/b2b-support-web/src/commands/createTicket.ts +8 -2
  278. package/templates/b2b-support-web/src/queries/getTicket.ts +8 -1
  279. package/templates/b2b-support-web/web/components/CreateTicketForm.tsx +1 -2
  280. package/templates/b2b-support-web/web/components/PolicyDeniedDemo.tsx +1 -2
  281. package/templates/b2b-support-web/web/components/TicketList.tsx +1 -2
  282. package/templates/b2b-support-web/web/components/TraceDetails.tsx +1 -1
  283. package/templates/b2b-support-web/web/lib/forge.ts +1 -0
@@ -1,17 +1,17 @@
1
- export { forgeAdd, seedWorkspacePackage, type ForgeAddOptions, type ForgeAddResult } from "./add.ts";
2
- export {
3
- buildIntegrationEmitPlan,
4
- loadExistingForgeLock,
5
- type IntegrationPlanInput,
6
- } from "./plan.ts";
7
- export {
8
- parseAdapterContext,
9
- renderAdapterModule,
10
- renderIntegrationDoc,
11
- renderTestkitModule,
12
- } from "./render.ts";
13
- export {
14
- restoreVersionControlledSnapshot,
15
- snapshotVersionControlled,
16
- type VersionControlledSnapshot,
17
- } from "./snapshot.ts";
1
+ export { forgeAdd, seedWorkspacePackage, type ForgeAddOptions, type ForgeAddResult } from "./add.ts";
2
+ export {
3
+ buildIntegrationEmitPlan,
4
+ loadExistingForgeLock,
5
+ type IntegrationPlanInput,
6
+ } from "./plan.ts";
7
+ export {
8
+ parseAdapterContext,
9
+ renderAdapterModule,
10
+ renderIntegrationDoc,
11
+ renderTestkitModule,
12
+ } from "./render.ts";
13
+ export {
14
+ restoreVersionControlledSnapshot,
15
+ snapshotVersionControlled,
16
+ type VersionControlledSnapshot,
17
+ } from "./snapshot.ts";
@@ -1,283 +1,283 @@
1
1
  import { join } from "node:path";
2
2
  import { nodeFileSystem } from "../fs/index.ts";
3
3
  import type { AppGraph } from "../types/app-graph.ts";
4
- import type { EmitFile, EmitPlan } from "../types/emit.ts";
5
- import type { ForgeLock, ForgeLockEntry } from "../types/lock.ts";
6
- import type { IntegrationRecipe } from "../types/integration.ts";
7
- import type { RuntimeContext } from "../types/runtime.ts";
8
- import type { ClassifiedPackage } from "../classifier/runtime-matrix.ts";
9
- import { buildRuntimeMatrix } from "../classifier/runtime-matrix.ts";
10
- import { detectCapabilities } from "../classifier/capabilities.ts";
11
- import { detectSecrets } from "../classifier/secrets.ts";
12
- import { buildGuardArtifactEmitFiles } from "../guards/artifacts.ts";
13
- import {
14
- FORGE_LOCK_PATH,
15
- FORGE_LOCK_SCHEMA_VERSION,
16
- GENERATED_DIR,
17
- GENERATOR_VERSION,
18
- } from "../emitter/constants.ts";
19
- import { PACKAGE_ANALYZER_VERSION } from "../package-graph/constants.ts";
20
- import { RECIPE_SCHEMA_VERSION } from "../recipes/definitions.ts";
21
- import { hashStable } from "../primitives/hash.ts";
22
- import { stableSortEmitFiles, stableSortStrings } from "../primitives/index.ts";
23
- import { detectOrphanedGeneratedFiles } from "../orchestrator/orphans.ts";
24
- import type { DiscoverContext } from "../orchestrator/types.ts";
25
- import {
26
- createRenderContext,
27
- parseAdapterContext,
28
- renderAdapterModule,
29
- renderIntegrationDoc,
30
- renderIntegrationModule,
31
- renderTestkitModule,
32
- } from "./render.ts";
33
-
34
- export interface IntegrationPlanInput {
35
- alias: string;
36
- recipe: IntegrationRecipe;
37
- classified: ClassifiedPackage[];
38
- allClassified: ClassifiedPackage[];
39
- appGraph: AppGraph;
40
- ctx: DiscoverContext;
41
- existingLock: ForgeLock | null;
42
- }
43
-
44
- function makeEmitFile(path: string, content: string): EmitFile {
45
- return {
46
- path,
47
- content,
48
- contentHash: hashStable(content),
49
- };
50
- }
51
-
52
- function primaryPackageName(recipe: IntegrationRecipe): string {
53
- return recipe.packages[0]?.packageName ?? recipe.alias;
54
- }
55
-
56
- function mergedCompatibleContexts(
57
- recipe: IntegrationRecipe,
58
- classified: ClassifiedPackage[],
59
- ): RuntimeContext[] {
60
- const contexts = new Set<RuntimeContext>(recipe.contexts.allowed);
61
- for (const pkg of recipe.packages) {
62
- for (const ctx of pkg.contexts?.allowed ?? []) {
63
- contexts.add(ctx);
64
- }
65
- }
66
- for (const item of classified) {
67
- for (const ctx of item.classification.compatible) {
68
- contexts.add(ctx);
69
- }
70
- }
71
- return [...contexts];
72
- }
73
-
74
- function shouldEmitAdapter(
75
- adapterFilename: string,
76
- compatible: RuntimeContext[],
77
- ): boolean {
78
- const context = parseAdapterContext(adapterFilename);
79
- if (context === null) {
80
- return true;
81
- }
82
- return compatible.includes(context);
83
- }
84
-
85
- function buildGeneratedPaths(
86
- recipe: IntegrationRecipe,
87
- compatible: RuntimeContext[],
88
- ): string[] {
89
- const paths: string[] = [];
90
-
91
- for (const adapter of recipe.adapters) {
92
- if (!shouldEmitAdapter(adapter, compatible)) {
93
- continue;
94
- }
95
- paths.push(`${GENERATED_DIR}/packages/${adapter}`);
96
- }
97
-
98
- for (const testkit of recipe.testkits) {
99
- paths.push(`${GENERATED_DIR}/testkits/${testkit}`);
100
- }
101
-
102
- for (const doc of recipe.docs) {
103
- paths.push(`${GENERATED_DIR}/docs/${doc}`);
104
- }
105
-
106
- for (const integration of recipe.integrations ?? []) {
107
- paths.push(`${GENERATED_DIR}/integrations/${integration}`);
108
- }
109
-
110
- paths.push(
111
- `${GENERATED_DIR}/runtimeMatrix.ts`,
112
- `${GENERATED_DIR}/runtimeMatrix.json`,
113
- `${GENERATED_DIR}/importGuards.ts`,
114
- `${GENERATED_DIR}/importGuards.json`,
115
- );
116
-
117
- return stableSortStrings(paths);
118
- }
119
-
120
- function buildLockEntry(
121
- recipe: IntegrationRecipe,
122
- classified: ClassifiedPackage[],
123
- generatedFiles: string[],
124
- ): ForgeLockEntry {
125
- const primary = classified[0]!;
126
- const capabilities = detectCapabilities(primary.api, recipe);
127
- const secrets = detectSecrets(primary.api, recipe);
128
-
129
- return {
130
- name: recipe.alias,
131
- version: primary.api.version,
132
- recipeVersion: recipe.recipeVersion,
4
+ import type { EmitFile, EmitPlan } from "../types/emit.ts";
5
+ import type { ForgeLock, ForgeLockEntry } from "../types/lock.ts";
6
+ import type { IntegrationRecipe } from "../types/integration.ts";
7
+ import type { RuntimeContext } from "../types/runtime.ts";
8
+ import type { ClassifiedPackage } from "../classifier/runtime-matrix.ts";
9
+ import { buildRuntimeMatrix } from "../classifier/runtime-matrix.ts";
10
+ import { detectCapabilities } from "../classifier/capabilities.ts";
11
+ import { detectSecrets } from "../classifier/secrets.ts";
12
+ import { buildGuardArtifactEmitFiles } from "../guards/artifacts.ts";
13
+ import {
14
+ FORGE_LOCK_PATH,
15
+ FORGE_LOCK_SCHEMA_VERSION,
16
+ GENERATED_DIR,
17
+ GENERATOR_VERSION,
18
+ } from "../emitter/constants.ts";
19
+ import { PACKAGE_ANALYZER_VERSION } from "../package-graph/constants.ts";
20
+ import { RECIPE_SCHEMA_VERSION } from "../recipes/definitions.ts";
21
+ import { hashStable } from "../primitives/hash.ts";
22
+ import { stableSortEmitFiles, stableSortStrings } from "../primitives/index.ts";
23
+ import { detectOrphanedGeneratedFiles } from "../orchestrator/orphans.ts";
24
+ import type { DiscoverContext } from "../orchestrator/types.ts";
25
+ import {
26
+ createRenderContext,
27
+ parseAdapterContext,
28
+ renderAdapterModule,
29
+ renderIntegrationDoc,
30
+ renderIntegrationModule,
31
+ renderTestkitModule,
32
+ } from "./render.ts";
33
+
34
+ export interface IntegrationPlanInput {
35
+ alias: string;
36
+ recipe: IntegrationRecipe;
37
+ classified: ClassifiedPackage[];
38
+ allClassified: ClassifiedPackage[];
39
+ appGraph: AppGraph;
40
+ ctx: DiscoverContext;
41
+ existingLock: ForgeLock | null;
42
+ }
43
+
44
+ function makeEmitFile(path: string, content: string): EmitFile {
45
+ return {
46
+ path,
47
+ content,
48
+ contentHash: hashStable(content),
49
+ };
50
+ }
51
+
52
+ function primaryPackageName(recipe: IntegrationRecipe): string {
53
+ return recipe.packages[0]?.packageName ?? recipe.alias;
54
+ }
55
+
56
+ function mergedCompatibleContexts(
57
+ recipe: IntegrationRecipe,
58
+ classified: ClassifiedPackage[],
59
+ ): RuntimeContext[] {
60
+ const contexts = new Set<RuntimeContext>(recipe.contexts.allowed);
61
+ for (const pkg of recipe.packages) {
62
+ for (const ctx of pkg.contexts?.allowed ?? []) {
63
+ contexts.add(ctx);
64
+ }
65
+ }
66
+ for (const item of classified) {
67
+ for (const ctx of item.classification.compatible) {
68
+ contexts.add(ctx);
69
+ }
70
+ }
71
+ return [...contexts];
72
+ }
73
+
74
+ function shouldEmitAdapter(
75
+ adapterFilename: string,
76
+ compatible: RuntimeContext[],
77
+ ): boolean {
78
+ const context = parseAdapterContext(adapterFilename);
79
+ if (context === null) {
80
+ return true;
81
+ }
82
+ return compatible.includes(context);
83
+ }
84
+
85
+ function buildGeneratedPaths(
86
+ recipe: IntegrationRecipe,
87
+ compatible: RuntimeContext[],
88
+ ): string[] {
89
+ const paths: string[] = [];
90
+
91
+ for (const adapter of recipe.adapters) {
92
+ if (!shouldEmitAdapter(adapter, compatible)) {
93
+ continue;
94
+ }
95
+ paths.push(`${GENERATED_DIR}/packages/${adapter}`);
96
+ }
97
+
98
+ for (const testkit of recipe.testkits) {
99
+ paths.push(`${GENERATED_DIR}/testkits/${testkit}`);
100
+ }
101
+
102
+ for (const doc of recipe.docs) {
103
+ paths.push(`${GENERATED_DIR}/docs/${doc}`);
104
+ }
105
+
106
+ for (const integration of recipe.integrations ?? []) {
107
+ paths.push(`${GENERATED_DIR}/integrations/${integration}`);
108
+ }
109
+
110
+ paths.push(
111
+ `${GENERATED_DIR}/runtimeMatrix.ts`,
112
+ `${GENERATED_DIR}/runtimeMatrix.json`,
113
+ `${GENERATED_DIR}/importGuards.ts`,
114
+ `${GENERATED_DIR}/importGuards.json`,
115
+ );
116
+
117
+ return stableSortStrings(paths);
118
+ }
119
+
120
+ function buildLockEntry(
121
+ recipe: IntegrationRecipe,
122
+ classified: ClassifiedPackage[],
123
+ generatedFiles: string[],
124
+ ): ForgeLockEntry {
125
+ const primary = classified[0]!;
126
+ const capabilities = detectCapabilities(primary.api, recipe);
127
+ const secrets = detectSecrets(primary.api, recipe);
128
+
129
+ return {
130
+ name: recipe.alias,
131
+ version: primary.api.version,
132
+ recipeVersion: recipe.recipeVersion,
133
133
  runtimeContexts: stableSortStrings([...primary.classification.compatible]) as ForgeLockEntry["runtimeContexts"],
134
- capabilities: {
135
- ...capabilities,
136
- secrets,
137
- },
138
- secrets,
139
- generatedFiles: stableSortStrings(generatedFiles),
140
- contentChecksum: primary.api.contentChecksum,
141
- };
142
- }
143
-
144
- function mergeLockPackages(
145
- existing: ForgeLock | null,
146
- newEntry: ForgeLockEntry,
147
- ctx: DiscoverContext,
148
- ): ForgeLock {
149
- const existingPackages = existing?.packages ?? [];
150
- const withoutAlias = existingPackages.filter(
151
- (entry) => entry.name !== newEntry.name,
152
- );
153
-
154
- const recipeVersion = newEntry.recipeVersion ?? RECIPE_SCHEMA_VERSION;
155
-
156
- return {
157
- schemaVersion: FORGE_LOCK_SCHEMA_VERSION,
158
- generatorVersion: GENERATOR_VERSION,
159
- analyzerVersion: PACKAGE_ANALYZER_VERSION,
160
- inputHash: ctx.inputFingerprint,
161
- lockfileHash: ctx.lockfileHash,
162
- packageManager: ctx.packageManager,
163
- recipeVersion,
164
- packages: [...withoutAlias, newEntry].sort((a, b) =>
165
- a.name < b.name ? -1 : a.name > b.name ? 1 : 0,
166
- ),
167
- };
168
- }
169
-
170
- export function buildIntegrationEmitPlan(input: IntegrationPlanInput): EmitPlan {
171
- const { recipe, classified, allClassified, appGraph, ctx } = input;
172
- const primary = classified[0];
173
- if (primary === undefined) {
174
- throw new Error(`no classified packages for alias '${input.alias}'`);
175
- }
176
-
177
- const compatible = mergedCompatibleContexts(recipe, classified);
178
- const incompatible = primary.classification.incompatible;
179
- const secrets = detectSecrets(primary.api, recipe);
180
- const packageNames = recipe.packages.map((pkg) => pkg.packageName);
181
- const templateCtx = createRenderContext({
182
- alias: recipe.alias,
183
- recipe,
184
- context: "server",
185
- packageName: primaryPackageName(recipe),
186
- packageNames,
187
- secrets,
188
- compatible,
189
- incompatible,
190
- });
191
-
192
- const files: EmitFile[] = [];
193
-
194
- for (const adapter of recipe.adapters) {
195
- if (!shouldEmitAdapter(adapter, compatible)) {
196
- continue;
197
- }
198
- const context = parseAdapterContext(adapter) ?? "server";
199
- files.push(
200
- makeEmitFile(
201
- `${GENERATED_DIR}/packages/${adapter}`,
202
- renderAdapterModule({
203
- alias: recipe.alias,
204
- recipe,
205
- context,
206
- packageName: primaryPackageName(recipe),
207
- packageNames,
208
- secrets,
209
- compatible,
210
- incompatible,
211
- }),
212
- ),
213
- );
214
- }
215
-
216
- for (const integration of recipe.integrations ?? []) {
217
- files.push(
218
- makeEmitFile(
219
- `${GENERATED_DIR}/integrations/${integration}`,
220
- renderIntegrationModule(integration, templateCtx),
221
- ),
222
- );
223
- }
224
-
225
- for (const testkit of recipe.testkits) {
226
- files.push(
227
- makeEmitFile(
228
- `${GENERATED_DIR}/testkits/${testkit}`,
229
- renderTestkitModule(recipe.alias, primaryPackageName(recipe), templateCtx),
230
- ),
231
- );
232
- }
233
-
234
- for (const doc of recipe.docs) {
235
- files.push(
236
- makeEmitFile(
237
- `${GENERATED_DIR}/docs/${doc}`,
238
- renderIntegrationDoc({
239
- alias: recipe.alias,
240
- recipe,
241
- packageNames,
242
- secrets,
243
- compatible,
244
- incompatible,
245
- }),
246
- ),
247
- );
248
- }
249
-
250
- const matrix = buildRuntimeMatrix(allClassified);
251
- files.push(...buildGuardArtifactEmitFiles(matrix, appGraph.moduleGraph));
252
-
253
- const generatedFiles = buildGeneratedPaths(recipe, compatible);
254
- const lockEntry = buildLockEntry(recipe, classified, generatedFiles);
255
- const lock = mergeLockPackages(input.existingLock, lockEntry, ctx);
256
-
257
- const sortedFiles = stableSortEmitFiles(files);
258
- const plannedPathSet = new Set(sortedFiles.map((file) => file.path));
259
- const orphanedFiles = detectOrphanedGeneratedFiles(
260
- ctx.workspaceRoot,
261
- ctx.generatedDir,
262
- plannedPathSet,
263
- );
264
-
265
- return {
266
- files: sortedFiles,
267
- orphanedFiles,
268
- lock,
269
- };
270
- }
271
-
272
- export function loadExistingForgeLock(workspaceRoot: string): ForgeLock | null {
273
- const absolute = join(workspaceRoot, FORGE_LOCK_PATH);
274
- if (!nodeFileSystem.exists(absolute)) {
275
- return null;
276
- }
277
-
278
- try {
279
- return JSON.parse((nodeFileSystem.readText(absolute) ?? "")) as ForgeLock;
280
- } catch {
281
- return null;
282
- }
283
- }
134
+ capabilities: {
135
+ ...capabilities,
136
+ secrets,
137
+ },
138
+ secrets,
139
+ generatedFiles: stableSortStrings(generatedFiles),
140
+ contentChecksum: primary.api.contentChecksum,
141
+ };
142
+ }
143
+
144
+ function mergeLockPackages(
145
+ existing: ForgeLock | null,
146
+ newEntry: ForgeLockEntry,
147
+ ctx: DiscoverContext,
148
+ ): ForgeLock {
149
+ const existingPackages = existing?.packages ?? [];
150
+ const withoutAlias = existingPackages.filter(
151
+ (entry) => entry.name !== newEntry.name,
152
+ );
153
+
154
+ const recipeVersion = newEntry.recipeVersion ?? RECIPE_SCHEMA_VERSION;
155
+
156
+ return {
157
+ schemaVersion: FORGE_LOCK_SCHEMA_VERSION,
158
+ generatorVersion: GENERATOR_VERSION,
159
+ analyzerVersion: PACKAGE_ANALYZER_VERSION,
160
+ inputHash: ctx.inputFingerprint,
161
+ lockfileHash: ctx.lockfileHash,
162
+ packageManager: ctx.packageManager,
163
+ recipeVersion,
164
+ packages: [...withoutAlias, newEntry].sort((a, b) =>
165
+ a.name < b.name ? -1 : a.name > b.name ? 1 : 0,
166
+ ),
167
+ };
168
+ }
169
+
170
+ export function buildIntegrationEmitPlan(input: IntegrationPlanInput): EmitPlan {
171
+ const { recipe, classified, allClassified, appGraph, ctx } = input;
172
+ const primary = classified[0];
173
+ if (primary === undefined) {
174
+ throw new Error(`no classified packages for alias '${input.alias}'`);
175
+ }
176
+
177
+ const compatible = mergedCompatibleContexts(recipe, classified);
178
+ const incompatible = primary.classification.incompatible;
179
+ const secrets = detectSecrets(primary.api, recipe);
180
+ const packageNames = recipe.packages.map((pkg) => pkg.packageName);
181
+ const templateCtx = createRenderContext({
182
+ alias: recipe.alias,
183
+ recipe,
184
+ context: "server",
185
+ packageName: primaryPackageName(recipe),
186
+ packageNames,
187
+ secrets,
188
+ compatible,
189
+ incompatible,
190
+ });
191
+
192
+ const files: EmitFile[] = [];
193
+
194
+ for (const adapter of recipe.adapters) {
195
+ if (!shouldEmitAdapter(adapter, compatible)) {
196
+ continue;
197
+ }
198
+ const context = parseAdapterContext(adapter) ?? "server";
199
+ files.push(
200
+ makeEmitFile(
201
+ `${GENERATED_DIR}/packages/${adapter}`,
202
+ renderAdapterModule({
203
+ alias: recipe.alias,
204
+ recipe,
205
+ context,
206
+ packageName: primaryPackageName(recipe),
207
+ packageNames,
208
+ secrets,
209
+ compatible,
210
+ incompatible,
211
+ }),
212
+ ),
213
+ );
214
+ }
215
+
216
+ for (const integration of recipe.integrations ?? []) {
217
+ files.push(
218
+ makeEmitFile(
219
+ `${GENERATED_DIR}/integrations/${integration}`,
220
+ renderIntegrationModule(integration, templateCtx),
221
+ ),
222
+ );
223
+ }
224
+
225
+ for (const testkit of recipe.testkits) {
226
+ files.push(
227
+ makeEmitFile(
228
+ `${GENERATED_DIR}/testkits/${testkit}`,
229
+ renderTestkitModule(recipe.alias, primaryPackageName(recipe), templateCtx),
230
+ ),
231
+ );
232
+ }
233
+
234
+ for (const doc of recipe.docs) {
235
+ files.push(
236
+ makeEmitFile(
237
+ `${GENERATED_DIR}/docs/${doc}`,
238
+ renderIntegrationDoc({
239
+ alias: recipe.alias,
240
+ recipe,
241
+ packageNames,
242
+ secrets,
243
+ compatible,
244
+ incompatible,
245
+ }),
246
+ ),
247
+ );
248
+ }
249
+
250
+ const matrix = buildRuntimeMatrix(allClassified);
251
+ files.push(...buildGuardArtifactEmitFiles(matrix, appGraph.moduleGraph));
252
+
253
+ const generatedFiles = buildGeneratedPaths(recipe, compatible);
254
+ const lockEntry = buildLockEntry(recipe, classified, generatedFiles);
255
+ const lock = mergeLockPackages(input.existingLock, lockEntry, ctx);
256
+
257
+ const sortedFiles = stableSortEmitFiles(files);
258
+ const plannedPathSet = new Set(sortedFiles.map((file) => file.path));
259
+ const orphanedFiles = detectOrphanedGeneratedFiles(
260
+ ctx.workspaceRoot,
261
+ ctx.generatedDir,
262
+ plannedPathSet,
263
+ );
264
+
265
+ return {
266
+ files: sortedFiles,
267
+ orphanedFiles,
268
+ lock,
269
+ };
270
+ }
271
+
272
+ export function loadExistingForgeLock(workspaceRoot: string): ForgeLock | null {
273
+ const absolute = join(workspaceRoot, FORGE_LOCK_PATH);
274
+ if (!nodeFileSystem.exists(absolute)) {
275
+ return null;
276
+ }
277
+
278
+ try {
279
+ return JSON.parse((nodeFileSystem.readText(absolute) ?? "")) as ForgeLock;
280
+ } catch {
281
+ return null;
282
+ }
283
+ }