forgeos 0.1.0-alpha.0 → 0.1.0-alpha.1

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 (262) hide show
  1. package/.npmignore +9 -1
  2. package/AGENTS.md +6 -1
  3. package/CHANGELOG.md +15 -0
  4. package/CONTRIBUTING.md +22 -1
  5. package/README.md +12 -1
  6. package/package.json +3 -1
  7. package/packages/eslint-plugin-forge/index.ts +15 -15
  8. package/packages/eslint-plugin-forge/package.json +10 -10
  9. package/packages/eslint-plugin-forge/src/check-source.ts +95 -95
  10. package/packages/eslint-plugin-forge/src/load-artifacts.ts +24 -24
  11. package/packages/eslint-plugin-forge/src/rule-no-forge-guard-violation.ts +93 -93
  12. package/src/forge/_generated/actionSubscriptions.json +2 -2
  13. package/src/forge/_generated/actionSubscriptions.ts +3 -3
  14. package/src/forge/_generated/agentAdapterManifest.json +2 -2
  15. package/src/forge/_generated/agentAdapterManifest.ts +3 -3
  16. package/src/forge/_generated/agentContract.json +2 -2
  17. package/src/forge/_generated/agentContract.ts +6786 -2
  18. package/src/forge/_generated/agentQuickstart.md +1 -1
  19. package/src/forge/_generated/aiContext.ts +1 -1
  20. package/src/forge/_generated/aiModels.json +1 -1
  21. package/src/forge/_generated/aiModels.ts +1 -1
  22. package/src/forge/_generated/aiProviders.json +1 -1
  23. package/src/forge/_generated/aiProviders.ts +1 -1
  24. package/src/forge/_generated/aiRegistry.json +2 -2
  25. package/src/forge/_generated/aiRegistry.ts +3 -3
  26. package/src/forge/_generated/api.json +2 -2
  27. package/src/forge/_generated/api.ts +1 -1
  28. package/src/forge/_generated/appGraph.json +2 -2
  29. package/src/forge/_generated/appGraph.ts +1112 -956
  30. package/src/forge/_generated/appMap.md +1 -1
  31. package/src/forge/_generated/artifactManifest.json +2 -2
  32. package/src/forge/_generated/artifactManifest.ts +2 -2
  33. package/src/forge/_generated/authClaims.json +1 -1
  34. package/src/forge/_generated/authClaims.ts +1 -1
  35. package/src/forge/_generated/authConfig.json +1 -1
  36. package/src/forge/_generated/authConfig.ts +1 -1
  37. package/src/forge/_generated/authContext.ts +1 -1
  38. package/src/forge/_generated/authRegistry.json +1 -1
  39. package/src/forge/_generated/authRegistry.ts +1 -1
  40. package/src/forge/_generated/buildInfo.json +2 -2
  41. package/src/forge/_generated/buildInfo.ts +4 -4
  42. package/src/forge/_generated/capabilityMap.json +2 -2
  43. package/src/forge/_generated/capabilityMap.md +1 -1
  44. package/src/forge/_generated/capabilityMap.ts +2 -2
  45. package/src/forge/_generated/client.ts +1 -1
  46. package/src/forge/_generated/clientApi.ts +1 -1
  47. package/src/forge/_generated/clientManifest.json +2 -2
  48. package/src/forge/_generated/clientManifest.ts +3 -3
  49. package/src/forge/_generated/clientTypes.ts +1 -1
  50. package/src/forge/_generated/configRegistry.json +1 -1
  51. package/src/forge/_generated/configRegistry.ts +1 -1
  52. package/src/forge/_generated/dataGraph.json +2 -2
  53. package/src/forge/_generated/dataGraph.ts +3 -3
  54. package/src/forge/_generated/db.json +1 -1
  55. package/src/forge/_generated/db.ts +1 -1
  56. package/src/forge/_generated/dbSecurityManifest.json +1 -1
  57. package/src/forge/_generated/dbSecurityManifest.ts +1 -1
  58. package/src/forge/_generated/dbSessionContext.json +1 -1
  59. package/src/forge/_generated/dbSessionContext.ts +1 -1
  60. package/src/forge/_generated/deployManifest.json +2 -2
  61. package/src/forge/_generated/deployManifest.ts +7 -7
  62. package/src/forge/_generated/devManifest.json +2 -2
  63. package/src/forge/_generated/devManifest.ts +3 -3
  64. package/src/forge/_generated/envSchema.json +1 -1
  65. package/src/forge/_generated/envSchema.ts +1 -1
  66. package/src/forge/_generated/frontendGraph.json +1 -1
  67. package/src/forge/_generated/frontendGraph.ts +1 -1
  68. package/src/forge/_generated/importGuards.json +2 -2
  69. package/src/forge/_generated/importGuards.ts +35 -1
  70. package/src/forge/_generated/index.ts +1 -1
  71. package/src/forge/_generated/liveProductionManifest.json +1 -1
  72. package/src/forge/_generated/liveProductionManifest.ts +1 -1
  73. package/src/forge/_generated/liveProtocol.json +1 -1
  74. package/src/forge/_generated/liveProtocol.ts +1 -1
  75. package/src/forge/_generated/liveQueryRegistry.json +2 -2
  76. package/src/forge/_generated/liveQueryRegistry.ts +3 -3
  77. package/src/forge/_generated/liveTransportConfig.json +1 -1
  78. package/src/forge/_generated/liveTransportConfig.ts +1 -1
  79. package/src/forge/_generated/makeRegistry.json +2 -2
  80. package/src/forge/_generated/makeRegistry.ts +2 -2
  81. package/src/forge/_generated/makeTemplates.json +1 -1
  82. package/src/forge/_generated/makeTemplates.ts +1 -1
  83. package/src/forge/_generated/mockMap.json +1 -1
  84. package/src/forge/_generated/mockMap.ts +1 -1
  85. package/src/forge/_generated/operationPlaybooks.md +7 -5
  86. package/src/forge/_generated/packageGraph.json +2 -2
  87. package/src/forge/_generated/packageGraph.ts +90964 -14284
  88. package/src/forge/_generated/packageUpgradeRegistry.json +2 -2
  89. package/src/forge/_generated/packageUpgradeRegistry.ts +2 -2
  90. package/src/forge/_generated/permissionMatrix.json +2 -2
  91. package/src/forge/_generated/permissionMatrix.ts +3 -3
  92. package/src/forge/_generated/policyRegistry.json +2 -2
  93. package/src/forge/_generated/policyRegistry.ts +3 -3
  94. package/src/forge/_generated/queryRegistry.json +2 -2
  95. package/src/forge/_generated/queryRegistry.ts +3 -3
  96. package/src/forge/_generated/react.d.ts +1 -1
  97. package/src/forge/_generated/react.ts +1 -1
  98. package/src/forge/_generated/reactManifest.json +2 -2
  99. package/src/forge/_generated/reactManifest.ts +3 -3
  100. package/src/forge/_generated/releaseManifest.json +2 -2
  101. package/src/forge/_generated/releaseManifest.ts +3 -3
  102. package/src/forge/_generated/rlsPolicies.json +1 -1
  103. package/src/forge/_generated/rlsPolicies.sql +1 -1
  104. package/src/forge/_generated/rlsPolicies.ts +1 -1
  105. package/src/forge/_generated/runtimeGraph.json +2 -2
  106. package/src/forge/_generated/runtimeGraph.ts +3 -3
  107. package/src/forge/_generated/runtimeMatrix.json +2 -2
  108. package/src/forge/_generated/runtimeMatrix.ts +106177 -7917
  109. package/src/forge/_generated/runtimeRegistry.ts +1 -1
  110. package/src/forge/_generated/runtimeRules.md +1 -1
  111. package/src/forge/_generated/secretRegistry.json +1 -1
  112. package/src/forge/_generated/secretRegistry.ts +1 -1
  113. package/src/forge/_generated/secretsContext.ts +1 -1
  114. package/src/forge/_generated/serverApi.ts +1 -1
  115. package/src/forge/_generated/sourceMapManifest.json +2 -2
  116. package/src/forge/_generated/sourceMapManifest.ts +2 -2
  117. package/src/forge/_generated/sqlPlan.json +1 -1
  118. package/src/forge/_generated/sqlPlan.ts +1 -1
  119. package/src/forge/_generated/subscriptionManifest.json +2 -2
  120. package/src/forge/_generated/subscriptionManifest.ts +3 -3
  121. package/src/forge/_generated/symbolicationManifest.json +2 -2
  122. package/src/forge/_generated/symbolicationManifest.ts +2 -2
  123. package/src/forge/_generated/telemetryRegistry.json +2 -2
  124. package/src/forge/_generated/telemetryRegistry.ts +3 -3
  125. package/src/forge/_generated/telemetrySinks.json +2 -2
  126. package/src/forge/_generated/telemetrySinks.ts +2 -2
  127. package/src/forge/_generated/tenantScope.json +2 -2
  128. package/src/forge/_generated/tenantScope.ts +3 -3
  129. package/src/forge/_generated/testGraph.json +2 -2
  130. package/src/forge/_generated/testGraph.ts +75 -75
  131. package/src/forge/_generated/testPlanRegistry.json +2 -2
  132. package/src/forge/_generated/testPlanRegistry.ts +2 -2
  133. package/src/forge/_generated/uiRoutes.json +1 -1
  134. package/src/forge/_generated/uiRoutes.ts +1 -1
  135. package/src/forge/_generated/uiScenarios.json +1 -1
  136. package/src/forge/_generated/uiScenarios.ts +1 -1
  137. package/src/forge/_generated/uiTestManifest.json +2 -2
  138. package/src/forge/_generated/uiTestManifest.ts +2 -2
  139. package/src/forge/_generated/workflowRegistry.json +2 -2
  140. package/src/forge/_generated/workflowRegistry.ts +3 -3
  141. package/src/forge/_generated/workflowSubscriptions.json +2 -2
  142. package/src/forge/_generated/workflowSubscriptions.ts +3 -3
  143. package/src/forge/cli/commands.ts +861 -861
  144. package/src/forge/cli/deps.ts +178 -11
  145. package/src/forge/cli/index.ts +7 -7
  146. package/src/forge/cli/main.ts +54 -54
  147. package/src/forge/cli/output.ts +97 -97
  148. package/src/forge/cli/parse.ts +679 -673
  149. package/src/forge/cli/version.ts +1 -1
  150. package/src/forge/compiler/agent-contract/build.ts +28 -0
  151. package/src/forge/compiler/agent-contract/types.ts +16 -0
  152. package/src/forge/compiler/app-graph/build.ts +112 -112
  153. package/src/forge/compiler/app-graph/classify.ts +10 -10
  154. package/src/forge/compiler/app-graph/dup-symbol.ts +29 -29
  155. package/src/forge/compiler/app-graph/extract.ts +123 -123
  156. package/src/forge/compiler/app-graph/forge-apis.ts +29 -29
  157. package/src/forge/compiler/app-graph/index.ts +11 -11
  158. package/src/forge/compiler/app-graph/module-graph.ts +316 -316
  159. package/src/forge/compiler/app-graph/parser.ts +119 -119
  160. package/src/forge/compiler/app-graph/symbols.ts +48 -48
  161. package/src/forge/compiler/app-graph/tsconfig-hash.ts +62 -62
  162. package/src/forge/compiler/app-graph/types.ts +43 -43
  163. package/src/forge/compiler/app-graph/versions.ts +14 -14
  164. package/src/forge/compiler/cache/index.ts +17 -17
  165. package/src/forge/compiler/cache/key.ts +46 -46
  166. package/src/forge/compiler/cache/scheduler.ts +72 -72
  167. package/src/forge/compiler/cache/store.ts +78 -78
  168. package/src/forge/compiler/classifier/capabilities.ts +78 -78
  169. package/src/forge/compiler/classifier/classify.ts +113 -113
  170. package/src/forge/compiler/classifier/contexts.ts +188 -188
  171. package/src/forge/compiler/classifier/index.ts +18 -18
  172. package/src/forge/compiler/classifier/runtime-matrix.ts +45 -45
  173. package/src/forge/compiler/classifier/secrets.ts +41 -41
  174. package/src/forge/compiler/classifier/signals.ts +129 -129
  175. package/src/forge/compiler/diagnostics/codes.ts +125 -120
  176. package/src/forge/compiler/diagnostics/create.ts +87 -87
  177. package/src/forge/compiler/diagnostics/index.ts +41 -41
  178. package/src/forge/compiler/emitter/artifact-kind.ts +14 -14
  179. package/src/forge/compiler/emitter/barrel.ts +38 -38
  180. package/src/forge/compiler/emitter/constants.ts +7 -7
  181. package/src/forge/compiler/emitter/emit.ts +234 -237
  182. package/src/forge/compiler/emitter/index.ts +24 -24
  183. package/src/forge/compiler/emitter/lock.ts +61 -61
  184. package/src/forge/compiler/emitter/render.ts +73 -73
  185. package/src/forge/compiler/guards/artifacts.ts +96 -96
  186. package/src/forge/compiler/guards/check-import-guards.ts +106 -106
  187. package/src/forge/compiler/guards/index.ts +11 -11
  188. package/src/forge/compiler/guards/propagate-contexts.ts +57 -57
  189. package/src/forge/compiler/index.ts +17 -17
  190. package/src/forge/compiler/integration/add.ts +493 -493
  191. package/src/forge/compiler/integration/index.ts +17 -17
  192. package/src/forge/compiler/integration/plan.ts +279 -279
  193. package/src/forge/compiler/integration/render.ts +189 -189
  194. package/src/forge/compiler/integration/snapshot.ts +52 -52
  195. package/src/forge/compiler/orchestrator/discover.ts +214 -214
  196. package/src/forge/compiler/orchestrator/guards.ts +5 -5
  197. package/src/forge/compiler/orchestrator/index.ts +27 -27
  198. package/src/forge/compiler/orchestrator/manifest.ts +69 -69
  199. package/src/forge/compiler/orchestrator/orphans.ts +51 -51
  200. package/src/forge/compiler/orchestrator/plan.ts +804 -804
  201. package/src/forge/compiler/orchestrator/run.ts +178 -178
  202. package/src/forge/compiler/orchestrator/serialize.ts +859 -859
  203. package/src/forge/compiler/orchestrator/types.ts +23 -23
  204. package/src/forge/compiler/orchestrator/verify.ts +35 -35
  205. package/src/forge/compiler/package-graph/capabilities-stub.ts +33 -33
  206. package/src/forge/compiler/package-graph/checksum.ts +107 -97
  207. package/src/forge/compiler/package-graph/compiler.ts +444 -363
  208. package/src/forge/compiler/package-graph/constants.ts +4 -4
  209. package/src/forge/compiler/package-graph/exports-discovery.ts +91 -84
  210. package/src/forge/compiler/package-graph/extract-dts.ts +32 -32
  211. package/src/forge/compiler/package-graph/index.ts +24 -24
  212. package/src/forge/compiler/package-graph/jsdoc.ts +50 -50
  213. package/src/forge/compiler/package-graph/oracle.ts +326 -0
  214. package/src/forge/compiler/package-graph/read-file.ts +21 -21
  215. package/src/forge/compiler/package-graph/resolve.ts +131 -127
  216. package/src/forge/compiler/package-manager/adapter.ts +232 -232
  217. package/src/forge/compiler/package-manager/commands.ts +47 -47
  218. package/src/forge/compiler/package-manager/detect.ts +65 -65
  219. package/src/forge/compiler/package-manager/executor.ts +29 -29
  220. package/src/forge/compiler/package-manager/index.ts +22 -22
  221. package/src/forge/compiler/package-manager/parse-spec.ts +16 -16
  222. package/src/forge/compiler/package-manager/version.ts +20 -20
  223. package/src/forge/compiler/primitives/compare.ts +26 -26
  224. package/src/forge/compiler/primitives/hash.ts +42 -33
  225. package/src/forge/compiler/primitives/header.ts +43 -43
  226. package/src/forge/compiler/primitives/index.ts +45 -45
  227. package/src/forge/compiler/primitives/paths.ts +24 -24
  228. package/src/forge/compiler/primitives/serialize.ts +66 -66
  229. package/src/forge/compiler/primitives/sort.ts +87 -87
  230. package/src/forge/compiler/recipes/definitions.ts +269 -269
  231. package/src/forge/compiler/recipes/helpers.ts +37 -37
  232. package/src/forge/compiler/recipes/index.ts +21 -21
  233. package/src/forge/compiler/recipes/registry.ts +87 -87
  234. package/src/forge/compiler/sandbox/artifact-sanitize.ts +26 -26
  235. package/src/forge/compiler/sandbox/backends/child.ts +123 -123
  236. package/src/forge/compiler/sandbox/backends/docker.ts +173 -173
  237. package/src/forge/compiler/sandbox/index.ts +51 -51
  238. package/src/forge/compiler/sandbox/inspect.ts +143 -143
  239. package/src/forge/compiler/sandbox/inspector-entry.ts +115 -115
  240. package/src/forge/compiler/sandbox/limits.ts +31 -31
  241. package/src/forge/compiler/sandbox/scrub-env.ts +60 -60
  242. package/src/forge/compiler/sandbox/secret-scan.ts +54 -54
  243. package/src/forge/compiler/sandbox/serialize.ts +106 -106
  244. package/src/forge/compiler/sandbox/types.ts +7 -7
  245. package/src/forge/compiler/types/app-graph.ts +71 -71
  246. package/src/forge/compiler/types/capability.ts +29 -29
  247. package/src/forge/compiler/types/classification.ts +9 -9
  248. package/src/forge/compiler/types/cli.ts +85 -85
  249. package/src/forge/compiler/types/diagnostic.ts +2 -2
  250. package/src/forge/compiler/types/emit.ts +25 -25
  251. package/src/forge/compiler/types/import-guards.ts +19 -19
  252. package/src/forge/compiler/types/index.ts +98 -98
  253. package/src/forge/compiler/types/integration.ts +25 -25
  254. package/src/forge/compiler/types/json.ts +3 -3
  255. package/src/forge/compiler/types/lock.ts +37 -37
  256. package/src/forge/compiler/types/package-graph.ts +122 -77
  257. package/src/forge/compiler/types/runtime-matrix.ts +16 -16
  258. package/src/forge/compiler/types/runtime.ts +30 -30
  259. package/src/forge/compiler/types/sandbox.ts +24 -24
  260. package/src/forge/refactor/index.ts +10 -2
  261. package/src/forge/refactor/runtime-rename.ts +598 -0
  262. package/src/forge/version.ts +3 -0
