@microwiseai/snapshot 0.8.0 → 0.9.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.
- package/dist/build-info.json +1 -0
- package/dist/commands/access.d.ts +25 -9
- package/dist/commands/access.d.ts.map +1 -1
- package/dist/commands/access.js +101 -47
- package/dist/commands/access.js.map +1 -1
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +37 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/install.d.ts +54 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +480 -65
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/publish.d.ts +10 -0
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +94 -12
- package/dist/commands/publish.js.map +1 -1
- package/dist/index.js +45 -8
- package/dist/index.js.map +1 -1
- package/dist/lib/access-index.d.ts +81 -0
- package/dist/lib/access-index.d.ts.map +1 -0
- package/dist/lib/access-index.js +175 -0
- package/dist/lib/access-index.js.map +1 -0
- package/dist/lib/access-sync.d.ts +66 -17
- package/dist/lib/access-sync.d.ts.map +1 -1
- package/dist/lib/access-sync.js +391 -217
- package/dist/lib/access-sync.js.map +1 -1
- package/dist/lib/extends-access.d.ts +34 -0
- package/dist/lib/extends-access.d.ts.map +1 -0
- package/dist/lib/extends-access.js +82 -0
- package/dist/lib/extends-access.js.map +1 -0
- package/dist/lib/gitlab-publisher.d.ts +70 -0
- package/dist/lib/gitlab-publisher.d.ts.map +1 -0
- package/dist/lib/gitlab-publisher.js +165 -0
- package/dist/lib/gitlab-publisher.js.map +1 -0
- package/dist/lib/gitlab.d.ts +4 -0
- package/dist/lib/gitlab.d.ts.map +1 -1
- package/dist/lib/gitlab.js +1 -1
- package/dist/lib/gitlab.js.map +1 -1
- package/dist/lib/grant.d.ts +157 -0
- package/dist/lib/grant.d.ts.map +1 -0
- package/dist/lib/grant.js +352 -0
- package/dist/lib/grant.js.map +1 -0
- package/dist/lib/install-verify.d.ts +16 -2
- package/dist/lib/install-verify.d.ts.map +1 -1
- package/dist/lib/install-verify.js +24 -3
- package/dist/lib/install-verify.js.map +1 -1
- package/dist/lib/ledger.d.ts +13 -0
- package/dist/lib/ledger.d.ts.map +1 -1
- package/dist/lib/ledger.js.map +1 -1
- package/dist/lib/prerequisites.d.ts.map +1 -1
- package/dist/lib/prerequisites.js +4 -1
- package/dist/lib/prerequisites.js.map +1 -1
- package/dist/lib/proxy-auth-globalconfig.d.ts +55 -0
- package/dist/lib/proxy-auth-globalconfig.d.ts.map +1 -0
- package/dist/lib/proxy-auth-globalconfig.js +110 -0
- package/dist/lib/proxy-auth-globalconfig.js.map +1 -0
- package/dist/lib/semver-range.d.ts +32 -0
- package/dist/lib/semver-range.d.ts.map +1 -0
- package/dist/lib/semver-range.js +243 -0
- package/dist/lib/semver-range.js.map +1 -0
- package/dist/lib/session.d.ts +5 -0
- package/dist/lib/session.d.ts.map +1 -1
- package/dist/lib/session.js +9 -0
- package/dist/lib/session.js.map +1 -1
- package/dist/lib/skit-adapter.d.ts.map +1 -1
- package/dist/lib/skit-adapter.js +26 -3
- package/dist/lib/skit-adapter.js.map +1 -1
- package/dist/lib/timing.d.ts +7 -0
- package/dist/lib/timing.d.ts.map +1 -0
- package/dist/lib/timing.js +14 -0
- package/dist/lib/timing.js.map +1 -0
- package/dist/lib/types.d.ts +3 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/command-specs.d.ts +25 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/command-specs.d.ts.map +1 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/command-specs.js +55 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/command-specs.js.map +1 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/config.d.ts +52 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/config.d.ts.map +1 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/config.js +62 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/config.js.map +1 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/detect.d.ts +30 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/detect.d.ts.map +1 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/detect.js +39 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/detect.js.map +1 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/index.d.ts +35 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/index.d.ts.map +1 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/index.js +31 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/index.js.map +1 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/policy.d.ts +42 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/policy.d.ts.map +1 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/policy.js +36 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/policy.js.map +1 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/report.d.ts +11 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/report.d.ts.map +1 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/report.js +46 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/report.js.map +1 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/semver.d.ts +11 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/semver.d.ts.map +1 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/semver.js +81 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/semver.js.map +1 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/types.d.ts +29 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/types.d.ts.map +1 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/types.js +6 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/dist/types.js.map +1 -0
- package/node_modules/@microwiseai/snapshot-downgrade-guard/package.json +55 -0
- package/package.json +5 -2
- package/dist/lib/transitive-resolver.d.ts +0 -89
- package/dist/lib/transitive-resolver.d.ts.map +0 -1
- package/dist/lib/transitive-resolver.js +0 -447
- package/dist/lib/transitive-resolver.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skit-adapter.d.ts","sourceRoot":"","sources":["../../src/lib/skit-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"skit-adapter.d.ts","sourceRoot":"","sources":["../../src/lib/skit-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAeH,MAAM,WAAW,kBAAkB;IACjC,wBAAwB;IACxB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,sCAAsC;IACtC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA8DD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAGzC;AA0FD;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CAY5B;AA2FD;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC,CAG3D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAO5C;AAED;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC;IACnD,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,SAAS,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;CACnC,CAAC,CASD"}
|
package/dist/lib/skit-adapter.js
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { execSync } from 'child_process';
|
|
13
13
|
import { REGISTRY_PROXY_URL, getInstallerGroupFromEnv } from './config.js';
|
|
14
|
+
import { maskSessionId } from './session.js';
|
|
15
|
+
import { createProxyAuthGlobalconfig, GLOBALCONFIG_ENV_KEYS, } from './proxy-auth-globalconfig.js';
|
|
14
16
|
// ============================================================
|
|
15
17
|
// Lib Loader
|
|
16
18
|
// ============================================================
|
|
@@ -68,7 +70,7 @@ function runSkitCli(command, env) {
|
|
|
68
70
|
return { success: false, error };
|
|
69
71
|
}
|
|
70
72
|
}
|
|
71
|
-
function installSkitViaCli(spec, options) {
|
|
73
|
+
function installSkitViaCli(spec, options, authCarrier) {
|
|
72
74
|
// Parse spec: "@ist/tda-kit@1.0.0" -> name: "@ist/tda-kit", version: "1.0.0"
|
|
73
75
|
const atIndex = spec.lastIndexOf('@');
|
|
74
76
|
let name;
|
|
@@ -108,6 +110,11 @@ function installSkitViaCli(spec, options) {
|
|
|
108
110
|
if (groupFromEnv) {
|
|
109
111
|
env['IST_GITLAB_GROUP'] = groupFromEnv;
|
|
110
112
|
}
|
|
113
|
+
// Proxy auth for skit's kit npm-dep installs (skit overrides USERCONFIG, so
|
|
114
|
+
// the ~/.npmrc auth line is invisible to it) — see proxy-auth-globalconfig.ts.
|
|
115
|
+
if (authCarrier) {
|
|
116
|
+
Object.assign(env, authCarrier.env);
|
|
117
|
+
}
|
|
111
118
|
const result = runSkitCli(command, Object.keys(env).length > 0 ? env : undefined);
|
|
112
119
|
return {
|
|
113
120
|
success: result.success,
|
|
@@ -129,6 +136,18 @@ function installSkitViaCli(spec, options) {
|
|
|
129
136
|
*/
|
|
130
137
|
export async function installSkitPackage(name, version, options) {
|
|
131
138
|
const spec = version ? `${name}@${version}` : name;
|
|
139
|
+
// Authenticated session → carry the proxy auth line into skit's npm installs
|
|
140
|
+
// via a temp GLOBALCONFIG (env reference only, no token value on disk).
|
|
141
|
+
// null in anonymous mode. Always removed in the finally below.
|
|
142
|
+
const authCarrier = createProxyAuthGlobalconfig({ proxyUrl: REGISTRY_PROXY_URL });
|
|
143
|
+
try {
|
|
144
|
+
return await installSkitPackageInner(name, version, spec, options, authCarrier);
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
authCarrier?.cleanup();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
async function installSkitPackageInner(name, version, spec, options, authCarrier) {
|
|
132
151
|
// Try lib first
|
|
133
152
|
const lib = await loadSkitLib();
|
|
134
153
|
if (lib) {
|
|
@@ -143,6 +162,7 @@ export async function installSkitPackage(name, version, options) {
|
|
|
143
162
|
'IST_REGISTRY_URL',
|
|
144
163
|
'IST_GITLAB_HOST',
|
|
145
164
|
'IST_GITLAB_GROUP',
|
|
165
|
+
...GLOBALCONFIG_ENV_KEYS,
|
|
146
166
|
];
|
|
147
167
|
const savedEnv = {};
|
|
148
168
|
for (const key of TOUCHED_ENV_KEYS) {
|
|
@@ -154,7 +174,7 @@ export async function installSkitPackage(name, version, options) {
|
|
|
154
174
|
process.env.SKIT_SESSION_ID = options.sessionId;
|
|
155
175
|
process.env.SKIT_REGISTRY = REGISTRY_PROXY_URL;
|
|
156
176
|
process.env.IST_REGISTRY_URL = REGISTRY_PROXY_URL;
|
|
157
|
-
console.log(`[skit-adapter] Using session: ${options.sessionId
|
|
177
|
+
console.log(`[skit-adapter] Using session: ${maskSessionId(options.sessionId)}`);
|
|
158
178
|
}
|
|
159
179
|
else {
|
|
160
180
|
console.log(`[skit-adapter] No sessionId provided`);
|
|
@@ -167,6 +187,9 @@ export async function installSkitPackage(name, version, options) {
|
|
|
167
187
|
if (groupFromEnv) {
|
|
168
188
|
process.env.IST_GITLAB_GROUP = groupFromEnv;
|
|
169
189
|
}
|
|
190
|
+
if (authCarrier) {
|
|
191
|
+
Object.assign(process.env, authCarrier.env);
|
|
192
|
+
}
|
|
170
193
|
try {
|
|
171
194
|
const libResult = await lib.installSkit(spec, {
|
|
172
195
|
onProgress: options?.silent ? undefined : options?.onProgress,
|
|
@@ -201,7 +224,7 @@ export async function installSkitPackage(name, version, options) {
|
|
|
201
224
|
}
|
|
202
225
|
}
|
|
203
226
|
// CLI fallback
|
|
204
|
-
return installSkitViaCli(spec, options);
|
|
227
|
+
return installSkitViaCli(spec, options, authCarrier);
|
|
205
228
|
}
|
|
206
229
|
/**
|
|
207
230
|
* Check if skit lib is available
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skit-adapter.js","sourceRoot":"","sources":["../../src/lib/skit-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"skit-adapter.js","sourceRoot":"","sources":["../../src/lib/skit-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opt-in stage timing for `snapshot install` (SNAPSHOT_TIMING=1).
|
|
3
|
+
* Prints `[timing] <label> <seconds>s` to stderr when a stage ends; no-op otherwise.
|
|
4
|
+
* Measurement harness lives in @microwiseai/snapshot-install-bench.
|
|
5
|
+
*/
|
|
6
|
+
export declare function timingStart(label: string): () => void;
|
|
7
|
+
//# sourceMappingURL=timing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timing.d.ts","sourceRoot":"","sources":["../../src/lib/timing.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,IAAI,CAMrD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opt-in stage timing for `snapshot install` (SNAPSHOT_TIMING=1).
|
|
3
|
+
* Prints `[timing] <label> <seconds>s` to stderr when a stage ends; no-op otherwise.
|
|
4
|
+
* Measurement harness lives in @microwiseai/snapshot-install-bench.
|
|
5
|
+
*/
|
|
6
|
+
export function timingStart(label) {
|
|
7
|
+
if (process.env.SNAPSHOT_TIMING !== '1')
|
|
8
|
+
return () => { };
|
|
9
|
+
const t0 = Date.now();
|
|
10
|
+
return () => {
|
|
11
|
+
process.stderr.write(`[timing] ${label} ${((Date.now() - t0) / 1000).toFixed(2)}s\n`);
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=timing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timing.js","sourceRoot":"","sources":["../../src/lib/timing.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,GAAG;QAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;IACzD,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACtB,OAAO,GAAG,EAAE;QACV,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACxF,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -24,6 +24,9 @@ export interface Snapshot {
|
|
|
24
24
|
install?: Record<string, Record<string, string>>;
|
|
25
25
|
packages?: Record<string, string>;
|
|
26
26
|
skits?: Record<string, string>;
|
|
27
|
+
policy?: {
|
|
28
|
+
onDowngrade?: 'refuse' | 'warn' | 'allow';
|
|
29
|
+
};
|
|
27
30
|
}
|
|
28
31
|
export interface InstalledSnapshot {
|
|
29
32
|
name: string;
|
package/dist/lib/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,eAAe,GAAG,sBAAsB,CAAC;AAEjF,MAAM,WAAW,QAAQ;IAEvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,MAAM,CAAC,EAAE,cAAc,CAAC;IAExB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAG1C,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAGjD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,eAAe,GAAG,sBAAsB,CAAC;AAEjF,MAAM,WAAW,QAAQ;IAEvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,MAAM,CAAC,EAAE,cAAc,CAAC;IAExB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAG1C,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAGjD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAO/B,MAAM,CAAC,EAAE;QACP,WAAW,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;KAC3C,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse the `name -> version` specs out of a GLOBAL install command string.
|
|
3
|
+
*
|
|
4
|
+
* This is the bridge that lets the downgrade guard sit at core's single
|
|
5
|
+
* npm-exec choke point (the raw `runCommand`/`runCommandSync` spawn wrappers),
|
|
6
|
+
* which are also used for uninstall / probe / hint commands. We only engage when
|
|
7
|
+
* the command is a *global install* carrying versioned specs; everything else
|
|
8
|
+
* returns {} so the guard is a no-op.
|
|
9
|
+
*
|
|
10
|
+
* Pure and tolerant: unknown shapes → {}. Only exact `name@version` tokens are
|
|
11
|
+
* extracted (scoped names supported: `@ist/sesh@0.3.0`). Tokens without a
|
|
12
|
+
* version (`@microwiseai/skit`), flags (`-g`), and the binary/subcommand words
|
|
13
|
+
* are ignored. Non-exact versions are still returned verbatim — the caller's
|
|
14
|
+
* detector treats non-exact semver as incomparable and skips it.
|
|
15
|
+
*
|
|
16
|
+
* Examples:
|
|
17
|
+
* 'npm install -g @ist/sesh@0.3.0 chalk@5.3.0' -> { '@ist/sesh':'0.3.0', chalk:'5.3.0' }
|
|
18
|
+
* 'glpkg install @ist/sesh@0.3.0' -> { '@ist/sesh':'0.3.0' } (glpkg installs globally)
|
|
19
|
+
* 'npm uninstall -g @ist/sesh' -> {} (uninstall)
|
|
20
|
+
* 'npm install -g @microwiseai/skit' -> {} (no version)
|
|
21
|
+
* 'npm install @ist/x@1.0.0' -> {} (not global)
|
|
22
|
+
* 'npm list -g @ist/sesh --json' -> {} (not an install)
|
|
23
|
+
*/
|
|
24
|
+
export declare function extractGlobalInstallSpecs(command: unknown): Record<string, string>;
|
|
25
|
+
//# sourceMappingURL=command-specs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-specs.d.ts","sourceRoot":"","sources":["../src/command-specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA2BlF"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse the `name -> version` specs out of a GLOBAL install command string.
|
|
3
|
+
*
|
|
4
|
+
* This is the bridge that lets the downgrade guard sit at core's single
|
|
5
|
+
* npm-exec choke point (the raw `runCommand`/`runCommandSync` spawn wrappers),
|
|
6
|
+
* which are also used for uninstall / probe / hint commands. We only engage when
|
|
7
|
+
* the command is a *global install* carrying versioned specs; everything else
|
|
8
|
+
* returns {} so the guard is a no-op.
|
|
9
|
+
*
|
|
10
|
+
* Pure and tolerant: unknown shapes → {}. Only exact `name@version` tokens are
|
|
11
|
+
* extracted (scoped names supported: `@ist/sesh@0.3.0`). Tokens without a
|
|
12
|
+
* version (`@microwiseai/skit`), flags (`-g`), and the binary/subcommand words
|
|
13
|
+
* are ignored. Non-exact versions are still returned verbatim — the caller's
|
|
14
|
+
* detector treats non-exact semver as incomparable and skips it.
|
|
15
|
+
*
|
|
16
|
+
* Examples:
|
|
17
|
+
* 'npm install -g @ist/sesh@0.3.0 chalk@5.3.0' -> { '@ist/sesh':'0.3.0', chalk:'5.3.0' }
|
|
18
|
+
* 'glpkg install @ist/sesh@0.3.0' -> { '@ist/sesh':'0.3.0' } (glpkg installs globally)
|
|
19
|
+
* 'npm uninstall -g @ist/sesh' -> {} (uninstall)
|
|
20
|
+
* 'npm install -g @microwiseai/skit' -> {} (no version)
|
|
21
|
+
* 'npm install @ist/x@1.0.0' -> {} (not global)
|
|
22
|
+
* 'npm list -g @ist/sesh --json' -> {} (not an install)
|
|
23
|
+
*/
|
|
24
|
+
export function extractGlobalInstallSpecs(command) {
|
|
25
|
+
if (typeof command !== 'string' || command.length === 0)
|
|
26
|
+
return {};
|
|
27
|
+
// A command is a GLOBAL install when it carries the -g/--global flag OR is run
|
|
28
|
+
// through an installer whose installs are inherently global (glpkg /
|
|
29
|
+
// gitlab-install both install global npm packages, without a -g flag).
|
|
30
|
+
const hasGlobalFlag = /(?:^|\s)(?:-g|--global)(?:\s|$)/.test(command);
|
|
31
|
+
const isGlobalInstaller = /^\s*(?:glpkg|gitlab-install)(?:\s|$)/.test(command);
|
|
32
|
+
if (!hasGlobalFlag && !isGlobalInstaller)
|
|
33
|
+
return {};
|
|
34
|
+
const isUninstall = /(?:^|\s)(?:uninstall|remove|rm|un)(?:\s|$)/.test(command);
|
|
35
|
+
if (isUninstall)
|
|
36
|
+
return {};
|
|
37
|
+
const isInstall = /(?:^|\s)(?:install|add|i)(?:\s|$)/.test(command);
|
|
38
|
+
if (!isInstall)
|
|
39
|
+
return {};
|
|
40
|
+
const specs = {};
|
|
41
|
+
for (const tok of command.split(/\s+/)) {
|
|
42
|
+
if (!tok || tok.startsWith('-'))
|
|
43
|
+
continue; // flags / empty
|
|
44
|
+
const at = tok.lastIndexOf('@');
|
|
45
|
+
if (at <= 0)
|
|
46
|
+
continue; // no version, or a leading-@ scope with no version
|
|
47
|
+
const name = tok.slice(0, at);
|
|
48
|
+
const version = tok.slice(at + 1);
|
|
49
|
+
if (!name || !version)
|
|
50
|
+
continue;
|
|
51
|
+
specs[name] = version;
|
|
52
|
+
}
|
|
53
|
+
return specs;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=command-specs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-specs.js","sourceRoot":"","sources":["../src/command-specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAgB;IACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEnE,+EAA+E;IAC/E,qEAAqE;IACrE,uEAAuE;IACvE,MAAM,aAAa,GAAG,iCAAiC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtE,MAAM,iBAAiB,GAAG,sCAAsC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/E,IAAI,CAAC,aAAa,IAAI,CAAC,iBAAiB;QAAE,OAAO,EAAE,CAAC;IAEpD,MAAM,WAAW,GAAG,4CAA4C,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/E,IAAI,WAAW;QAAE,OAAO,EAAE,CAAC;IAE3B,MAAM,SAAS,GAAG,mCAAmC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpE,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,CAAC;IAE1B,MAAM,KAAK,GAA2B,EAAE,CAAC;IACzC,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACvC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS,CAAC,gBAAgB;QAC3D,MAAM,EAAE,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,EAAE,IAAI,CAAC;YAAE,SAAS,CAAC,mDAAmD;QAC1E,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9B,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO;YAAE,SAAS;QAChC,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;IACxB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { DowngradeMode } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Machine-level snapshot config (~/.config/ist-snapshot/config.json).
|
|
4
|
+
* Only `install.onDowngrade` is meaningful here; unknown keys are preserved on
|
|
5
|
+
* round-trip so this package never clobbers config owned by other tools.
|
|
6
|
+
*/
|
|
7
|
+
export interface MachineConfig {
|
|
8
|
+
install?: {
|
|
9
|
+
onDowngrade?: DowngradeMode;
|
|
10
|
+
[k: string]: unknown;
|
|
11
|
+
};
|
|
12
|
+
[k: string]: unknown;
|
|
13
|
+
}
|
|
14
|
+
/** Minimal fs surface, injectable for hermetic tests. Defaults to node:fs. */
|
|
15
|
+
export interface ConfigFs {
|
|
16
|
+
existsSync: (p: string) => boolean;
|
|
17
|
+
readFileSync: (p: string, enc: 'utf-8') => string;
|
|
18
|
+
writeFileSync: (p: string, data: string) => void;
|
|
19
|
+
mkdirSync: (p: string, opts: {
|
|
20
|
+
recursive: boolean;
|
|
21
|
+
}) => void;
|
|
22
|
+
}
|
|
23
|
+
export interface ConfigIoOptions {
|
|
24
|
+
/** Config directory. Defaults to ~/.config/ist-snapshot. Injectable for tests. */
|
|
25
|
+
configDir?: string;
|
|
26
|
+
/** fs implementation. Defaults to node:fs. Injectable for tests. */
|
|
27
|
+
fs?: ConfigFs;
|
|
28
|
+
}
|
|
29
|
+
/** Default config directory (~/.config/ist-snapshot). */
|
|
30
|
+
export declare function getConfigDir(opts?: ConfigIoOptions): string;
|
|
31
|
+
/** Absolute path to config.json. */
|
|
32
|
+
export declare function getConfigPath(opts?: ConfigIoOptions): string;
|
|
33
|
+
/**
|
|
34
|
+
* Read the machine config. Returns {} when the file is absent or unparseable
|
|
35
|
+
* (tolerant — a broken/foreign file must not crash an install decision).
|
|
36
|
+
*/
|
|
37
|
+
export declare function readMachineConfig(opts?: ConfigIoOptions): MachineConfig;
|
|
38
|
+
/**
|
|
39
|
+
* Write the machine config (pretty JSON), creating the config dir if needed.
|
|
40
|
+
*/
|
|
41
|
+
export declare function writeMachineConfig(config: MachineConfig, opts?: ConfigIoOptions): void;
|
|
42
|
+
/**
|
|
43
|
+
* Read `install.onDowngrade` from machine config, validated.
|
|
44
|
+
* Returns null when unset or invalid.
|
|
45
|
+
*/
|
|
46
|
+
export declare function getMachineDowngradeMode(opts?: ConfigIoOptions): DowngradeMode | null;
|
|
47
|
+
/**
|
|
48
|
+
* Set `install.onDowngrade` in machine config (read-modify-write), preserving
|
|
49
|
+
* every other key. Returns the written config.
|
|
50
|
+
*/
|
|
51
|
+
export declare function setMachineDowngradeMode(mode: DowngradeMode, opts?: ConfigIoOptions): MachineConfig;
|
|
52
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE;QACR,WAAW,CAAC,EAAE,aAAa,CAAC;QAC5B,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;KACtB,CAAC;IACF,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB;AAED,8EAA8E;AAC9E,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IACnC,YAAY,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;IAClD,aAAa,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;CAC9D;AAED,MAAM,WAAW,eAAe;IAC9B,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,EAAE,CAAC,EAAE,QAAQ,CAAC;CACf;AAID,yDAAyD;AACzD,wBAAgB,YAAY,CAAC,IAAI,GAAE,eAAoB,GAAG,MAAM,CAE/D;AAED,oCAAoC;AACpC,wBAAgB,aAAa,CAAC,IAAI,GAAE,eAAoB,GAAG,MAAM,CAEhE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,eAAoB,GAAG,aAAa,CAU3E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,GAAE,eAAoB,GAAG,IAAI,CAO1F;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,GAAE,eAAoB,GAAG,aAAa,GAAG,IAAI,CAExF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,aAAa,EACnB,IAAI,GAAE,eAAoB,GACzB,aAAa,CAQf"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
2
|
+
import { homedir } from 'os';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { asDowngradeMode } from './policy.js';
|
|
5
|
+
const DEFAULT_FS = { existsSync, readFileSync, writeFileSync, mkdirSync };
|
|
6
|
+
/** Default config directory (~/.config/ist-snapshot). */
|
|
7
|
+
export function getConfigDir(opts = {}) {
|
|
8
|
+
return opts.configDir ?? join(homedir(), '.config', 'ist-snapshot');
|
|
9
|
+
}
|
|
10
|
+
/** Absolute path to config.json. */
|
|
11
|
+
export function getConfigPath(opts = {}) {
|
|
12
|
+
return join(getConfigDir(opts), 'config.json');
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Read the machine config. Returns {} when the file is absent or unparseable
|
|
16
|
+
* (tolerant — a broken/foreign file must not crash an install decision).
|
|
17
|
+
*/
|
|
18
|
+
export function readMachineConfig(opts = {}) {
|
|
19
|
+
const fs = opts.fs ?? DEFAULT_FS;
|
|
20
|
+
const path = getConfigPath(opts);
|
|
21
|
+
try {
|
|
22
|
+
if (!fs.existsSync(path))
|
|
23
|
+
return {};
|
|
24
|
+
const parsed = JSON.parse(fs.readFileSync(path, 'utf-8'));
|
|
25
|
+
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Write the machine config (pretty JSON), creating the config dir if needed.
|
|
33
|
+
*/
|
|
34
|
+
export function writeMachineConfig(config, opts = {}) {
|
|
35
|
+
const fs = opts.fs ?? DEFAULT_FS;
|
|
36
|
+
const dir = getConfigDir(opts);
|
|
37
|
+
if (!fs.existsSync(dir)) {
|
|
38
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
fs.writeFileSync(getConfigPath(opts), JSON.stringify(config, null, 2) + '\n');
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Read `install.onDowngrade` from machine config, validated.
|
|
44
|
+
* Returns null when unset or invalid.
|
|
45
|
+
*/
|
|
46
|
+
export function getMachineDowngradeMode(opts = {}) {
|
|
47
|
+
return asDowngradeMode(readMachineConfig(opts).install?.onDowngrade);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Set `install.onDowngrade` in machine config (read-modify-write), preserving
|
|
51
|
+
* every other key. Returns the written config.
|
|
52
|
+
*/
|
|
53
|
+
export function setMachineDowngradeMode(mode, opts = {}) {
|
|
54
|
+
const current = readMachineConfig(opts);
|
|
55
|
+
const next = {
|
|
56
|
+
...current,
|
|
57
|
+
install: { ...(current.install ?? {}), onDowngrade: mode },
|
|
58
|
+
};
|
|
59
|
+
writeMachineConfig(next, opts);
|
|
60
|
+
return next;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AA+B9C,MAAM,UAAU,GAAa,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC;AAEpF,yDAAyD;AACzD,MAAM,UAAU,YAAY,CAAC,OAAwB,EAAE;IACrD,OAAO,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;AACtE,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,aAAa,CAAC,OAAwB,EAAE;IACtD,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC;AACjD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAwB,EAAE;IAC1D,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,IAAI,UAAU,CAAC;IACjC,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1D,OAAO,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAE,MAAwB,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAqB,EAAE,OAAwB,EAAE;IAClF,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,IAAI,UAAU,CAAC;IACjC,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,EAAE,CAAC,aAAa,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAChF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAAwB,EAAE;IAChE,OAAO,eAAe,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AACvE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,IAAmB,EACnB,OAAwB,EAAE;IAE1B,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,IAAI,GAAkB;QAC1B,GAAG,OAAO;QACV,OAAO,EAAE,EAAE,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE;KAC3D,CAAC;IACF,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC/B,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { DetectResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Reads the currently-installed (global) version of a package, or null/undefined
|
|
4
|
+
* when it is not installed. MUST be injected — this package never shells out to
|
|
5
|
+
* npm, keeping it pure and side-effect-free. Core supplies a real implementation
|
|
6
|
+
* (e.g. `npm ls -g`); tests inject a stub.
|
|
7
|
+
*/
|
|
8
|
+
export type ReadVersionFn = (pkg: string) => string | null | undefined;
|
|
9
|
+
export interface DetectOptions {
|
|
10
|
+
/** Injected version reader. Required — no default npm execution. */
|
|
11
|
+
readVersion: ReadVersionFn;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Detect which pinned packages would be DOWNGRADED relative to what is already
|
|
15
|
+
* installed globally.
|
|
16
|
+
*
|
|
17
|
+
* For each `pkg -> pinned` entry:
|
|
18
|
+
* - not installed (readVersion returns null/undefined/empty) → OK (skip)
|
|
19
|
+
* - installed === pinned → OK (skip)
|
|
20
|
+
* - installed < pinned (an upgrade) → OK (skip)
|
|
21
|
+
* - installed > pinned (a downgrade, strict) → OFFENDER
|
|
22
|
+
* - either side not an exact semver (incomparable) → OK (skip, tolerant)
|
|
23
|
+
*
|
|
24
|
+
* A clean Docker sandbox has nothing installed globally, so every entry skips
|
|
25
|
+
* and `wouldDowngrade` is false — the guard auto-passes with no config.
|
|
26
|
+
*
|
|
27
|
+
* Pure: no I/O, no mutation of `installMap`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function detectDowngrades(installMap: Record<string, string>, opts?: DetectOptions): DetectResult;
|
|
30
|
+
//# sourceMappingURL=detect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,YAAY,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;AAEvE,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,WAAW,EAAE,aAAa,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,IAAI,CAAC,EAAE,aAAa,GACnB,YAAY,CAwBd"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { compareExact } from './semver.js';
|
|
2
|
+
/**
|
|
3
|
+
* Detect which pinned packages would be DOWNGRADED relative to what is already
|
|
4
|
+
* installed globally.
|
|
5
|
+
*
|
|
6
|
+
* For each `pkg -> pinned` entry:
|
|
7
|
+
* - not installed (readVersion returns null/undefined/empty) → OK (skip)
|
|
8
|
+
* - installed === pinned → OK (skip)
|
|
9
|
+
* - installed < pinned (an upgrade) → OK (skip)
|
|
10
|
+
* - installed > pinned (a downgrade, strict) → OFFENDER
|
|
11
|
+
* - either side not an exact semver (incomparable) → OK (skip, tolerant)
|
|
12
|
+
*
|
|
13
|
+
* A clean Docker sandbox has nothing installed globally, so every entry skips
|
|
14
|
+
* and `wouldDowngrade` is false — the guard auto-passes with no config.
|
|
15
|
+
*
|
|
16
|
+
* Pure: no I/O, no mutation of `installMap`.
|
|
17
|
+
*/
|
|
18
|
+
export function detectDowngrades(installMap, opts) {
|
|
19
|
+
const readVersion = opts?.readVersion;
|
|
20
|
+
if (typeof readVersion !== 'function') {
|
|
21
|
+
throw new Error('detectDowngrades: opts.readVersion injection is required (this package never runs npm itself).');
|
|
22
|
+
}
|
|
23
|
+
const offenders = [];
|
|
24
|
+
for (const [pkg, pinned] of Object.entries(installMap ?? {})) {
|
|
25
|
+
const installed = readVersion(pkg);
|
|
26
|
+
if (installed === null || installed === undefined || installed === '') {
|
|
27
|
+
continue; // not installed → no downgrade
|
|
28
|
+
}
|
|
29
|
+
const cmp = compareExact(installed, pinned);
|
|
30
|
+
if (cmp === null) {
|
|
31
|
+
continue; // incomparable (non-exact semver) → tolerant skip
|
|
32
|
+
}
|
|
33
|
+
if (cmp > 0) {
|
|
34
|
+
offenders.push({ pkg, installed, pinned });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { wouldDowngrade: offenders.length > 0, offenders };
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAgB3C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,gBAAgB,CAC9B,UAAkC,EAClC,IAAoB;IAEpB,MAAM,WAAW,GAAG,IAAI,EAAE,WAAW,CAAC;IACtC,IAAI,OAAO,WAAW,KAAK,UAAU,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CACb,gGAAgG,CACjG,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAe,EAAE,CAAC;IACjC,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC,EAAE,CAAC;QAC7D,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,EAAE,EAAE,CAAC;YACtE,SAAS,CAAC,+BAA+B;QAC3C,CAAC;QACD,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC5C,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,SAAS,CAAC,kDAAkD;QAC9D,CAAC;QACD,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;YACZ,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,OAAO,EAAE,cAAc,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,SAAS,EAAE,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @microwiseai/snapshot-downgrade-guard
|
|
3
|
+
*
|
|
4
|
+
* Auto-detects when a snapshot install would DOWNGRADE already-installed global
|
|
5
|
+
* tooling, and resolves the layered refuse/warn/allow policy. Pure and
|
|
6
|
+
* dependency-injected: it never runs npm, touches the network, or mutates state
|
|
7
|
+
* except through the explicit machine-config writers. A clean Docker sandbox
|
|
8
|
+
* (nothing installed globally) produces zero offenders and auto-passes.
|
|
9
|
+
*
|
|
10
|
+
* Usage (in core, at the npm-exec boundary):
|
|
11
|
+
* import {
|
|
12
|
+
* detectDowngrades, resolveDowngradePolicy, readOneShotOverride,
|
|
13
|
+
* readMachineConfig, formatDowngradeReport,
|
|
14
|
+
* } from '@microwiseai/snapshot-downgrade-guard';
|
|
15
|
+
*
|
|
16
|
+
* const { wouldDowngrade, offenders } = detectDowngrades(installMap, { readVersion });
|
|
17
|
+
* const mode = resolveDowngradePolicy({
|
|
18
|
+
* override: readOneShotOverride({ env: process.env, allowDowngradeFlag }),
|
|
19
|
+
* machine: readMachineConfig().install?.onDowngrade,
|
|
20
|
+
* snapshot: snapshot.policy?.onDowngrade,
|
|
21
|
+
* });
|
|
22
|
+
* if (wouldDowngrade && mode === 'refuse') throw new Error(formatDowngradeReport(offenders, mode));
|
|
23
|
+
*/
|
|
24
|
+
export { detectDowngrades } from './detect.js';
|
|
25
|
+
export type { DetectOptions, ReadVersionFn } from './detect.js';
|
|
26
|
+
export { resolveDowngradePolicy, readOneShotOverride, asDowngradeMode, DEFAULT_DOWNGRADE_MODE, } from './policy.js';
|
|
27
|
+
export type { PolicySources, OneShotOverrideInput } from './policy.js';
|
|
28
|
+
export { getConfigDir, getConfigPath, readMachineConfig, writeMachineConfig, getMachineDowngradeMode, setMachineDowngradeMode, } from './config.js';
|
|
29
|
+
export type { MachineConfig, ConfigFs, ConfigIoOptions } from './config.js';
|
|
30
|
+
export { formatDowngradeReport } from './report.js';
|
|
31
|
+
export { extractGlobalInstallSpecs } from './command-specs.js';
|
|
32
|
+
export { isExactSemver, compareExact } from './semver.js';
|
|
33
|
+
export type { DowngradeMode, Offender, DetectResult } from './types.js';
|
|
34
|
+
export { DOWNGRADE_MODES } from './types.js';
|
|
35
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,eAAe,EACf,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEvE,OAAO,EACL,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEpD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE1D,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @microwiseai/snapshot-downgrade-guard
|
|
3
|
+
*
|
|
4
|
+
* Auto-detects when a snapshot install would DOWNGRADE already-installed global
|
|
5
|
+
* tooling, and resolves the layered refuse/warn/allow policy. Pure and
|
|
6
|
+
* dependency-injected: it never runs npm, touches the network, or mutates state
|
|
7
|
+
* except through the explicit machine-config writers. A clean Docker sandbox
|
|
8
|
+
* (nothing installed globally) produces zero offenders and auto-passes.
|
|
9
|
+
*
|
|
10
|
+
* Usage (in core, at the npm-exec boundary):
|
|
11
|
+
* import {
|
|
12
|
+
* detectDowngrades, resolveDowngradePolicy, readOneShotOverride,
|
|
13
|
+
* readMachineConfig, formatDowngradeReport,
|
|
14
|
+
* } from '@microwiseai/snapshot-downgrade-guard';
|
|
15
|
+
*
|
|
16
|
+
* const { wouldDowngrade, offenders } = detectDowngrades(installMap, { readVersion });
|
|
17
|
+
* const mode = resolveDowngradePolicy({
|
|
18
|
+
* override: readOneShotOverride({ env: process.env, allowDowngradeFlag }),
|
|
19
|
+
* machine: readMachineConfig().install?.onDowngrade,
|
|
20
|
+
* snapshot: snapshot.policy?.onDowngrade,
|
|
21
|
+
* });
|
|
22
|
+
* if (wouldDowngrade && mode === 'refuse') throw new Error(formatDowngradeReport(offenders, mode));
|
|
23
|
+
*/
|
|
24
|
+
export { detectDowngrades } from './detect.js';
|
|
25
|
+
export { resolveDowngradePolicy, readOneShotOverride, asDowngradeMode, DEFAULT_DOWNGRADE_MODE, } from './policy.js';
|
|
26
|
+
export { getConfigDir, getConfigPath, readMachineConfig, writeMachineConfig, getMachineDowngradeMode, setMachineDowngradeMode, } from './config.js';
|
|
27
|
+
export { formatDowngradeReport } from './report.js';
|
|
28
|
+
export { extractGlobalInstallSpecs } from './command-specs.js';
|
|
29
|
+
export { isExactSemver, compareExact } from './semver.js';
|
|
30
|
+
export { DOWNGRADE_MODES } from './types.js';
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,eAAe,EACf,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEpD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG1D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type DowngradeMode } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Policy values read from each layer. Any field may be absent (undefined/null)
|
|
4
|
+
* or invalid; invalid values are ignored (treated as absent) so a typo never
|
|
5
|
+
* silently weakens the guard.
|
|
6
|
+
*
|
|
7
|
+
* Precedence (highest wins):
|
|
8
|
+
* (a) override — CLI flag / one-shot env (already mapped to a mode)
|
|
9
|
+
* (b) machine — machine config (~/.config/ist-snapshot/config.json)
|
|
10
|
+
* (c) snapshot — snapshot.json `policy.onDowngrade`
|
|
11
|
+
* (d) default — 'refuse'
|
|
12
|
+
*/
|
|
13
|
+
export interface PolicySources {
|
|
14
|
+
override?: DowngradeMode | string | null;
|
|
15
|
+
machine?: DowngradeMode | string | null;
|
|
16
|
+
snapshot?: DowngradeMode | string | null;
|
|
17
|
+
}
|
|
18
|
+
/** The default when no layer specifies a valid mode. */
|
|
19
|
+
export declare const DEFAULT_DOWNGRADE_MODE: DowngradeMode;
|
|
20
|
+
/** Narrow an arbitrary value to a valid DowngradeMode, or null if invalid. */
|
|
21
|
+
export declare function asDowngradeMode(v: unknown): DowngradeMode | null;
|
|
22
|
+
/**
|
|
23
|
+
* Resolve the effective downgrade policy from the layered sources.
|
|
24
|
+
* Pure: first valid value in precedence order (a > b > c), else the default.
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveDowngradePolicy(sources?: PolicySources): DowngradeMode;
|
|
27
|
+
export interface OneShotOverrideInput {
|
|
28
|
+
/** Environment map (e.g. process.env). SNAPSHOT_ALLOW_LOCAL=1 → allow. */
|
|
29
|
+
env?: NodeJS.ProcessEnv | Record<string, string | undefined>;
|
|
30
|
+
/** CLI flag, e.g. --allow-downgrade → allow. */
|
|
31
|
+
allowDowngradeFlag?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Map the one-shot escape hatches (CLI `--allow-downgrade` or env
|
|
35
|
+
* `SNAPSHOT_ALLOW_LOCAL=1`) to an override mode.
|
|
36
|
+
*
|
|
37
|
+
* Returns 'allow' when either hatch is engaged, otherwise null (no override).
|
|
38
|
+
* Pure — reads only the injected inputs. Core passes the result as
|
|
39
|
+
* `PolicySources.override`.
|
|
40
|
+
*/
|
|
41
|
+
export declare function readOneShotOverride(input?: OneShotOverrideInput): DowngradeMode | null;
|
|
42
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAEjE;;;;;;;;;;GAUG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAAC;IACzC,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAAC;CAC1C;AAED,wDAAwD;AACxD,eAAO,MAAM,sBAAsB,EAAE,aAAwB,CAAC;AAE9D,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAIhE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,aAAkB,GAAG,aAAa,CAOjF;AAED,MAAM,WAAW,oBAAoB;IACnC,0EAA0E;IAC1E,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAC7D,gDAAgD;IAChD,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,GAAE,oBAAyB,GAAG,aAAa,GAAG,IAAI,CAK1F"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { DOWNGRADE_MODES } from './types.js';
|
|
2
|
+
/** The default when no layer specifies a valid mode. */
|
|
3
|
+
export const DEFAULT_DOWNGRADE_MODE = 'refuse';
|
|
4
|
+
/** Narrow an arbitrary value to a valid DowngradeMode, or null if invalid. */
|
|
5
|
+
export function asDowngradeMode(v) {
|
|
6
|
+
return typeof v === 'string' && DOWNGRADE_MODES.includes(v)
|
|
7
|
+
? v
|
|
8
|
+
: null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Resolve the effective downgrade policy from the layered sources.
|
|
12
|
+
* Pure: first valid value in precedence order (a > b > c), else the default.
|
|
13
|
+
*/
|
|
14
|
+
export function resolveDowngradePolicy(sources = {}) {
|
|
15
|
+
return (asDowngradeMode(sources.override) ??
|
|
16
|
+
asDowngradeMode(sources.machine) ??
|
|
17
|
+
asDowngradeMode(sources.snapshot) ??
|
|
18
|
+
DEFAULT_DOWNGRADE_MODE);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Map the one-shot escape hatches (CLI `--allow-downgrade` or env
|
|
22
|
+
* `SNAPSHOT_ALLOW_LOCAL=1`) to an override mode.
|
|
23
|
+
*
|
|
24
|
+
* Returns 'allow' when either hatch is engaged, otherwise null (no override).
|
|
25
|
+
* Pure — reads only the injected inputs. Core passes the result as
|
|
26
|
+
* `PolicySources.override`.
|
|
27
|
+
*/
|
|
28
|
+
export function readOneShotOverride(input = {}) {
|
|
29
|
+
const env = input.env ?? {};
|
|
30
|
+
if (input.allowDowngradeFlag === true)
|
|
31
|
+
return 'allow';
|
|
32
|
+
if (env.SNAPSHOT_ALLOW_LOCAL === '1')
|
|
33
|
+
return 'allow';
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=policy.js.map
|