@maverickcer/env-cap 0.2.0

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 (195) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +279 -0
  3. package/dist/.dts/build/assemble-project.d.ts +47 -0
  4. package/dist/.dts/build/assemble-project.d.ts.map +1 -0
  5. package/dist/.dts/build/change-model.d.ts +62 -0
  6. package/dist/.dts/build/change-model.d.ts.map +1 -0
  7. package/dist/.dts/build/check-artifacts.d.ts +48 -0
  8. package/dist/.dts/build/check-artifacts.d.ts.map +1 -0
  9. package/dist/.dts/build/citation-verification.d.ts +62 -0
  10. package/dist/.dts/build/citation-verification.d.ts.map +1 -0
  11. package/dist/.dts/build/compatibility.d.ts +76 -0
  12. package/dist/.dts/build/compatibility.d.ts.map +1 -0
  13. package/dist/.dts/build/contract-model.d.ts +92 -0
  14. package/dist/.dts/build/contract-model.d.ts.map +1 -0
  15. package/dist/.dts/build/deep-equal.d.ts +9 -0
  16. package/dist/.dts/build/deep-equal.d.ts.map +1 -0
  17. package/dist/.dts/build/deep-freeze.d.ts +20 -0
  18. package/dist/.dts/build/deep-freeze.d.ts.map +1 -0
  19. package/dist/.dts/build/dependency-graph.d.ts +168 -0
  20. package/dist/.dts/build/dependency-graph.d.ts.map +1 -0
  21. package/dist/.dts/build/dependency-model.d.ts +79 -0
  22. package/dist/.dts/build/dependency-model.d.ts.map +1 -0
  23. package/dist/.dts/build/discover.d.ts +25 -0
  24. package/dist/.dts/build/discover.d.ts.map +1 -0
  25. package/dist/.dts/build/display-path.d.ts +24 -0
  26. package/dist/.dts/build/display-path.d.ts.map +1 -0
  27. package/dist/.dts/build/docs.d.ts +176 -0
  28. package/dist/.dts/build/docs.d.ts.map +1 -0
  29. package/dist/.dts/build/env-example.d.ts +85 -0
  30. package/dist/.dts/build/env-example.d.ts.map +1 -0
  31. package/dist/.dts/build/errors.d.ts +78 -0
  32. package/dist/.dts/build/errors.d.ts.map +1 -0
  33. package/dist/.dts/build/evidence-cache.d.ts +74 -0
  34. package/dist/.dts/build/evidence-cache.d.ts.map +1 -0
  35. package/dist/.dts/build/evidence-model.d.ts +50 -0
  36. package/dist/.dts/build/evidence-model.d.ts.map +1 -0
  37. package/dist/.dts/build/evidence-reference.d.ts +67 -0
  38. package/dist/.dts/build/evidence-reference.d.ts.map +1 -0
  39. package/dist/.dts/build/evidence-snapshot.d.ts +123 -0
  40. package/dist/.dts/build/evidence-snapshot.d.ts.map +1 -0
  41. package/dist/.dts/build/exclusive-group.d.ts +19 -0
  42. package/dist/.dts/build/exclusive-group.d.ts.map +1 -0
  43. package/dist/.dts/build/finding-model.d.ts +79 -0
  44. package/dist/.dts/build/finding-model.d.ts.map +1 -0
  45. package/dist/.dts/build/generate-documentation.d.ts +176 -0
  46. package/dist/.dts/build/generate-documentation.d.ts.map +1 -0
  47. package/dist/.dts/build/generate-env-artifacts.d.ts +176 -0
  48. package/dist/.dts/build/generate-env-artifacts.d.ts.map +1 -0
  49. package/dist/.dts/build/generate-evidence.d.ts +77 -0
  50. package/dist/.dts/build/generate-evidence.d.ts.map +1 -0
  51. package/dist/.dts/build/generate-manifest.d.ts +101 -0
  52. package/dist/.dts/build/generate-manifest.d.ts.map +1 -0
  53. package/dist/.dts/build/generate-usage.d.ts +95 -0
  54. package/dist/.dts/build/generate-usage.d.ts.map +1 -0
  55. package/dist/.dts/build/generated-banner.d.ts +52 -0
  56. package/dist/.dts/build/generated-banner.d.ts.map +1 -0
  57. package/dist/.dts/build/glob.d.ts +18 -0
  58. package/dist/.dts/build/glob.d.ts.map +1 -0
  59. package/dist/.dts/build/governance-fields.d.ts +34 -0
  60. package/dist/.dts/build/governance-fields.d.ts.map +1 -0
  61. package/dist/.dts/build/humanize-key.d.ts +14 -0
  62. package/dist/.dts/build/humanize-key.d.ts.map +1 -0
  63. package/dist/.dts/build/index.d.ts +107 -0
  64. package/dist/.dts/build/index.d.ts.map +1 -0
  65. package/dist/.dts/build/lifecycle-model.d.ts +64 -0
  66. package/dist/.dts/build/lifecycle-model.d.ts.map +1 -0
  67. package/dist/.dts/build/link.d.ts +215 -0
  68. package/dist/.dts/build/link.d.ts.map +1 -0
  69. package/dist/.dts/build/literal-eval.d.ts +23 -0
  70. package/dist/.dts/build/literal-eval.d.ts.map +1 -0
  71. package/dist/.dts/build/live-expirations.d.ts +47 -0
  72. package/dist/.dts/build/live-expirations.d.ts.map +1 -0
  73. package/dist/.dts/build/manifest-snapshot.d.ts +229 -0
  74. package/dist/.dts/build/manifest-snapshot.d.ts.map +1 -0
  75. package/dist/.dts/build/manifest.d.ts +31 -0
  76. package/dist/.dts/build/manifest.d.ts.map +1 -0
  77. package/dist/.dts/build/map-utils.d.ts +8 -0
  78. package/dist/.dts/build/map-utils.d.ts.map +1 -0
  79. package/dist/.dts/build/ownership-model.d.ts +57 -0
  80. package/dist/.dts/build/ownership-model.d.ts.map +1 -0
  81. package/dist/.dts/build/parse.d.ts +199 -0
  82. package/dist/.dts/build/parse.d.ts.map +1 -0
  83. package/dist/.dts/build/reference-projections.d.ts +156 -0
  84. package/dist/.dts/build/reference-projections.d.ts.map +1 -0
  85. package/dist/.dts/build/resolution/resolve-import.d.ts +53 -0
  86. package/dist/.dts/build/resolution/resolve-import.d.ts.map +1 -0
  87. package/dist/.dts/build/resolution/resolve-package-schema.d.ts +83 -0
  88. package/dist/.dts/build/resolution/resolve-package-schema.d.ts.map +1 -0
  89. package/dist/.dts/build/resolution/resolve-tsconfig-paths.d.ts +101 -0
  90. package/dist/.dts/build/resolution/resolve-tsconfig-paths.d.ts.map +1 -0
  91. package/dist/.dts/build/resolution/resolve-within-root.d.ts +35 -0
  92. package/dist/.dts/build/resolution/resolve-within-root.d.ts.map +1 -0
  93. package/dist/.dts/build/resolve-import.d.ts +50 -0
  94. package/dist/.dts/build/resolve-import.d.ts.map +1 -0
  95. package/dist/.dts/build/resolve-package-schema.d.ts +99 -0
  96. package/dist/.dts/build/resolve-package-schema.d.ts.map +1 -0
  97. package/dist/.dts/build/resolve-tsconfig-paths.d.ts +100 -0
  98. package/dist/.dts/build/resolve-tsconfig-paths.d.ts.map +1 -0
  99. package/dist/.dts/build/resolve-within-root.d.ts +35 -0
  100. package/dist/.dts/build/resolve-within-root.d.ts.map +1 -0
  101. package/dist/.dts/build/sarif.d.ts +66 -0
  102. package/dist/.dts/build/sarif.d.ts.map +1 -0
  103. package/dist/.dts/build/scan-dependencies.d.ts +47 -0
  104. package/dist/.dts/build/scan-dependencies.d.ts.map +1 -0
  105. package/dist/.dts/build/sort-by-identity.d.ts +14 -0
  106. package/dist/.dts/build/sort-by-identity.d.ts.map +1 -0
  107. package/dist/.dts/build/source-position.d.ts +69 -0
  108. package/dist/.dts/build/source-position.d.ts.map +1 -0
  109. package/dist/.dts/build/tool-version.d.ts +8 -0
  110. package/dist/.dts/build/tool-version.d.ts.map +1 -0
  111. package/dist/.dts/build/types.d.ts +53 -0
  112. package/dist/.dts/build/types.d.ts.map +1 -0
  113. package/dist/.dts/build/usage-report.d.ts +124 -0
  114. package/dist/.dts/build/usage-report.d.ts.map +1 -0
  115. package/dist/.dts/cli/filesystem.d.ts +3 -0
  116. package/dist/.dts/cli/filesystem.d.ts.map +1 -0
  117. package/dist/.dts/eslint-plugin/glob.d.ts +18 -0
  118. package/dist/.dts/eslint-plugin/glob.d.ts.map +1 -0
  119. package/dist/.dts/eslint-plugin/index.d.ts +27 -0
  120. package/dist/.dts/eslint-plugin/index.d.ts.map +1 -0
  121. package/dist/.dts/eslint-plugin/no-node-fs.d.ts +25 -0
  122. package/dist/.dts/eslint-plugin/no-node-fs.d.ts.map +1 -0
  123. package/dist/.dts/eslint-plugin/no-raw-process-env.d.ts +23 -0
  124. package/dist/.dts/eslint-plugin/no-raw-process-env.d.ts.map +1 -0
  125. package/dist/.dts/evidence/define-projection.d.ts +51 -0
  126. package/dist/.dts/evidence/define-projection.d.ts.map +1 -0
  127. package/dist/.dts/evidence/index.d.ts +23 -0
  128. package/dist/.dts/evidence/index.d.ts.map +1 -0
  129. package/dist/.dts/helpers/index.d.ts +135 -0
  130. package/dist/.dts/helpers/index.d.ts.map +1 -0
  131. package/dist/.dts/helpers/processors.d.ts +32 -0
  132. package/dist/.dts/helpers/processors.d.ts.map +1 -0
  133. package/dist/.dts/helpers/validators.d.ts +68 -0
  134. package/dist/.dts/helpers/validators.d.ts.map +1 -0
  135. package/dist/.dts/node/index.d.ts +2 -0
  136. package/dist/.dts/node/index.d.ts.map +1 -0
  137. package/dist/.dts/runtime/cache.d.ts +20 -0
  138. package/dist/.dts/runtime/cache.d.ts.map +1 -0
  139. package/dist/.dts/runtime/create.d.ts +20 -0
  140. package/dist/.dts/runtime/create.d.ts.map +1 -0
  141. package/dist/.dts/runtime/document.d.ts +181 -0
  142. package/dist/.dts/runtime/document.d.ts.map +1 -0
  143. package/dist/.dts/runtime/errors.d.ts +55 -0
  144. package/dist/.dts/runtime/errors.d.ts.map +1 -0
  145. package/dist/.dts/runtime/index.d.ts +24 -0
  146. package/dist/.dts/runtime/index.d.ts.map +1 -0
  147. package/dist/.dts/runtime/registry.d.ts +12 -0
  148. package/dist/.dts/runtime/registry.d.ts.map +1 -0
  149. package/dist/.dts/runtime/reset.d.ts +8 -0
  150. package/dist/.dts/runtime/reset.d.ts.map +1 -0
  151. package/dist/.dts/runtime/types.d.ts +175 -0
  152. package/dist/.dts/runtime/types.d.ts.map +1 -0
  153. package/dist/.dts/runtime/validate.d.ts +14 -0
  154. package/dist/.dts/runtime/validate.d.ts.map +1 -0
  155. package/dist/build.cjs +83 -0
  156. package/dist/build.cjs.map +1 -0
  157. package/dist/build.d.cts +1 -0
  158. package/dist/build.d.ts +1 -0
  159. package/dist/build.js +19 -0
  160. package/dist/build.js.map +1 -0
  161. package/dist/cli/index.js +134 -0
  162. package/dist/cli/index.js.map +1 -0
  163. package/dist/eslint-plugin/index.cjs +12 -0
  164. package/dist/eslint-plugin/index.cjs.map +1 -0
  165. package/dist/eslint-plugin/index.d.cts +1 -0
  166. package/dist/eslint-plugin/index.d.ts +1 -0
  167. package/dist/eslint-plugin/index.js +5 -0
  168. package/dist/eslint-plugin/index.js.map +1 -0
  169. package/dist/evidence.cjs +7 -0
  170. package/dist/evidence.cjs.map +1 -0
  171. package/dist/evidence.d.cts +1 -0
  172. package/dist/evidence.d.ts +1 -0
  173. package/dist/evidence.js +5 -0
  174. package/dist/evidence.js.map +1 -0
  175. package/dist/helpers.cjs +8 -0
  176. package/dist/helpers.cjs.map +1 -0
  177. package/dist/helpers.d.cts +1 -0
  178. package/dist/helpers.d.ts +1 -0
  179. package/dist/helpers.js +5 -0
  180. package/dist/helpers.js.map +1 -0
  181. package/dist/index.cjs +15 -0
  182. package/dist/index.cjs.map +1 -0
  183. package/dist/index.d.cts +1 -0
  184. package/dist/index.d.ts +1 -0
  185. package/dist/index.js +7 -0
  186. package/dist/index.js.map +1 -0
  187. package/dist/node.cjs +13 -0
  188. package/dist/node.cjs.map +1 -0
  189. package/dist/node.d.cts +1 -0
  190. package/dist/node.d.ts +1 -0
  191. package/dist/node.js +7 -0
  192. package/dist/node.js.map +1 -0
  193. package/package.json +183 -0
  194. package/schemas/contract-model.schema.json +321 -0
  195. package/schemas/env-cap-report.schema.json +2369 -0
