@microwiseai/snapshot 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/dist/commands/install.d.ts.map +1 -1
  2. package/dist/commands/install.js +195 -34
  3. package/dist/commands/install.js.map +1 -1
  4. package/dist/commands/preflight.d.ts +31 -0
  5. package/dist/commands/preflight.d.ts.map +1 -0
  6. package/dist/commands/preflight.js +83 -0
  7. package/dist/commands/preflight.js.map +1 -0
  8. package/dist/commands/publish.d.ts +4 -0
  9. package/dist/commands/publish.d.ts.map +1 -1
  10. package/dist/commands/publish.js +35 -1
  11. package/dist/commands/publish.js.map +1 -1
  12. package/dist/index.js +13 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/lib/distkit-closure-bridge.d.ts +102 -0
  15. package/dist/lib/distkit-closure-bridge.d.ts.map +1 -0
  16. package/dist/lib/distkit-closure-bridge.js +177 -0
  17. package/dist/lib/distkit-closure-bridge.js.map +1 -0
  18. package/dist/lib/distkit-closure-parity.d.ts +110 -0
  19. package/dist/lib/distkit-closure-parity.d.ts.map +1 -0
  20. package/dist/lib/distkit-closure-parity.js +134 -0
  21. package/dist/lib/distkit-closure-parity.js.map +1 -0
  22. package/dist/lib/distkit-routing-port.d.ts +37 -0
  23. package/dist/lib/distkit-routing-port.d.ts.map +1 -0
  24. package/dist/lib/distkit-routing-port.js +72 -0
  25. package/dist/lib/distkit-routing-port.js.map +1 -0
  26. package/dist/lib/install-timeline.d.ts +81 -0
  27. package/dist/lib/install-timeline.d.ts.map +1 -0
  28. package/dist/lib/install-timeline.js +243 -0
  29. package/dist/lib/install-timeline.js.map +1 -0
  30. package/dist/lib/preflight-adapter.d.ts +52 -0
  31. package/dist/lib/preflight-adapter.d.ts.map +1 -0
  32. package/dist/lib/preflight-adapter.js +224 -0
  33. package/dist/lib/preflight-adapter.js.map +1 -0
  34. package/dist/lib/transitive-resolver.d.ts +121 -0
  35. package/dist/lib/transitive-resolver.d.ts.map +1 -1
  36. package/dist/lib/transitive-resolver.js +190 -0
  37. package/dist/lib/transitive-resolver.js.map +1 -1
  38. package/node_modules/@gitdot/clone-lib/README.md +117 -0
  39. package/node_modules/@gitdot/clone-lib/dist/bin/gitdot-resolve.d.ts +9 -0
  40. package/node_modules/@gitdot/clone-lib/dist/bin/gitdot-resolve.d.ts.map +1 -0
  41. package/node_modules/@gitdot/clone-lib/dist/bin/gitdot-resolve.js +154 -0
  42. package/node_modules/@gitdot/clone-lib/dist/bin/gitdot-resolve.js.map +1 -0
  43. package/node_modules/@gitdot/clone-lib/dist/clone.d.ts +21 -0
  44. package/node_modules/@gitdot/clone-lib/dist/clone.d.ts.map +1 -0
  45. package/node_modules/@gitdot/clone-lib/dist/clone.js +228 -0
  46. package/node_modules/@gitdot/clone-lib/dist/clone.js.map +1 -0
  47. package/node_modules/@gitdot/clone-lib/dist/dotpath.d.ts +10 -0
  48. package/node_modules/@gitdot/clone-lib/dist/dotpath.d.ts.map +1 -0
  49. package/node_modules/@gitdot/clone-lib/dist/dotpath.js +27 -0
  50. package/node_modules/@gitdot/clone-lib/dist/dotpath.js.map +1 -0
  51. package/node_modules/@gitdot/clone-lib/dist/git.d.ts +23 -0
  52. package/node_modules/@gitdot/clone-lib/dist/git.d.ts.map +1 -0
  53. package/node_modules/@gitdot/clone-lib/dist/git.js +134 -0
  54. package/node_modules/@gitdot/clone-lib/dist/git.js.map +1 -0
  55. package/node_modules/@gitdot/clone-lib/dist/index.d.ts +17 -0
  56. package/node_modules/@gitdot/clone-lib/dist/index.d.ts.map +1 -0
  57. package/node_modules/@gitdot/clone-lib/dist/index.js +35 -0
  58. package/node_modules/@gitdot/clone-lib/dist/index.js.map +1 -0
  59. package/node_modules/@gitdot/clone-lib/dist/lock.d.ts +24 -0
  60. package/node_modules/@gitdot/clone-lib/dist/lock.d.ts.map +1 -0
  61. package/node_modules/@gitdot/clone-lib/dist/lock.js +97 -0
  62. package/node_modules/@gitdot/clone-lib/dist/lock.js.map +1 -0
  63. package/node_modules/@gitdot/clone-lib/dist/resolve/gitlab.d.ts +15 -0
  64. package/node_modules/@gitdot/clone-lib/dist/resolve/gitlab.d.ts.map +1 -0
  65. package/node_modules/@gitdot/clone-lib/dist/resolve/gitlab.js +124 -0
  66. package/node_modules/@gitdot/clone-lib/dist/resolve/gitlab.js.map +1 -0
  67. package/node_modules/@gitdot/clone-lib/dist/resolve/index.d.ts +12 -0
  68. package/node_modules/@gitdot/clone-lib/dist/resolve/index.d.ts.map +1 -0
  69. package/node_modules/@gitdot/clone-lib/dist/resolve/index.js +31 -0
  70. package/node_modules/@gitdot/clone-lib/dist/resolve/index.js.map +1 -0
  71. package/node_modules/@gitdot/clone-lib/dist/resolve/manifest.d.ts +32 -0
  72. package/node_modules/@gitdot/clone-lib/dist/resolve/manifest.d.ts.map +1 -0
  73. package/node_modules/@gitdot/clone-lib/dist/resolve/manifest.js +159 -0
  74. package/node_modules/@gitdot/clone-lib/dist/resolve/manifest.js.map +1 -0
  75. package/node_modules/@gitdot/clone-lib/dist/resolve/member.d.ts +44 -0
  76. package/node_modules/@gitdot/clone-lib/dist/resolve/member.d.ts.map +1 -0
  77. package/node_modules/@gitdot/clone-lib/dist/resolve/member.js +163 -0
  78. package/node_modules/@gitdot/clone-lib/dist/resolve/member.js.map +1 -0
  79. package/node_modules/@gitdot/clone-lib/dist/resolve/resolve.d.ts +18 -0
  80. package/node_modules/@gitdot/clone-lib/dist/resolve/resolve.d.ts.map +1 -0
  81. package/node_modules/@gitdot/clone-lib/dist/resolve/resolve.js +155 -0
  82. package/node_modules/@gitdot/clone-lib/dist/resolve/resolve.js.map +1 -0
  83. package/node_modules/@gitdot/clone-lib/dist/types.d.ts +225 -0
  84. package/node_modules/@gitdot/clone-lib/dist/types.d.ts.map +1 -0
  85. package/node_modules/@gitdot/clone-lib/dist/types.js +9 -0
  86. package/node_modules/@gitdot/clone-lib/dist/types.js.map +1 -0
  87. package/node_modules/@gitdot/clone-lib/package.json +53 -0
  88. package/node_modules/@microwiseai/install-preflight/dist/index.d.ts +27 -0
  89. package/node_modules/@microwiseai/install-preflight/dist/index.d.ts.map +1 -0
  90. package/node_modules/@microwiseai/install-preflight/dist/index.js +26 -0
  91. package/node_modules/@microwiseai/install-preflight/dist/index.js.map +1 -0
  92. package/node_modules/@microwiseai/install-preflight/dist/policy.d.ts +42 -0
  93. package/node_modules/@microwiseai/install-preflight/dist/policy.d.ts.map +1 -0
  94. package/node_modules/@microwiseai/install-preflight/dist/policy.js +79 -0
  95. package/node_modules/@microwiseai/install-preflight/dist/policy.js.map +1 -0
  96. package/node_modules/@microwiseai/install-preflight/dist/preflight.d.ts +18 -0
  97. package/node_modules/@microwiseai/install-preflight/dist/preflight.d.ts.map +1 -0
  98. package/node_modules/@microwiseai/install-preflight/dist/preflight.js +0 -0
  99. package/node_modules/@microwiseai/install-preflight/dist/preflight.js.map +1 -0
  100. package/node_modules/@microwiseai/install-preflight/dist/resolvers.d.ts +26 -0
  101. package/node_modules/@microwiseai/install-preflight/dist/resolvers.d.ts.map +1 -0
  102. package/node_modules/@microwiseai/install-preflight/dist/resolvers.js +63 -0
  103. package/node_modules/@microwiseai/install-preflight/dist/resolvers.js.map +1 -0
  104. package/node_modules/@microwiseai/install-preflight/dist/semver.d.ts +45 -0
  105. package/node_modules/@microwiseai/install-preflight/dist/semver.d.ts.map +1 -0
  106. package/node_modules/@microwiseai/install-preflight/dist/semver.js +195 -0
  107. package/node_modules/@microwiseai/install-preflight/dist/semver.js.map +1 -0
  108. package/node_modules/@microwiseai/install-preflight/dist/types.d.ts +136 -0
  109. package/node_modules/@microwiseai/install-preflight/dist/types.d.ts.map +1 -0
  110. package/node_modules/@microwiseai/install-preflight/dist/types.js +11 -0
  111. package/node_modules/@microwiseai/install-preflight/dist/types.js.map +1 -0
  112. package/node_modules/@microwiseai/install-preflight/package.json +49 -0
  113. package/package.json +12 -4
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Snapshot ↔ install-preflight adapter (thin).
3
+ *
4
+ * Maps a snapshot.json into the registry-agnostic preflight engine's inputs and
5
+ * runs the gate. The engine (@microwiseai/install-preflight) knows nothing about
6
+ * snapshots; all snapshot-specific knowledge lives here:
7
+ *
8
+ * • install groups (npm-proxy / glpkg / skit) + legacy packages/skits → channels
9
+ * + package requests, all probed ANONYMOUSLY (reproduces a first-time
10
+ * end-user with no token).
11
+ * • transitive closure discovery: uses the publisher's token to expand npm
12
+ * deps via the proxy, then hands the discovered nodes back to the engine to
13
+ * probe anonymously — so a private transitive dep (401 for end-users) is
14
+ * caught even though the publisher can see it.
15
+ * • [B] the snapshot's OWN version must be stable when promoted to `latest`.
16
+ *
17
+ * See architecture/decisions — this is the blocking preflight gate wired into
18
+ * `snapshot publish` and the `snapshot preflight` command.
19
+ */
20
+ import { preflight, formatReport, createNpmPackumentResolver, checkStableRelease, } from '@microwiseai/install-preflight';
21
+ import { REGISTRY_PROXY_URL, GITLAB_GROUP_ID, getLicenseKey, getProxyAuthToken } from './config.js';
22
+ import { resolveDepsFromLicenseAPI, isDistkitClosureEnabled } from './transitive-resolver.js';
23
+ /** Installer groups whose members resolve as npm-style packages through the proxy. */
24
+ const NPM_LIKE_GROUPS = new Set(['npm-proxy', 'glpkg', 'gitlab-install', 'skit']);
25
+ /** Extract the `@scope` prefix of a package name, or null. */
26
+ function scopeOf(name) {
27
+ return name.startsWith('@') && name.includes('/') ? name.split('/')[0] : null;
28
+ }
29
+ /** True for names that legacy `packages`/`skits` maps treat as skits. */
30
+ function isSkitName(name) {
31
+ return name.endsWith('-kit') || name.endsWith('kit');
32
+ }
33
+ /**
34
+ * Build one anonymous channel per installer lane actually used by the snapshot.
35
+ * All lanes hit the same registry-proxy packument endpoint (`GET /{name}`),
36
+ * differing only by id/scope for reporting.
37
+ */
38
+ function buildChannels(scopes) {
39
+ const base = {
40
+ registryUrl: REGISTRY_PROXY_URL,
41
+ auth: { kind: 'anonymous' },
42
+ strategy: 'npm-packument',
43
+ scopes,
44
+ groupId: GITLAB_GROUP_ID,
45
+ };
46
+ return [
47
+ { id: 'npm-proxy', ...base },
48
+ { id: 'glpkg', ...base },
49
+ { id: 'skit', ...base },
50
+ ];
51
+ }
52
+ /** Collect the DIRECT pins declared by a snapshot into engine requests. */
53
+ function collectDirectRequests(snapshot) {
54
+ const requests = [];
55
+ const push = (channel, name, range) => {
56
+ requests.push({ name, range, channel });
57
+ };
58
+ // New installer-based structure.
59
+ if (snapshot.install) {
60
+ for (const [installer, pkgs] of Object.entries(snapshot.install)) {
61
+ const channel = installer === 'gitlab-install' ? 'glpkg' : installer;
62
+ for (const [name, version] of Object.entries(pkgs)) {
63
+ push(channel === 'npm-proxy' || channel === 'glpkg' || channel === 'skit' ? channel : 'npm-proxy', name, version);
64
+ }
65
+ }
66
+ }
67
+ // Legacy maps.
68
+ if (snapshot.packages) {
69
+ for (const [name, version] of Object.entries(snapshot.packages)) {
70
+ push(isSkitName(name) ? 'skit' : 'npm-proxy', name, version);
71
+ }
72
+ }
73
+ if (snapshot.skits) {
74
+ for (const [name, version] of Object.entries(snapshot.skits)) {
75
+ push('skit', name, version);
76
+ }
77
+ }
78
+ return requests;
79
+ }
80
+ /** Scopes declared by the snapshot's registry block (fallback to pins' scopes). */
81
+ function collectScopes(snapshot, requests) {
82
+ const scopes = new Set();
83
+ if (snapshot.registry) {
84
+ for (const scope of Object.keys(snapshot.registry))
85
+ scopes.add(scope);
86
+ }
87
+ if (scopes.size === 0) {
88
+ for (const r of requests) {
89
+ const s = scopeOf(r.name);
90
+ if (s)
91
+ scopes.add(s);
92
+ }
93
+ }
94
+ return Array.from(scopes);
95
+ }
96
+ /**
97
+ * Discover transitive npm deps via the proxy (token-authenticated), returning
98
+ * extra requests to probe ANONYMOUSLY. Failure is non-fatal: it returns a
99
+ * warning so coverage gaps are surfaced, never silently dropped.
100
+ */
101
+ async function discoverTransitive(direct, scopes) {
102
+ const token = getLicenseKey() || getProxyAuthToken();
103
+ if (!token) {
104
+ return {
105
+ requests: [],
106
+ warning: 'Transitive-closure discovery skipped: no token available (login for full coverage). ' +
107
+ 'Only directly-declared pins were checked.',
108
+ };
109
+ }
110
+ // Expand npm/glpkg-lane pins within tracked scopes.
111
+ const npmDirect = direct.filter((r) => (r.channel === 'npm-proxy' || r.channel === 'glpkg') && scopes.some((s) => r.name.startsWith(s)));
112
+ if (npmDirect.length === 0 || scopes.length === 0)
113
+ return { requests: [] };
114
+ // ── §5-step6 CUTOVER SWITCH (behind SNAPSHOT_DISTKIT_CLOSURE) ──────────────
115
+ // flag ON: resolve the transitive closure CLIENT-SIDE via distkit walkClosure
116
+ // (subsumes /resolve-deps — §3d). PREFLIGHT probes the PRIVATE lane (a private
117
+ // transitive dep that 401s anonymously is the risk this gate exists for; public
118
+ // deps are npmjs-anonymous-trivial). §1.4 fail-loud: a resolver error propagates
119
+ // (NOT swallowed into a warning) — a partial closure would be a wrong gate.
120
+ // The full public-inclusive closure/lock is produced separately by
121
+ // resolveSnapshotToLock; it is not what the anonymous-probe gate needs.
122
+ if (isDistkitClosureEnabled()) {
123
+ // DYNAMIC import: the distkit bridge is loaded ONLY on the flag-ON path, so
124
+ // flag-OFF (default) has NO load-time dependency on distkit — 100% reversible
125
+ // and shippable even while distkit is unpublished/unlinked.
126
+ const { resolveTransitiveClosureFromPins } = await import('./distkit-closure-bridge.js');
127
+ const closure = await resolveTransitiveClosureFromPins(npmDirect.map((r) => ({ name: r.name, version: r.range })), scopes);
128
+ const directNames = new Set(direct.map((r) => `${r.channel}:${r.name}`));
129
+ const requests = [];
130
+ for (const node of closure) {
131
+ if (!scopes.some((s) => node.name.startsWith(s)))
132
+ continue; // private lane only (preflight)
133
+ if (directNames.has(`npm-proxy:${node.name}`) || directNames.has(`glpkg:${node.name}`))
134
+ continue;
135
+ requests.push({
136
+ name: node.name,
137
+ range: node.version,
138
+ channel: 'npm-proxy',
139
+ requestedBy: node.requestedBy.join(', ') || '(transitive closure)',
140
+ });
141
+ }
142
+ return { requests };
143
+ }
144
+ // flag OFF (default): legacy /resolve-deps path — COMPLETELY UNCHANGED.
145
+ try {
146
+ const resolved = await resolveDepsFromLicenseAPI({
147
+ packages: npmDirect.map((r) => `${r.name}@${r.range}`),
148
+ groupId: GITLAB_GROUP_ID,
149
+ scopes,
150
+ includePeer: true,
151
+ });
152
+ const directNames = new Set(direct.map((r) => `${r.channel}:${r.name}`));
153
+ const requests = [];
154
+ for (const [name, version] of Object.entries(resolved.dependencies)) {
155
+ if (directNames.has(`npm-proxy:${name}`) || directNames.has(`glpkg:${name}`))
156
+ continue;
157
+ requests.push({
158
+ name,
159
+ range: version,
160
+ channel: 'npm-proxy',
161
+ requestedBy: '(transitive closure)',
162
+ });
163
+ }
164
+ for (const [name, version] of Object.entries(resolved.peerDependencies ?? {})) {
165
+ if (requests.some((r) => r.name === name) || directNames.has(`npm-proxy:${name}`))
166
+ continue;
167
+ requests.push({ name, range: version, channel: 'npm-proxy', requestedBy: '(peer dependency)' });
168
+ }
169
+ return { requests };
170
+ }
171
+ catch (err) {
172
+ return {
173
+ requests: [],
174
+ warning: `Transitive-closure discovery failed (${err instanceof Error ? err.message : String(err)}). ` +
175
+ 'Only directly-declared pins were checked — transitive private/unpublished deps may be missed.',
176
+ };
177
+ }
178
+ }
179
+ /**
180
+ * Build the full engine input for a snapshot: anonymous channels + direct pins
181
+ * (+ discovered transitive closure). Exposed for testing/other callers.
182
+ */
183
+ export async function buildSnapshotPreflightInput(snapshot, options = {}) {
184
+ const { includeTransitive = true, distTag = 'latest' } = options;
185
+ const warnings = [];
186
+ const direct = collectDirectRequests(snapshot);
187
+ const scopes = collectScopes(snapshot, direct);
188
+ let packages = direct;
189
+ if (includeTransitive) {
190
+ const { requests, warning } = await discoverTransitive(direct, scopes);
191
+ if (warning)
192
+ warnings.push(warning);
193
+ packages = [...direct, ...requests];
194
+ }
195
+ const input = {
196
+ channels: buildChannels(scopes),
197
+ packages,
198
+ policy: { distTag, requireStableForTags: ['latest'], forbidPrereleaseDefaultResolve: true },
199
+ resolver: options.resolver,
200
+ };
201
+ return { input, warnings };
202
+ }
203
+ /**
204
+ * Run the blocking preflight gate for a snapshot. Combines:
205
+ * [A] anonymous resolvability of the whole closure (engine), and
206
+ * [B] the snapshot's own version must be stable when promoted to `latest`.
207
+ */
208
+ export async function runSnapshotPreflight(snapshot, options = {}) {
209
+ const distTag = options.distTag ?? 'latest';
210
+ const { input, warnings } = await buildSnapshotPreflightInput(snapshot, options);
211
+ options.log?.(`Preflight: probing ${input.packages.length} package(s) anonymously across ${input.channels.length} channel(s)...`);
212
+ const report = await preflight(input);
213
+ // [B] (b1): the snapshot itself must be a stable release when → latest.
214
+ const selfFinding = snapshot.version
215
+ ? checkStableRelease(snapshot.version, { package: snapshot.name, channel: 'snapshot', requested: snapshot.version }, { distTag, requireStableForTags: ['latest'] })
216
+ : null;
217
+ if (selfFinding) {
218
+ report.findings.unshift(selfFinding);
219
+ report.ok = false;
220
+ }
221
+ return { report, warnings };
222
+ }
223
+ export { formatReport, createNpmPackumentResolver };
224
+ //# sourceMappingURL=preflight-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preflight-adapter.js","sourceRoot":"","sources":["../../src/lib/preflight-adapter.ts"],"names":[],"mappings":"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"}
@@ -43,6 +43,49 @@ export interface LicenseApiResolveDepsResponse {
43
43
  dependencies: Record<string, string>;
44
44
  peerDependencies?: Record<string, string>;
45
45
  }