@@ -1,350 +1,431 @@
1
1
  import { join, relative } from "node:path";
2
- import ts from "typescript";
3
- import type { Diagnostic } from "../types/diagnostic.ts";
4
- import type {
5
- AnalyzeOptions,
6
- Dependency,
7
- Entrypoint,
8
- PackageApi,
9
- PackageGraph,
10
- } from "../types/package-graph.ts";
11
- import type { PackageCacheKey } from "../types/lock.ts";
12
- import type { ResolutionMode } from "../types/runtime.ts";
13
- import { forgePkgNoTypes } from "../diagnostics/create.ts";
14
- import { createDiagnostic } from "../diagnostics/create.ts";
15
- import { stableSortEntrypoints, stableSortPackages } from "../primitives/sort.ts";
16
- import {
17
- PackageCacheStore,
18
- forgeCacheDiscardedMessage,
19
- } from "../cache/store.ts";
20
- import { buildPackageCacheKey, cacheKeysEqual } from "../cache/key.ts";
21
- import { runWithConcurrency } from "../cache/scheduler.ts";
22
- import {
23
- GENERATOR_VERSION,
24
- PACKAGE_ANALYZER_VERSION,
25
- PACKAGE_GRAPH_SCHEMA_VERSION,
26
- DEFAULT_PATTERN_EXPANSION_LIMIT,
27
- } from "./constants.ts";
28
- import {
29
- computeContentChecksum,
30
- hashDtsFiles,
31
- hashDtsFilesForCache,
32
- hashPackageJson,
33
- hashPackageJsonForCache,
34
- } from "./checksum.ts";
35
- import {
36
- discoverSubpathsFromExports,
37
- expandPatternSubpaths,
38
- } from "./exports-discovery.ts";
39
- import { DtsSignatureExtractor } from "./dts-extractor.ts";
40
- import { readTextFile } from "./read-file.ts";
41
- import {
42
- resolveEntrypointTypes,
43
- resolveTypesPackage,
44
- typesPackageName,
45
- } from "./resolve.ts";
46
- import {
47
- assertPackageApiSecretSafe,
48
- defaultSandboxLimits,
49
- inspectExports,
50
- } from "../sandbox/index.ts";
51
- import type { SandboxBackend } from "../types/runtime.ts";
52
-
53
- export interface BuildOptions extends AnalyzeOptions {
54
- concurrency?: number;
55
- patternExpansionLimit?: number;
56
- /** Informational only does not invalidate per-package cache entries. */
57
- lockfileHash?: string;
58
- }
59
-
60
- export interface AnalyzeResult {
61
- api: PackageApi;
62
- diagnostics: Diagnostic[];
63
- cacheHit: boolean;
64
- }
65
-
66
- export interface BuildResult {
67
- graph: PackageGraph;
68
- diagnostics: Diagnostic[];
69
- }
70
-
71
- export class PackageGraphCompiler {
72
- async build(
73
- deps: Dependency[],
74
- opts: BuildOptions,
75
- ): Promise<BuildResult> {
76
- const concurrency = Math.max(1, opts.concurrency ?? 4);
77
- const cache = new PackageCacheStore(opts.cacheDir);
78
- const diagnostics: Diagnostic[] = [];
79
-
80
- const results = await runWithConcurrency(
81
- deps,
82
- concurrency,
83
- async (dep) => this.analyzeWithCache(dep, opts, cache),
84
- );
85
-
86
- for (const result of results) {
87
- diagnostics.push(...result.diagnostics);
88
- }
89
-
90
- const packages = stableSortPackages(results.map((r) => r.api));
91
-
92
- return {
93
- graph: {
94
- schemaVersion: PACKAGE_GRAPH_SCHEMA_VERSION,
95
- generatorVersion: GENERATOR_VERSION,
96
- analyzerVersion: PACKAGE_ANALYZER_VERSION,
97
- packages,
98
- },
99
- diagnostics,
100
- };
101
- }
102
-
103
- async analyze(
104
- dep: Dependency,
105
- opts: AnalyzeOptions,
106
- ): Promise<PackageApi> {
107
- const result = await this.analyzeWithCache(
108
- dep,
109
- opts,
110
- new PackageCacheStore(opts.cacheDir),
111
- );
112
- return result.api;
113
- }
114
-
115
- private async analyzeWithCache(
116
- dep: Dependency,
117
- opts: BuildOptions,
118
- cache: PackageCacheStore,
119
- ): Promise<AnalyzeResult> {
120
- const cacheKey = buildPackageCacheKey({
121
- name: dep.name,
122
- version: dep.version,
123
- packageManager: dep.packageManager,
124
- packageIntegrity: dep.packageIntegrity,
125
- packageJsonHash: hashPackageJsonForCache(dep.installPath),
126
- dtsFilesHash: hashDtsFilesForCache(dep.installPath),
127
- analyzerVersion: PACKAGE_ANALYZER_VERSION,
128
- typescriptVersion: ts.version,
129
- resolutionMode: opts.resolutionMode,
130
- recipeVersion: opts.recipeVersion,
131
- });
132
-
133
- const lookup = cache.getWithValidation(cacheKey);
134
- if ("hit" in lookup) {
135
- return { api: lookup.hit, diagnostics: [], cacheHit: true };
136
- }
137
-
138
- const diagnostics: Diagnostic[] = [];
139
- if ("corrupt" in lookup) {
140
- diagnostics.push(
141
- createDiagnostic({
142
- severity: "warning",
143
- code: "FORGE_CACHE_DISCARD",
144
- message: forgeCacheDiscardedMessage(),
145
- }),
146
- );
147
- }
148
-
149
- const analyzed = await this.analyzeWithOptionalRuntime(dep, opts, {
150
- packageJsonHash: hashPackageJson(dep.installPath),
151
- dtsFilesHash: hashDtsFiles(dep.installPath),
152
- });
153
- diagnostics.push(...analyzed.diagnostics);
154
- assertPackageApiSecretSafe(analyzed.api);
155
- await cache.put(cacheKey, analyzed.api);
156
- return { api: analyzed.api, diagnostics, cacheHit: false };
157
- }
158
-
159
- private async analyzeWithOptionalRuntime(
160
- dep: Dependency,
161
- opts: BuildOptions,
162
- packageHashes: { packageJsonHash: string; dtsFilesHash: string },
163
- ): Promise<{ api: PackageApi; diagnostics: Diagnostic[] }> {
164
- const staticResult = this.analyzeStatic(dep, opts, packageHashes);
165
- if (!opts.runtimeInspect) {
166
- return staticResult;
167
- }
168
-
169
- const backend = resolveSandboxBackend(opts);
170
- const sandbox = await inspectExports(
171
- dep,
172
- defaultSandboxLimits(backend),
173
- );
174
-
175
- const diagnostics = [
176
- ...staticResult.diagnostics,
177
- ...sandbox.diagnostics,
178
- ];
179
-
180
- if (!sandbox.runtimeUsed) {
181
- return { api: staticResult.api, diagnostics };
182
- }
183
-
184
- const api: PackageApi = {
185
- ...staticResult.api,
186
- source: "static+runtime",
187
- runtimeShape: sandbox.shape,
188
- contentChecksum: computeContentChecksum(
189
- packageHashes.packageJsonHash,
190
- packageHashes.dtsFilesHash,
191
- {
192
- ...staticResult.api,
193
- source: "static+runtime",
194
- runtimeShape: sandbox.shape,
195
- },
196
- ),
197
- };
198
-
199
- return { api, diagnostics };
200
- }
201
-
202
- analyzeStatic(
203
- dep: Dependency,
204
- opts: BuildOptions,
205
- packageHashes?: { packageJsonHash: string; dtsFilesHash: string },
206
- ): { api: PackageApi; diagnostics: Diagnostic[] } {
207
- const diagnostics: Diagnostic[] = [];
208
- const packageJson = readPackageJson(dep.installPath);
209
- const patternLimit =
210
- opts.patternExpansionLimit ?? DEFAULT_PATTERN_EXPANSION_LIMIT;
211
-
212
- const discovered = discoverSubpathsFromExports(packageJson.exports);
213
- const subpathsToAnalyze: Array<{
214
- subpath: string;
215
- patternBacked: boolean;
216
- }> = [];
217
-
218
- for (const item of discovered) {
219
- if (item.patternBacked) {
220
- const expanded = expandPatternSubpaths(
221
- dep.installPath,
222
- item.subpath,
223
- patternLimit,
224
- );
225
- for (const sub of expanded) {
226
- subpathsToAnalyze.push({ subpath: sub, patternBacked: true });
227
- }
228
- if (expanded.length === 0) {
229
- subpathsToAnalyze.push(item);
230
- }
231
- } else {
232
- subpathsToAnalyze.push(item);
233
- }
234
- }
235
-
236
- const entrypoints: Entrypoint[] = [];
237
- const dtsExtractor = new DtsSignatureExtractor(opts.resolutionMode);
238
-
239
- for (const { subpath, patternBacked } of subpathsToAnalyze) {
240
- const entry = this.analyzeEntrypoint(
241
- dep,
242
- subpath,
243
- patternBacked,
244
- opts.resolutionMode,
245
- diagnostics,
246
- dtsExtractor,
247
- );
248
- entrypoints.push(entry);
249
- }
250
-
251
- const sortedEntrypoints = stableSortEntrypoints(entrypoints);
252
- const packageJsonHash =
253
- packageHashes?.packageJsonHash ?? hashPackageJson(dep.installPath);
254
- const dtsFilesHash =
255
- packageHashes?.dtsFilesHash ?? hashDtsFiles(dep.installPath);
256
-
257
- const partialApi = {
258
- name: dep.name,
259
- version: dep.version,
260
- packageManager: dep.packageManager,
261
- resolutionMode: opts.resolutionMode,
262
- entrypoints: sortedEntrypoints,
263
- source: "static" as const,
264
- };
265
-
266
- const contentChecksum = computeContentChecksum(
267
- packageJsonHash,
268
- dtsFilesHash,
269
- partialApi,
270
- );
271
-
272
- return {
273
- api: { ...partialApi, contentChecksum },
274
- diagnostics,
275
- };
276
- }
277
-
278
- private analyzeEntrypoint(
279
- dep: Dependency,
280
- subpath: string,
281
- patternBacked: boolean,
282
- mode: ResolutionMode,
283
- diagnostics: Diagnostic[],
284
- dtsExtractor: DtsSignatureExtractor,
285
- ): Entrypoint {
286
- let resolved = resolveEntrypointTypes(
287
- dep.installPath,
288
- dep.name,
289
- subpath,
290
- mode,
291
- );
292
-
293
- if (resolved.dtsPath == null) {
294
- const typesPackage = typesPackageName(dep.name);
295
- const fallbackPath = resolveTypesPackage(
296
- typesPackage,
297
- dep.installPath,
298
- mode,
299
- );
300
- if (fallbackPath != null) {
301
- resolved = { dtsPath: fallbackPath, conditions: ["types"] };
302
- }
303
- }
304
-
305
- if (resolved.dtsPath == null) {
306
- diagnostics.push(forgePkgNoTypes(dep.name, subpath));
307
- return {
308
- subpath,
309
- conditions: resolved.conditions,
310
- patternBacked,
311
- dtsPath: null,
312
- exports: [],
313
- };
314
- }
315
-
316
- let exports: Entrypoint["exports"];
317
- try {
318
- exports = dtsExtractor.extract(
319
- resolved.dtsPath,
320
- dep.name,
321
- subpath,
322
- );
323
- } catch {
324
- diagnostics.push(forgePkgNoTypes(dep.name, subpath));
325
- return {
326
- subpath,
327
- conditions: resolved.conditions,
328
- patternBacked,
2
+ import ts from "typescript";
3
+ import type { Diagnostic } from "../types/diagnostic.ts";
4
+ import type {
5
+ AnalyzeOptions,
6
+ Dependency,
7
+ Entrypoint,
8
+ PackageApi,
9
+ PackageGraph,
10
+ } from "../types/package-graph.ts";
11
+ import type { PackageCacheKey } from "../types/lock.ts";
12
+ import type { ResolutionMode } from "../types/runtime.ts";
13
+ import { forgePkgNoTypes } from "../diagnostics/create.ts";
14
+ import { createDiagnostic } from "../diagnostics/create.ts";
15
+ import { stableSortEntrypoints, stableSortPackages } from "../primitives/sort.ts";
16
+ import {
17
+ PackageCacheStore,
18
+ forgeCacheDiscardedMessage,
19
+ } from "../cache/store.ts";
20
+ import { buildPackageCacheKey, cacheKeysEqual } from "../cache/key.ts";
21
+ import { runWithConcurrency } from "../cache/scheduler.ts";
22
+ import {
23
+ GENERATOR_VERSION,
24
+ PACKAGE_ANALYZER_VERSION,
25
+ PACKAGE_GRAPH_SCHEMA_VERSION,
26
+ DEFAULT_PATTERN_EXPANSION_LIMIT,
27
+ } from "./constants.ts";
28
+ import {
29
+ computeContentChecksum,
30
+ hashDtsFiles,
31
+ hashDtsFilesForCache,
32
+ hashPackageJson,
33
+ hashPackageJsonForCache,
34
+ } from "./checksum.ts";
35
+ import {
36
+ discoverSubpathsFromExports,
37
+ expandPatternSubpaths,
38
+ } from "./exports-discovery.ts";
39
+ import { DtsSignatureExtractor } from "./dts-extractor.ts";
40
+ import { readTextFile } from "./read-file.ts";
41
+ import {
42
+ resolveEntrypointTypes,
43
+ resolveTypesPackage,
44
+ typesPackageName,
45
+ } from "./resolve.ts";
46
+ import {
47
+ buildRuntimeCompatibility,
48
+ readPackageMetadata,
49
+ runtimeTypeMismatches,
50
+ } from "./oracle.ts";
51
+ import {
52
+ assertPackageApiSecretSafe,
53
+ defaultSandboxLimits,
54
+ inspectExports,
55
+ } from "../sandbox/index.ts";
56
+ import type { SandboxBackend } from "../types/runtime.ts";
57
+
58
+ export interface BuildOptions extends AnalyzeOptions {
59
+ concurrency?: number;
60
+ patternExpansionLimit?: number;
61
+ /** Informational only — does not invalidate per-package cache entries. */
62
+ lockfileHash?: string;
63
+ }
64
+
65
+ export interface AnalyzeResult {
66
+ api: PackageApi;
67
+ diagnostics: Diagnostic[];
68
+ cacheHit: boolean;
69
+ }
70
+
71
+ export interface BuildResult {
72
+ graph: PackageGraph;
73
+ diagnostics: Diagnostic[];
74
+ }
75
+
76
+ export class PackageGraphCompiler {
77
+ async build(
78
+ deps: Dependency[],
79
+ opts: BuildOptions,
80
+ ): Promise<BuildResult> {
81
+ const concurrency = Math.max(1, opts.concurrency ?? 4);
82
+ const cache = new PackageCacheStore(opts.cacheDir);
83
+ const diagnostics: Diagnostic[] = [];
84
+
85
+ const results = await runWithConcurrency(
86
+ deps,
87
+ concurrency,
88
+ async (dep) => this.analyzeWithCache(dep, opts, cache),
89
+ );
90
+
91
+ for (const result of results) {
92
+ diagnostics.push(...result.diagnostics);
93
+ }
94
+
95
+ const packages = stableSortPackages(results.map((r) => r.api));
96
+
97
+ return {
98
+ graph: {
99
+ schemaVersion: PACKAGE_GRAPH_SCHEMA_VERSION,
100
+ generatorVersion: GENERATOR_VERSION,
101
+ analyzerVersion: PACKAGE_ANALYZER_VERSION,
102
+ packages,
103
+ },
104
+ diagnostics,
105
+ };
106
+ }
107
+
108
+ async analyze(
109
+ dep: Dependency,
110
+ opts: AnalyzeOptions,
111
+ ): Promise<PackageApi> {
112
+ const result = await this.analyzeWithCache(
113
+ dep,
114
+ opts,
115
+ new PackageCacheStore(opts.cacheDir),
116
+ );
117
+ return result.api;
118
+ }
119
+
120
+ private async analyzeWithCache(
121
+ dep: Dependency,
122
+ opts: BuildOptions,
123
+ cache: PackageCacheStore,
124
+ ): Promise<AnalyzeResult> {
125
+ const cacheKey = buildPackageCacheKey({
126
+ name: dep.name,
127
+ version: dep.version,
128
+ packageManager: dep.packageManager,
129
+ packageIntegrity: dep.packageIntegrity,
130
+ packageJsonHash: hashPackageJsonForCache(dep.installPath),
131
+ dtsFilesHash: hashDtsFilesForCache(dep.installPath),
132
+ analyzerVersion: PACKAGE_ANALYZER_VERSION,
133
+ typescriptVersion: ts.version,
134
+ resolutionMode: opts.resolutionMode,
135
+ recipeVersion: opts.recipeVersion,
136
+ });
137
+
138
+ const lookup = cache.getWithValidation(cacheKey);
139
+ if ("hit" in lookup) {
140
+ return { api: lookup.hit, diagnostics: [], cacheHit: true };
141
+ }
142
+
143
+ const diagnostics: Diagnostic[] = [];
144
+ if ("corrupt" in lookup) {
145
+ diagnostics.push(
146
+ createDiagnostic({
147
+ severity: "warning",
148
+ code: "FORGE_CACHE_DISCARD",
149
+ message: forgeCacheDiscardedMessage(),
150
+ }),
151
+ );
152
+ }
153
+
154
+ const analyzed = await this.analyzeWithOptionalRuntime(dep, opts, {
155
+ packageJsonHash: hashPackageJson(dep.installPath),
156
+ dtsFilesHash: hashDtsFiles(dep.installPath),
157
+ });
158
+ diagnostics.push(...analyzed.diagnostics);
159
+ assertPackageApiSecretSafe(analyzed.api);
160
+ await cache.put(cacheKey, analyzed.api);
161
+ return { api: analyzed.api, diagnostics, cacheHit: false };
162
+ }
163
+
164
+ private async analyzeWithOptionalRuntime(
165
+ dep: Dependency,
166
+ opts: BuildOptions,
167
+ packageHashes: { packageJsonHash: string; dtsFilesHash: string },
168
+ ): Promise<{ api: PackageApi; diagnostics: Diagnostic[] }> {
169
+ const staticResult = this.analyzeStatic(dep, opts, packageHashes);
170
+ if (!opts.runtimeInspect) {
171
+ return staticResult;
172
+ }
173
+
174
+ const backend = resolveSandboxBackend(opts);
175
+ const sandbox = await inspectExports(
176
+ dep,
177
+ defaultSandboxLimits(backend),
178
+ );
179
+
180
+ const diagnostics = [
181
+ ...staticResult.diagnostics,
182
+ ...sandbox.diagnostics,
183
+ ];
184
+
185
+ if (!sandbox.runtimeUsed) {
186
+ return { api: staticResult.api, diagnostics };
187
+ }
188
+
189
+ const api: PackageApi = {
190
+ ...staticResult.api,
191
+ source: "static+runtime",
192
+ runtimeShape: sandbox.shape,
193
+ runtimeTypeMismatches: runtimeTypeMismatches({
194
+ entrypoints: staticResult.api.entrypoints,
195
+ runtimeShape: sandbox.shape,
196
+ }),
197
+ contentChecksum: computeContentChecksum(
198
+ packageHashes.packageJsonHash,
199
+ packageHashes.dtsFilesHash,
200
+ {
201
+ ...staticResult.api,
202
+ source: "static+runtime",
203
+ runtimeShape: sandbox.shape,
204
+ },
205
+ ),
206
+ };
207
+
208
+ return { api, diagnostics };
209
+ }
210
+
211
+ analyzeStatic(
212
+ dep: Dependency,
213
+ opts: BuildOptions,
214
+ packageHashes?: { packageJsonHash: string; dtsFilesHash: string },
215
+ ): { api: PackageApi; diagnostics: Diagnostic[] } {
216
+ const diagnostics: Diagnostic[] = [];
217
+ const packageJson = readPackageJson(dep.installPath);
218
+ const patternLimit =
219
+ opts.patternExpansionLimit ?? DEFAULT_PATTERN_EXPANSION_LIMIT;
220
+
221
+ const discovered = discoverSubpathsFromExports(packageJson.exports);
222
+ const subpathsToAnalyze: Array<{
223
+ subpath: string;
224
+ patternBacked: boolean;
225
+ }> = [];
226
+
227
+ for (const item of discovered) {
228
+ if (item.patternBacked) {
229
+ const expanded = expandPatternSubpaths(
230
+ dep.installPath,
231
+ item.subpath,
232
+ patternLimit,
233
+ );
234
+ for (const sub of expanded) {
235
+ subpathsToAnalyze.push({ subpath: sub, patternBacked: true });
236
+ }
237
+ if (expanded.length === 0) {
238
+ subpathsToAnalyze.push(item);
239
+ }
240
+ } else {
241
+ subpathsToAnalyze.push(item);
242
+ }
243
+ }
244
+
245
+ const entrypoints: Entrypoint[] = [];
246
+ const dtsExtractor = new DtsSignatureExtractor(opts.resolutionMode);
247
+
248
+ for (const { subpath, patternBacked } of subpathsToAnalyze) {
249
+ const entry = this.analyzeEntrypoint(
250
+ dep,
251
+ subpath,
252
+ patternBacked,
253
+ opts.resolutionMode,
254
+ diagnostics,
255
+ dtsExtractor,
256
+ );
257
+ entrypoints.push(entry);
258
+ }
259
+
260
+ const sortedEntrypoints = stableSortEntrypoints(entrypoints);
261
+ const metadata = readPackageMetadata(dep.installPath, sortedEntrypoints.length);
262
+ const runtimeCompatibility = buildRuntimeCompatibility(metadata);
263
+ const packageJsonHash =
264
+ packageHashes?.packageJsonHash ?? hashPackageJson(dep.installPath);
265
+ const dtsFilesHash =
266
+ packageHashes?.dtsFilesHash ?? hashDtsFiles(dep.installPath);
267
+
268
+ const partialApi = {
269
+ name: dep.name,
270
+ version: dep.version,
271
+ packageManager: dep.packageManager,
272
+ resolutionMode: opts.resolutionMode,
273
+ entrypoints: sortedEntrypoints,
274
+ source: "static" as const,
275
+ runtimeTypeMismatches: [],
276
+ runtimeCompatibility,
277
+ metadata,
278
+ };
279
+
280
+ const contentChecksum = computeContentChecksum(
281
+ packageJsonHash,
282
+ dtsFilesHash,
283
+ partialApi,
284
+ );
285
+
286
+ return {
287
+ api: { ...partialApi, contentChecksum },
288
+ diagnostics,
289
+ };
290
+ }
291
+
292
+ private analyzeEntrypoint(
293
+ dep: Dependency,
294
+ subpath: string,
295
+ patternBacked: boolean,
296
+ mode: ResolutionMode,
297
+ diagnostics: Diagnostic[],
298
+ dtsExtractor: DtsSignatureExtractor,
299
+ ): Entrypoint {
300
+ if (isPackageJsonSubpath(subpath)) {
301
+ return {
302
+ subpath,
303
+ conditions: [],
304
+ patternBacked,
305
+ dtsPath: null,
306
+ resolutionTrace: [
307
+ {
308
+ step: "package.metadata",
309
+ status: "ok",
310
+ detail: "package.json export is metadata and has no type API",
311
+ },
312
+ ],
313
+ exports: [],
314
+ };
315
+ }
316
+
317
+ const resolutionTrace: Entrypoint["resolutionTrace"] = [
318
+ {
319
+ step: "typescript.resolveModuleName",
320
+ status: "ok",
321
+ detail: `resolve ${dep.name} ${subpath} with ${mode}`,
322
+ },
323
+ ];
324
+ let resolved = resolveEntrypointTypes(
325
+ dep.installPath,
326
+ dep.name,
327
+ subpath,
328
+ mode,
329
+ );
330
+
331
+ if (resolved.dtsPath == null) {
332
+ resolutionTrace.push({
333
+ step: "package.types",
334
+ status: "miss",
335
+ detail: "no bundled type declaration resolved",
336
+ });
337
+ const typesPackage = typesPackageName(dep.name);
338
+ const fallbackPath = resolveTypesPackage(
339
+ typesPackage,
340
+ dep.installPath,
341
+ mode,
342
+ );
343
+ if (fallbackPath != null) {
344
+ resolutionTrace.push({
345
+ step: "typesPackage.fallback",
346
+ status: "fallback",
347
+ detail: `resolved ${typesPackage}`,
348
+ });
349
+ resolved = { dtsPath: fallbackPath, conditions: ["types"] };
350
+ } else {
351
+ resolutionTrace.push({
352
+ step: "typesPackage.fallback",
353
+ status: "miss",
354
+ detail: `${typesPackage} not found`,
355
+ });
356
+ }
357
+ } else {
358
+ resolutionTrace.push({
359
+ step: "package.types",
360
+ status: "ok",
361
+ detail: portableDtsPath(resolved.dtsPath, dep),
362
+ });
363
+ }
364
+
365
+ if (resolved.dtsPath == null) {
366
+ diagnostics.push(forgePkgNoTypes(dep.name, subpath));
367
+ return {
368
+ subpath,
369
+ conditions: resolved.conditions,
370
+ patternBacked,
371
+ dtsPath: null,
372
+ resolutionTrace,
373
+ exports: [],
374
+ };
375
+ }
376
+
377
+ let exports: Entrypoint["exports"];
378
+ try {
379
+ exports = dtsExtractor.extract(
380
+ resolved.dtsPath,
381
+ dep.name,
382
+ subpath,
383
+ );
384
+ } catch {
385
+ diagnostics.push(forgePkgNoTypes(dep.name, subpath));
386
+ return {
387
+ subpath,
388
+ conditions: resolved.conditions,
389
+ patternBacked,
329
390
  dtsPath: portableDtsPath(resolved.dtsPath, dep),
391
+ resolutionTrace: [
392
+ ...resolutionTrace,
393
+ {
394
+ step: "dts.extract",
395
+ status: "warning",
396
+ detail: "failed to extract declarations",
397
+ },
398
+ ],
330
399
  exports: [],
331
400
  };
332
- }
333
-
334
- if (exports.length === 0) {
335
- diagnostics.push(forgePkgNoTypes(dep.name, subpath));
336
- }
337
-
338
- return {
401
+ }
402
+
403
+ if (exports.length === 0) {
404
+ diagnostics.push(forgePkgNoTypes(dep.name, subpath));
405
+ }
406
+
407
+ return {
339
408
  subpath,
340
409
  conditions: resolved.conditions,
341
410
  patternBacked,
342
411
  dtsPath: portableDtsPath(resolved.dtsPath, dep),
412
+ resolutionTrace: [
413
+ ...resolutionTrace,
414
+ {
415
+ step: "dts.extract",
416
+ status: exports.length > 0 ? "ok" : "warning",
417
+ detail: `${exports.length} exports extracted`,
418
+ },
419
+ ],
343
420
  exports,
344
421
  };
345
422
  }
346
423
  }
347
424
 
425
+ function isPackageJsonSubpath(subpath: string): boolean {
426
+ return subpath === "./package.json" || subpath === "package.json";
427
+ }
428
+
348
429
  function portableDtsPath(dtsPath: string, dep: Pick<Dependency, "installPath" | "name">): string {
349
430
  const normalized = dtsPath.replace(/\\/g, "/");
350
431
  const marker = "/node_modules/";
@@ -361,32 +442,32 @@ function portableDtsPath(dtsPath: string, dep: Pick<Dependency, "installPath" |
361
442
  }
362
443
  return normalized;
363
444
  }
364
-
365
- function readPackageJson(installPath: string): {
366
- exports?: unknown;
367
- } {
368
- const raw = readTextFile(join(installPath, "package.json"));
369
- return JSON.parse(raw) as { exports?: unknown };
370
- }
371
-
372
- function resolveSandboxBackend(
373
- opts: Pick<AnalyzeOptions, "sandboxBackend">,
374
- ): SandboxBackend {
375
- return opts.sandboxBackend ?? "none";
376
- }
377
-
378
- export function recomputeFromInputs(
379
- dep: Dependency,
380
- opts: Pick<BuildOptions, "resolutionMode" | "patternExpansionLimit">,
381
- ): PackageApi {
382
- const compiler = new PackageGraphCompiler();
383
- return compiler.analyzeStatic(dep, {
384
- runtimeInspect: false,
385
- resolutionMode: opts.resolutionMode,
386
- cacheDir: "",
387
- patternExpansionLimit: opts.patternExpansionLimit,
388
- }).api;
389
- }
390
-
391
- export { cacheKeysEqual, buildPackageCacheKey };
392
- export type { PackageCacheKey };
445
+
446
+ function readPackageJson(installPath: string): {
447
+ exports?: unknown;
448
+ } {
449
+ const raw = readTextFile(join(installPath, "package.json"));
450
+ return JSON.parse(raw) as { exports?: unknown };
451
+ }
452
+
453
+ function resolveSandboxBackend(
454
+ opts: Pick<AnalyzeOptions, "sandboxBackend">,
455
+ ): SandboxBackend {
456
+ return opts.sandboxBackend ?? "none";
457
+ }
458
+
459
+ export function recomputeFromInputs(
460
+ dep: Dependency,
461
+ opts: Pick<BuildOptions, "resolutionMode" | "patternExpansionLimit">,
462
+ ): PackageApi {
463
+ const compiler = new PackageGraphCompiler();
464
+ return compiler.analyzeStatic(dep, {
465
+ runtimeInspect: false,
466
+ resolutionMode: opts.resolutionMode,
467
+ cacheDir: "",
468
+ patternExpansionLimit: opts.patternExpansionLimit,
469
+ }).api;
470
+ }
471
+
472
+ export { cacheKeysEqual, buildPackageCacheKey };
473
+ export type { PackageCacheKey };