@@ -0,0 +1,101 @@
1
+ import ts from "typescript";
2
+ import type { ParseWarning } from "../parse.js";
3
+ import type { BuildFileSystem } from "../types.js";
4
+ /**
5
+ * TypeScript path-alias resolution (ADR 0023, Experimental -- see VERSIONING.md).
6
+ *
7
+ * Resolves a bare import specifier (`"@/lib/env.schema.js"`) against a project's own
8
+ * `tsconfig.json` `compilerOptions.paths`/`baseUrl`, so a schema or consumer reached only
9
+ * through an alias isn't misreported by `link.ts`/`dependency-graph.ts` as unresolved or
10
+ * abandoned. Unlike `resolve-package-schema.ts` (ADR 0014), this never crosses a
11
+ * trust/versioning boundary -- every resolved file is already local, already-trusted
12
+ * project source -- so it is on by default (auto-detecting `root/tsconfig.json`) rather
13
+ * than requiring an explicit allowlist.
14
+ *
15
+ * The actual `paths`/`baseUrl` matching algorithm (longest-prefix matching, `*` wildcard
16
+ * substitution, multiple fallback targets, `extends`-chain merging, JSONC parsing) is
17
+ * delegated entirely to the TypeScript compiler via `ts.resolveModuleName()` and
18
+ * `ts.parseJsonConfigFileContent()` -- the same functions `tsc`/`tsserver` themselves use --
19
+ * rather than reimplemented here. This module's own logic is limited to loading the config,
20
+ * caching resolutions, and enforcing the `node_modules` safety boundary below.
21
+ */
22
+ /** Parsed `tsconfig.json` `paths`/`baseUrl` configuration, immutable for the life of one generate*() run. See {@link loadTsconfigPaths}. */
23
+ export interface TsconfigPathsResolution {
24
+ /** The subset of `compilerOptions` `ts.resolveModuleName()` needs -- at minimum `paths` and/or `baseUrl`. */
25
+ readonly compilerOptions: ts.CompilerOptions;
26
+ /** Absolute path of the tsconfig.json this was loaded from, for diagnostics. */
27
+ readonly configFile: string;
28
+ }
29
+ /**
30
+ * Opaque memoization for {@link resolveAliasImport}, created once per generate*() run via
31
+ * {@link createAliasResolutionCache} and threaded through `ImportResolutionContext`. Kept
32
+ * distinct from `TsconfigPathsResolution` (immutable config) so the cache's internal
33
+ * representation stays free to change without touching that type's shape.
34
+ */
35
+ export interface AliasResolutionCache {
36
+ /**
37
+ * Keyed by `` `${importingFile}\0${specifier}` ``, not by `specifier` alone. With one
38
+ * fixed `compilerOptions` object and no project-reference support, `paths`-pattern
39
+ * substitution itself doesn't depend on the importing file -- but `ts.resolveModuleName()`'s
40
+ * fallback behavior when `paths` doesn't match a real file (classic-mode ancestor search,
41
+ * extension-preference edge cases) legitimately can. A `Map`, not a network call, so
42
+ * keying defensively by both costs nothing.
43
+ */
44
+ readonly resolutions: Map<string, string | undefined>;
45
+ }
46
+ /** Creates a fresh, empty {@link AliasResolutionCache} for one generate*()/computeArtifacts() run. */
47
+ export declare function createAliasResolutionCache(): AliasResolutionCache;
48
+ export interface LoadTsconfigPathsResult {
49
+ readonly resolution: TsconfigPathsResolution | undefined;
50
+ readonly warning: ParseWarning | undefined;
51
+ }
52
+ /**
53
+ * Loads and parses a `tsconfig.json` for alias resolution. Called exactly once per
54
+ * `generate*()`/`computeArtifacts()` invocation, at the same point
55
+ * `resolveAllowlistedPackages()` is already called once -- so at most one tsconfig-related
56
+ * warning is ever produced per run, never once per file scanned.
57
+ *
58
+ * @remarks
59
+ * `tsconfigOption === false` disables alias resolution entirely.
60
+ * `tsconfigOption === undefined` (the default) looks for `root/tsconfig.json` exactly --
61
+ * deliberately not `ts.findConfigFile()`'s upward directory walk, since every other
62
+ * root-relative mechanism in this codebase (schema discovery, `packages` resolution)
63
+ * treats `root` as a hard boundary. A missing default tsconfig is silent (most projects
64
+ * don't use aliases); a missing *explicit* `tsconfigOption` is a real misconfiguration and
65
+ * warns. `jsconfig.json` is intentionally not auto-detected -- pass `tsconfig:
66
+ * "jsconfig.json"` explicitly if needed; this loader only cares about the file's JSON
67
+ * shape, not its name.
68
+ *
69
+ * The gate for building a resolution is "`paths` non-empty OR `baseUrl` set", not `paths`
70
+ * alone -- a `baseUrl`-only tsconfig (no `paths` at all) still makes TypeScript resolve
71
+ * bare specifiers relative to `baseUrl`, and `ts.resolveModuleName()` already handles that
72
+ * once `compilerOptions.baseUrl` is passed through.
73
+ */
74
+ export declare function loadTsconfigPaths(root: string, tsconfigOption: string | false | undefined, fs: BuildFileSystem): Promise<LoadTsconfigPathsResult>;
75
+ /**
76
+ * Resolves one bare import specifier against a project's `tsconfig.json` `paths`/`baseUrl`,
77
+ * or returns `undefined` if it doesn't resolve through this mechanism.
78
+ *
79
+ * @remarks
80
+ * Necessarily synchronous -- `ts.resolveModuleName()` has no async form, matching how
81
+ * `tsc`/`tsserver` themselves always call it. `ts.sys` is used directly as the resolution
82
+ * host (an existing Node-backed singleton the `typescript` package exports; nothing to
83
+ * construct).
84
+ *
85
+ * Two safety/scope filters apply to any candidate `ts.resolveModuleName()` returns,
86
+ * independent of its own internal fallback behavior:
87
+ * - **Never resolves into `node_modules`.** `ts.resolveModuleName()` can, in principle,
88
+ * fall through to classic Node resolution and land inside `node_modules`; any resolved
89
+ * path containing a `node_modules` path segment (checked after `path.normalize()`, so
90
+ * mixed separators can't slip past it on Windows) is discarded here. Bare package
91
+ * specifiers continue to be handled exclusively by `resolvePackageImport()`
92
+ * (ADR 0014) -- this mechanism never overlaps with that trust boundary.
93
+ * - **`.ts`/`.tsx` only.** Matches `resolveRelativeImport()`'s own existing candidate set
94
+ * and `resolve-package-schema.ts`'s `SCHEMA_FILE_EXTENSIONS` -- this codebase's static-
95
+ * analysis pipeline is `.ts`/`.tsx` only today. A resolved non-`.ts`/`.tsx` file is a
96
+ * real risk, not just a gap: feeding it straight into `ts.createSourceFile()` wouldn't
97
+ * error, it would silently parse garbage -- exactly the "guess" this codebase's
98
+ * warn-don't-guess philosophy exists to avoid.
99
+ */
100
+ export declare function resolveAliasImport(specifier: string, importingFile: string, resolution: TsconfigPathsResolution, cache: AliasResolutionCache): string | undefined;
101
+ //# sourceMappingURL=resolve-tsconfig-paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-tsconfig-paths.d.ts","sourceRoot":"","sources":["../../../../src/build/resolution/resolve-tsconfig-paths.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,YAAY,CAAA;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElD;;;;;;;;;;;;;;;;;GAiBG;AAEH,4IAA4I;AAC5I,MAAM,WAAW,uBAAuB;IACtC,6GAA6G;IAC7G,QAAQ,CAAC,eAAe,EAAE,EAAE,CAAC,eAAe,CAAA;IAC5C,gFAAgF;IAChF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CACtD;AAED,sGAAsG;AACtG,wBAAgB,0BAA0B,IAAI,oBAAoB,CAEjE;AAcD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,UAAU,EAAE,uBAAuB,GAAG,SAAS,CAAA;IACxD,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,SAAS,CAAA;CAC3C;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,EAC1C,EAAE,EAAE,eAAe,GAClB,OAAO,CAAC,uBAAuB,CAAC,CA4ClC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,uBAAuB,EACnC,KAAK,EAAE,oBAAoB,GAC1B,MAAM,GAAG,SAAS,CAiBpB"}
@@ -0,0 +1,35 @@
1
+ import type { CompatibilityIssue } from "../compatibility.js";
2
+ export type ResolveWithinRootResult = {
3
+ readonly ok: true;
4
+ readonly resolved: string;
5
+ } | {
6
+ readonly ok: false;
7
+ readonly issue: CompatibilityIssue;
8
+ };
9
+ /**
10
+ * Plain lexical bounds-check: is `targetPath` inside `baseDir`? Shared by
11
+ * `resolveWithinRoot()` below (output paths, checked lexically since they
12
+ * usually don't exist on disk yet) and `resolve-package-schema.ts` (which
13
+ * additionally re-checks this against `fs.realpath`-resolved paths, since a
14
+ * package-declared schema path both exists on disk and crosses a real trust
15
+ * boundary -- see ADR 0014). Boundary-agnostic on purpose: neither caller's
16
+ * notion of "root" is baked in here.
17
+ */
18
+ export declare function isWithinDirectory(baseDir: string, targetPath: string): boolean;
19
+ /**
20
+ * Resolves `location` against `root` and checks the result doesn't escape it
21
+ * (e.g. `location: "../../malicious.ts"`, or an absolute path on another
22
+ * branch of the filesystem entirely). Discovery (`include`/`exclude`) is
23
+ * already safe by construction -- it only ever walks *down* from `root` via
24
+ * `readdir`, so a pattern can't make it read outside `root`. Output
25
+ * locations have no such structural guarantee, since `path.resolve` happily
26
+ * walks back out via `..` segments, so this is a plain lexical bounds-check
27
+ * (not a symlink-aware `realpath` check -- these are *output* paths that
28
+ * usually don't exist yet).
29
+ *
30
+ * Never throws itself -- returns a `CompatibilityIssue`-shaped finding on
31
+ * escape so each generator function (`generateEnvManifest`, `generateDocumentation`,
32
+ * `generateUsageReport`, `generateEnvArtifacts`) can wrap it in its own error type.
33
+ */
34
+ export declare function resolveWithinRoot(root: string, location: string, optionName: string, functionName: string): ResolveWithinRootResult;
35
+ //# sourceMappingURL=resolve-within-root.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-within-root.d.ts","sourceRoot":"","sources":["../../../../src/build/resolution/resolve-within-root.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAE7D,MAAM,MAAM,uBAAuB,GAC/B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAA;CAAE,CAAA;AAE9D;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAG9E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,GACnB,uBAAuB,CAgBzB"}
@@ -0,0 +1,50 @@
1
+ import { type PackageSchemaResolutionResult } from "./resolve-package-schema.js";
2
+ import { type AliasResolutionCache, type TsconfigPathsResolution } from "./resolve-tsconfig-paths.js";
3
+ /**
4
+ * Resolves a relative import specifier (as written in source: `"./schema.js"`,
5
+ * matching this codebase's own convention of `.js`-suffixed relative imports
6
+ * pointing at `.ts` source files) to an absolute file path, relative to the
7
+ * file that contains the import.
8
+ *
9
+ * @remarks
10
+ * Deliberately narrow: only handles a direct relative specifier resolving to
11
+ * a real `.ts`/`.tsx` file on disk. Bare/package specifiers, namespace
12
+ * imports, and anything requiring real module resolution (re-export chains,
13
+ * `exports` map lookups, etc.) return `undefined` -- the caller treats that
14
+ * as "couldn't statically link" and warns rather than guesses, the same
15
+ * philosophy `evaluateLiteral` already uses for non-literal expressions.
16
+ *
17
+ * @returns The resolved absolute path, or `undefined` when the specifier isn't relative or doesn't resolve to a real file.
18
+ */
19
+ export declare function resolveRelativeImport(importingFile: string, specifier: string): Promise<string | undefined>;
20
+ /** Shared inputs threaded through every call to {@link resolveImportSpecifier} for one discovery/link run. */
21
+ export interface ImportResolutionContext {
22
+ /** Absolute path of the project root, used to resolve package specifiers. */
23
+ readonly root: string;
24
+ /** Explicit allowlist -- see ADR 0014. Empty/omitted means package resolution never fires, identical to today's behavior. */
25
+ readonly packages: readonly string[];
26
+ /** Memoizes package resolution per specifier across the whole run -- see `resolvePackageImport`'s own doc comment for why. */
27
+ readonly cache: Map<string, Promise<PackageSchemaResolutionResult>>;
28
+ /** Parsed `tsconfig.json` `paths`/`baseUrl`, or `undefined` when alias resolution found nothing to do or was disabled -- see ADR 0023. */
29
+ readonly tsconfigPaths: TsconfigPathsResolution | undefined;
30
+ /** Memoizes alias resolution across the whole run -- see `resolveAliasImport`'s own doc comment for why. Always allocated, even when `tsconfigPaths` is `undefined`, mirroring `cache` above. */
31
+ readonly aliasCache: AliasResolutionCache;
32
+ }
33
+ /**
34
+ * The one specifier-resolution entry point `link.ts` and `dependency-graph.ts`
35
+ * call, instead of each duplicating a
36
+ * `(await resolveRelativeImport(...)) ?? resolveAliasImport(...) ?? (await resolvePackageImport(...))`
37
+ * chain at every call site.
38
+ *
39
+ * @remarks
40
+ * Purely a composition point -- no new resolution logic lives here. Tries, in order: the
41
+ * relative resolver (cheap, no `fs.stat` beyond the local filesystem check it already
42
+ * does); tsconfig path-alias resolution (ADR 0023, on by default) for a bare specifier
43
+ * matching the project's own `tsconfig.json` `paths`/`baseUrl`; then package resolution
44
+ * (ADR 0014) for a bare specifier matching an allow-listed package name. Alias resolution
45
+ * runs before package resolution because it resolves the consuming project's own local
46
+ * source (already-trusted, no versioning boundary), the same precedence relative
47
+ * resolution already has over package resolution.
48
+ */
49
+ export declare function resolveImportSpecifier(importingFile: string, specifier: string, context: ImportResolutionContext): Promise<string | undefined>;
50
+ //# sourceMappingURL=resolve-import.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-import.d.ts","sourceRoot":"","sources":["../../../src/build/resolve-import.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,6BAA6B,EACnC,MAAM,6BAA6B,CAAA;AACpC,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC7B,MAAM,6BAA6B,CAAA;AAEpC;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAe7B;AAWD,8GAA8G;AAC9G,MAAM,WAAW,uBAAuB;IACtC,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,6HAA6H;IAC7H,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,8HAA8H;IAC9H,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,6BAA6B,CAAC,CAAC,CAAA;IACnE,0IAA0I;IAC1I,QAAQ,CAAC,aAAa,EAAE,uBAAuB,GAAG,SAAS,CAAA;IAC3D,iMAAiM;IACjM,QAAQ,CAAC,UAAU,EAAE,oBAAoB,CAAA;CAC1C;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,sBAAsB,CAC1C,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAe7B"}
@@ -0,0 +1,99 @@
1
+ import type { ParseWarning } from "./parse.js";
2
+ /**
3
+ * Cross-package schema discovery (ADR 0014, Experimental -- see VERSIONING.md).
4
+ *
5
+ * Resolves an explicitly allow-listed installed package name to the one
6
+ * schema file it declares via its own `"envCap": { "schema": "<path>" }`
7
+ * package.json field. Every step here is `createRequire(...).resolve(...)`,
8
+ * `fs.stat`/`fs.realpath`/`fs.readFile` on a path already fully known --
9
+ * never a `readdir` walk of any directory, named package or not. This is a
10
+ * completely separate code path from `discover.ts`'s `discoverSchemaFiles()`,
11
+ * which continues to unconditionally prune `node_modules` during its own
12
+ * walk exactly as before; the two never overlap.
13
+ *
14
+ * This module only ever locates a file. It never imports, requires, or
15
+ * executes it -- a package-resolved file is fed into the exact same
16
+ * `parseSchemaFile()`/AST-only pipeline as a locally-discovered file,
17
+ * indistinguishable from it after resolution. See ADR 0002 and ADR 0014.
18
+ */
19
+ export declare const SCHEMA_FILE_EXTENSIONS: readonly [".ts", ".tsx"];
20
+ /** 1 MiB. New hardening specific to this trust tier -- a package crosses a
21
+ * real versioning/trust boundary that locally-discovered source doesn't,
22
+ * so this caps the cost of parsing an oversized or adversarial file before
23
+ * any of its content is even read into memory. See ADR 0014. */
24
+ export declare const MAX_PACKAGE_SCHEMA_FILE_BYTES = 1048576;
25
+ export type PackageResolutionFailureCode = "PACKAGE_NOT_FOUND" | "MALFORMED_PACKAGE_JSON" | "FIELD_MISSING" | "INVALID_EXTENSION" | "OUTSIDE_PACKAGE" | "FILE_TOO_LARGE";
26
+ /** Both the authored and resolved forms are kept -- diagnostics benefit from
27
+ * showing exactly what a package author wrote versus what it resolved to. */
28
+ export interface PackageOrigin {
29
+ /** The allow-listed package name that declared this schema. */
30
+ readonly packageName: string;
31
+ /** The `"envCap.schema"` value exactly as the package author wrote it. */
32
+ readonly declaredField: string;
33
+ /** Absolute, realpath-canonicalized path to the resolved schema file. */
34
+ readonly resolvedFile: string;
35
+ /** Absolute, realpath-canonicalized path to the package's own directory. */
36
+ readonly packageDir: string;
37
+ }
38
+ export type PackageSchemaResolutionResult = {
39
+ readonly ok: true;
40
+ readonly origin: PackageOrigin;
41
+ } | {
42
+ readonly ok: false;
43
+ readonly code: PackageResolutionFailureCode;
44
+ readonly reason: string;
45
+ };
46
+ /**
47
+ * Resolves one allow-listed package name. Memoized in a caller-owned
48
+ * `cache` (one per `generate*()` invocation, shared with linking/dependency-
49
+ * graph resolution) so a name referenced from multiple places -- multiple
50
+ * scanned files bare-importing the same package, or a duplicate entry in
51
+ * `packages` -- is only ever resolved once. The cache is populated with the
52
+ * in-flight promise before it settles, so concurrent callers await the same
53
+ * resolution rather than racing duplicate work.
54
+ */
55
+ export declare function resolvePackageSchemaFile(packageName: string, root: string, cache: Map<string, Promise<PackageSchemaResolutionResult>>): Promise<PackageSchemaResolutionResult>;
56
+ export interface ResolvedPackageFile {
57
+ readonly packageName: string;
58
+ readonly file: string;
59
+ }
60
+ export interface ResolvePackagesResult {
61
+ readonly files: readonly ResolvedPackageFile[];
62
+ /** Keyed by resolved file path, for `DiscoveredContract.packageOrigin` lookups downstream. */
63
+ readonly origins: ReadonlyMap<string, PackageOrigin>;
64
+ readonly warnings: readonly ParseWarning[];
65
+ }
66
+ /**
67
+ * Resolves every allow-listed package name. Input is deduplicated first, so
68
+ * a duplicate entry in `packages` (accidental or defensive) produces exactly
69
+ * one resolution attempt and, on failure, exactly one warning -- never two.
70
+ * Never throws: every failure becomes one `ParseWarning`, consistent with
71
+ * every other static-analysis boundary in this codebase.
72
+ */
73
+ export declare function resolveAllowlistedPackages(packages: readonly string[], root: string, cache: Map<string, Promise<PackageSchemaResolutionResult>>): Promise<ResolvePackagesResult>;
74
+ /**
75
+ * Combines local schema-discovery hits with package-resolved files into one
76
+ * deduplicated list, keyed by realpath rather than lexical absolute path --
77
+ * package-resolved files are already realpath-canonicalized (see
78
+ * `resolveUncached` above), but local `discoverSchemaFiles()` hits are plain
79
+ * `readdir`-derived absolute paths that may themselves traverse a symlink (a
80
+ * symlinked `root`, or an included path reached through one). Deduplicating
81
+ * on the lexical path alone would miss the case where the same physical file
82
+ * is reached twice through two different symlinked routes -- one via local
83
+ * glob discovery, one via package resolution -- and silently double-count it
84
+ * into two identical contracts, including the more mundane case of a package
85
+ * that's both locally glob-reachable (e.g. during a monorepo migration) and
86
+ * explicitly allow-listed. On a collision, the local path string identity
87
+ * wins (the package-resolved duplicate is dropped).
88
+ */
89
+ export declare function mergeLocalAndPackageFiles(localFiles: readonly string[], packageFiles: readonly string[]): Promise<string[]>;
90
+ /**
91
+ * Bare-specifier-to-allowlist matching, used by `resolve-import.ts`'s
92
+ * `resolveImportSpecifier()` as its package-resolution fallback. Only ever
93
+ * attempts resolution for a specifier that is (or is a subpath of) an
94
+ * allow-listed package name -- any other bare specifier is not this
95
+ * mechanism's concern and returns `undefined` immediately, identical to
96
+ * `resolveRelativeImport()`'s existing bare-specifier no-op.
97
+ */
98
+ export declare function resolvePackageImport(specifier: string, allowedPackages: readonly string[], root: string, cache: Map<string, Promise<PackageSchemaResolutionResult>>): Promise<string | undefined>;
99
+ //# sourceMappingURL=resolve-package-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-package-schema.d.ts","sourceRoot":"","sources":["../../../src/build/resolve-package-schema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAG9C;;;;;;;;;;;;;;;;GAgBG;AAEH,eAAO,MAAM,sBAAsB,0BAA2B,CAAA;AAE9D;;;iEAGiE;AACjE,eAAO,MAAM,6BAA6B,UAAY,CAAA;AAItD,MAAM,MAAM,4BAA4B,GACpC,mBAAmB,GACnB,wBAAwB,GACxB,eAAe,GACf,mBAAmB,GACnB,iBAAiB,GACjB,gBAAgB,CAAA;AAEpB;8EAC8E;AAC9E,MAAM,WAAW,aAAa;IAC5B,+DAA+D;IAC/D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,0EAA0E;IAC1E,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,yEAAyE;IACzE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,MAAM,6BAA6B,GACrC;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,4BAA4B,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AA0LhG;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,6BAA6B,CAAC,CAAC,GACzD,OAAO,CAAC,6BAA6B,CAAC,CAOxC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,SAAS,mBAAmB,EAAE,CAAA;IAC9C,8FAA8F;IAC9F,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IACpD,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAA;CAC3C;AAED;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,6BAA6B,CAAC,CAAC,GACzD,OAAO,CAAC,qBAAqB,CAAC,CAuBhC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,YAAY,EAAE,SAAS,MAAM,EAAE,GAC9B,OAAO,CAAC,MAAM,EAAE,CAAC,CAuBnB;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,SAAS,MAAM,EAAE,EAClC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,6BAA6B,CAAC,CAAC,GACzD,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAO7B"}
@@ -0,0 +1,100 @@
1
+ import ts from "typescript";
2
+ import type { ParseWarning } from "./parse.js";
3
+ /**
4
+ * TypeScript path-alias resolution (ADR 0023, Experimental -- see VERSIONING.md).
5
+ *
6
+ * Resolves a bare import specifier (`"@/lib/env.schema.js"`) against a project's own
7
+ * `tsconfig.json` `compilerOptions.paths`/`baseUrl`, so a schema or consumer reached only
8
+ * through an alias isn't misreported by `link.ts`/`dependency-graph.ts` as unresolved or
9
+ * abandoned. Unlike `resolve-package-schema.ts` (ADR 0014), this never crosses a
10
+ * trust/versioning boundary -- every resolved file is already local, already-trusted
11
+ * project source -- so it is on by default (auto-detecting `root/tsconfig.json`) rather
12
+ * than requiring an explicit allowlist.
13
+ *
14
+ * The actual `paths`/`baseUrl` matching algorithm (longest-prefix matching, `*` wildcard
15
+ * substitution, multiple fallback targets, `extends`-chain merging, JSONC parsing) is
16
+ * delegated entirely to the TypeScript compiler via `ts.resolveModuleName()` and
17
+ * `ts.parseJsonConfigFileContent()` -- the same functions `tsc`/`tsserver` themselves use --
18
+ * rather than reimplemented here. This module's own logic is limited to loading the config,
19
+ * caching resolutions, and enforcing the `node_modules` safety boundary below.
20
+ */
21
+ /** Parsed `tsconfig.json` `paths`/`baseUrl` configuration, immutable for the life of one generate*() run. See {@link loadTsconfigPaths}. */
22
+ export interface TsconfigPathsResolution {
23
+ /** The subset of `compilerOptions` `ts.resolveModuleName()` needs -- at minimum `paths` and/or `baseUrl`. */
24
+ readonly compilerOptions: ts.CompilerOptions;
25
+ /** Absolute path of the tsconfig.json this was loaded from, for diagnostics. */
26
+ readonly configFile: string;
27
+ }
28
+ /**
29
+ * Opaque memoization for {@link resolveAliasImport}, created once per generate*() run via
30
+ * {@link createAliasResolutionCache} and threaded through `ImportResolutionContext`. Kept
31
+ * distinct from `TsconfigPathsResolution` (immutable config) so the cache's internal
32
+ * representation stays free to change without touching that type's shape.
33
+ */
34
+ export interface AliasResolutionCache {
35
+ /**
36
+ * Keyed by `` `${importingFile}\0${specifier}` ``, not by `specifier` alone. With one
37
+ * fixed `compilerOptions` object and no project-reference support, `paths`-pattern
38
+ * substitution itself doesn't depend on the importing file -- but `ts.resolveModuleName()`'s
39
+ * fallback behavior when `paths` doesn't match a real file (classic-mode ancestor search,
40
+ * extension-preference edge cases) legitimately can. A `Map`, not a network call, so
41
+ * keying defensively by both costs nothing.
42
+ */
43
+ readonly resolutions: Map<string, string | undefined>;
44
+ }
45
+ /** Creates a fresh, empty {@link AliasResolutionCache} for one generate*()/computeArtifacts() run. */
46
+ export declare function createAliasResolutionCache(): AliasResolutionCache;
47
+ export interface LoadTsconfigPathsResult {
48
+ readonly resolution: TsconfigPathsResolution | undefined;
49
+ readonly warning: ParseWarning | undefined;
50
+ }
51
+ /**
52
+ * Loads and parses a `tsconfig.json` for alias resolution. Called exactly once per
53
+ * `generate*()`/`computeArtifacts()` invocation, at the same point
54
+ * `resolveAllowlistedPackages()` is already called once -- so at most one tsconfig-related
55
+ * warning is ever produced per run, never once per file scanned.
56
+ *
57
+ * @remarks
58
+ * `tsconfigOption === false` disables alias resolution entirely.
59
+ * `tsconfigOption === undefined` (the default) looks for `root/tsconfig.json` exactly --
60
+ * deliberately not `ts.findConfigFile()`'s upward directory walk, since every other
61
+ * root-relative mechanism in this codebase (schema discovery, `packages` resolution)
62
+ * treats `root` as a hard boundary. A missing default tsconfig is silent (most projects
63
+ * don't use aliases); a missing *explicit* `tsconfigOption` is a real misconfiguration and
64
+ * warns. `jsconfig.json` is intentionally not auto-detected -- pass `tsconfig:
65
+ * "jsconfig.json"` explicitly if needed; this loader only cares about the file's JSON
66
+ * shape, not its name.
67
+ *
68
+ * The gate for building a resolution is "`paths` non-empty OR `baseUrl` set", not `paths`
69
+ * alone -- a `baseUrl`-only tsconfig (no `paths` at all) still makes TypeScript resolve
70
+ * bare specifiers relative to `baseUrl`, and `ts.resolveModuleName()` already handles that
71
+ * once `compilerOptions.baseUrl` is passed through.
72
+ */
73
+ export declare function loadTsconfigPaths(root: string, tsconfigOption: string | false | undefined): Promise<LoadTsconfigPathsResult>;
74
+ /**
75
+ * Resolves one bare import specifier against a project's `tsconfig.json` `paths`/`baseUrl`,
76
+ * or returns `undefined` if it doesn't resolve through this mechanism.
77
+ *
78
+ * @remarks
79
+ * Necessarily synchronous -- `ts.resolveModuleName()` has no async form, matching how
80
+ * `tsc`/`tsserver` themselves always call it. `ts.sys` is used directly as the resolution
81
+ * host (an existing Node-backed singleton the `typescript` package exports; nothing to
82
+ * construct).
83
+ *
84
+ * Two safety/scope filters apply to any candidate `ts.resolveModuleName()` returns,
85
+ * independent of its own internal fallback behavior:
86
+ * - **Never resolves into `node_modules`.** `ts.resolveModuleName()` can, in principle,
87
+ * fall through to classic Node resolution and land inside `node_modules`; any resolved
88
+ * path containing a `node_modules` path segment (checked after `path.normalize()`, so
89
+ * mixed separators can't slip past it on Windows) is discarded here. Bare package
90
+ * specifiers continue to be handled exclusively by `resolvePackageImport()`
91
+ * (ADR 0014) -- this mechanism never overlaps with that trust boundary.
92
+ * - **`.ts`/`.tsx` only.** Matches `resolveRelativeImport()`'s own existing candidate set
93
+ * and `resolve-package-schema.ts`'s `SCHEMA_FILE_EXTENSIONS` -- this codebase's static-
94
+ * analysis pipeline is `.ts`/`.tsx` only today. A resolved non-`.ts`/`.tsx` file is a
95
+ * real risk, not just a gap: feeding it straight into `ts.createSourceFile()` wouldn't
96
+ * error, it would silently parse garbage -- exactly the "guess" this codebase's
97
+ * warn-don't-guess philosophy exists to avoid.
98
+ */
99
+ export declare function resolveAliasImport(specifier: string, importingFile: string, resolution: TsconfigPathsResolution, cache: AliasResolutionCache): string | undefined;
100
+ //# sourceMappingURL=resolve-tsconfig-paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-tsconfig-paths.d.ts","sourceRoot":"","sources":["../../../src/build/resolve-tsconfig-paths.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,YAAY,CAAA;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C;;;;;;;;;;;;;;;;;GAiBG;AAEH,4IAA4I;AAC5I,MAAM,WAAW,uBAAuB;IACtC,6GAA6G;IAC7G,QAAQ,CAAC,eAAe,EAAE,EAAE,CAAC,eAAe,CAAA;IAC5C,gFAAgF;IAChF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CACtD;AAED,sGAAsG;AACtG,wBAAgB,0BAA0B,IAAI,oBAAoB,CAEjE;AAWD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,UAAU,EAAE,uBAAuB,GAAG,SAAS,CAAA;IACxD,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,SAAS,CAAA;CAC3C;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,GACzC,OAAO,CAAC,uBAAuB,CAAC,CAqClC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,uBAAuB,EACnC,KAAK,EAAE,oBAAoB,GAC1B,MAAM,GAAG,SAAS,CAiBpB"}
@@ -0,0 +1,35 @@
1
+ import type { CompatibilityIssue } from "./compatibility.js";
2
+ export type ResolveWithinRootResult = {
3
+ readonly ok: true;
4
+ readonly resolved: string;
5
+ } | {
6
+ readonly ok: false;
7
+ readonly issue: CompatibilityIssue;
8
+ };
9
+ /**
10
+ * Plain lexical bounds-check: is `targetPath` inside `baseDir`? Shared by
11
+ * `resolveWithinRoot()` below (output paths, checked lexically since they
12
+ * usually don't exist on disk yet) and `resolve-package-schema.ts` (which
13
+ * additionally re-checks this against `fs.realpath`-resolved paths, since a
14
+ * package-declared schema path both exists on disk and crosses a real trust
15
+ * boundary -- see ADR 0014). Boundary-agnostic on purpose: neither caller's
16
+ * notion of "root" is baked in here.
17
+ */
18
+ export declare function isWithinDirectory(baseDir: string, targetPath: string): boolean;
19
+ /**
20
+ * Resolves `location` against `root` and checks the result doesn't escape it
21
+ * (e.g. `location: "../../malicious.ts"`, or an absolute path on another
22
+ * branch of the filesystem entirely). Discovery (`include`/`exclude`) is
23
+ * already safe by construction -- it only ever walks *down* from `root` via
24
+ * `readdir`, so a pattern can't make it read outside `root`. Output
25
+ * locations have no such structural guarantee, since `path.resolve` happily
26
+ * walks back out via `..` segments, so this is a plain lexical bounds-check
27
+ * (not a symlink-aware `realpath` check -- these are *output* paths that
28
+ * usually don't exist yet).
29
+ *
30
+ * Never throws itself -- returns a `CompatibilityIssue`-shaped finding on
31
+ * escape so each generator function (`generateEnvManifest`, `generateDocumentation`,
32
+ * `generateUsageReport`, `generateEnvArtifacts`) can wrap it in its own error type.
33
+ */
34
+ export declare function resolveWithinRoot(root: string, location: string, optionName: string, functionName: string): ResolveWithinRootResult;
35
+ //# sourceMappingURL=resolve-within-root.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-within-root.d.ts","sourceRoot":"","sources":["../../../src/build/resolve-within-root.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAE5D,MAAM,MAAM,uBAAuB,GAC/B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAA;CAAE,CAAA;AAE9D;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAG9E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,GACnB,uBAAuB,CAgBzB"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * SARIF export -- an adapter over Finding Model, not a new fact source.
3
+ * Produces a minimal, spec-conformant SARIF 2.1.0 log
4
+ * (https://docs.oasis-open.org/sarif/sarif/v2.1.0/) so env-cap's findings can
5
+ * be consumed by any SARIF-aware tool (GitHub code scanning, most CI security
6
+ * dashboards) without a bespoke integration.
7
+ *
8
+ * Pure and synchronous: every input is already computed by the time this
9
+ * runs, so this never re-derives a finding, never reads the filesystem, and
10
+ * never decides what is or isn't a problem -- it only re-shapes what
11
+ * `buildFindingModel()` already concluded.
12
+ */
13
+ import type { FindingModel } from "./finding-model.js";
14
+ /** SARIF's `level` enum -- see the SARIF 2.1.0 spec, section 3.27.10. */
15
+ type SarifLevel = "none" | "note" | "warning" | "error";
16
+ interface SarifLocation {
17
+ readonly physicalLocation: {
18
+ readonly artifactLocation: {
19
+ readonly uri: string;
20
+ };
21
+ readonly region?: {
22
+ readonly startLine: number;
23
+ readonly startColumn: number;
24
+ };
25
+ };
26
+ }
27
+ interface SarifResult {
28
+ readonly ruleId: string;
29
+ readonly level: SarifLevel;
30
+ readonly message: {
31
+ readonly text: string;
32
+ };
33
+ readonly locations?: readonly SarifLocation[];
34
+ }
35
+ /** A minimal SARIF 2.1.0 log -- only the properties this adapter actually populates, not the full spec surface. */
36
+ export interface SarifLog {
37
+ readonly $schema: string;
38
+ readonly version: "2.1.0";
39
+ readonly runs: readonly {
40
+ readonly tool: {
41
+ readonly driver: {
42
+ readonly name: string;
43
+ readonly informationUri: string;
44
+ readonly version: string;
45
+ readonly rules: readonly {
46
+ readonly id: string;
47
+ }[];
48
+ };
49
+ };
50
+ readonly results: readonly SarifResult[];
51
+ }[];
52
+ }
53
+ /**
54
+ * Projects Finding Model into a SARIF 2.1.0 log.
55
+ *
56
+ * @remarks
57
+ * `rules` lists every distinct `FindingCode` actually present in this run,
58
+ * sorted -- not the full `FindingCode` union. A SARIF consumer treats the
59
+ * rules array as "what this tool reported", and advertising rules that
60
+ * produced no result makes a clean run look like it has unexplained silent
61
+ * rules. `results` preserves Finding Model's own order, which a caller wanting
62
+ * a different one sorts themselves.
63
+ */
64
+ export declare function buildSarifLog(findingModel: FindingModel): SarifLog;
65
+ export {};
66
+ //# sourceMappingURL=sarif.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif.d.ts","sourceRoot":"","sources":["../../../src/build/sarif.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAW,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAG/D,yEAAyE;AACzE,KAAK,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAA;AAOvD,UAAU,aAAa;IACrB,QAAQ,CAAC,gBAAgB,EAAE;QACzB,QAAQ,CAAC,gBAAgB,EAAE;YAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAA;QACnD,QAAQ,CAAC,MAAM,CAAC,EAAE;YAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;SAAE,CAAA;KAC/E,CAAA;CACF;AAuCD,UAAU,WAAW;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3C,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,aAAa,EAAE,CAAA;CAC9C;AAED,mHAAmH;AACnH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS;QACtB,QAAQ,CAAC,IAAI,EAAE;YACb,QAAQ,CAAC,MAAM,EAAE;gBACf,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;gBACrB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;gBAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;gBACxB,QAAQ,CAAC,KAAK,EAAE,SAAS;oBAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;iBAAE,EAAE,CAAA;aACnD,CAAA;SACF,CAAA;QACD,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAA;KACzC,EAAE,CAAA;CACJ;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,YAAY,GAAG,QAAQ,CA0BlE"}
@@ -0,0 +1,47 @@
1
+ import type { ImportBinding } from "./parse.js";
2
+ /**
3
+ * Why a tracked binding's value flowed somewhere this single-file, syntactic
4
+ * walk cannot follow -- see ADR 0039. Each reason names the exact construct
5
+ * so a downstream "cannot determine whether X is read" message can cite it,
6
+ * rather than a single opaque "escape" label.
7
+ */
8
+ export type EscapeReason =
9
+ /** `const { ...rest } = contract` -- a rest element captures every remaining key at once. */
10
+ "rest"
11
+ /** `const { X: { Y } } = contract` -- the bound value itself gets destructured again, one level too deep for this pass. */
12
+ | "nested-pattern"
13
+ /** `const { [expr]: v } = contract` where `expr` isn't a string literal -- the bound key can't be read without evaluating `expr`. */
14
+ | "computed-key"
15
+ /** `const e = contract` where `e` isn't file-unique/never-assigned (see `resolveAliasTargets`) -- the read is real, but this pass declines to follow `e` any further. */
16
+ | "reassignment";
17
+ /** One observed use of a tracked contract binding in a consumer file -- see ADR 0039. Consumed by `dependency-graph.ts`. */
18
+ export type AccessSite = {
19
+ readonly kind: "member";
20
+ readonly member: string;
21
+ readonly line: number;
22
+ readonly column: number;
23
+ } | {
24
+ readonly kind: "dynamic";
25
+ readonly line: number;
26
+ readonly column: number;
27
+ } | {
28
+ readonly kind: "reference";
29
+ readonly line: number;
30
+ readonly column: number;
31
+ } | {
32
+ readonly kind: "escape";
33
+ readonly via: EscapeReason;
34
+ readonly line: number;
35
+ readonly column: number;
36
+ };
37
+ export interface FileScanResult {
38
+ readonly file: string;
39
+ readonly imports: ReadonlyMap<string, ImportBinding>;
40
+ readonly accessesByLocalName: ReadonlyMap<string, readonly AccessSite[]>;
41
+ /** True if this file contains a bare `export * from "..."` -- used only to
42
+ * flag ambiguous barrel forwarding elsewhere as "unresolved", never to
43
+ * follow it (see ADR 0010's scope boundary). */
44
+ readonly hasWildcardReExport: boolean;
45
+ }
46
+ export declare function scanFileForDependencies(filePath: string, sourceText: string): FileScanResult;
47
+ //# sourceMappingURL=scan-dependencies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-dependencies.d.ts","sourceRoot":"","sources":["../../../src/build/scan-dependencies.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAG/C;;;;;GAKG;AACH,MAAM,MAAM,YAAY;AACtB,6FAA6F;AAC3F,MAAM;AACR,2HAA2H;GACzH,gBAAgB;AAClB,qIAAqI;GACnI,cAAc;AAChB,yKAAyK;GACvK,cAAc,CAAA;AAElB,4HAA4H;AAC5H,MAAM,MAAM,UAAU,GAClB;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5E;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC9E;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;IACvB,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB,CAAA;AAEL,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IACpD,QAAQ,CAAC,mBAAmB,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC,CAAA;IACxE;;qDAEiD;IACjD,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAA;CACtC;AAuPD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,cAAc,CAwK5F"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The canonical ordering every fact model's contract list is sorted by: `file`
3
+ * (root-relative, POSIX) then `exportName`. One definition so `JSON.stringify`
4
+ * output is stable and diffs cleanly across Contract / Ownership / Lifecycle /
5
+ * Dependency Models. Internal -- not re-exported from the public `.` barrel.
6
+ */
7
+ export declare function byContractIdentity(a: {
8
+ readonly file: string;
9
+ readonly exportName: string;
10
+ }, b: {
11
+ readonly file: string;
12
+ readonly exportName: string;
13
+ }): number;
14
+ //# sourceMappingURL=sort-by-identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sort-by-identity.d.ts","sourceRoot":"","sources":["../../../src/build/sort-by-identity.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,CAAC,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,EACzD,CAAC,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GACxD,MAAM,CAER"}