@microwiseai/snapshot 0.3.46 → 0.3.57

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 (53) hide show
  1. package/dist/commands/access.js +1 -1
  2. package/dist/commands/access.js.map +1 -1
  3. package/dist/commands/doctor.d.ts +2 -0
  4. package/dist/commands/doctor.d.ts.map +1 -0
  5. package/dist/commands/doctor.js +37 -0
  6. package/dist/commands/doctor.js.map +1 -0
  7. package/dist/commands/install.d.ts.map +1 -1
  8. package/dist/commands/install.js +335 -112
  9. package/dist/commands/install.js.map +1 -1
  10. package/dist/commands/setup.d.ts +5 -0
  11. package/dist/commands/setup.d.ts.map +1 -0
  12. package/dist/commands/setup.js +52 -0
  13. package/dist/commands/setup.js.map +1 -0
  14. package/dist/index.js +16 -0
  15. package/dist/index.js.map +1 -1
  16. package/dist/lib/access-sync.d.ts.map +1 -1
  17. package/dist/lib/access-sync.js +2 -0
  18. package/dist/lib/access-sync.js.map +1 -1
  19. package/dist/lib/config.d.ts +15 -0
  20. package/dist/lib/config.d.ts.map +1 -1
  21. package/dist/lib/config.js +96 -0
  22. package/dist/lib/config.js.map +1 -1
  23. package/dist/lib/gitlab.js +3 -3
  24. package/dist/lib/gitlab.js.map +1 -1
  25. package/dist/lib/prerequisites.d.ts +33 -0
  26. package/dist/lib/prerequisites.d.ts.map +1 -0
  27. package/dist/lib/prerequisites.js +109 -0
  28. package/dist/lib/prerequisites.js.map +1 -0
  29. package/dist/lib/session.d.ts +6 -8
  30. package/dist/lib/session.d.ts.map +1 -1
  31. package/dist/lib/session.js +10 -12
  32. package/dist/lib/session.js.map +1 -1
  33. package/dist/lib/types.d.ts +1 -1
  34. package/dist/lib/types.d.ts.map +1 -1
  35. package/node_modules/@microwiseai/snapshot-dedup/dist/dedup.d.ts +108 -0
  36. package/node_modules/@microwiseai/snapshot-dedup/dist/dedup.d.ts.map +1 -0
  37. package/node_modules/@microwiseai/snapshot-dedup/dist/dedup.js +196 -0
  38. package/node_modules/@microwiseai/snapshot-dedup/dist/dedup.js.map +1 -0
  39. package/node_modules/@microwiseai/snapshot-dedup/dist/index.d.ts +21 -0
  40. package/node_modules/@microwiseai/snapshot-dedup/dist/index.d.ts.map +1 -0
  41. package/node_modules/@microwiseai/snapshot-dedup/dist/index.js +27 -0
  42. package/node_modules/@microwiseai/snapshot-dedup/dist/index.js.map +1 -0
  43. package/node_modules/@microwiseai/snapshot-dedup/package.json +41 -0
  44. package/node_modules/@microwiseai/snapshot-parallel/dist/index.d.ts +9 -0
  45. package/node_modules/@microwiseai/snapshot-parallel/dist/index.d.ts.map +1 -0
  46. package/node_modules/@microwiseai/snapshot-parallel/dist/index.js +8 -0
  47. package/node_modules/@microwiseai/snapshot-parallel/dist/index.js.map +1 -0
  48. package/node_modules/@microwiseai/snapshot-parallel/dist/parallel-installer.d.ts +86 -0
  49. package/node_modules/@microwiseai/snapshot-parallel/dist/parallel-installer.d.ts.map +1 -0
  50. package/node_modules/@microwiseai/snapshot-parallel/dist/parallel-installer.js +159 -0
  51. package/node_modules/@microwiseai/snapshot-parallel/dist/parallel-installer.js.map +1 -0
  52. package/node_modules/@microwiseai/snapshot-parallel/package.json +41 -0
  53. package/package.json +7 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prerequisites.d.ts","sourceRoot":"","sources":["../../src/lib/prerequisites.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,EAAE,MAAM,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAqCD;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,YAAY,EAiC/C,CAAC;AAEF;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,GAAE,YAAY,EAA0B,GAAG,WAAW,EAAE,CAWvG;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAU7F"}