46
+ /** distkit-schema `Ecosystem` (opened union). Mirror. */
47
+ export type Ecosystem = 'npm' | 'pypi' | (string & {});
48
+ /** distkit-schema `Installer` (opened union). Mirror. */
49
+ export type Installer = 'npm' | 'glpkg' | 'skit' | 'pip' | (string & {});
50
+ /** distkit-schema `InstallTarget` (closed union). Mirror. */
51
+ export type InstallTarget = 'cli-global' | 'project-local';
52
+ /** distkit-schema `AccessTier` (closed union). Mirror. */
53
+ export type AccessTier = 'public' | 'authenticated' | 'licensed' | 'restricted';
54
+ /**
55
+ * The `package.json`-shaped manifest the distkit npm adapter's
56
+ * `parseDependencies` consumes (`adapters/npm.ts` `PackumentVersion`). Only the
57
+ * four dependency maps are meaningful to the adapter; everything else is ignored.
58
+ * This is what a ClosureRoot in the `'npm'` lane carries as its `manifest`.
59
+ */
60
+ export interface NpmPackageJsonManifest {
61
+ dependencies?: Record<string, string>;
62
+ optionalDependencies?: Record<string, string>;
63
+ devDependencies?: Record<string, string>;
64
+ peerDependencies?: Record<string, string>;
65
+ }
66
+ /**
67
+ * Mirror of distkit `ClosureRoot` (closure.ts:57): one already-pinned entry
68
+ * package whose `manifest` declares the first level of dependencies distkit's
69
+ * walker will expand transitively. `manifest` is `unknown` in the contract (the
70
+ * adapter knows its own shape); for the npm lane we populate it with an
71
+ * {@link NpmPackageJsonManifest}.
72
+ */
73
+ export interface ClosureRoot {
74
+ /** package name, e.g. "@microwiseai/foo". */
75
+ name: string;
76
+ /** exact version of the root (already pinned). */
77
+ version: string;
78
+ /** ecosystem of the root; omitted ⇒ the matching adapter's ecosystem (C4). */
79
+ ecosystem?: Ecosystem;
80
+ /** the root's manifest, fed to `EcosystemAdapter.parseDependencies`. */
81
+ manifest: unknown;
82
+ /** installer to record for produced entries (else the adapter's default). */
83
+ installer?: Installer;
84
+ /** intended install location for produced entries. */
85
+ installTarget?: InstallTarget;
86
+ /** observed access tier for produced entries (authority = license-mgr). */
87
+ accessTier?: AccessTier;
88
+ }
46
89
  export interface ResolveOptions {
47
90
  /** proxy를 통해 transitive deps 해석 */
48
91
  resolveTransitive?: boolean;
@@ -82,6 +125,84 @@ export interface ResolveDepsFromLicenseOptions {
82
125
  * // result.peerDependencies: { "typescript": "^5.0.0" }
83
126
  */
84
127
  export declare function resolveDepsFromLicenseAPI(options: ResolveDepsFromLicenseOptions): Promise<LicenseApiResolveDepsResponse>;
128
+ /**
129
+ * Feature-flag gate for the new distkit closure path (§1.2 wiring target).
130
+ *
131
+ * OFF by default. Defined now so the future §1.2 caller has a single, documented
132
+ * switch; the collector itself is a pure additive export that no live path calls,
133
+ * so flipping this on has NO effect until §1.2 wires `walkClosure` behind it.
134
+ *
135
+ * Env: `SNAPSHOT_DISTKIT_CLOSURE=1` (or `true`).
136
+ */
137
+ export declare const SNAPSHOT_DISTKIT_CLOSURE_FLAG: "SNAPSHOT_DISTKIT_CLOSURE";
138
+ /** True iff the distkit closure path is enabled via {@link SNAPSHOT_DISTKIT_CLOSURE_FLAG}. */
139
+ export declare function isDistkitClosureEnabled(): boolean;
140
+ /** Options for {@link collectNpmClosureRoots}. */
141
+ export interface CollectClosureRootsOptions {
142
+ /**
143
+ * Restrict roots to npm packages whose name starts with one of these scopes.
144
+ * Omitted ⇒ ALL declared npm packages become roots (recommended: distkit's
145
+ * walker expands each into its own transitive closure).
146
+ */
147
+ scopes?: string[];
148
+ /** `installTarget` hint stamped on every produced root. Default `'cli-global'`. */
149
+ installTarget?: InstallTarget;
150
+ }
151
+ /** Result of {@link collectNpmClosureRoots}. */
152
+ export interface NpmClosureRootsResult {
153
+ /** one {@link ClosureRoot} per directly-declared npm entry package (ecosystem `'npm'`). */
154
+ roots: ClosureRoot[];
155
+ /** domain-walk + manifest-fetch failures (fail-soft at this pre-wiring stage). */
156
+ errors: Array<{
157
+ name: string;
158
+ error: string;
159
+ }>;
160
+ /** scope → groupId map collected from the snapshot `registry` fields (§1.3 routing feed). */
161
+ scopeGroups: Record<string, string>;
162
+ }
163
+ /**
164
+ * Phase-2b §1.1 collector: walk the snapshot/skit domain graph and emit the npm
165
+ * lane as `ClosureRoot[]` for distkit's `walkClosure`.
166
+ *
167
+ * Reuses `traverseSnapshot` (the unchanged domain-graph walk: `extends`, `skits`,
168
+ * `install`, `packages`, `registry`, and skit.json `dependencies.{npm,skit,cli}`)
169
+ * to discover the directly-declared npm packages, then fetches each one's
170
+ * `package.json`-shaped manifest and maps it to a {@link ClosureRoot}:
171
+ *
172
+ * { name, version, ecosystem: 'npm', manifest, installTarget }
173
+ *
174
+ * NOTE (pre-wiring, fail-soft): a package whose manifest cannot be fetched is
175
+ * still emitted (with an empty `{}` manifest) and an error is recorded — so a
176
+ * parity fixture surfaces the gap. Authoritative fail-loud + range→exact version
177
+ * resolution move in with distkit's adapter at §1.2 / §1.4.
178
+ *
179
+ * This function is on NO live install path — it is the §1.1 deliverable only.
180
+ */
181
+ export declare function collectNpmClosureRoots(snapshotName: string, options?: CollectClosureRootsOptions): Promise<NpmClosureRootsResult>;
182
+ /**
183
+ * Build `ClosureRoot[]` from an explicit list of npm pins (name + exact version),
184
+ * fetching each pin's `package.json`-shaped manifest from the registry-proxy
185
+ * packument. Extracted from {@link collectNpmClosureRoots} (behaviour-identical)
186
+ * so the §5-step6 install-resolution switch can build roots from the pins the
187
+ * preflight adapter already computed (WITHOUT re-walking the snapshot graph —
188
+ * important during `snapshot publish`, where the snapshot is LOCAL/unpublished).
189
+ *
190
+ * Deterministic (sorted by name). A pin whose manifest cannot be fetched is still
191
+ * emitted (empty `{}` manifest) AND recorded in `errors` — the caller decides
192
+ * fail-soft (collector §1.1) vs fail-loud (install path §1.4).
193
+ */
194
+ export declare function buildNpmClosureRoots(pins: ReadonlyArray<{
195
+ name: string;
196
+ version: string;
197
+ }>, options?: {
198
+ installTarget?: InstallTarget;
199
+ }): Promise<{
200
+ roots: ClosureRoot[];
201
+ errors: Array<{
202
+ name: string;
203
+ error: string;
204
+ }>;
205
+ }>;
85
206
  /**
86
207
  * 캐시 클리어
87
208
  */
@@ -1 +1 @@
1
- {"version":3,"file":"transitive-resolver.d.ts","sourceRoot":"","sources":["../../src/lib/transitive-resolver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE;QACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9B,GAAG,CAAC,EAAE,KAAK,CAAC;YACV,IAAI,EAAE,MAAM,CAAC;YACb,OAAO,EAAE,MAAM,CAAC;SACjB,CAAC,CAAC;KACJ,CAAC;CACH;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,YAAY,CAAC;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,0BAA0B;IACzC,uCAAuC;IACvC,GAAG,EAAE,eAAe,EAAE,CAAC;IACvB,sBAAsB;IACtB,IAAI,EAAE,eAAe,EAAE,CAAC;IACxB,kBAAkB;IAClB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,kDAAkD;IAClD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAYD;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AAmWD,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,sBAAsB;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,0BAA0B,CAAC,CAqDrC;AAMD,MAAM,WAAW,6BAA6B;IAC5C,iEAAiE;IACjE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,6BAA6B,CAAC,CAiGxC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
1
+ {"version":3,"file":"transitive-resolver.d.ts","sourceRoot":"","sources":["../../src/lib/transitive-resolver.ts"],"names":[],"mappings":"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"}
@@ -427,10 +427,200 @@ export async function resolveDepsFromLicenseAPI(options) {
427
427
  throw new Error(`[resolveDepsFromLicenseAPI] Network error: ${error instanceof Error ? error.message : String(error)}`);
428
428
  }
429
429
  }
430
+ // ============================================================
431
+ // Phase-2b §1.1 — ClosureRoot[] collector (distkit npm lane)
432
+ // ============================================================
433
+ //
434
+ // NEW PATH — behind a flag, called by NOBODY on the live install path yet.
435
+ //
436
+ // Scope (SSOT §1.1, §5 step 3): KEEP snapshot's snapshot/skit domain-graph walk
437
+ // (`traverseSnapshot`/`traverseSkit`) exactly as-is; only change the OUTPUT
438
+ // SHAPE. This collector reuses that walk (via a fresh TraversalContext, same as
439
+ // `resolveAllDependencies`) to discover the directly-declared npm entry packages,
440
+ // then emits one {@link ClosureRoot} per package for distkit's `walkClosure`.
441
+ //
442
+ // Explicitly OUT OF SCOPE here (later phases / sign-off gate):
443
+ // • §1.2 wiring distkit `walkClosure` / lock emit / cutover.
444
+ // • porting a cycle guard or first-writer dedup into this path — distkit's
445
+ // walker OWNS transitive cycle-safety + multi-parent dedup (§1.1 note). The
446
+ // `visited*` Sets used inside `traverseSnapshot`/`traverseSkit` are the
447
+ // snapshot DOMAIN-graph guard (extends/skit recursion) and stay on the
448
+ // legacy path only; they are NOT re-implemented for the npm closure here.
449
+ // • skit / glpkg lanes (§4 Phase-2c) — this collector is the npm lane only.
450
+ /**
451
+ * Feature-flag gate for the new distkit closure path (§1.2 wiring target).
452
+ *
453
+ * OFF by default. Defined now so the future §1.2 caller has a single, documented
454
+ * switch; the collector itself is a pure additive export that no live path calls,
455
+ * so flipping this on has NO effect until §1.2 wires `walkClosure` behind it.
456
+ *
457
+ * Env: `SNAPSHOT_DISTKIT_CLOSURE=1` (or `true`).
458
+ */
459
+ export const SNAPSHOT_DISTKIT_CLOSURE_FLAG = 'SNAPSHOT_DISTKIT_CLOSURE';
460
+ /** True iff the distkit closure path is enabled via {@link SNAPSHOT_DISTKIT_CLOSURE_FLAG}. */
461
+ export function isDistkitClosureEnabled() {
462
+ const v = process.env[SNAPSHOT_DISTKIT_CLOSURE_FLAG];
463
+ return v === '1' || v === 'true';
464
+ }
465
+ /**
466
+ * Cache of fetched npm root manifests (package.json-shaped), keyed `name@version`.
467
+ * Separate from {@link skitManifestCache} (that reads the packument `skit` field;
468
+ * this reads the standard npm dependency maps).
469
+ */
470
+ const npmRootManifestCache = new Map();
471
+ /**
472
+ * Fetch an npm root's `package.json`-shaped manifest from the registry-proxy
473
+ * packument (`GET {REGISTRY_PROXY_URL}/{name}` → `{ 'dist-tags', versions }`).
474
+ *
475
+ * This is the npm analogue of {@link fetchSkitManifest}: same packument source,
476
+ * but it reads the standard npm dependency maps
477
+ * (`dependencies`/`optionalDependencies`/`devDependencies`/`peerDependencies`)
478
+ * that the distkit npm adapter's `parseDependencies` expects — NOT the `skit`
479
+ * field. Resolves the `latest` dist-tag; other specs are looked up as exact keys.
480
+ *
481
+ * @returns the manifest + the exact version it resolved to, or `null` if the
482
+ * package / version is not present (surfaced by the collector as an error;
483
+ * authoritative range→exact resolution is distkit's adapter job at §1.2).
484
+ */
485
+ async function fetchNpmRootManifest(pkgName, version) {
486
+ const cacheKey = `${pkgName}@${version}`;
487
+ const cached = npmRootManifestCache.get(cacheKey);
488
+ if (cached) {
489
+ return cached;
490
+ }
491
+ const sessionToken = getLicenseKey();
492
+ const headers = {
493
+ 'Accept': 'application/json',
494
+ };
495
+ if (sessionToken) {
496
+ headers['Authorization'] = `Bearer ${sessionToken}`;
497
+ }
498
+ try {
499
+ const url = `${REGISTRY_PROXY_URL}/${pkgName}`;
500
+ const response = await fetch(url, { headers });
501
+ if (!response.ok) {
502
+ return null;
503
+ }
504
+ const data = await response.json();
505
+ const distTags = data['dist-tags'];
506
+ const versions = data['versions'];
507
+ // Resolve the `latest` dist-tag; otherwise treat `version` as an exact key.
508
+ // (Range specs are NOT resolved here — distkit's adapter owns range→exact at
509
+ // §1.2; an unresolvable spec yields null and a recorded collector error.)
510
+ let targetVersion = version;
511
+ if ((version === 'latest' || version === '') && distTags?.['latest']) {
512
+ targetVersion = distTags['latest'];
513
+ }
514
+ const versionData = versions?.[targetVersion];
515
+ if (!versionData) {
516
+ return null;
517
+ }
518
+ const manifest = {};
519
+ const deps = versionData['dependencies'];
520
+ const optional = versionData['optionalDependencies'];
521
+ const dev = versionData['devDependencies'];
522
+ const peer = versionData['peerDependencies'];
523
+ if (deps)
524
+ manifest.dependencies = { ...deps };
525
+ if (optional)
526
+ manifest.optionalDependencies = { ...optional };
527
+ if (dev)
528
+ manifest.devDependencies = { ...dev };
529
+ if (peer)
530
+ manifest.peerDependencies = { ...peer };
531
+ const result = { manifest, resolvedVersion: targetVersion };
532
+ npmRootManifestCache.set(cacheKey, result);
533
+ return result;
534
+ }
535
+ catch {
536
+ return null;
537
+ }
538
+ }
539
+ /**
540
+ * Phase-2b §1.1 collector: walk the snapshot/skit domain graph and emit the npm
541
+ * lane as `ClosureRoot[]` for distkit's `walkClosure`.
542
+ *
543
+ * Reuses `traverseSnapshot` (the unchanged domain-graph walk: `extends`, `skits`,
544
+ * `install`, `packages`, `registry`, and skit.json `dependencies.{npm,skit,cli}`)
545
+ * to discover the directly-declared npm packages, then fetches each one's
546
+ * `package.json`-shaped manifest and maps it to a {@link ClosureRoot}:
547
+ *
548
+ * { name, version, ecosystem: 'npm', manifest, installTarget }
549
+ *
550
+ * NOTE (pre-wiring, fail-soft): a package whose manifest cannot be fetched is
551
+ * still emitted (with an empty `{}` manifest) and an error is recorded — so a
552
+ * parity fixture surfaces the gap. Authoritative fail-loud + range→exact version
553
+ * resolution move in with distkit's adapter at §1.2 / §1.4.
554
+ *
555
+ * This function is on NO live install path — it is the §1.1 deliverable only.
556
+ */
557
+ export async function collectNpmClosureRoots(snapshotName, options = {}) {
558
+ const { scopes, installTarget = 'cli-global' } = options;
559
+ // 1. Reuse the unchanged snapshot/skit domain-graph walk (same ctx shape as
560
+ // resolveAllDependencies) to collect the directly-declared npm packages.
561
+ const ctx = {
562
+ visitedSnapshots: new Set(),
563
+ visitedSkits: new Set(),
564
+ collectedNpm: new Map(),
565
+ collectedSkit: new Map(),
566
+ errors: [],
567
+ scopeGroups: new Map(),
568
+ };
569
+ await traverseSnapshot(snapshotName, ctx);
570
+ // 2. Select npm entry packages → optionally filter by scope.
571
+ let entries = Array.from(ctx.collectedNpm.values());
572
+ if (scopes && scopes.length > 0) {
573
+ entries = entries.filter(p => scopes.some(scope => p.name.startsWith(scope)));
574
+ }
575
+ // 3. Fetch each root's package.json-shaped manifest and map → ClosureRoot[].
576
+ const { roots, errors: rootErrors } = await buildNpmClosureRoots(entries, { installTarget });
577
+ return {
578
+ roots,
579
+ errors: [...ctx.errors, ...rootErrors],
580
+ scopeGroups: Object.fromEntries(ctx.scopeGroups),
581
+ };
582
+ }
583
+ /**
584
+ * Build `ClosureRoot[]` from an explicit list of npm pins (name + exact version),
585
+ * fetching each pin's `package.json`-shaped manifest from the registry-proxy
586
+ * packument. Extracted from {@link collectNpmClosureRoots} (behaviour-identical)
587
+ * so the §5-step6 install-resolution switch can build roots from the pins the
588
+ * preflight adapter already computed (WITHOUT re-walking the snapshot graph —
589
+ * important during `snapshot publish`, where the snapshot is LOCAL/unpublished).
590
+ *
591
+ * Deterministic (sorted by name). A pin whose manifest cannot be fetched is still
592
+ * emitted (empty `{}` manifest) AND recorded in `errors` — the caller decides
593
+ * fail-soft (collector §1.1) vs fail-loud (install path §1.4).
594
+ */
595
+ export async function buildNpmClosureRoots(pins, options = {}) {
596
+ const { installTarget = 'cli-global' } = options;
597
+ const errors = [];
598
+ const roots = [];
599
+ for (const pkg of pins) {
600
+ const fetched = await fetchNpmRootManifest(pkg.name, pkg.version);
601
+ if (!fetched) {
602
+ errors.push({
603
+ name: `${pkg.name}@${pkg.version}`,
604
+ error: 'Failed to fetch npm root manifest (package/version not in packument, or non-exact spec)',
605
+ });
606
+ }
607
+ roots.push({
608
+ name: pkg.name,
609
+ version: fetched?.resolvedVersion ?? pkg.version,
610
+ ecosystem: 'npm',
611
+ manifest: fetched?.manifest ?? {},
612
+ installTarget,
613
+ });
614
+ }
615
+ // Deterministic order (parity-friendly; distkit re-sorts internally anyway).
616
+ roots.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
617
+ return { roots, errors };
618
+ }
430
619
  /**
431
620
  * 캐시 클리어
432
621
  */
433
622
  export function clearTransitiveCache() {
434
623
  skitManifestCache.clear();
624
+ npmRootManifestCache.clear();
435
625
  }
436
626
  //# sourceMappingURL=transitive-resolver.js.map