@memberjunction/cli 5.41.0 → 5.42.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/commands/bundle/index.d.ts +1 -0
- package/dist/commands/bundle/index.d.ts.map +1 -1
- package/dist/commands/bundle/index.js +7 -1
- package/dist/commands/bundle/index.js.map +1 -1
- package/dist/commands/codegen/index.d.ts +6 -16
- package/dist/commands/codegen/index.d.ts.map +1 -1
- package/dist/commands/codegen/index.js +6 -90
- package/dist/commands/codegen/index.js.map +1 -1
- package/dist/commands/codegen/usage.d.ts +7 -0
- package/dist/commands/codegen/usage.d.ts.map +1 -0
- package/dist/commands/codegen/usage.js +10 -0
- package/dist/commands/codegen/usage.js.map +1 -0
- package/dist/commands/install/claude.d.ts +35 -0
- package/dist/commands/install/claude.d.ts.map +1 -0
- package/dist/commands/install/claude.js +108 -0
- package/dist/commands/install/claude.js.map +1 -0
- package/dist/commands/install/index.d.ts +1 -0
- package/dist/commands/install/index.d.ts.map +1 -1
- package/dist/commands/install/index.js +4 -0
- package/dist/commands/install/index.js.map +1 -1
- package/dist/commands/migrate/convert.d.ts +59 -12
- package/dist/commands/migrate/convert.d.ts.map +1 -1
- package/dist/commands/migrate/convert.js +294 -21
- package/dist/commands/migrate/convert.js.map +1 -1
- package/dist/commands/migrate/rebake.d.ts +41 -0
- package/dist/commands/migrate/rebake.d.ts.map +1 -0
- package/dist/commands/migrate/rebake.js +193 -0
- package/dist/commands/migrate/rebake.js.map +1 -0
- package/dist/commands/plugin/add.d.ts +18 -0
- package/dist/commands/plugin/add.d.ts.map +1 -0
- package/dist/commands/plugin/add.js +53 -0
- package/dist/commands/plugin/add.js.map +1 -0
- package/dist/commands/sync/pull.d.ts +6 -26
- package/dist/commands/sync/pull.d.ts.map +1 -1
- package/dist/commands/sync/pull.js +6 -281
- package/dist/commands/sync/pull.js.map +1 -1
- package/dist/commands/sync/push.d.ts +8 -19
- package/dist/commands/sync/push.d.ts.map +1 -1
- package/dist/commands/sync/push.js +8 -328
- package/dist/commands/sync/push.js.map +1 -1
- package/dist/commands/sync/usage.d.ts +7 -0
- package/dist/commands/sync/usage.d.ts.map +1 -0
- package/dist/commands/sync/usage.js +10 -0
- package/dist/commands/sync/usage.js.map +1 -0
- package/dist/commands/update/claude.d.ts +37 -0
- package/dist/commands/update/claude.d.ts.map +1 -0
- package/dist/commands/update/claude.js +90 -0
- package/dist/commands/update/claude.js.map +1 -0
- package/dist/commands/usage.d.ts +17 -0
- package/dist/commands/usage.d.ts.map +1 -0
- package/dist/commands/usage.js +29 -0
- package/dist/commands/usage.js.map +1 -0
- package/dist/hooks/prerun.d.ts.map +1 -1
- package/dist/hooks/prerun.js +49 -8
- package/dist/hooks/prerun.js.map +1 -1
- package/dist/lib/claude-pack/ManagedBlockEditor.d.ts +40 -0
- package/dist/lib/claude-pack/ManagedBlockEditor.d.ts.map +1 -0
- package/dist/lib/claude-pack/ManagedBlockEditor.js +127 -0
- package/dist/lib/claude-pack/ManagedBlockEditor.js.map +1 -0
- package/dist/lib/claude-pack/PackFetcher.d.ts +86 -0
- package/dist/lib/claude-pack/PackFetcher.d.ts.map +1 -0
- package/dist/lib/claude-pack/PackFetcher.js +163 -0
- package/dist/lib/claude-pack/PackFetcher.js.map +1 -0
- package/dist/lib/claude-pack/PackInstaller.d.ts +62 -0
- package/dist/lib/claude-pack/PackInstaller.d.ts.map +1 -0
- package/dist/lib/claude-pack/PackInstaller.js +197 -0
- package/dist/lib/claude-pack/PackInstaller.js.map +1 -0
- package/dist/lib/claude-pack/PackMerger.d.ts +61 -0
- package/dist/lib/claude-pack/PackMerger.d.ts.map +1 -0
- package/dist/lib/claude-pack/PackMerger.js +315 -0
- package/dist/lib/claude-pack/PackMerger.js.map +1 -0
- package/dist/lib/claude-pack/PackOutputFormatter.d.ts +29 -0
- package/dist/lib/claude-pack/PackOutputFormatter.d.ts.map +1 -0
- package/dist/lib/claude-pack/PackOutputFormatter.js +82 -0
- package/dist/lib/claude-pack/PackOutputFormatter.js.map +1 -0
- package/dist/lib/claude-pack/PackPaths.d.ts +80 -0
- package/dist/lib/claude-pack/PackPaths.d.ts.map +1 -0
- package/dist/lib/claude-pack/PackPaths.js +182 -0
- package/dist/lib/claude-pack/PackPaths.js.map +1 -0
- package/dist/lib/claude-pack/PackTypes.d.ts +124 -0
- package/dist/lib/claude-pack/PackTypes.d.ts.map +1 -0
- package/dist/lib/claude-pack/PackTypes.js +32 -0
- package/dist/lib/claude-pack/PackTypes.js.map +1 -0
- package/dist/lib/claude-pack/SettingsMerger.d.ts +47 -0
- package/dist/lib/claude-pack/SettingsMerger.d.ts.map +1 -0
- package/dist/lib/claude-pack/SettingsMerger.js +163 -0
- package/dist/lib/claude-pack/SettingsMerger.js.map +1 -0
- package/dist/lib/cli-plugins.d.ts +16 -0
- package/dist/lib/cli-plugins.d.ts.map +1 -0
- package/dist/lib/cli-plugins.js +26 -0
- package/dist/lib/cli-plugins.js.map +1 -0
- package/dist/lib/domain-usage-command.d.ts +16 -0
- package/dist/lib/domain-usage-command.d.ts.map +1 -0
- package/dist/lib/domain-usage-command.js +23 -0
- package/dist/lib/domain-usage-command.js.map +1 -0
- package/dist/lib/usage-render.d.ts +14 -0
- package/dist/lib/usage-render.d.ts.map +1 -0
- package/dist/lib/usage-render.js +64 -0
- package/dist/lib/usage-render.js.map +1 -0
- package/dist/light-commands.d.ts.map +1 -1
- package/dist/light-commands.js +11 -0
- package/dist/light-commands.js.map +1 -1
- package/oclif.manifest.json +815 -135
- package/package.json +17 -15
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import { CLIPluginRegistry } from '@memberjunction/cli-core';
|
|
3
|
+
import { loadAllCliPlugins } from '../lib/cli-plugins.js';
|
|
4
|
+
import { emitUsage, renderDomainMap } from '../lib/usage-render.js';
|
|
5
|
+
/**
|
|
6
|
+
* Tier-1 progressive disclosure (plan §5, the linearis model). Returns a compact
|
|
7
|
+
* domain map — each domain + one-line summary + runtime class — so an agent
|
|
8
|
+
* discovers the CLI's surface in ~200 tokens instead of pulling the full ~13k
|
|
9
|
+
* command tree. The guidance string tells the agent to run `mj <domain> usage`
|
|
10
|
+
* before invoking, rather than guessing flags.
|
|
11
|
+
*/
|
|
12
|
+
export default class Usage extends Command {
|
|
13
|
+
static { this.description = 'List mj command domains (AI-agent-friendly, tier-1 progressive disclosure). Then run `mj <domain> usage`.'; }
|
|
14
|
+
static { this.examples = [
|
|
15
|
+
`<%= config.bin %> <%= command.id %>`,
|
|
16
|
+
`<%= config.bin %> <%= command.id %> --format=json`,
|
|
17
|
+
]; }
|
|
18
|
+
static { this.flags = {
|
|
19
|
+
format: Flags.string({ options: ['text', 'json', 'md'], default: 'text', description: 'Output format' }),
|
|
20
|
+
}; }
|
|
21
|
+
async run() {
|
|
22
|
+
const { flags } = await this.parse(Usage);
|
|
23
|
+
await loadAllCliPlugins(process.cwd());
|
|
24
|
+
const map = CLIPluginRegistry.BuildDomainMap();
|
|
25
|
+
const result = CLIPluginRegistry.AsResult('usage', { guidance: map.guidance, domains: map.domains });
|
|
26
|
+
emitUsage((m) => this.log(m), flags.format, result, renderDomainMap(map));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/commands/usage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEpE;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,OAAO;aACjC,gBAAW,GAAG,2GAA2G,CAAC;aAE1H,aAAQ,GAAG;QAChB,qCAAqC;QACrC,mDAAmD;KACpD,CAAC;aAEK,UAAK,GAAG;QACb,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC;KACzG,CAAC;IAEF,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,iBAAiB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,iBAAiB,CAAC,cAAc,EAAE,CAAC;QAC/C,MAAM,MAAM,GAAG,iBAAiB,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACrG,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,MAAgB,EAAE,MAAM,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;IACtF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prerun.d.ts","sourceRoot":"","sources":["../../src/hooks/prerun.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAInC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,QAAQ,
|
|
1
|
+
{"version":3,"file":"prerun.d.ts","sourceRoot":"","sources":["../../src/hooks/prerun.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAInC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,QAAQ,CAoExB,CAAC;AAcF,eAAe,IAAI,CAAC"}
|
package/dist/hooks/prerun.js
CHANGED
|
@@ -1,14 +1,48 @@
|
|
|
1
1
|
import figlet from 'figlet';
|
|
2
2
|
import { LIGHT_COMMANDS } from '../light-commands.js';
|
|
3
3
|
const hook = async function (options) {
|
|
4
|
+
const argv = options.argv ?? [];
|
|
5
|
+
// Machine-readable output must keep stdout clean — suppress the banner AND the
|
|
6
|
+
// userAgent line entirely for `--format=json|md` and `--no-banner` (plan §1a/D4).
|
|
7
|
+
const formatArg = (() => {
|
|
8
|
+
const eq = argv.find((a) => a.startsWith('--format='));
|
|
9
|
+
if (eq)
|
|
10
|
+
return eq.slice('--format='.length);
|
|
11
|
+
const i = argv.indexOf('--format');
|
|
12
|
+
return i >= 0 ? argv[i + 1] : undefined;
|
|
13
|
+
})();
|
|
14
|
+
const machineFormat = formatArg === 'json' || formatArg === 'md';
|
|
15
|
+
const noBanner = argv.includes('--no-banner');
|
|
16
|
+
// `--no-banner` is global chrome — every command renders the banner, so suppressing
|
|
17
|
+
// it must work on ANY command, including those not yet migrated to BaseCLIPlugin
|
|
18
|
+
// (which don't declare the flag and would otherwise fail oclif's strict parser with
|
|
19
|
+
// "Nonexistent flag"). Signal suppression to MJCLIRuntimeHost via env (so migrated
|
|
20
|
+
// commands still gate their runtime advisory) and strip the flag from argv in place
|
|
21
|
+
// so the per-command parser never sees an undeclared flag.
|
|
22
|
+
if (noBanner) {
|
|
23
|
+
process.env.MJ_CLI_NO_BANNER = '1';
|
|
24
|
+
for (let i = argv.length - 1; i >= 0; i--) {
|
|
25
|
+
if (argv[i] === '--no-banner')
|
|
26
|
+
argv.splice(i, 1);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
4
29
|
// Skip banners if --quiet flag is present (or appears to be present)
|
|
5
|
-
if (
|
|
30
|
+
if (machineFormat || noBanner || argv.some((arg) => arg === '--quiet' || (/^-[^-]+/.test(arg) && arg.includes('q')))) {
|
|
31
|
+
// Still conditionally load bootstrap below — just no decorative output.
|
|
32
|
+
return await maybeLoadBootstrap(options);
|
|
33
|
+
}
|
|
34
|
+
// Skip banners entirely when --json is requested — the contract for --json
|
|
35
|
+
// is that stdout is parseable JSON, and any banner above it breaks
|
|
36
|
+
// `mj … --json | jq`. This early-return also skips the userAgent line below.
|
|
37
|
+
if (options.argv?.some((arg) => arg === '--json')) {
|
|
6
38
|
return;
|
|
7
39
|
}
|
|
8
40
|
// Suppress the large figlet banner for hot-path, frequently-run commands (e.g. `mj sync *`)
|
|
9
|
-
// where it's pure scrollback cost. The
|
|
41
|
+
// and the agent-facing usage commands, where it's pure scrollback cost. The
|
|
42
|
+
// compact userAgent line below still prints.
|
|
10
43
|
const commandIdForBanner = options.Command.id ?? '';
|
|
11
|
-
const
|
|
44
|
+
const isUsageCommand = commandIdForBanner === 'usage' || commandIdForBanner.endsWith('usage');
|
|
45
|
+
const showFiglet = !commandIdForBanner.startsWith('sync') && !isUsageCommand;
|
|
12
46
|
if (showFiglet) {
|
|
13
47
|
options.context.log(process.stdout.columns >= 81
|
|
14
48
|
? figlet.textSync('MemberJunction', {
|
|
@@ -20,16 +54,23 @@ const hook = async function (options) {
|
|
|
20
54
|
})
|
|
21
55
|
: '~ M e m b e r J u n c t i o n ~');
|
|
22
56
|
}
|
|
23
|
-
|
|
57
|
+
// The agent-facing usage commands (`mj usage`, `mj <domain> usage`) are meant to
|
|
58
|
+
// be a terse domain map — skip the userAgent line so text-mode stdout stays clean.
|
|
59
|
+
if (options.Command.id !== 'version' && !isUsageCommand) {
|
|
24
60
|
options.context.log(options.config.userAgent + '\n');
|
|
25
61
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
62
|
+
await maybeLoadBootstrap(options);
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Conditionally load MJ bootstrap for heavy commands. Light commands (version,
|
|
66
|
+
* help, bump, migrate, clean, install, dbdoc/*, usage/*) skip the ~1,400 class
|
|
67
|
+
* registrations for instant startup.
|
|
68
|
+
*/
|
|
69
|
+
async function maybeLoadBootstrap(options) {
|
|
29
70
|
const commandId = options.Command.id ?? '';
|
|
30
71
|
if (!LIGHT_COMMANDS.has(commandId)) {
|
|
31
72
|
await import('@memberjunction/server-bootstrap-lite/mj-class-registrations');
|
|
32
73
|
}
|
|
33
|
-
}
|
|
74
|
+
}
|
|
34
75
|
export default hook;
|
|
35
76
|
//# sourceMappingURL=prerun.js.map
|
package/dist/hooks/prerun.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prerun.js","sourceRoot":"","sources":["../../src/hooks/prerun.ts"],"names":[],"mappings":"AACA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,IAAI,GAAmB,KAAK,WAAW,OAAO;IAClD,
|
|
1
|
+
{"version":3,"file":"prerun.js","sourceRoot":"","sources":["../../src/hooks/prerun.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse + rewrite the MJ-managed block in a user's `CLAUDE.md`.
|
|
3
|
+
*
|
|
4
|
+
* The block is delimited by HTML comment markers:
|
|
5
|
+
* <!-- MJ-MANAGED:CLAUDE-PACK START key=value key=value -->
|
|
6
|
+
* ... managed content ...
|
|
7
|
+
* <!-- MJ-MANAGED:CLAUDE-PACK END -->
|
|
8
|
+
*
|
|
9
|
+
* Everything before and after the block is the user's free section and must
|
|
10
|
+
* never be touched.
|
|
11
|
+
*
|
|
12
|
+
* @see plans/claude-install-pack.md §3.3, §6.4 (CLAUDE.md row), §10.4
|
|
13
|
+
*/
|
|
14
|
+
import type { ManagedBlock } from './PackTypes.js';
|
|
15
|
+
export declare class ManagedBlockError extends Error {
|
|
16
|
+
constructor(message: string);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Find the managed block in a CLAUDE.md file. Returns `null` when no markers
|
|
20
|
+
* are present (caller should handle the "file exists but unmanaged" case).
|
|
21
|
+
* Throws `ManagedBlockError` when markers are malformed (e.g. END before
|
|
22
|
+
* START, only one marker present, multiple START markers).
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseManagedBlock(content: string): ManagedBlock | null;
|
|
25
|
+
/**
|
|
26
|
+
* Replace the managed block in `content` with `newBody`, updating attributes
|
|
27
|
+
* on the START marker.
|
|
28
|
+
*
|
|
29
|
+
* Throws `ManagedBlockError` if no managed block is present — callers should
|
|
30
|
+
* use `wrapWithManagedBlock` for the first-install case.
|
|
31
|
+
*/
|
|
32
|
+
export declare function rewriteManagedBlock(content: string, newBody: string, newAttrs: Record<string, string>): string;
|
|
33
|
+
/**
|
|
34
|
+
* Wrap arbitrary `content` with a managed block, placing the block at the
|
|
35
|
+
* top and the original content below (as the user's free section).
|
|
36
|
+
*
|
|
37
|
+
* If `content` is empty, the result is just the rendered managed block.
|
|
38
|
+
*/
|
|
39
|
+
export declare function wrapWithManagedBlock(content: string, body: string, attrs: Record<string, string>): string;
|
|
40
|
+
//# sourceMappingURL=ManagedBlockEditor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ManagedBlockEditor.d.ts","sourceRoot":"","sources":["../../../src/lib/claude-pack/ManagedBlockEditor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAenD,qBAAa,iBAAkB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI9B;AAMD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAiCtE;AA0BD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,MAAM,CAMR;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,MAAM,CAKR"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse + rewrite the MJ-managed block in a user's `CLAUDE.md`.
|
|
3
|
+
*
|
|
4
|
+
* The block is delimited by HTML comment markers:
|
|
5
|
+
* <!-- MJ-MANAGED:CLAUDE-PACK START key=value key=value -->
|
|
6
|
+
* ... managed content ...
|
|
7
|
+
* <!-- MJ-MANAGED:CLAUDE-PACK END -->
|
|
8
|
+
*
|
|
9
|
+
* Everything before and after the block is the user's free section and must
|
|
10
|
+
* never be touched.
|
|
11
|
+
*
|
|
12
|
+
* @see plans/claude-install-pack.md §3.3, §6.4 (CLAUDE.md row), §10.4
|
|
13
|
+
*/
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Marker constants
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
/** Match a START marker line and capture the attribute string. */
|
|
18
|
+
const START_RE = /<!--\s*MJ-MANAGED:CLAUDE-PACK\s+START\s*([^>]*?)\s*-->/;
|
|
19
|
+
/** Match an END marker line. */
|
|
20
|
+
const END_RE = /<!--\s*MJ-MANAGED:CLAUDE-PACK\s+END\s*-->/;
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Errors
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
export class ManagedBlockError extends Error {
|
|
25
|
+
constructor(message) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = 'ManagedBlockError';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Parse
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
/**
|
|
34
|
+
* Find the managed block in a CLAUDE.md file. Returns `null` when no markers
|
|
35
|
+
* are present (caller should handle the "file exists but unmanaged" case).
|
|
36
|
+
* Throws `ManagedBlockError` when markers are malformed (e.g. END before
|
|
37
|
+
* START, only one marker present, multiple START markers).
|
|
38
|
+
*/
|
|
39
|
+
export function parseManagedBlock(content) {
|
|
40
|
+
const startMatch = START_RE.exec(content);
|
|
41
|
+
const endMatch = END_RE.exec(content);
|
|
42
|
+
if (!startMatch && !endMatch)
|
|
43
|
+
return null;
|
|
44
|
+
if (!startMatch) {
|
|
45
|
+
throw new ManagedBlockError('CLAUDE.md has MJ-MANAGED END marker without a matching START.');
|
|
46
|
+
}
|
|
47
|
+
if (!endMatch) {
|
|
48
|
+
throw new ManagedBlockError('CLAUDE.md has MJ-MANAGED START marker without a matching END.');
|
|
49
|
+
}
|
|
50
|
+
if (endMatch.index < startMatch.index) {
|
|
51
|
+
throw new ManagedBlockError('CLAUDE.md has MJ-MANAGED END marker before its START marker.');
|
|
52
|
+
}
|
|
53
|
+
// Detect a second START marker — that's a corrupted file we won't auto-fix.
|
|
54
|
+
const secondStart = START_RE.exec(content.slice(startMatch.index + startMatch[0].length));
|
|
55
|
+
if (secondStart) {
|
|
56
|
+
throw new ManagedBlockError('CLAUDE.md has multiple MJ-MANAGED START markers; expected exactly one.');
|
|
57
|
+
}
|
|
58
|
+
const before = content.slice(0, startMatch.index);
|
|
59
|
+
const bodyStart = startMatch.index + startMatch[0].length;
|
|
60
|
+
const bodyEnd = endMatch.index;
|
|
61
|
+
const body = content.slice(bodyStart, bodyEnd);
|
|
62
|
+
const after = content.slice(endMatch.index + endMatch[0].length);
|
|
63
|
+
const attrs = parseAttrs(startMatch[1]);
|
|
64
|
+
return { before, body, after, attrs };
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Parse `key=value key2=value2` attribute strings from a START marker.
|
|
68
|
+
*
|
|
69
|
+
* Supports unquoted values without spaces (which is what build-pack.mjs emits).
|
|
70
|
+
* Returns an empty record for an empty attribute string.
|
|
71
|
+
*/
|
|
72
|
+
function parseAttrs(raw) {
|
|
73
|
+
const out = {};
|
|
74
|
+
const trimmed = raw.trim();
|
|
75
|
+
if (!trimmed)
|
|
76
|
+
return out;
|
|
77
|
+
for (const pair of trimmed.split(/\s+/)) {
|
|
78
|
+
const eq = pair.indexOf('=');
|
|
79
|
+
if (eq <= 0)
|
|
80
|
+
continue; // skip malformed pairs silently
|
|
81
|
+
const key = pair.slice(0, eq);
|
|
82
|
+
const value = pair.slice(eq + 1);
|
|
83
|
+
out[key] = value;
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
// Rewrite
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
/**
|
|
91
|
+
* Replace the managed block in `content` with `newBody`, updating attributes
|
|
92
|
+
* on the START marker.
|
|
93
|
+
*
|
|
94
|
+
* Throws `ManagedBlockError` if no managed block is present — callers should
|
|
95
|
+
* use `wrapWithManagedBlock` for the first-install case.
|
|
96
|
+
*/
|
|
97
|
+
export function rewriteManagedBlock(content, newBody, newAttrs) {
|
|
98
|
+
const block = parseManagedBlock(content);
|
|
99
|
+
if (!block) {
|
|
100
|
+
throw new ManagedBlockError('Cannot rewrite — no managed block found in content.');
|
|
101
|
+
}
|
|
102
|
+
return block.before + formatStartMarker(newAttrs) + newBody + formatEndMarker() + block.after;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Wrap arbitrary `content` with a managed block, placing the block at the
|
|
106
|
+
* top and the original content below (as the user's free section).
|
|
107
|
+
*
|
|
108
|
+
* If `content` is empty, the result is just the rendered managed block.
|
|
109
|
+
*/
|
|
110
|
+
export function wrapWithManagedBlock(content, body, attrs) {
|
|
111
|
+
const startMarker = formatStartMarker(attrs);
|
|
112
|
+
const endMarker = formatEndMarker();
|
|
113
|
+
const trailing = content.length > 0 ? '\n\n' + content : '\n';
|
|
114
|
+
return startMarker + body + endMarker + trailing;
|
|
115
|
+
}
|
|
116
|
+
function formatStartMarker(attrs) {
|
|
117
|
+
const attrString = Object.entries(attrs)
|
|
118
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
119
|
+
.join(' ');
|
|
120
|
+
return attrString
|
|
121
|
+
? `<!-- MJ-MANAGED:CLAUDE-PACK START ${attrString} -->`
|
|
122
|
+
: `<!-- MJ-MANAGED:CLAUDE-PACK START -->`;
|
|
123
|
+
}
|
|
124
|
+
function formatEndMarker() {
|
|
125
|
+
return `<!-- MJ-MANAGED:CLAUDE-PACK END -->`;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=ManagedBlockEditor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ManagedBlockEditor.js","sourceRoot":"","sources":["../../../src/lib/claude-pack/ManagedBlockEditor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
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 type { Manifest } from './PackTypes.js';
|
|
16
|
+
/**
|
|
17
|
+
* Response body is typed as `Uint8Array` (Buffer's superclass) so this type
|
|
18
|
+
* stays portable across Node typings versions that vary in how strictly they
|
|
19
|
+
* model Buffer's ArrayBuffer parameter. `Buffer.concat` and `createHash`
|
|
20
|
+
* both accept `Uint8Array` directly.
|
|
21
|
+
*/
|
|
22
|
+
export interface HttpResponse {
|
|
23
|
+
statusCode: number;
|
|
24
|
+
body: Uint8Array;
|
|
25
|
+
}
|
|
26
|
+
/** Promise-based GET. Production = node:https; tests = mock. */
|
|
27
|
+
export type HttpGetter = (url: string) => Promise<HttpResponse>;
|
|
28
|
+
/**
|
|
29
|
+
* Real production fetcher using `node:https`.
|
|
30
|
+
*
|
|
31
|
+
* Implementation note: builds the response body via manual Uint8Array
|
|
32
|
+
* concatenation instead of `Buffer.concat()` — the latter's return type
|
|
33
|
+
* (`Buffer`) doesn't cleanly assign to `Uint8Array` in the strict @types/node
|
|
34
|
+
* generics that ship with v20+, even though Buffer extends Uint8Array.
|
|
35
|
+
*/
|
|
36
|
+
export declare const realHttpGet: HttpGetter;
|
|
37
|
+
export declare class PackFetchError extends Error {
|
|
38
|
+
url?: string;
|
|
39
|
+
statusCode?: number;
|
|
40
|
+
constructor(message: string, url?: string, statusCode?: number);
|
|
41
|
+
}
|
|
42
|
+
export declare class PackChecksumError extends Error {
|
|
43
|
+
path: string;
|
|
44
|
+
expected: string;
|
|
45
|
+
actual: string;
|
|
46
|
+
constructor(message: string, path: string, expected: string, actual: string);
|
|
47
|
+
}
|
|
48
|
+
export interface FetchPackOptions {
|
|
49
|
+
/** MJ major version (e.g. `5`). Required — used to locate `dist/v{N}/`. */
|
|
50
|
+
Major: string;
|
|
51
|
+
/**
|
|
52
|
+
* Git ref to fetch from. Defaults to `'main'`. If a specific tag is given
|
|
53
|
+
* and it 404s, the fetcher transparently falls back to `'main'`.
|
|
54
|
+
*/
|
|
55
|
+
Ref?: string;
|
|
56
|
+
/** Injected HTTP getter — test seam. Defaults to `realHttpGet`. */
|
|
57
|
+
HttpGet?: HttpGetter;
|
|
58
|
+
/** Progress callback for verbose mode. */
|
|
59
|
+
OnProgress?: (message: string) => void;
|
|
60
|
+
/**
|
|
61
|
+
* When true, fetch only the manifest and skip the per-file downloads.
|
|
62
|
+
* Used by `mj update:claude --check` to compare versions without paying
|
|
63
|
+
* for content the caller won't write. The returned `Files` map is empty.
|
|
64
|
+
*/
|
|
65
|
+
ManifestOnly?: boolean;
|
|
66
|
+
}
|
|
67
|
+
export interface FetchedPack {
|
|
68
|
+
/** Parsed MANIFEST.json. */
|
|
69
|
+
Manifest: Manifest;
|
|
70
|
+
/**
|
|
71
|
+
* Pack file contents keyed by manifest path (e.g. `.claude/mj/core.md`).
|
|
72
|
+
* Bytes verified against the manifest's sha256 before insertion.
|
|
73
|
+
*/
|
|
74
|
+
Files: Map<string, Uint8Array>;
|
|
75
|
+
/** Which ref was actually used (after fallback). */
|
|
76
|
+
RefUsed: string;
|
|
77
|
+
/** The full base URL the fetcher ultimately read from. */
|
|
78
|
+
BaseUrl: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Fetch a pack: manifest first, then every file listed in it, verifying
|
|
82
|
+
* sha256 along the way. Falls back from a specific tag to `main` if the
|
|
83
|
+
* manifest 404s.
|
|
84
|
+
*/
|
|
85
|
+
export declare function fetchPack(opts: FetchPackOptions): Promise<FetchedPack>;
|
|
86
|
+
//# sourceMappingURL=PackFetcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PackFetcher.d.ts","sourceRoot":"","sources":["../../../src/lib/claude-pack/PackFetcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,gBAAgB,CAAC;AAO9D;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,UAAU,CAAC;CACpB;AAED,gEAAgE;AAChE,MAAM,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;AAEhE;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,EAAE,UAcpB,CAAC;AAiBP,qBAAa,cAAe,SAAQ,KAAK;IACD,GAAG,CAAC,EAAE,MAAM;IAAS,UAAU,CAAC,EAAE,MAAM;gBAAhE,OAAO,EAAE,MAAM,EAAS,GAAG,CAAC,EAAE,MAAM,EAAS,UAAU,CAAC,EAAE,MAAM;CAI/E;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAG7B,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,MAAM;IAChB,MAAM,EAAE,MAAM;gBAHrB,OAAO,EAAE,MAAM,EACR,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM;CAK5B;AAMD,MAAM,WAAW,gBAAgB;IAC7B,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IACxB,4BAA4B;IAC5B,QAAQ,EAAE,QAAQ,CAAC;IACnB;;;OAGG;IACH,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC/B,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;CACnB;AAMD;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAiC5E"}
|
|
@@ -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"}
|