@@ -0,0 +1,109 @@
1
+ import { execSync } from 'child_process';
2
+ import { existsSync } from 'fs';
3
+ import { homedir, platform } from 'os';
4
+ import { join } from 'path';
5
+ /**
6
+ * Get OS-specific platform key
7
+ */
8
+ function getPlatformKey() {
9
+ const os = platform();
10
+ if (os === 'darwin')
11
+ return 'macos-brew';
12
+ if (os === 'linux') {
13
+ // Detect apt vs yum
14
+ try {
15
+ execSync('which apt-get', { stdio: 'ignore' });
16
+ return 'linux-apt';
17
+ }
18
+ catch {
19
+ try {
20
+ execSync('which yum', { stdio: 'ignore' });
21
+ return 'linux-yum';
22
+ }
23
+ catch {
24
+ return 'linux-unknown';
25
+ }
26
+ }
27
+ }
28
+ return 'unknown';
29
+ }
30
+ /**
31
+ * Check if a command exists
32
+ */
33
+ function hasCommand(cmd) {
34
+ try {
35
+ execSync(`which ${cmd} 2>/dev/null`, { stdio: 'ignore' });
36
+ return true;
37
+ }
38
+ catch {
39
+ return false;
40
+ }
41
+ }
42
+ /**
43
+ * Minimal snapshot prerequisites
44
+ */
45
+ export const MINIMAL_PREREQUISITES = [
46
+ {
47
+ name: 'tmux',
48
+ description: 'Terminal multiplexer (session management)',
49
+ requiredBy: ['@ist/sesh'],
50
+ check: () => hasCommand('tmux'),
51
+ install: {
52
+ 'linux-apt': 'sudo apt-get update -qq && sudo apt-get install -y tmux',
53
+ 'linux-yum': 'sudo yum install -y tmux',
54
+ 'macos-brew': 'brew install tmux',
55
+ },
56
+ autoInstall: true,
57
+ },
58
+ {
59
+ name: 'Claude Code',
60
+ description: 'AI CLI for session creation',
61
+ requiredBy: ['@ist/sesh'],
62
+ check: () => hasCommand('claude'),
63
+ install: {
64
+ 'linux-apt': 'npm install -g @anthropic-ai/claude-code',
65
+ 'linux-yum': 'npm install -g @anthropic-ai/claude-code',
66
+ 'macos-brew': 'npm install -g @anthropic-ai/claude-code',
67
+ },
68
+ autoInstall: true,
69
+ },
70
+ {
71
+ name: 'IST Credentials',
72
+ description: 'Authentication for session isolation',
73
+ requiredBy: ['@ist/detector-agent'],
74
+ check: () => existsSync(join(homedir(), '.ist', 'credentials')),
75
+ autoInstall: false,
76
+ guide: 'Run "claude login" to authenticate (opens browser).',
77
+ },
78
+ ];
79
+ /**
80
+ * Check all prerequisites and return results
81
+ */
82
+ export function checkPrerequisites(prerequisites = MINIMAL_PREREQUISITES) {
83
+ const platformKey = getPlatformKey();
84
+ return prerequisites.map(prereq => ({
85
+ name: prereq.name,
86
+ description: prereq.description,
87
+ requiredBy: prereq.requiredBy,
88
+ installed: prereq.check(),
89
+ guide: prereq.guide,
90
+ installCommand: prereq.install?.[platformKey] || prereq.install?.['linux-apt'],
91
+ }));
92
+ }
93
+ /**
94
+ * Install a single prerequisite
95
+ */
96
+ export function installPrerequisite(result) {
97
+ if (result.installed)
98
+ return { success: true };
99
+ if (!result.installCommand)
100
+ return { success: false, error: 'No install command available. ' + (result.guide || '') };
101
+ try {
102
+ execSync(result.installCommand, { stdio: 'inherit' });
103
+ return { success: true };
104
+ }
105
+ catch (err) {
106
+ return { success: false, error: err.message };
107
+ }
108
+ }
109
+ //# sourceMappingURL=prerequisites.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prerequisites.js","sourceRoot":"","sources":["../../src/lib/prerequisites.ts"],"names":[],"mappings":"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"}
@@ -16,19 +16,17 @@ export interface AuthorizeSessionResponse {
16
16
  /**
17
17
  * Registry-proxy에 세션 승인 요청
18
18
  *
19
- * @param licenseKey - License key (사용자 인증용)
19
+ * @param authToken - License key 또는 session token (사용자 인증용)
20
20
  * @param snapshotSpec - Snapshot spec (e.g., "@ist/full")
21
21
  * @param packages - 패키지 목록 (transitive deps 포함)
22
22
  * @returns sessionId - 승인된 세션 ID
23
23
  *
24
- * @example
25
- * const sessionId = await authorizeSession(
26
- * 'LICENSE_KEY_HERE',
27
- * '@ist/full',
28
- * ['@mwd-deps/core@0.2.3', '@ist/mwd-kit@0.3.1']
29
- * );
24
+ * @remarks
25
+ * authToken은 licenseKey 또는 sessionToken 모두 가능.
26
+ * proxy API 호환성을 위해 body에는 항상 licenseKey 필드로 전송.
27
+ * Bearer 헤더로도 동일 토큰 전송.
30
28
  */
31
- export declare function authorizeSession(licenseKey: string, snapshotSpec: string, packages: string[]): Promise<string>;
29
+ export declare function authorizeSession(authToken: string, snapshotSpec: string, packages: string[]): Promise<string>;
32
30
  /**
33
31
  * 패키지 목록에서 스펙 문자열 배열 생성
34
32
  * Record<string, string> -> string[] (name@version format)
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/lib/session.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,MAAM,CAAC,CAiDjB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,EAAE,CAE1E"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/lib/session.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,MAAM,CAAC,CAiDjB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,EAAE,CAE1E"}
@@ -12,21 +12,19 @@ import { REGISTRY_PROXY_URL } from './config.js';
12
12
  /**
13
13
  * Registry-proxy에 세션 승인 요청
14
14
  *
15
- * @param licenseKey - License key (사용자 인증용)
15
+ * @param authToken - License key 또는 session token (사용자 인증용)
16
16
  * @param snapshotSpec - Snapshot spec (e.g., "@ist/full")
17
17
  * @param packages - 패키지 목록 (transitive deps 포함)
18
18
  * @returns sessionId - 승인된 세션 ID
19
19
  *
20
- * @example
21
- * const sessionId = await authorizeSession(
22
- * 'LICENSE_KEY_HERE',
23
- * '@ist/full',
24
- * ['@mwd-deps/core@0.2.3', '@ist/mwd-kit@0.3.1']
25
- * );
20
+ * @remarks
21
+ * authToken은 licenseKey 또는 sessionToken 모두 가능.
22
+ * proxy API 호환성을 위해 body에는 항상 licenseKey 필드로 전송.
23
+ * Bearer 헤더로도 동일 토큰 전송.
26
24
  */
27
- export async function authorizeSession(licenseKey, snapshotSpec, packages) {
28
- if (!licenseKey) {
29
- throw new Error('[authorizeSession] licenseKey is required');
25
+ export async function authorizeSession(authToken, snapshotSpec, packages) {
26
+ if (!authToken) {
27
+ throw new Error('[authorizeSession] authToken (licenseKey or sessionToken) is required');
30
28
  }
31
29
  if (!snapshotSpec) {
32
30
  throw new Error('[authorizeSession] snapshotSpec is required');
@@ -39,10 +37,10 @@ export async function authorizeSession(licenseKey, snapshotSpec, packages) {
39
37
  method: 'POST',
40
38
  headers: {
41
39
  'Content-Type': 'application/json',
42
- 'Authorization': `Bearer ${licenseKey}`,
40
+ 'Authorization': `Bearer ${authToken}`,
43
41
  },
44
42
  body: JSON.stringify({
45
- licenseKey,
43
+ licenseKey: authToken,
46
44
  snapshotSpec,
47
45
  packages,
48
46
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/lib/session.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAgBjD,+DAA+D;AAC/D,wBAAwB;AACxB,+DAA+D;AAE/D;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,UAAkB,EAClB,YAAoB,EACpB,QAAkB;IAElB,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,GAAG,GAAG,GAAG,kBAAkB,oBAAoB,CAAC;IAEtD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,eAAe,EAAE,UAAU,UAAU,EAAE;SACxC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,UAAU;YACV,YAAY;YACZ,QAAQ;SACyB,CAAC;KACrC,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,8BAA8B;QAC9B,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;QAC7F,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;QAC9F,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,sGAAsG,CAAC,CAAC;QAC1H,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,mDAAmD,QAAQ,CAAC,MAAM,IAAI,SAAS,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;IAC5H,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAA8B,CAAC;IAE/D,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IAED,OAAO,IAAI,CAAC,SAAS,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgC;IAC9D,OAAO,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;AACjF,CAAC"}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/lib/session.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAgBjD,+DAA+D;AAC/D,wBAAwB;AACxB,+DAA+D;AAE/D;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAAiB,EACjB,YAAoB,EACpB,QAAkB;IAElB,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;IAC3F,CAAC;IACD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,GAAG,GAAG,GAAG,kBAAkB,oBAAoB,CAAC;IAEtD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,eAAe,EAAE,UAAU,SAAS,EAAE;SACvC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,UAAU,EAAE,SAAS;YACrB,YAAY;YACZ,QAAQ;SACyB,CAAC;KACrC,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,8BAA8B;QAC9B,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;QAC7F,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;QAC9F,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,sGAAsG,CAAC,CAAC;QAC1H,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,mDAAmD,QAAQ,CAAC,MAAM,IAAI,SAAS,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;IAC5H,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAA8B,CAAC;IAE/D,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IAED,OAAO,IAAI,CAAC,SAAS,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgC;IAC9D,OAAO,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;AACjF,CAAC"}
@@ -11,7 +11,7 @@ export interface SnapshotAccessLicensed {
11
11
  type: 'licensed';
12
12
  productId: string;
13
13
  }
14
- export type SnapshotAccess = 'public' | SnapshotAccessLicensed;
14
+ export type SnapshotAccess = 'public' | 'authenticated' | SnapshotAccessLicensed;
15
15
  export interface Snapshot {
16
16
  name: string;
17
17
  version: string;
@@ -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;CACd;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,sBAAsB,CAAC;AAE/D,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;CAChC;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"}
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;CACd;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;CAChC;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,108 @@
1
+ /**
2
+ * Snapshot Deduplication Logic
3
+ *
4
+ * Detects already-installed packages and removes duplicates from install lists.
5
+ * Prevents redundant installs when extending snapshots (e.g., full extends minimal).
6
+ *
7
+ * Storage: ~/.config/ist-snapshot/installed-history.json
8
+ * Format: { "packages": { "@ist/sesh@0.3.33": { snapshot, installedAt } } }
9
+ */
10
+ export interface InstalledPackageEntry {
11
+ /** Which snapshot installed this package */
12
+ snapshot: string;
13
+ /** ISO timestamp */
14
+ installedAt: string;
15
+ /** Package version */
16
+ version: string;
17
+ }
18
+ export interface InstallHistory {
19
+ /** Map of "name@version" -> metadata */
20
+ packages: Record<string, InstalledPackageEntry>;
21
+ /** Last updated timestamp */
22
+ updatedAt: string;
23
+ }
24
+ export interface DedupResult {
25
+ /** Packages that need to be installed (not yet installed) */
26
+ toInstall: Record<string, string>;
27
+ /** Packages skipped because already installed */
28
+ skipped: SkippedPackage[];
29
+ }
30
+ export interface SkippedPackage {
31
+ name: string;
32
+ version: string;
33
+ /** The snapshot that originally installed this package */
34
+ installedBy: string;
35
+ /** When it was originally installed */
36
+ installedAt: string;
37
+ }
38
+ export interface DedupReport {
39
+ /** Total packages in the original list */
40
+ totalRequested: number;
41
+ /** Number of packages that will be installed */
42
+ toInstallCount: number;
43
+ /** Number of packages skipped (already installed) */
44
+ skippedCount: number;
45
+ /** Details of skipped packages */
46
+ skipped: SkippedPackage[];
47
+ }
48
+ /**
49
+ * Get the path to the install history file.
50
+ * Exposed for testing/override purposes.
51
+ */
52
+ export declare function getHistoryFilePath(): string;
53
+ /**
54
+ * Load install history from disk
55
+ */
56
+ export declare function loadInstallHistory(historyPath?: string): InstallHistory;
57
+ /**
58
+ * Save install history to disk
59
+ */
60
+ export declare function saveInstallHistory(history: InstallHistory, historyPath?: string): void;
61
+ /**
62
+ * Record successfully installed packages into history
63
+ */
64
+ export declare function recordInstalledPackages(packages: Record<string, string>, snapshotName: string, historyPath?: string): void;
65
+ /**
66
+ * Record a list of installed package specs (e.g., ["@ist/sesh@0.3.33"])
67
+ */
68
+ export declare function recordInstalledSpecs(specs: string[], snapshotName: string, historyPath?: string): void;
69
+ /**
70
+ * Check if a specific package@version is already installed
71
+ */
72
+ export declare function isAlreadyInstalled(name: string, version: string, history?: InstallHistory): boolean;
73
+ /**
74
+ * Deduplicate a package list against previously installed packages.
75
+ *
76
+ * @param packages - Record of { name: version } to install
77
+ * @param history - Optional pre-loaded history (avoids re-reading from disk)
78
+ * @returns DedupResult with toInstall and skipped lists
79
+ */
80
+ export declare function dedup(packages: Record<string, string>, history?: InstallHistory): DedupResult;
81
+ /**
82
+ * Deduplicate and generate a human-readable report
83
+ */
84
+ export declare function dedupWithReport(packages: Record<string, string>, history?: InstallHistory): {
85
+ result: DedupResult;
86
+ report: DedupReport;
87
+ };
88
+ /**
89
+ * Deduplicate an install block (multiple installer types)
90
+ * Used for snapshot.install which has structure: { "skit": {...}, "npm-proxy": {...} }
91
+ */
92
+ export declare function dedupInstallBlock(installBlock: Record<string, Record<string, string>>, history?: InstallHistory): {
93
+ dedupedBlock: Record<string, Record<string, string>>;
94
+ totalSkipped: SkippedPackage[];
95
+ };
96
+ /**
97
+ * Clear all install history (useful for fresh installs or testing)
98
+ */
99
+ export declare function clearInstallHistory(historyPath?: string): void;
100
+ /**
101
+ * Get packages installed by a specific snapshot
102
+ */
103
+ export declare function getPackagesBySnapshot(snapshotName: string, historyPath?: string): Record<string, string>;
104
+ /**
105
+ * Get total count of installed packages
106
+ */
107
+ export declare function getInstalledCount(historyPath?: string): number;
108
+ //# sourceMappingURL=dedup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dedup.d.ts","sourceRoot":"","sources":["../src/dedup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Snapshot Deduplication Logic
3
+ *
4
+ * Detects already-installed packages and removes duplicates from install lists.
5
+ * Prevents redundant installs when extending snapshots (e.g., full extends minimal).
6
+ *
7
+ * Storage: ~/.config/ist-snapshot/installed-history.json
8
+ * Format: { "packages": { "@ist/sesh@0.3.33": { snapshot, installedAt } } }
9
+ */
10
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
11
+ import { homedir } from 'os';
12
+ import { join } from 'path';
13
+ // ============================================================
14
+ // History File Management
15
+ // ============================================================
16
+ const HISTORY_DIR = join(homedir(), '.config', 'ist-snapshot');
17
+ const HISTORY_FILE = join(HISTORY_DIR, 'installed-history.json');
18
+ /**
19
+ * Get the path to the install history file.
20
+ * Exposed for testing/override purposes.
21
+ */
22
+ export function getHistoryFilePath() {
23
+ return HISTORY_FILE;
24
+ }
25
+ /**
26
+ * Load install history from disk
27
+ */
28
+ export function loadInstallHistory(historyPath) {
29
+ const filePath = historyPath || HISTORY_FILE;
30
+ if (!existsSync(filePath)) {
31
+ return { packages: {}, updatedAt: new Date().toISOString() };
32
+ }
33
+ try {
34
+ const content = readFileSync(filePath, 'utf-8');
35
+ const data = JSON.parse(content);
36
+ // Validate structure
37
+ if (!data.packages || typeof data.packages !== 'object') {
38
+ return { packages: {}, updatedAt: new Date().toISOString() };
39
+ }
40
+ return data;
41
+ }
42
+ catch {
43
+ // Corrupted file - start fresh
44
+ return { packages: {}, updatedAt: new Date().toISOString() };
45
+ }
46
+ }
47
+ /**
48
+ * Save install history to disk
49
+ */
50
+ export function saveInstallHistory(history, historyPath) {
51
+ const filePath = historyPath || HISTORY_FILE;
52
+ const dir = join(filePath, '..');
53
+ if (!existsSync(dir)) {
54
+ mkdirSync(dir, { recursive: true });
55
+ }
56
+ history.updatedAt = new Date().toISOString();
57
+ writeFileSync(filePath, JSON.stringify(history, null, 2));
58
+ }
59
+ /**
60
+ * Record successfully installed packages into history
61
+ */
62
+ export function recordInstalledPackages(packages, snapshotName, historyPath) {
63
+ const history = loadInstallHistory(historyPath);
64
+ const now = new Date().toISOString();
65
+ for (const [name, version] of Object.entries(packages)) {
66
+ const key = `${name}@${version}`;
67
+ history.packages[key] = {
68
+ snapshot: snapshotName,
69
+ installedAt: now,
70
+ version,
71
+ };
72
+ }
73
+ saveInstallHistory(history, historyPath);
74
+ }
75
+ /**
76
+ * Record a list of installed package specs (e.g., ["@ist/sesh@0.3.33"])
77
+ */
78
+ export function recordInstalledSpecs(specs, snapshotName, historyPath) {
79
+ const packages = {};
80
+ for (const spec of specs) {
81
+ const atIdx = spec.lastIndexOf('@');
82
+ if (atIdx > 0) {
83
+ const name = spec.substring(0, atIdx);
84
+ const version = spec.substring(atIdx + 1);
85
+ packages[name] = version;
86
+ }
87
+ }
88
+ recordInstalledPackages(packages, snapshotName, historyPath);
89
+ }
90
+ // ============================================================
91
+ // Dedup Logic
92
+ // ============================================================
93
+ /**
94
+ * Check if a specific package@version is already installed
95
+ */
96
+ export function isAlreadyInstalled(name, version, history) {
97
+ const h = history || loadInstallHistory();
98
+ const key = `${name}@${version}`;
99
+ return key in h.packages;
100
+ }
101
+ /**
102
+ * Deduplicate a package list against previously installed packages.
103
+ *
104
+ * @param packages - Record of { name: version } to install
105
+ * @param history - Optional pre-loaded history (avoids re-reading from disk)
106
+ * @returns DedupResult with toInstall and skipped lists
107
+ */
108
+ export function dedup(packages, history) {
109
+ const h = history || loadInstallHistory();
110
+ const toInstall = {};
111
+ const skipped = [];
112
+ for (const [name, version] of Object.entries(packages)) {
113
+ const key = `${name}@${version}`;
114
+ const existing = h.packages[key];
115
+ if (existing) {
116
+ skipped.push({
117
+ name,
118
+ version,
119
+ installedBy: existing.snapshot,
120
+ installedAt: existing.installedAt,
121
+ });
122
+ }
123
+ else {
124
+ toInstall[name] = version;
125
+ }
126
+ }
127
+ return { toInstall, skipped };
128
+ }
129
+ /**
130
+ * Deduplicate and generate a human-readable report
131
+ */
132
+ export function dedupWithReport(packages, history) {
133
+ const result = dedup(packages, history);
134
+ const totalRequested = Object.keys(packages).length;
135
+ const report = {
136
+ totalRequested,
137
+ toInstallCount: Object.keys(result.toInstall).length,
138
+ skippedCount: result.skipped.length,
139
+ skipped: result.skipped,
140
+ };
141
+ return { result, report };
142
+ }
143
+ /**
144
+ * Deduplicate an install block (multiple installer types)
145
+ * Used for snapshot.install which has structure: { "skit": {...}, "npm-proxy": {...} }
146
+ */
147
+ export function dedupInstallBlock(installBlock, history) {
148
+ const h = history || loadInstallHistory();
149
+ const dedupedBlock = {};
150
+ const totalSkipped = [];
151
+ for (const [installerName, packages] of Object.entries(installBlock)) {
152
+ const { toInstall, skipped } = dedup(packages, h);
153
+ dedupedBlock[installerName] = toInstall;
154
+ totalSkipped.push(...skipped);
155
+ }
156
+ return { dedupedBlock, totalSkipped };
157
+ }
158
+ // ============================================================
159
+ // History Utilities
160
+ // ============================================================
161
+ /**
162
+ * Clear all install history (useful for fresh installs or testing)
163
+ */
164
+ export function clearInstallHistory(historyPath) {
165
+ const filePath = historyPath || HISTORY_FILE;
166
+ const emptyHistory = {
167
+ packages: {},
168
+ updatedAt: new Date().toISOString(),
169
+ };
170
+ saveInstallHistory(emptyHistory, filePath);
171
+ }
172
+ /**
173
+ * Get packages installed by a specific snapshot
174
+ */
175
+ export function getPackagesBySnapshot(snapshotName, historyPath) {
176
+ const history = loadInstallHistory(historyPath);
177
+ const result = {};
178
+ for (const [key, entry] of Object.entries(history.packages)) {
179
+ if (entry.snapshot === snapshotName) {
180
+ const atIdx = key.lastIndexOf('@');
181
+ if (atIdx > 0) {
182
+ const name = key.substring(0, atIdx);
183
+ result[name] = entry.version;
184
+ }
185
+ }
186
+ }
187
+ return result;
188
+ }
189
+ /**
190
+ * Get total count of installed packages
191
+ */
192
+ export function getInstalledCount(historyPath) {
193
+ const history = loadInstallHistory(historyPath);
194
+ return Object.keys(history.packages).length;
195
+ }
196
+ //# sourceMappingURL=dedup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dedup.js","sourceRoot":"","sources":["../src/dedup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @microwiseai/snapshot-dedup
3
+ *
4
+ * Deduplication module for Snapshot CLI.
5
+ * Prevents redundant package installations across snapshot extends chains.
6
+ *
7
+ * Usage:
8
+ * import { dedup, dedupWithReport, recordInstalledPackages } from '@microwiseai/snapshot-dedup';
9
+ *
10
+ * // Before installing
11
+ * const { result, report } = dedupWithReport(packages);
12
+ * console.log(`Skipping ${report.skippedCount} already-installed packages`);
13
+ *
14
+ * // Install only result.toInstall
15
+ * // ...
16
+ *
17
+ * // After successful install, record them
18
+ * recordInstalledPackages(result.toInstall, '@ist/full');
19
+ */
20
+ export { dedup, dedupWithReport, dedupInstallBlock, isAlreadyInstalled, loadInstallHistory, saveInstallHistory, recordInstalledPackages, recordInstalledSpecs, clearInstallHistory, getPackagesBySnapshot, getInstalledCount, getHistoryFilePath, type InstalledPackageEntry, type InstallHistory, type DedupResult, type DedupReport, type SkippedPackage, } from './dedup.js';
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAEL,KAAK,EACL,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAGlB,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EAGnB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAGlB,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,cAAc,GACpB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @microwiseai/snapshot-dedup
3
+ *
4
+ * Deduplication module for Snapshot CLI.
5
+ * Prevents redundant package installations across snapshot extends chains.
6
+ *
7
+ * Usage:
8
+ * import { dedup, dedupWithReport, recordInstalledPackages } from '@microwiseai/snapshot-dedup';
9
+ *
10
+ * // Before installing
11
+ * const { result, report } = dedupWithReport(packages);
12
+ * console.log(`Skipping ${report.skippedCount} already-installed packages`);
13
+ *
14
+ * // Install only result.toInstall
15
+ * // ...
16
+ *
17
+ * // After successful install, record them
18
+ * recordInstalledPackages(result.toInstall, '@ist/full');
19
+ */
20
+ export {
21
+ // Core dedup functions
22
+ dedup, dedupWithReport, dedupInstallBlock, isAlreadyInstalled,
23
+ // History management
24
+ loadInstallHistory, saveInstallHistory, recordInstalledPackages, recordInstalledSpecs, clearInstallHistory,
25
+ // Utility functions
26
+ getPackagesBySnapshot, getInstalledCount, getHistoryFilePath, } from './dedup.js';
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO;AACL,uBAAuB;AACvB,KAAK,EACL,eAAe,EACf,iBAAiB,EACjB,kBAAkB;AAElB,qBAAqB;AACrB,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB;AAEnB,oBAAoB;AACpB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,GAQnB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@microwiseai/snapshot-dedup",
3
+ "version": "0.1.0",
4
+ "description": "Deduplication logic for Snapshot CLI - prevents reinstalling already-installed packages",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "dev": "tsc --watch",
17
+ "test": "vitest",
18
+ "test:run": "vitest run",
19
+ "prepublishOnly": "npm run build"
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "keywords": [
25
+ "snapshot",
26
+ "dedup",
27
+ "deduplication",
28
+ "install"
29
+ ],
30
+ "author": "IST Team",
31
+ "license": "MIT",
32
+ "dependencies": {},
33
+ "devDependencies": {
34
+ "@types/node": "^20.11.0",
35
+ "typescript": "^5.7.3",
36
+ "vitest": "^4.0.18"
37
+ },
38
+ "engines": {
39
+ "node": ">=18.0.0"
40
+ }
41
+ }