@slats/claude-assets-sync 0.1.4 → 0.3.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/README.md +89 -581
- package/bin/inject-claude-settings.mjs +4 -0
- package/dist/claude-hashes.json +20 -0
- package/dist/commands/index.d.ts +1 -112
- package/dist/commands/runCli/index.d.ts +2 -0
- package/dist/commands/runCli/runCli.cjs +53 -0
- package/dist/commands/runCli/runCli.d.ts +14 -0
- package/dist/commands/runCli/runCli.mjs +51 -0
- package/dist/commands/runCli/type.d.ts +19 -0
- package/dist/commands/runCli/utils/classifyTarget.cjs +48 -0
- package/dist/commands/runCli/utils/classifyTarget.d.ts +19 -0
- package/dist/commands/runCli/utils/classifyTarget.mjs +46 -0
- package/dist/commands/runCli/utils/injectOne.cjs +47 -0
- package/dist/commands/runCli/utils/injectOne.d.ts +3 -0
- package/dist/commands/runCli/utils/injectOne.mjs +45 -0
- package/dist/commands/runCli/utils/resolvePackage.cjs +77 -0
- package/dist/commands/runCli/utils/resolvePackage.d.ts +16 -0
- package/dist/commands/runCli/utils/resolvePackage.mjs +74 -0
- package/dist/commands/runCli/utils/resolveScopeAlias.cjs +69 -0
- package/dist/commands/runCli/utils/resolveScopeAlias.d.ts +2 -0
- package/dist/commands/runCli/utils/resolveScopeAlias.mjs +67 -0
- package/dist/commands/runCli/utils/resolveScopeFlag.cjs +28 -0
- package/dist/commands/runCli/utils/resolveScopeFlag.d.ts +2 -0
- package/dist/commands/runCli/utils/resolveScopeFlag.mjs +26 -0
- package/dist/commands/runCli/utils/resolveTargets.cjs +40 -0
- package/dist/commands/runCli/utils/resolveTargets.d.ts +15 -0
- package/dist/commands/runCli/utils/resolveTargets.mjs +38 -0
- package/dist/commands/runCli/utils/runInject.cjs +52 -0
- package/dist/commands/runCli/utils/runInject.d.ts +3 -0
- package/dist/commands/runCli/utils/runInject.mjs +50 -0
- package/dist/core/buildPlan/buildPlan.cjs +42 -0
- package/dist/core/buildPlan/buildPlan.d.ts +2 -0
- package/dist/core/buildPlan/buildPlan.mjs +40 -0
- package/dist/core/buildPlan/index.d.ts +2 -0
- package/dist/core/buildPlan/type.d.ts +32 -0
- package/dist/core/buildPlan/utils/toPosix.cjs +9 -0
- package/dist/core/buildPlan/utils/toPosix.d.ts +1 -0
- package/dist/core/buildPlan/utils/toPosix.mjs +7 -0
- package/dist/core/buildPlan/utils/walkFiles.cjs +25 -0
- package/dist/core/buildPlan/utils/walkFiles.d.ts +1 -0
- package/dist/core/buildPlan/utils/walkFiles.mjs +23 -0
- package/dist/core/hash/hash.cjs +30 -0
- package/dist/core/hash/hash.d.ts +4 -0
- package/dist/core/hash/hash.mjs +26 -0
- package/dist/core/hash/index.d.ts +1 -0
- package/dist/core/hashManifest/hashManifest.cjs +27 -0
- package/dist/core/hashManifest/hashManifest.d.ts +17 -0
- package/dist/core/hashManifest/hashManifest.mjs +23 -0
- package/dist/core/hashManifest/index.d.ts +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/injectDocs/index.d.ts +2 -0
- package/dist/core/injectDocs/injectDocs.cjs +43 -0
- package/dist/core/injectDocs/injectDocs.d.ts +2 -0
- package/dist/core/injectDocs/injectDocs.mjs +41 -0
- package/dist/core/injectDocs/type.d.ts +30 -0
- package/dist/core/injectDocs/utils/applyAction.cjs +21 -0
- package/dist/core/injectDocs/utils/applyAction.d.ts +2 -0
- package/dist/core/injectDocs/utils/applyAction.mjs +19 -0
- package/dist/core/injectDocs/utils/emitCiForceList.cjs +10 -0
- package/dist/core/injectDocs/utils/emitCiForceList.d.ts +2 -0
- package/dist/core/injectDocs/utils/emitCiForceList.mjs +8 -0
- package/dist/core/injectDocs/utils/printPlan.cjs +20 -0
- package/dist/core/injectDocs/utils/printPlan.d.ts +2 -0
- package/dist/core/injectDocs/utils/printPlan.mjs +18 -0
- package/dist/core/injectDocs/utils/summarize.cjs +27 -0
- package/dist/core/injectDocs/utils/summarize.d.ts +3 -0
- package/dist/core/injectDocs/utils/summarize.mjs +25 -0
- package/dist/core/scope/index.d.ts +1 -0
- package/dist/core/scope/scope.cjs +46 -0
- package/dist/core/scope/scope.d.ts +16 -0
- package/dist/core/scope/scope.mjs +41 -0
- package/dist/core/scope/utils/isDirectory.cjs +14 -0
- package/dist/core/scope/utils/isDirectory.d.ts +1 -0
- package/dist/core/scope/utils/isDirectory.mjs +12 -0
- package/dist/index.cjs +15 -9
- package/dist/index.d.ts +3 -5
- package/dist/index.mjs +7 -3
- package/dist/prompts/confirmForce.cjs +27 -0
- package/dist/prompts/confirmForce.d.ts +1 -0
- package/dist/prompts/confirmForce.mjs +25 -0
- package/dist/prompts/index.d.ts +2 -0
- package/dist/prompts/selectScope.cjs +30 -0
- package/dist/prompts/selectScope.d.ts +2 -0
- package/dist/prompts/selectScope.mjs +28 -0
- package/dist/utils/heartbeat.cjs +25 -0
- package/dist/utils/heartbeat.d.ts +16 -0
- package/dist/utils/heartbeat.mjs +23 -0
- package/dist/utils/logger.cjs +7 -0
- package/dist/utils/logger.d.ts +8 -0
- package/dist/utils/logger.mjs +7 -0
- package/dist/utils/types.d.ts +1 -252
- package/dist/utils/version.cjs +2 -14
- package/dist/utils/version.d.ts +3 -53
- package/dist/utils/version.mjs +2 -13
- package/docs/bundle-size-decision.md +36 -0
- package/docs/claude/skills/claude-docs-asset-wiring/SKILL.md +159 -0
- package/docs/claude/skills/claude-docs-asset-wiring/knowledge/claude-md-template.md +86 -0
- package/docs/claude/skills/claude-docs-asset-wiring/knowledge/dependency-cruiser.md +54 -0
- package/docs/claude/skills/claude-docs-asset-wiring/knowledge/gotchas.md +122 -0
- package/docs/claude/skills/claude-docs-asset-wiring/knowledge/package-json-patches.md +145 -0
- package/docs/claude/skills/claude-docs-asset-wiring/knowledge/reference-files.md +37 -0
- package/docs/claude/skills/claude-docs-asset-wiring/knowledge/smoke-tests.md +111 -0
- package/docs/consumer-integration.md +94 -0
- package/package.json +24 -16
- package/scripts/build-hashes.mjs +30 -0
- package/scripts/buildHashes.d.mts +15 -0
- package/scripts/buildHashes.mjs +82 -0
- package/scripts/claude-build-hashes.mjs +42 -0
- package/scripts/inject-version.js +112 -0
- package/dist/cli.cjs +0 -8
- package/dist/cli.d.ts +0 -1
- package/dist/cli.mjs +0 -7
- package/dist/commands/add.cjs +0 -80
- package/dist/commands/add.d.ts +0 -8
- package/dist/commands/add.mjs +0 -78
- package/dist/commands/list.cjs +0 -94
- package/dist/commands/list.d.ts +0 -15
- package/dist/commands/list.mjs +0 -91
- package/dist/commands/migrate.cjs +0 -9
- package/dist/commands/migrate.d.ts +0 -6
- package/dist/commands/migrate.mjs +0 -7
- package/dist/commands/remove.cjs +0 -127
- package/dist/commands/remove.d.ts +0 -6
- package/dist/commands/remove.mjs +0 -105
- package/dist/commands/status.cjs +0 -193
- package/dist/commands/status.d.ts +0 -6
- package/dist/commands/status.mjs +0 -171
- package/dist/commands/sync.cjs +0 -28
- package/dist/commands/sync.d.ts +0 -6
- package/dist/commands/sync.mjs +0 -26
- package/dist/commands/types.d.ts +0 -89
- package/dist/commands/update.cjs +0 -209
- package/dist/commands/update.d.ts +0 -29
- package/dist/commands/update.mjs +0 -206
- package/dist/components/add/AddCommand.cjs +0 -103
- package/dist/components/add/AddCommand.d.ts +0 -14
- package/dist/components/add/AddCommand.mjs +0 -101
- package/dist/components/add/BulkAddView.cjs +0 -165
- package/dist/components/add/BulkAddView.d.ts +0 -11
- package/dist/components/add/BulkAddView.mjs +0 -163
- package/dist/components/add/index.d.ts +0 -2
- package/dist/components/index.d.ts +0 -2
- package/dist/components/list/EditableTreeItem.d.ts +0 -13
- package/dist/components/list/ListCommand.cjs +0 -651
- package/dist/components/list/ListCommand.d.ts +0 -5
- package/dist/components/list/ListCommand.mjs +0 -649
- package/dist/components/list/SyncedPackageTree.d.ts +0 -14
- package/dist/components/list/index.d.ts +0 -10
- package/dist/components/list/types.d.ts +0 -14
- package/dist/components/primitives/Box.d.ts +0 -4
- package/dist/components/primitives/Spinner.d.ts +0 -6
- package/dist/components/primitives/Text.d.ts +0 -4
- package/dist/components/primitives/index.d.ts +0 -3
- package/dist/components/remove/RemoveConfirm.cjs +0 -18
- package/dist/components/remove/RemoveConfirm.d.ts +0 -11
- package/dist/components/remove/RemoveConfirm.mjs +0 -16
- package/dist/components/shared/Confirm.cjs +0 -30
- package/dist/components/shared/Confirm.d.ts +0 -8
- package/dist/components/shared/Confirm.mjs +0 -28
- package/dist/components/shared/MenuItem.cjs +0 -18
- package/dist/components/shared/MenuItem.d.ts +0 -7
- package/dist/components/shared/MenuItem.mjs +0 -16
- package/dist/components/shared/ProgressBar.d.ts +0 -7
- package/dist/components/shared/StepRunner.cjs +0 -58
- package/dist/components/shared/StepRunner.d.ts +0 -15
- package/dist/components/shared/StepRunner.mjs +0 -56
- package/dist/components/shared/Table.cjs +0 -19
- package/dist/components/shared/Table.d.ts +0 -8
- package/dist/components/shared/Table.mjs +0 -17
- package/dist/components/shared/index.d.ts +0 -6
- package/dist/components/status/PackageStatusCard.d.ts +0 -10
- package/dist/components/status/StatusDisplay.cjs +0 -26
- package/dist/components/status/StatusDisplay.d.ts +0 -23
- package/dist/components/status/StatusDisplay.mjs +0 -24
- package/dist/components/status/StatusTreeNode.cjs +0 -40
- package/dist/components/status/StatusTreeNode.d.ts +0 -15
- package/dist/components/status/StatusTreeNode.mjs +0 -38
- package/dist/components/status/index.d.ts +0 -6
- package/dist/components/tree/AssetTreeNode.cjs +0 -54
- package/dist/components/tree/AssetTreeNode.d.ts +0 -12
- package/dist/components/tree/AssetTreeNode.mjs +0 -52
- package/dist/components/tree/TreeSelect.cjs +0 -129
- package/dist/components/tree/TreeSelect.d.ts +0 -12
- package/dist/components/tree/TreeSelect.mjs +0 -127
- package/dist/components/tree/index.d.ts +0 -4
- package/dist/core/assetStructure.cjs +0 -30
- package/dist/core/assetStructure.d.ts +0 -36
- package/dist/core/assetStructure.mjs +0 -27
- package/dist/core/cli.cjs +0 -106
- package/dist/core/cli.d.ts +0 -9
- package/dist/core/cli.mjs +0 -103
- package/dist/core/constants.cjs +0 -28
- package/dist/core/constants.d.ts +0 -94
- package/dist/core/constants.mjs +0 -21
- package/dist/core/filesystem.cjs +0 -98
- package/dist/core/filesystem.d.ts +0 -94
- package/dist/core/filesystem.mjs +0 -88
- package/dist/core/github.cjs +0 -115
- package/dist/core/github.d.ts +0 -61
- package/dist/core/github.mjs +0 -107
- package/dist/core/io.cjs +0 -46
- package/dist/core/io.d.ts +0 -40
- package/dist/core/io.mjs +0 -39
- package/dist/core/listOperations.cjs +0 -228
- package/dist/core/listOperations.d.ts +0 -43
- package/dist/core/listOperations.mjs +0 -205
- package/dist/core/localSource.cjs +0 -126
- package/dist/core/localSource.d.ts +0 -33
- package/dist/core/localSource.mjs +0 -120
- package/dist/core/migration.cjs +0 -201
- package/dist/core/migration.d.ts +0 -57
- package/dist/core/migration.mjs +0 -198
- package/dist/core/packageScanner.cjs +0 -360
- package/dist/core/packageScanner.d.ts +0 -22
- package/dist/core/packageScanner.mjs +0 -356
- package/dist/core/sync.cjs +0 -400
- package/dist/core/sync.d.ts +0 -21
- package/dist/core/sync.mjs +0 -397
- package/dist/core/syncMeta.cjs +0 -242
- package/dist/core/syncMeta.d.ts +0 -75
- package/dist/core/syncMeta.mjs +0 -229
- package/dist/utils/dependencies.cjs +0 -57
- package/dist/utils/dependencies.d.ts +0 -10
- package/dist/utils/dependencies.mjs +0 -34
- package/dist/utils/nameTransform.cjs +0 -13
- package/dist/utils/nameTransform.d.ts +0 -65
- package/dist/utils/nameTransform.mjs +0 -11
- package/dist/utils/package.cjs +0 -170
- package/dist/utils/package.d.ts +0 -105
- package/dist/utils/package.mjs +0 -157
- package/dist/utils/packageName.cjs +0 -24
- package/dist/utils/packageName.d.ts +0 -32
- package/dist/utils/packageName.mjs +0 -21
- package/dist/utils/paths.cjs +0 -18
- package/dist/utils/paths.d.ts +0 -55
- package/dist/utils/paths.mjs +0 -15
- package/dist/version.cjs +0 -5
- package/dist/version.d.ts +0 -5
- package/dist/version.mjs +0 -3
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var node_fs = require('node:fs');
|
|
4
|
+
var promises = require('node:fs/promises');
|
|
5
|
+
var node_path = require('node:path');
|
|
6
|
+
var logger = require('../../../utils/logger.cjs');
|
|
7
|
+
var resolvePackage = require('./resolvePackage.cjs');
|
|
8
|
+
|
|
9
|
+
async function resolveScopeAlias(scope, rootCwd) {
|
|
10
|
+
const packagesRoot = findPackagesRoot(rootCwd);
|
|
11
|
+
if (!packagesRoot) {
|
|
12
|
+
logger.logger.error(`cannot locate a monorepo root with a "packages/" directory starting from "${rootCwd}". Scope alias "@${scope}" requires a workspace root.`);
|
|
13
|
+
process.exit(2);
|
|
14
|
+
}
|
|
15
|
+
const scopeDir = node_path.join(packagesRoot, 'packages', scope);
|
|
16
|
+
let entries;
|
|
17
|
+
try {
|
|
18
|
+
entries = await promises.readdir(scopeDir);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
logger.logger.error(`scope alias "@${scope}" has no matching directory at ${scopeDir}.`);
|
|
22
|
+
process.exit(2);
|
|
23
|
+
}
|
|
24
|
+
const matchedNames = [];
|
|
25
|
+
const expectedPrefix = `@${scope}/`;
|
|
26
|
+
for (const entry of entries) {
|
|
27
|
+
const pkgJsonPath = node_path.join(scopeDir, entry, 'package.json');
|
|
28
|
+
if (!node_fs.existsSync(pkgJsonPath))
|
|
29
|
+
continue;
|
|
30
|
+
let parsed;
|
|
31
|
+
try {
|
|
32
|
+
const raw = await promises.readFile(pkgJsonPath, 'utf-8');
|
|
33
|
+
parsed = JSON.parse(raw);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (typeof parsed.name === 'string' &&
|
|
39
|
+
parsed.name.startsWith(expectedPrefix) &&
|
|
40
|
+
parsed.name.length > expectedPrefix.length) {
|
|
41
|
+
matchedNames.push(parsed.name);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (matchedNames.length === 0) {
|
|
45
|
+
logger.logger.warn(`scope alias "@${scope}" matched no workspace packages under ${scopeDir}.`);
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
const resolved = [];
|
|
49
|
+
for (const name of matchedNames) {
|
|
50
|
+
const meta = await resolvePackage.resolvePackage(name, { skipMissingAsset: true });
|
|
51
|
+
if (meta)
|
|
52
|
+
resolved.push(meta);
|
|
53
|
+
}
|
|
54
|
+
return resolved;
|
|
55
|
+
}
|
|
56
|
+
function findPackagesRoot(start) {
|
|
57
|
+
let cur = node_path.resolve(start);
|
|
58
|
+
while (true) {
|
|
59
|
+
if (node_fs.existsSync(node_path.join(cur, 'package.json')) && node_fs.existsSync(node_path.join(cur, 'packages'))) {
|
|
60
|
+
return cur;
|
|
61
|
+
}
|
|
62
|
+
const parent = node_path.dirname(cur);
|
|
63
|
+
if (parent === cur)
|
|
64
|
+
return null;
|
|
65
|
+
cur = parent;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
exports.resolveScopeAlias = resolveScopeAlias;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
3
|
+
import { join, resolve, dirname } from 'node:path';
|
|
4
|
+
import { logger } from '../../../utils/logger.mjs';
|
|
5
|
+
import { resolvePackage } from './resolvePackage.mjs';
|
|
6
|
+
|
|
7
|
+
async function resolveScopeAlias(scope, rootCwd) {
|
|
8
|
+
const packagesRoot = findPackagesRoot(rootCwd);
|
|
9
|
+
if (!packagesRoot) {
|
|
10
|
+
logger.error(`cannot locate a monorepo root with a "packages/" directory starting from "${rootCwd}". Scope alias "@${scope}" requires a workspace root.`);
|
|
11
|
+
process.exit(2);
|
|
12
|
+
}
|
|
13
|
+
const scopeDir = join(packagesRoot, 'packages', scope);
|
|
14
|
+
let entries;
|
|
15
|
+
try {
|
|
16
|
+
entries = await readdir(scopeDir);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
logger.error(`scope alias "@${scope}" has no matching directory at ${scopeDir}.`);
|
|
20
|
+
process.exit(2);
|
|
21
|
+
}
|
|
22
|
+
const matchedNames = [];
|
|
23
|
+
const expectedPrefix = `@${scope}/`;
|
|
24
|
+
for (const entry of entries) {
|
|
25
|
+
const pkgJsonPath = join(scopeDir, entry, 'package.json');
|
|
26
|
+
if (!existsSync(pkgJsonPath))
|
|
27
|
+
continue;
|
|
28
|
+
let parsed;
|
|
29
|
+
try {
|
|
30
|
+
const raw = await readFile(pkgJsonPath, 'utf-8');
|
|
31
|
+
parsed = JSON.parse(raw);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (typeof parsed.name === 'string' &&
|
|
37
|
+
parsed.name.startsWith(expectedPrefix) &&
|
|
38
|
+
parsed.name.length > expectedPrefix.length) {
|
|
39
|
+
matchedNames.push(parsed.name);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (matchedNames.length === 0) {
|
|
43
|
+
logger.warn(`scope alias "@${scope}" matched no workspace packages under ${scopeDir}.`);
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
const resolved = [];
|
|
47
|
+
for (const name of matchedNames) {
|
|
48
|
+
const meta = await resolvePackage(name, { skipMissingAsset: true });
|
|
49
|
+
if (meta)
|
|
50
|
+
resolved.push(meta);
|
|
51
|
+
}
|
|
52
|
+
return resolved;
|
|
53
|
+
}
|
|
54
|
+
function findPackagesRoot(start) {
|
|
55
|
+
let cur = resolve(start);
|
|
56
|
+
while (true) {
|
|
57
|
+
if (existsSync(join(cur, 'package.json')) && existsSync(join(cur, 'packages'))) {
|
|
58
|
+
return cur;
|
|
59
|
+
}
|
|
60
|
+
const parent = dirname(cur);
|
|
61
|
+
if (parent === cur)
|
|
62
|
+
return null;
|
|
63
|
+
cur = parent;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export { resolveScopeAlias };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
require('node:crypto');
|
|
4
|
+
require('node:fs/promises');
|
|
5
|
+
require('node:path');
|
|
6
|
+
var logger = require('../../../utils/logger.cjs');
|
|
7
|
+
var scope = require('../../../core/scope/scope.cjs');
|
|
8
|
+
var selectScope = require('../../../prompts/selectScope.cjs');
|
|
9
|
+
require('@inquirer/prompts');
|
|
10
|
+
require('picocolors');
|
|
11
|
+
|
|
12
|
+
async function resolveScopeFlag(flag) {
|
|
13
|
+
if (flag) {
|
|
14
|
+
if (!scope.isValidScope(flag)) {
|
|
15
|
+
logger.logger.error(`Invalid --scope: ${flag}. Expected user | project.`);
|
|
16
|
+
process.exit(2);
|
|
17
|
+
}
|
|
18
|
+
return flag;
|
|
19
|
+
}
|
|
20
|
+
if (!scope.isInteractive()) {
|
|
21
|
+
logger.logger.error('--scope is required in non-interactive environments.');
|
|
22
|
+
logger.logger.error(' Pass --scope=user | --scope=project.');
|
|
23
|
+
process.exit(2);
|
|
24
|
+
}
|
|
25
|
+
return selectScope.selectScopeAsync();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
exports.resolveScopeFlag = resolveScopeFlag;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import 'node:crypto';
|
|
2
|
+
import 'node:fs/promises';
|
|
3
|
+
import 'node:path';
|
|
4
|
+
import { logger } from '../../../utils/logger.mjs';
|
|
5
|
+
import { isValidScope, isInteractive } from '../../../core/scope/scope.mjs';
|
|
6
|
+
import { selectScopeAsync } from '../../../prompts/selectScope.mjs';
|
|
7
|
+
import '@inquirer/prompts';
|
|
8
|
+
import 'picocolors';
|
|
9
|
+
|
|
10
|
+
async function resolveScopeFlag(flag) {
|
|
11
|
+
if (flag) {
|
|
12
|
+
if (!isValidScope(flag)) {
|
|
13
|
+
logger.error(`Invalid --scope: ${flag}. Expected user | project.`);
|
|
14
|
+
process.exit(2);
|
|
15
|
+
}
|
|
16
|
+
return flag;
|
|
17
|
+
}
|
|
18
|
+
if (!isInteractive()) {
|
|
19
|
+
logger.error('--scope is required in non-interactive environments.');
|
|
20
|
+
logger.error(' Pass --scope=user | --scope=project.');
|
|
21
|
+
process.exit(2);
|
|
22
|
+
}
|
|
23
|
+
return selectScopeAsync();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { resolveScopeFlag };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var logger = require('../../../utils/logger.cjs');
|
|
4
|
+
var classifyTarget = require('./classifyTarget.cjs');
|
|
5
|
+
var resolvePackage = require('./resolvePackage.cjs');
|
|
6
|
+
var resolveScopeAlias = require('./resolveScopeAlias.cjs');
|
|
7
|
+
|
|
8
|
+
async function resolveTargets(targets, rootCwd) {
|
|
9
|
+
if (targets.length === 0)
|
|
10
|
+
return [];
|
|
11
|
+
const isSingleTarget = targets.length === 1;
|
|
12
|
+
const seen = new Set();
|
|
13
|
+
const results = [];
|
|
14
|
+
for (const target of targets) {
|
|
15
|
+
const classification = classifyTarget.classifyTarget(target);
|
|
16
|
+
if (classification.kind === 'invalid') {
|
|
17
|
+
logger.logger.error(classification.reason);
|
|
18
|
+
process.exit(2);
|
|
19
|
+
}
|
|
20
|
+
let candidates;
|
|
21
|
+
if (classification.kind === 'scope') {
|
|
22
|
+
candidates = await resolveScopeAlias.resolveScopeAlias(classification.scope, rootCwd);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
const meta = await resolvePackage.resolvePackage(classification.name, {
|
|
26
|
+
skipMissingAsset: !isSingleTarget,
|
|
27
|
+
});
|
|
28
|
+
candidates = meta ? [meta] : [];
|
|
29
|
+
}
|
|
30
|
+
for (const meta of candidates) {
|
|
31
|
+
if (!seen.has(meta.packageName)) {
|
|
32
|
+
seen.add(meta.packageName);
|
|
33
|
+
results.push(meta);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return results;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
exports.resolveTargets = resolveTargets;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ResolvedMetadata } from './resolvePackage.js';
|
|
2
|
+
/**
|
|
3
|
+
* Classify each `--package` value, resolve them all, and dedupe the
|
|
4
|
+
* result by `packageName`.
|
|
5
|
+
*
|
|
6
|
+
* - `@<scope>` values enumerate through `resolveScopeAlias` (soft skip
|
|
7
|
+
* when a workspace package lacks `claude.assetPath`).
|
|
8
|
+
* - `@<scope>/<name>` and `<name>` values go through `resolvePackage`.
|
|
9
|
+
* When there is a single `--package` value, the call is strict
|
|
10
|
+
* (asset-missing → exit 2); otherwise asset-missing is a soft skip
|
|
11
|
+
* so the rest of the batch can proceed.
|
|
12
|
+
*
|
|
13
|
+
* Invalid `--package` values exit with code 2 before any filesystem IO.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveTargets(targets: readonly string[], rootCwd: string): Promise<ResolvedMetadata[]>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { logger } from '../../../utils/logger.mjs';
|
|
2
|
+
import { classifyTarget } from './classifyTarget.mjs';
|
|
3
|
+
import { resolvePackage } from './resolvePackage.mjs';
|
|
4
|
+
import { resolveScopeAlias } from './resolveScopeAlias.mjs';
|
|
5
|
+
|
|
6
|
+
async function resolveTargets(targets, rootCwd) {
|
|
7
|
+
if (targets.length === 0)
|
|
8
|
+
return [];
|
|
9
|
+
const isSingleTarget = targets.length === 1;
|
|
10
|
+
const seen = new Set();
|
|
11
|
+
const results = [];
|
|
12
|
+
for (const target of targets) {
|
|
13
|
+
const classification = classifyTarget(target);
|
|
14
|
+
if (classification.kind === 'invalid') {
|
|
15
|
+
logger.error(classification.reason);
|
|
16
|
+
process.exit(2);
|
|
17
|
+
}
|
|
18
|
+
let candidates;
|
|
19
|
+
if (classification.kind === 'scope') {
|
|
20
|
+
candidates = await resolveScopeAlias(classification.scope, rootCwd);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
const meta = await resolvePackage(classification.name, {
|
|
24
|
+
skipMissingAsset: !isSingleTarget,
|
|
25
|
+
});
|
|
26
|
+
candidates = meta ? [meta] : [];
|
|
27
|
+
}
|
|
28
|
+
for (const meta of candidates) {
|
|
29
|
+
if (!seen.has(meta.packageName)) {
|
|
30
|
+
seen.add(meta.packageName);
|
|
31
|
+
results.push(meta);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return results;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { resolveTargets };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var promises = require('node:fs/promises');
|
|
4
|
+
var node_path = require('node:path');
|
|
5
|
+
var logger = require('../../../utils/logger.cjs');
|
|
6
|
+
var injectOne = require('./injectOne.cjs');
|
|
7
|
+
var resolveScopeFlag = require('./resolveScopeFlag.cjs');
|
|
8
|
+
|
|
9
|
+
async function runInject(flags, metadataList) {
|
|
10
|
+
if (metadataList.length === 0)
|
|
11
|
+
return;
|
|
12
|
+
for (const metadata of metadataList) {
|
|
13
|
+
if (!node_path.isAbsolute(metadata.packageRoot)) {
|
|
14
|
+
logger.logger.error(`packageRoot must be an absolute path; received: ${metadata.packageRoot}`);
|
|
15
|
+
process.exit(2);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const originCwd = flags.root ?? process.cwd();
|
|
19
|
+
const scope = await resolveScopeFlag.resolveScopeFlag(flags.scope);
|
|
20
|
+
const fatalOnError = metadataList.length === 1;
|
|
21
|
+
let failureCount = 0;
|
|
22
|
+
for (const metadata of metadataList) {
|
|
23
|
+
const assetRoot = node_path.resolve(metadata.packageRoot, metadata.assetPath);
|
|
24
|
+
const hashesPath = node_path.join(metadata.packageRoot, 'dist', 'claude-hashes.json');
|
|
25
|
+
const hashesPresent = await promises.stat(hashesPath).then(() => true, () => false);
|
|
26
|
+
const target = {
|
|
27
|
+
name: metadata.packageName,
|
|
28
|
+
version: metadata.packageVersion,
|
|
29
|
+
packageRoot: metadata.packageRoot,
|
|
30
|
+
assetRoot,
|
|
31
|
+
hashesPresent,
|
|
32
|
+
};
|
|
33
|
+
let exitCode;
|
|
34
|
+
try {
|
|
35
|
+
exitCode = await injectOne.injectOne(target, scope, flags, originCwd);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
39
|
+
logger.logger.error(`${target.name}: ${msg}`);
|
|
40
|
+
exitCode = 1;
|
|
41
|
+
}
|
|
42
|
+
if (exitCode !== 0) {
|
|
43
|
+
if (fatalOnError)
|
|
44
|
+
process.exit(exitCode);
|
|
45
|
+
failureCount += 1;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (failureCount > 0)
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
exports.runInject = runInject;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { stat } from 'node:fs/promises';
|
|
2
|
+
import { isAbsolute, resolve, join } from 'node:path';
|
|
3
|
+
import { logger } from '../../../utils/logger.mjs';
|
|
4
|
+
import { injectOne } from './injectOne.mjs';
|
|
5
|
+
import { resolveScopeFlag } from './resolveScopeFlag.mjs';
|
|
6
|
+
|
|
7
|
+
async function runInject(flags, metadataList) {
|
|
8
|
+
if (metadataList.length === 0)
|
|
9
|
+
return;
|
|
10
|
+
for (const metadata of metadataList) {
|
|
11
|
+
if (!isAbsolute(metadata.packageRoot)) {
|
|
12
|
+
logger.error(`packageRoot must be an absolute path; received: ${metadata.packageRoot}`);
|
|
13
|
+
process.exit(2);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
const originCwd = flags.root ?? process.cwd();
|
|
17
|
+
const scope = await resolveScopeFlag(flags.scope);
|
|
18
|
+
const fatalOnError = metadataList.length === 1;
|
|
19
|
+
let failureCount = 0;
|
|
20
|
+
for (const metadata of metadataList) {
|
|
21
|
+
const assetRoot = resolve(metadata.packageRoot, metadata.assetPath);
|
|
22
|
+
const hashesPath = join(metadata.packageRoot, 'dist', 'claude-hashes.json');
|
|
23
|
+
const hashesPresent = await stat(hashesPath).then(() => true, () => false);
|
|
24
|
+
const target = {
|
|
25
|
+
name: metadata.packageName,
|
|
26
|
+
version: metadata.packageVersion,
|
|
27
|
+
packageRoot: metadata.packageRoot,
|
|
28
|
+
assetRoot,
|
|
29
|
+
hashesPresent,
|
|
30
|
+
};
|
|
31
|
+
let exitCode;
|
|
32
|
+
try {
|
|
33
|
+
exitCode = await injectOne(target, scope, flags, originCwd);
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
37
|
+
logger.error(`${target.name}: ${msg}`);
|
|
38
|
+
exitCode = 1;
|
|
39
|
+
}
|
|
40
|
+
if (exitCode !== 0) {
|
|
41
|
+
if (fatalOnError)
|
|
42
|
+
process.exit(exitCode);
|
|
43
|
+
failureCount += 1;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (failureCount > 0)
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { runInject };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var node_path = require('node:path');
|
|
4
|
+
var hash = require('../hash/hash.cjs');
|
|
5
|
+
var toPosix = require('./utils/toPosix.cjs');
|
|
6
|
+
var walkFiles = require('./utils/walkFiles.cjs');
|
|
7
|
+
|
|
8
|
+
async function buildPlan(input) {
|
|
9
|
+
const { sourceHashes, targetRoot, namespacePrefixes, force } = input;
|
|
10
|
+
const actions = [];
|
|
11
|
+
let requiresForce = false;
|
|
12
|
+
for (const [relPath, srcHash] of Object.entries(sourceHashes)) {
|
|
13
|
+
const dstAbs = node_path.join(targetRoot, relPath);
|
|
14
|
+
const dstHash = await hash.hashFile(dstAbs);
|
|
15
|
+
if (dstHash === null)
|
|
16
|
+
actions.push({ kind: 'copy', relPath, dstAbs });
|
|
17
|
+
else if (hash.hashEquals(dstHash, srcHash))
|
|
18
|
+
actions.push({ kind: 'skip-uptodate', relPath, dstAbs });
|
|
19
|
+
else {
|
|
20
|
+
actions.push({ kind: 'warn-diverged', relPath, dstAbs });
|
|
21
|
+
requiresForce = true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const known = new Set(Object.keys(sourceHashes));
|
|
25
|
+
for (const prefix of namespacePrefixes) {
|
|
26
|
+
const prefixRoot = node_path.join(targetRoot, prefix);
|
|
27
|
+
for await (const abs of walkFiles.walkFiles(prefixRoot)) {
|
|
28
|
+
const relPath = toPosix.toPosix(node_path.relative(targetRoot, abs));
|
|
29
|
+
if (known.has(relPath))
|
|
30
|
+
continue;
|
|
31
|
+
if (force)
|
|
32
|
+
actions.push({ kind: 'delete', relPath, dstAbs: abs });
|
|
33
|
+
else {
|
|
34
|
+
actions.push({ kind: 'warn-orphan', relPath, dstAbs: abs });
|
|
35
|
+
requiresForce = true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return { actions, requiresForce };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
exports.buildPlan = buildPlan;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { join, relative } from 'node:path';
|
|
2
|
+
import { hashFile, hashEquals } from '../hash/hash.mjs';
|
|
3
|
+
import { toPosix } from './utils/toPosix.mjs';
|
|
4
|
+
import { walkFiles } from './utils/walkFiles.mjs';
|
|
5
|
+
|
|
6
|
+
async function buildPlan(input) {
|
|
7
|
+
const { sourceHashes, targetRoot, namespacePrefixes, force } = input;
|
|
8
|
+
const actions = [];
|
|
9
|
+
let requiresForce = false;
|
|
10
|
+
for (const [relPath, srcHash] of Object.entries(sourceHashes)) {
|
|
11
|
+
const dstAbs = join(targetRoot, relPath);
|
|
12
|
+
const dstHash = await hashFile(dstAbs);
|
|
13
|
+
if (dstHash === null)
|
|
14
|
+
actions.push({ kind: 'copy', relPath, dstAbs });
|
|
15
|
+
else if (hashEquals(dstHash, srcHash))
|
|
16
|
+
actions.push({ kind: 'skip-uptodate', relPath, dstAbs });
|
|
17
|
+
else {
|
|
18
|
+
actions.push({ kind: 'warn-diverged', relPath, dstAbs });
|
|
19
|
+
requiresForce = true;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const known = new Set(Object.keys(sourceHashes));
|
|
23
|
+
for (const prefix of namespacePrefixes) {
|
|
24
|
+
const prefixRoot = join(targetRoot, prefix);
|
|
25
|
+
for await (const abs of walkFiles(prefixRoot)) {
|
|
26
|
+
const relPath = toPosix(relative(targetRoot, abs));
|
|
27
|
+
if (known.has(relPath))
|
|
28
|
+
continue;
|
|
29
|
+
if (force)
|
|
30
|
+
actions.push({ kind: 'delete', relPath, dstAbs: abs });
|
|
31
|
+
else {
|
|
32
|
+
actions.push({ kind: 'warn-orphan', relPath, dstAbs: abs });
|
|
33
|
+
requiresForce = true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { actions, requiresForce };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export { buildPlan };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Sha256Hex } from '../hash/index.js';
|
|
2
|
+
export type Action = {
|
|
3
|
+
kind: 'copy';
|
|
4
|
+
relPath: string;
|
|
5
|
+
dstAbs: string;
|
|
6
|
+
} | {
|
|
7
|
+
kind: 'skip-uptodate';
|
|
8
|
+
relPath: string;
|
|
9
|
+
dstAbs: string;
|
|
10
|
+
} | {
|
|
11
|
+
kind: 'warn-diverged';
|
|
12
|
+
relPath: string;
|
|
13
|
+
dstAbs: string;
|
|
14
|
+
} | {
|
|
15
|
+
kind: 'warn-orphan';
|
|
16
|
+
relPath: string;
|
|
17
|
+
dstAbs: string;
|
|
18
|
+
} | {
|
|
19
|
+
kind: 'delete';
|
|
20
|
+
relPath: string;
|
|
21
|
+
dstAbs: string;
|
|
22
|
+
};
|
|
23
|
+
export interface InjectPlan {
|
|
24
|
+
actions: Action[];
|
|
25
|
+
requiresForce: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface PlanInput {
|
|
28
|
+
sourceHashes: Record<string, Sha256Hex>;
|
|
29
|
+
targetRoot: string;
|
|
30
|
+
namespacePrefixes: string[];
|
|
31
|
+
force: boolean;
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function toPosix(p: string): string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var promises = require('node:fs/promises');
|
|
4
|
+
var node_path = require('node:path');
|
|
5
|
+
|
|
6
|
+
async function* walkFiles(root) {
|
|
7
|
+
let entries;
|
|
8
|
+
try {
|
|
9
|
+
entries = await promises.readdir(root, { withFileTypes: true });
|
|
10
|
+
}
|
|
11
|
+
catch (err) {
|
|
12
|
+
if (err.code === 'ENOENT')
|
|
13
|
+
return;
|
|
14
|
+
throw err;
|
|
15
|
+
}
|
|
16
|
+
for (const entry of entries) {
|
|
17
|
+
const abs = node_path.join(root, entry.name);
|
|
18
|
+
if (entry.isDirectory())
|
|
19
|
+
yield* walkFiles(abs);
|
|
20
|
+
else if (entry.isFile())
|
|
21
|
+
yield abs;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
exports.walkFiles = walkFiles;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function walkFiles(root: string): AsyncGenerator<string>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { readdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
|
|
4
|
+
async function* walkFiles(root) {
|
|
5
|
+
let entries;
|
|
6
|
+
try {
|
|
7
|
+
entries = await readdir(root, { withFileTypes: true });
|
|
8
|
+
}
|
|
9
|
+
catch (err) {
|
|
10
|
+
if (err.code === 'ENOENT')
|
|
11
|
+
return;
|
|
12
|
+
throw err;
|
|
13
|
+
}
|
|
14
|
+
for (const entry of entries) {
|
|
15
|
+
const abs = join(root, entry.name);
|
|
16
|
+
if (entry.isDirectory())
|
|
17
|
+
yield* walkFiles(abs);
|
|
18
|
+
else if (entry.isFile())
|
|
19
|
+
yield abs;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { walkFiles };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var node_crypto = require('node:crypto');
|
|
4
|
+
var promises = require('node:fs/promises');
|
|
5
|
+
|
|
6
|
+
function hashContent(buffer) {
|
|
7
|
+
return node_crypto.createHash('sha256').update(buffer).digest('hex');
|
|
8
|
+
}
|
|
9
|
+
async function hashFile(absPath) {
|
|
10
|
+
try {
|
|
11
|
+
const buf = await promises.readFile(absPath);
|
|
12
|
+
return hashContent(buf);
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
if (err.code === 'ENOENT')
|
|
16
|
+
return null;
|
|
17
|
+
throw err;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function hashEquals(a, b) {
|
|
21
|
+
if (a === null || b === null)
|
|
22
|
+
return false;
|
|
23
|
+
if (a.length !== b.length)
|
|
24
|
+
return false;
|
|
25
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
exports.hashContent = hashContent;
|
|
29
|
+
exports.hashEquals = hashEquals;
|
|
30
|
+
exports.hashFile = hashFile;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type Sha256Hex = string;
|
|
2
|
+
export declare function hashContent(buffer: Buffer | string): Sha256Hex;
|
|
3
|
+
export declare function hashFile(absPath: string): Promise<Sha256Hex | null>;
|
|
4
|
+
export declare function hashEquals(a: Sha256Hex | null, b: Sha256Hex | null): boolean;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
|
|
4
|
+
function hashContent(buffer) {
|
|
5
|
+
return createHash('sha256').update(buffer).digest('hex');
|
|
6
|
+
}
|
|
7
|
+
async function hashFile(absPath) {
|
|
8
|
+
try {
|
|
9
|
+
const buf = await readFile(absPath);
|
|
10
|
+
return hashContent(buf);
|
|
11
|
+
}
|
|
12
|
+
catch (err) {
|
|
13
|
+
if (err.code === 'ENOENT')
|
|
14
|
+
return null;
|
|
15
|
+
throw err;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function hashEquals(a, b) {
|
|
19
|
+
if (a === null || b === null)
|
|
20
|
+
return false;
|
|
21
|
+
if (a.length !== b.length)
|
|
22
|
+
return false;
|
|
23
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { hashContent, hashEquals, hashFile };
|