@memberjunction/cli 5.41.0 → 5.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/dist/commands/app/install.d.ts.map +1 -1
  2. package/dist/commands/app/install.js +2 -1
  3. package/dist/commands/app/install.js.map +1 -1
  4. package/dist/commands/bundle/index.d.ts +1 -0
  5. package/dist/commands/bundle/index.d.ts.map +1 -1
  6. package/dist/commands/bundle/index.js +7 -1
  7. package/dist/commands/bundle/index.js.map +1 -1
  8. package/dist/commands/codegen/index.d.ts +6 -16
  9. package/dist/commands/codegen/index.d.ts.map +1 -1
  10. package/dist/commands/codegen/index.js +6 -90
  11. package/dist/commands/codegen/index.js.map +1 -1
  12. package/dist/commands/codegen/manifest.d.ts +41 -10
  13. package/dist/commands/codegen/manifest.d.ts.map +1 -1
  14. package/dist/commands/codegen/manifest.js +66 -0
  15. package/dist/commands/codegen/manifest.js.map +1 -1
  16. package/dist/commands/codegen/usage.d.ts +7 -0
  17. package/dist/commands/codegen/usage.d.ts.map +1 -0
  18. package/dist/commands/codegen/usage.js +10 -0
  19. package/dist/commands/codegen/usage.js.map +1 -0
  20. package/dist/commands/install/claude.d.ts +35 -0
  21. package/dist/commands/install/claude.d.ts.map +1 -0
  22. package/dist/commands/install/claude.js +108 -0
  23. package/dist/commands/install/claude.js.map +1 -0
  24. package/dist/commands/install/index.d.ts +1 -0
  25. package/dist/commands/install/index.d.ts.map +1 -1
  26. package/dist/commands/install/index.js +4 -0
  27. package/dist/commands/install/index.js.map +1 -1
  28. package/dist/commands/migrate/convert.d.ts +59 -12
  29. package/dist/commands/migrate/convert.d.ts.map +1 -1
  30. package/dist/commands/migrate/convert.js +294 -21
  31. package/dist/commands/migrate/convert.js.map +1 -1
  32. package/dist/commands/migrate/rebake.d.ts +41 -0
  33. package/dist/commands/migrate/rebake.d.ts.map +1 -0
  34. package/dist/commands/migrate/rebake.js +193 -0
  35. package/dist/commands/migrate/rebake.js.map +1 -0
  36. package/dist/commands/plugin/add.d.ts +18 -0
  37. package/dist/commands/plugin/add.d.ts.map +1 -0
  38. package/dist/commands/plugin/add.js +53 -0
  39. package/dist/commands/plugin/add.js.map +1 -0
  40. package/dist/commands/sync/pull.d.ts +6 -26
  41. package/dist/commands/sync/pull.d.ts.map +1 -1
  42. package/dist/commands/sync/pull.js +6 -281
  43. package/dist/commands/sync/pull.js.map +1 -1
  44. package/dist/commands/sync/push.d.ts +8 -19
  45. package/dist/commands/sync/push.d.ts.map +1 -1
  46. package/dist/commands/sync/push.js +8 -328
  47. package/dist/commands/sync/push.js.map +1 -1
  48. package/dist/commands/sync/usage.d.ts +7 -0
  49. package/dist/commands/sync/usage.d.ts.map +1 -0
  50. package/dist/commands/sync/usage.js +10 -0
  51. package/dist/commands/sync/usage.js.map +1 -0
  52. package/dist/commands/update/claude.d.ts +37 -0
  53. package/dist/commands/update/claude.d.ts.map +1 -0
  54. package/dist/commands/update/claude.js +90 -0
  55. package/dist/commands/update/claude.js.map +1 -0
  56. package/dist/commands/usage.d.ts +17 -0
  57. package/dist/commands/usage.d.ts.map +1 -0
  58. package/dist/commands/usage.js +29 -0
  59. package/dist/commands/usage.js.map +1 -0
  60. package/dist/config.d.ts +41 -7
  61. package/dist/config.d.ts.map +1 -1
  62. package/dist/config.js +9 -4
  63. package/dist/config.js.map +1 -1
  64. package/dist/hooks/prerun.d.ts.map +1 -1
  65. package/dist/hooks/prerun.js +49 -8
  66. package/dist/hooks/prerun.js.map +1 -1
  67. package/dist/lib/claude-pack/ManagedBlockEditor.d.ts +40 -0
  68. package/dist/lib/claude-pack/ManagedBlockEditor.d.ts.map +1 -0
  69. package/dist/lib/claude-pack/ManagedBlockEditor.js +127 -0
  70. package/dist/lib/claude-pack/ManagedBlockEditor.js.map +1 -0
  71. package/dist/lib/claude-pack/PackFetcher.d.ts +86 -0
  72. package/dist/lib/claude-pack/PackFetcher.d.ts.map +1 -0
  73. package/dist/lib/claude-pack/PackFetcher.js +163 -0
  74. package/dist/lib/claude-pack/PackFetcher.js.map +1 -0
  75. package/dist/lib/claude-pack/PackInstaller.d.ts +62 -0
  76. package/dist/lib/claude-pack/PackInstaller.d.ts.map +1 -0
  77. package/dist/lib/claude-pack/PackInstaller.js +197 -0
  78. package/dist/lib/claude-pack/PackInstaller.js.map +1 -0
  79. package/dist/lib/claude-pack/PackMerger.d.ts +61 -0
  80. package/dist/lib/claude-pack/PackMerger.d.ts.map +1 -0
  81. package/dist/lib/claude-pack/PackMerger.js +315 -0
  82. package/dist/lib/claude-pack/PackMerger.js.map +1 -0
  83. package/dist/lib/claude-pack/PackOutputFormatter.d.ts +29 -0
  84. package/dist/lib/claude-pack/PackOutputFormatter.d.ts.map +1 -0
  85. package/dist/lib/claude-pack/PackOutputFormatter.js +82 -0
  86. package/dist/lib/claude-pack/PackOutputFormatter.js.map +1 -0
  87. package/dist/lib/claude-pack/PackPaths.d.ts +80 -0
  88. package/dist/lib/claude-pack/PackPaths.d.ts.map +1 -0
  89. package/dist/lib/claude-pack/PackPaths.js +182 -0
  90. package/dist/lib/claude-pack/PackPaths.js.map +1 -0
  91. package/dist/lib/claude-pack/PackTypes.d.ts +124 -0
  92. package/dist/lib/claude-pack/PackTypes.d.ts.map +1 -0
  93. package/dist/lib/claude-pack/PackTypes.js +32 -0
  94. package/dist/lib/claude-pack/PackTypes.js.map +1 -0
  95. package/dist/lib/claude-pack/SettingsMerger.d.ts +47 -0
  96. package/dist/lib/claude-pack/SettingsMerger.d.ts.map +1 -0
  97. package/dist/lib/claude-pack/SettingsMerger.js +163 -0
  98. package/dist/lib/claude-pack/SettingsMerger.js.map +1 -0
  99. package/dist/lib/cli-plugins.d.ts +16 -0
  100. package/dist/lib/cli-plugins.d.ts.map +1 -0
  101. package/dist/lib/cli-plugins.js +26 -0
  102. package/dist/lib/cli-plugins.js.map +1 -0
  103. package/dist/lib/domain-usage-command.d.ts +16 -0
  104. package/dist/lib/domain-usage-command.d.ts.map +1 -0
  105. package/dist/lib/domain-usage-command.js +23 -0
  106. package/dist/lib/domain-usage-command.js.map +1 -0
  107. package/dist/lib/usage-render.d.ts +14 -0
  108. package/dist/lib/usage-render.d.ts.map +1 -0
  109. package/dist/lib/usage-render.js +64 -0
  110. package/dist/lib/usage-render.js.map +1 -0
  111. package/dist/light-commands.d.ts.map +1 -1
  112. package/dist/light-commands.js +11 -0
  113. package/dist/light-commands.js.map +1 -1
  114. package/dist/utils/open-app-context.d.ts +5 -5
  115. package/dist/utils/open-app-context.d.ts.map +1 -1
  116. package/dist/utils/open-app-context.js +44 -48
  117. package/dist/utils/open-app-context.js.map +1 -1
  118. package/oclif.manifest.json +821 -134
  119. package/package.json +17 -15
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Fetches a Claude Code pack from `raw.githubusercontent.com`, verifies sha256
3
+ * against the manifest, and handles the tag→main ref-fallback per plan §8.5.
4
+ *
5
+ * Design notes:
6
+ * - HTTP transport is injected via `HttpGetter` so tests can plug in a mock
7
+ * without `vi.mock('node:https')`. Production uses `realHttpGet` (a thin
8
+ * wrapper over `node:https`).
9
+ * - No tokens, no auth headers — `raw.githubusercontent.com` is public
10
+ * (plan §7.7). The fetcher never includes credentials.
11
+ * - No caching here. The orchestrator decides whether to re-fetch.
12
+ *
13
+ * @see plans/claude-install-pack.md §5.2 (manifest), §6.3, §8.5 (ref fallback)
14
+ */
15
+ import { createHash } from 'node:crypto';
16
+ import https from 'node:https';
17
+ import { buildRemoteUrlPrefix } from './PackPaths.js';
18
+ /**
19
+ * Real production fetcher using `node:https`.
20
+ *
21
+ * Implementation note: builds the response body via manual Uint8Array
22
+ * concatenation instead of `Buffer.concat()` — the latter's return type
23
+ * (`Buffer`) doesn't cleanly assign to `Uint8Array` in the strict @types/node
24
+ * generics that ship with v20+, even though Buffer extends Uint8Array.
25
+ */
26
+ export const realHttpGet = (url) => new Promise((resolve, reject) => {
27
+ const req = https.get(url, (res) => {
28
+ const chunks = [];
29
+ res.on('data', (chunk) => chunks.push(chunk));
30
+ res.on('end', () => {
31
+ resolve({ statusCode: res.statusCode ?? 0, body: concatBytes(chunks) });
32
+ });
33
+ res.on('error', reject);
34
+ });
35
+ req.on('error', reject);
36
+ req.setTimeout(30_000, () => {
37
+ req.destroy(new Error(`Timed out after 30s fetching ${url}`));
38
+ });
39
+ });
40
+ function concatBytes(chunks) {
41
+ const total = chunks.reduce((s, c) => s + c.byteLength, 0);
42
+ const out = new Uint8Array(total);
43
+ let offset = 0;
44
+ for (const c of chunks) {
45
+ out.set(c, offset);
46
+ offset += c.byteLength;
47
+ }
48
+ return out;
49
+ }
50
+ // ---------------------------------------------------------------------------
51
+ // Errors
52
+ // ---------------------------------------------------------------------------
53
+ export class PackFetchError extends Error {
54
+ constructor(message, url, statusCode) {
55
+ super(message);
56
+ this.url = url;
57
+ this.statusCode = statusCode;
58
+ this.name = 'PackFetchError';
59
+ }
60
+ }
61
+ export class PackChecksumError extends Error {
62
+ constructor(message, path, expected, actual) {
63
+ super(message);
64
+ this.path = path;
65
+ this.expected = expected;
66
+ this.actual = actual;
67
+ this.name = 'PackChecksumError';
68
+ }
69
+ }
70
+ // ---------------------------------------------------------------------------
71
+ // Main entry point
72
+ // ---------------------------------------------------------------------------
73
+ /**
74
+ * Fetch a pack: manifest first, then every file listed in it, verifying
75
+ * sha256 along the way. Falls back from a specific tag to `main` if the
76
+ * manifest 404s.
77
+ */
78
+ export async function fetchPack(opts) {
79
+ const httpGet = opts.HttpGet ?? realHttpGet;
80
+ const requestedRef = opts.Ref ?? 'main';
81
+ const onProgress = opts.OnProgress ?? (() => { });
82
+ const { manifest, refUsed, baseUrl } = await fetchManifestWithFallback(opts.Major, requestedRef, httpGet, onProgress);
83
+ const files = new Map();
84
+ if (opts.ManifestOnly) {
85
+ return { Manifest: manifest, Files: files, RefUsed: refUsed, BaseUrl: baseUrl };
86
+ }
87
+ for (const entry of manifest.files) {
88
+ const url = baseUrl + entry.path;
89
+ onProgress(`fetching ${entry.path}`);
90
+ const res = await httpGet(url);
91
+ if (res.statusCode !== 200) {
92
+ throw new PackFetchError(`Failed to fetch ${entry.path}: HTTP ${res.statusCode}`, url, res.statusCode);
93
+ }
94
+ verifyChecksum(entry, res.body);
95
+ files.set(entry.path, res.body);
96
+ }
97
+ return { Manifest: manifest, Files: files, RefUsed: refUsed, BaseUrl: baseUrl };
98
+ }
99
+ // ---------------------------------------------------------------------------
100
+ // Internals
101
+ // ---------------------------------------------------------------------------
102
+ async function fetchManifestWithFallback(major, requestedRef, httpGet, onProgress) {
103
+ const tryRef = async (ref) => {
104
+ const baseUrl = buildRemoteUrlPrefix(major, ref);
105
+ const manifestUrl = baseUrl + '.claude/mj/MANIFEST.json';
106
+ onProgress(`fetching manifest from ref=${ref}`);
107
+ const res = await httpGet(manifestUrl);
108
+ return { res, baseUrl, manifestUrl };
109
+ };
110
+ // First attempt: requested ref
111
+ const first = await tryRef(requestedRef);
112
+ if (first.res.statusCode === 200) {
113
+ return {
114
+ manifest: parseManifest(first.res.body, first.manifestUrl),
115
+ refUsed: requestedRef,
116
+ baseUrl: first.baseUrl,
117
+ };
118
+ }
119
+ // Fallback: try `main` if we weren't already on it AND the failure was 404.
120
+ // Other status codes (5xx, network errors) propagate immediately —
121
+ // fallback is for "this tag doesn't have the pack yet", not for "the
122
+ // network is broken".
123
+ if (first.res.statusCode === 404 && requestedRef !== 'main') {
124
+ onProgress(`ref ${requestedRef} 404; falling back to main`);
125
+ const second = await tryRef('main');
126
+ if (second.res.statusCode === 200) {
127
+ return {
128
+ manifest: parseManifest(second.res.body, second.manifestUrl),
129
+ refUsed: 'main',
130
+ baseUrl: second.baseUrl,
131
+ };
132
+ }
133
+ throw new PackFetchError(`Failed to fetch manifest from both ${requestedRef} and main (HTTP ${second.res.statusCode})`, second.manifestUrl, second.res.statusCode);
134
+ }
135
+ throw new PackFetchError(`Failed to fetch manifest from ${requestedRef}: HTTP ${first.res.statusCode}`, first.manifestUrl, first.res.statusCode);
136
+ }
137
+ function parseManifest(body, url) {
138
+ let raw;
139
+ try {
140
+ raw = JSON.parse(new TextDecoder('utf-8').decode(body));
141
+ }
142
+ catch (err) {
143
+ throw new PackFetchError(`Manifest at ${url} is not valid JSON: ${err.message}`, url);
144
+ }
145
+ if (!raw ||
146
+ typeof raw !== 'object' ||
147
+ typeof raw.packVersion !== 'string' ||
148
+ typeof raw.mjMajor !== 'string' ||
149
+ !Array.isArray(raw.files)) {
150
+ throw new PackFetchError(`Manifest at ${url} has the wrong shape`, url);
151
+ }
152
+ return raw;
153
+ }
154
+ function verifyChecksum(entry, body) {
155
+ const actual = createHash('sha256').update(body).digest('hex');
156
+ if (actual !== entry.sha256) {
157
+ throw new PackChecksumError(`Checksum mismatch for ${entry.path}: expected ${entry.sha256}, got ${actual}`, entry.path, entry.sha256, actual);
158
+ }
159
+ if (body.length !== entry.bytes) {
160
+ throw new PackChecksumError(`Size mismatch for ${entry.path}: expected ${entry.bytes} bytes, got ${body.length}`, entry.path, String(entry.bytes), String(body.length));
161
+ }
162
+ }
163
+ //# sourceMappingURL=PackFetcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PackFetcher.js","sourceRoot":"","sources":["../../../src/lib/claude-pack/PackFetcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Top-level orchestrator for `mj install:claude` and `mj update:claude`.
3
+ *
4
+ * Composes:
5
+ * - source resolution (remote via PackFetcher, or local via PackPaths)
6
+ * - MJ-major detection and the cross-major guard
7
+ * - the --check fast path (compare versions without touching the FS)
8
+ * - the merge (PackMerger) and InstallResult assembly
9
+ *
10
+ * The CLI command files thinly wrap this with flag parsing + output rendering.
11
+ *
12
+ * @see plans/claude-install-pack.md §6.3, §6.5, §7.4, §7.5
13
+ */
14
+ import { type HttpGetter } from './PackFetcher.js';
15
+ import { buildRemoteUrlPrefix } from './PackPaths.js';
16
+ import { type InstallResult } from './PackTypes.js';
17
+ export interface InstallPackOptions {
18
+ /** Absolute or relative target directory (default: process.cwd()). */
19
+ TargetDir: string;
20
+ /** Override the detected MJ major. Useful when target dir has no MJ deps yet. */
21
+ Major?: string;
22
+ /** Git ref to fetch from (branch or tag). Default: `'main'`. */
23
+ Ref?: string;
24
+ /**
25
+ * Use a local pack source instead of fetching. Accepts an MJ repo root
26
+ * (looks under `templates/claude-pack/dist/v{N}/`) or an already-unpacked
27
+ * dist directory.
28
+ */
29
+ FromPath?: string;
30
+ /** Forbid network — requires FromPath. */
31
+ Offline?: boolean;
32
+ /** Don't write anything, just compute the action plan. */
33
+ DryRun?: boolean;
34
+ /** Overwrite user-customized commands/skills (skip prompts). */
35
+ Force?: boolean;
36
+ /** Skip the seed of `.claude/commands/`. */
37
+ SkipCommands?: boolean;
38
+ /** Skip the seed of `.claude/skills/`. */
39
+ SkipSkills?: boolean;
40
+ /** Skip the `.claude/settings.json` deep-merge. */
41
+ SkipSettings?: boolean;
42
+ /** update:claude only — resync commands. */
43
+ RefreshCommands?: boolean;
44
+ /** update:claude only — resync skills. */
45
+ RefreshSkills?: boolean;
46
+ /** update:claude only — don't write; compare versions and return. */
47
+ CheckOnly?: boolean;
48
+ /**
49
+ * update:claude only — required when the remote pack's major differs from
50
+ * the local MJ install's major. Without this flag, the installer refuses
51
+ * the cross-major migration as a guardrail.
52
+ */
53
+ AllowMajor?: boolean;
54
+ /** Injected HTTP getter (tests). Defaults to real `node:https`. */
55
+ HttpGet?: HttpGetter;
56
+ /** Progress callback for verbose mode. */
57
+ OnProgress?: (message: string) => void;
58
+ }
59
+ export declare function installPack(opts: InstallPackOptions): Promise<InstallResult>;
60
+ /** Re-export the default raw URL prefix for tests / verbose logging. */
61
+ export { buildRemoteUrlPrefix };
62
+ //# sourceMappingURL=PackInstaller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PackInstaller.d.ts","sourceRoot":"","sources":["../../../src/lib/claude-pack/PackInstaller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,EAAa,KAAK,UAAU,EAAkB,MAAM,kBAAkB,CAAC;AAE9E,OAAO,EACH,oBAAoB,EAIvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAGH,KAAK,aAAa,EAErB,MAAM,gBAAgB,CAAC;AAMxB,MAAM,WAAW,kBAAkB;IAC/B,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gEAAgE;IAChE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4CAA4C;IAC5C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mDAAmD;IACnD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,4CAA4C;IAC5C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,0CAA0C;IAC1C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qEAAqE;IACrE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mEAAmE;IACnE,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C;AAMD,wBAAsB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,CA2ElF;AA8ID,wEAAwE;AACxE,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Top-level orchestrator for `mj install:claude` and `mj update:claude`.
3
+ *
4
+ * Composes:
5
+ * - source resolution (remote via PackFetcher, or local via PackPaths)
6
+ * - MJ-major detection and the cross-major guard
7
+ * - the --check fast path (compare versions without touching the FS)
8
+ * - the merge (PackMerger) and InstallResult assembly
9
+ *
10
+ * The CLI command files thinly wrap this with flag parsing + output rendering.
11
+ *
12
+ * @see plans/claude-install-pack.md §6.3, §6.5, §7.4, §7.5
13
+ */
14
+ import { createHash } from 'node:crypto';
15
+ import { existsSync, readFileSync } from 'node:fs';
16
+ import path from 'node:path';
17
+ import { fetchPack, PackFetchError } from './PackFetcher.js';
18
+ import { mergePack } from './PackMerger.js';
19
+ import { buildRemoteUrlPrefix, detectMJMajor, detectMJVersionString, resolveLocalPackRoot, } from './PackPaths.js';
20
+ import { emptyActionLog, } from './PackTypes.js';
21
+ // ---------------------------------------------------------------------------
22
+ // Main entry point
23
+ // ---------------------------------------------------------------------------
24
+ export async function installPack(opts) {
25
+ const targetDir = path.resolve(opts.TargetDir);
26
+ const onProgress = opts.OnProgress ?? (() => { });
27
+ const major = opts.Major ?? detectMJMajor(targetDir);
28
+ if (!major) {
29
+ return errorResult(null, 'Could not detect MJ major version (no @memberjunction/* in package.json). ' +
30
+ 'Pass --major <N> to override.');
31
+ }
32
+ if (opts.Offline && !opts.FromPath) {
33
+ return errorResult(detectMJVersion(targetDir), '--offline requires --from <path>.');
34
+ }
35
+ onProgress(`resolving pack (major=v${major}${opts.FromPath ? `, from=${opts.FromPath}` : ''})`);
36
+ let manifest;
37
+ let files;
38
+ try {
39
+ ({ manifest, files } = await resolvePack(major, opts, onProgress));
40
+ }
41
+ catch (err) {
42
+ const installedMJ = detectMJVersion(targetDir);
43
+ if (err instanceof PackFetchError) {
44
+ return errorResult(installedMJ, `Failed to fetch pack: ${err.message}`);
45
+ }
46
+ return errorResult(installedMJ, `Failed to resolve pack: ${err.message}`);
47
+ }
48
+ const installedMJVersion = detectMJVersion(targetDir);
49
+ // --check: compare versions and return without writing.
50
+ if (opts.CheckOnly) {
51
+ return buildCheckResult(targetDir, manifest, installedMJVersion);
52
+ }
53
+ // Cross-major guardrail — pack's major must match local MJ unless explicitly allowed.
54
+ if (manifest.mjMajor !== major && !opts.AllowMajor) {
55
+ return errorResult(installedMJVersion, `Pack major v${manifest.mjMajor} doesn't match local MJ major v${major}. ` +
56
+ `Pass --allow-major to apply anyway.`);
57
+ }
58
+ // Inject MANIFEST.json into the files map so the merger writes it to disk.
59
+ // (The fetched MANIFEST.json itself is not in `files` because the manifest
60
+ // omits its own entry to avoid the self-reference.)
61
+ const manifestBytes = new TextEncoder().encode(JSON.stringify(manifest, null, 2) + '\n');
62
+ files.set('.claude/mj/MANIFEST.json', manifestBytes);
63
+ onProgress('merging pack into target');
64
+ const { Actions, Warnings } = mergePack({
65
+ TargetDir: targetDir,
66
+ PackFiles: files,
67
+ Manifest: manifest,
68
+ DryRun: opts.DryRun,
69
+ Force: opts.Force,
70
+ SkipCommands: opts.SkipCommands,
71
+ SkipSkills: opts.SkipSkills,
72
+ SkipSettings: opts.SkipSettings,
73
+ RefreshCommands: opts.RefreshCommands,
74
+ RefreshSkills: opts.RefreshSkills,
75
+ });
76
+ return {
77
+ ok: Actions.errors.length === 0,
78
+ packVersion: manifest.packVersion,
79
+ installedMJVersion,
80
+ actions: Actions,
81
+ warnings: Warnings,
82
+ notes: [],
83
+ };
84
+ }
85
+ // ---------------------------------------------------------------------------
86
+ // Source resolution
87
+ // ---------------------------------------------------------------------------
88
+ async function resolvePack(major, opts, onProgress) {
89
+ if (opts.FromPath) {
90
+ const localRoot = resolveLocalPackRoot(opts.FromPath, major);
91
+ if (!localRoot) {
92
+ throw new Error(`Could not find a Claude pack at --from path: ${opts.FromPath}. ` +
93
+ `Expected either an MJ repo root (with templates/claude-pack/dist/v${major}/) or an unpacked dist directory.`);
94
+ }
95
+ return loadLocalPack(localRoot, opts.CheckOnly ?? false);
96
+ }
97
+ const fetched = await fetchPack({
98
+ Major: major,
99
+ Ref: opts.Ref,
100
+ HttpGet: opts.HttpGet,
101
+ OnProgress: onProgress,
102
+ ManifestOnly: opts.CheckOnly,
103
+ });
104
+ return { manifest: fetched.Manifest, files: fetched.Files };
105
+ }
106
+ /**
107
+ * Read a pack from a local directory, verifying every file's sha256 against
108
+ * the manifest (sanity check — guards against partial/corrupt local copies).
109
+ */
110
+ function loadLocalPack(rootDir, manifestOnly) {
111
+ const manifestPath = path.join(rootDir, '.claude', 'mj', 'MANIFEST.json');
112
+ if (!existsSync(manifestPath)) {
113
+ throw new Error(`Local pack at ${rootDir} has no .claude/mj/MANIFEST.json`);
114
+ }
115
+ let manifest;
116
+ try {
117
+ manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
118
+ }
119
+ catch (err) {
120
+ throw new Error(`Local pack manifest at ${manifestPath} is not valid JSON: ${err.message}`);
121
+ }
122
+ const files = new Map();
123
+ if (manifestOnly) {
124
+ return { manifest, files };
125
+ }
126
+ for (const entry of manifest.files) {
127
+ const abs = path.join(rootDir, ...entry.path.split('/'));
128
+ if (!existsSync(abs)) {
129
+ throw new Error(`Local pack missing file: ${entry.path}`);
130
+ }
131
+ // `new Uint8Array(readFileSync(...))` normalizes Buffer → Uint8Array
132
+ // for the strict @types/node generics (see PackFetcher.ts for context).
133
+ const bytes = new Uint8Array(readFileSync(abs));
134
+ const hash = createHash('sha256').update(bytes).digest('hex');
135
+ if (hash !== entry.sha256) {
136
+ throw new Error(`Local pack checksum mismatch for ${entry.path}: expected ${entry.sha256}, got ${hash}`);
137
+ }
138
+ files.set(entry.path, bytes);
139
+ }
140
+ return { manifest, files };
141
+ }
142
+ // ---------------------------------------------------------------------------
143
+ // --check fast path
144
+ // ---------------------------------------------------------------------------
145
+ function buildCheckResult(targetDir, manifest, installedMJVersion) {
146
+ const localVersionFile = path.join(targetDir, '.claude', 'mj', 'VERSION');
147
+ const localVersion = existsSync(localVersionFile)
148
+ ? readFileSync(localVersionFile, 'utf8').trim()
149
+ : null;
150
+ const actions = emptyActionLog();
151
+ const warnings = [];
152
+ const notes = [];
153
+ if (!localVersion) {
154
+ // "No local pack" is a state worth flagging — the user ran --check
155
+ // expecting an installed pack and there isn't one.
156
+ warnings.push('No local pack found (.claude/mj/VERSION missing).');
157
+ }
158
+ else if (localVersion === manifest.packVersion) {
159
+ // "Up to date" is the success case for --check, not a warning.
160
+ notes.push(`Pack is up to date (v${localVersion}).`);
161
+ }
162
+ else {
163
+ // "Update available" is informational — there's an action the user
164
+ // *can* take, but nothing is wrong.
165
+ notes.push(`Update available: v${localVersion} → v${manifest.packVersion}. Run \`mj update:claude\` to apply.`);
166
+ }
167
+ return {
168
+ ok: true,
169
+ packVersion: manifest.packVersion,
170
+ installedMJVersion,
171
+ actions,
172
+ warnings,
173
+ notes,
174
+ };
175
+ }
176
+ // ---------------------------------------------------------------------------
177
+ // Helpers
178
+ // ---------------------------------------------------------------------------
179
+ function errorResult(installedMJVersion, message) {
180
+ return {
181
+ ok: false,
182
+ packVersion: '',
183
+ installedMJVersion,
184
+ actions: { ...emptyActionLog(), errors: [message] },
185
+ warnings: [],
186
+ notes: [],
187
+ };
188
+ }
189
+ /**
190
+ * Detect the full MJ semver in the target dir (e.g. `5.33.0`). Delegates
191
+ * to {@link detectMJVersionString} in PackPaths so the workspace-walk
192
+ * behavior stays in sync with {@link detectMJMajor}.
193
+ */
194
+ const detectMJVersion = detectMJVersionString;
195
+ /** Re-export the default raw URL prefix for tests / verbose logging. */
196
+ export { buildRemoteUrlPrefix };
197
+ //# sourceMappingURL=PackInstaller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PackInstaller.js","sourceRoot":"","sources":["../../../src/lib/claude-pack/PackInstaller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Per-file merge for the Claude Code pack.
3
+ *
4
+ * Implements the table in plans/claude-install-pack.md §6.4:
5
+ *
6
+ * CLAUDE.md — managed-block rewrite (preserves user content)
7
+ * .claude/mj/** — overwritten as a unit (incl. sweep of stale files)
8
+ * .claude/settings.json — deep-merge per §10.2
9
+ * .claude/commands/* — seed-once; overwrite needs --force / --refresh-commands
10
+ * .claude/skills/** — same rule as commands
11
+ *
12
+ * The merger never destroys user content by default. `Force` and the
13
+ * `Refresh*` flags are explicit opt-ins.
14
+ */
15
+ import { ManagedBlockError } from './ManagedBlockEditor.js';
16
+ import { type ActionLog, type Manifest } from './PackTypes.js';
17
+ export interface PackMergeOptions {
18
+ /** Absolute path to the user's project. */
19
+ TargetDir: string;
20
+ /**
21
+ * Pack contents keyed by pack-relative POSIX path. Must include the
22
+ * MANIFEST.json under `.claude/mj/MANIFEST.json` (PackInstaller injects it).
23
+ */
24
+ PackFiles: Map<string, Uint8Array>;
25
+ Manifest: Manifest;
26
+ /** Don't write anything — just compute the action plan. */
27
+ DryRun?: boolean;
28
+ /** Overwrite user-modified commands/skills without prompting. */
29
+ Force?: boolean;
30
+ /** Skip the seed of `.claude/commands/`. */
31
+ SkipCommands?: boolean;
32
+ /** Skip the seed of `.claude/skills/`. */
33
+ SkipSkills?: boolean;
34
+ /** Skip the settings.json deep-merge. */
35
+ SkipSettings?: boolean;
36
+ /** Resync commands from pack (update:claude). Equivalent to per-file --force on commands. */
37
+ RefreshCommands?: boolean;
38
+ /** Resync skills from pack (update:claude). */
39
+ RefreshSkills?: boolean;
40
+ }
41
+ export interface PackMergeResult {
42
+ Actions: ActionLog;
43
+ Warnings: string[];
44
+ }
45
+ export declare function mergePack(opts: PackMergeOptions): PackMergeResult;
46
+ declare function bytesEqual(a: Uint8Array, b: Uint8Array): boolean;
47
+ declare function collectPackPathsByPrefix(files: Map<string, Uint8Array>, prefix: string): string[];
48
+ /**
49
+ * Walk a directory and return file paths relative to `relativeTo`, using
50
+ * POSIX separators (`/`) regardless of host OS — these are pack-relative
51
+ * paths the rest of the merger compares with.
52
+ */
53
+ declare function walkRelativeFiles(dir: string, relativeTo: string): string[];
54
+ /** Re-export for tests that want to exercise the walker in isolation. */
55
+ export declare const _internals: {
56
+ walkRelativeFiles: typeof walkRelativeFiles;
57
+ bytesEqual: typeof bytesEqual;
58
+ collectPackPathsByPrefix: typeof collectPackPathsByPrefix;
59
+ };
60
+ export { ManagedBlockError };
61
+ //# sourceMappingURL=PackMerger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PackMerger.d.ts","sourceRoot":"","sources":["../../../src/lib/claude-pack/PackMerger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAYH,OAAO,EAIH,iBAAiB,EACpB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAGH,KAAK,SAAS,EAEd,KAAK,QAAQ,EAChB,MAAM,gBAAgB,CAAC;AAMxB,MAAM,WAAW,gBAAgB;IAC7B,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACnC,QAAQ,EAAE,QAAQ,CAAC;IACnB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iEAAiE;IACjE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4CAA4C;IAC5C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yCAAyC;IACzC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,6FAA6F;IAC7F,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,+CAA+C;IAC/C,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,SAAS,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AAMD,wBAAgB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,eAAe,CAejE;AAoQD,iBAAS,UAAU,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO,CAMzD;AAED,iBAAS,wBAAwB,CAC7B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EAC9B,MAAM,EAAE,MAAM,GACf,MAAM,EAAE,CAEV;AA8BD;;;;GAIG;AACH,iBAAS,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBpE;AAED,yEAAyE;AACzE,eAAO,MAAM,UAAU;;;;CAA8D,CAAC;AAGtF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}