@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,111 @@
|
|
|
1
|
+
# E2E Smoke Tests — 8-path matrix via engine dispatcher
|
|
2
|
+
|
|
3
|
+
**Run from `/tmp/...` — never from the monorepo root or `${TARGET_PATH}/`.**
|
|
4
|
+
|
|
5
|
+
`--scope=project` walks `cwd` upward looking for an existing `.claude`
|
|
6
|
+
directory. Running from the monorepo would reuse or mutate the real
|
|
7
|
+
repo's `.claude`, which is a destructive error.
|
|
8
|
+
|
|
9
|
+
No fake `node_modules` needed — the engine uses
|
|
10
|
+
`createRequire(import.meta.url).resolve(`${PACKAGE_NAME}/package.json`)`
|
|
11
|
+
from the engine's own installed location.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Setup
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
BIN="$PWD/packages/slats/claude-assets-sync/bin/inject-claude-settings.mjs"
|
|
19
|
+
DIR=/tmp/inject-smoke-${SHORTCUT:-target}
|
|
20
|
+
[ -d "$DIR" ] && find "$DIR" -mindepth 1 -delete
|
|
21
|
+
mkdir -p "$DIR" && cd "$DIR"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`[ -d ... ] && find -delete` keeps the setup idempotent. **Never** use
|
|
25
|
+
`rm -rf` or unquoted `*` globs — too easy to nuke the wrong directory.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Matrix
|
|
30
|
+
|
|
31
|
+
Execute sequentially. `EXIT=$?` after each so the value is captured
|
|
32
|
+
before the next command overwrites `$?`.
|
|
33
|
+
|
|
34
|
+
| # | Command | Expected exit | Purpose |
|
|
35
|
+
|----|--------------------------------------------------------------------------------------------------|---------------|--------------------------------------------------------------|
|
|
36
|
+
| 1 | `node "$BIN" --package=${PACKAGE_NAME} --scope=project --dry-run` | 0 | Dry run — previews actions, no writes. |
|
|
37
|
+
| 2 | `node "$BIN" --package=${PACKAGE_NAME} --scope=project` | 0 | First real install — writes `.claude/` under `$DIR`. |
|
|
38
|
+
| 3 | `node "$BIN" --package=${PACKAGE_NAME} --scope=project` | 0 | Re-run — no-op (idempotent). |
|
|
39
|
+
| 4 | (after tampering) `CI=true node "$BIN" --package=${PACKAGE_NAME} --scope=project` | **2** | CI + tampered content → refuse to overwrite. |
|
|
40
|
+
| 5 | `CI=true node "$BIN" --package=${PACKAGE_NAME} --scope=project --force` | 0 | `--force` overrides the refusal. |
|
|
41
|
+
| 6 | `CI=true node "$BIN" --package=${PACKAGE_NAME}` | **2** | Missing `--scope` in non-TTY context. |
|
|
42
|
+
| 7 | `node "$BIN"` | **2** | Missing `--package` (dispatcher-specific). |
|
|
43
|
+
| 8 | `node "$BIN" --package=@does/not-exist` | **2** | Unresolvable package (dispatcher-specific). |
|
|
44
|
+
|
|
45
|
+
### Tamper step (between path 3 and path 4)
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
find .claude -name SKILL.md -exec sh -c 'echo tampered >> "$1"' _ {} \;
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Appends `tampered` to every `SKILL.md` under the local `.claude/`.
|
|
52
|
+
Simulates a human edit that the CI-mode dispatcher must detect and
|
|
53
|
+
refuse to clobber.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Execution Shape
|
|
58
|
+
|
|
59
|
+
Split into **two bash calls** because `cwd` resets between Bash tool
|
|
60
|
+
invocations.
|
|
61
|
+
|
|
62
|
+
**First call** — paths 1–3:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
BIN="$PWD/packages/slats/claude-assets-sync/bin/inject-claude-settings.mjs"
|
|
66
|
+
DIR=/tmp/inject-smoke-${SHORTCUT:-target}
|
|
67
|
+
[ -d "$DIR" ] && find "$DIR" -mindepth 1 -delete
|
|
68
|
+
mkdir -p "$DIR" && cd "$DIR"
|
|
69
|
+
|
|
70
|
+
node "$BIN" --package=${PACKAGE_NAME} --scope=project --dry-run; echo "EXIT=$?"
|
|
71
|
+
node "$BIN" --package=${PACKAGE_NAME} --scope=project; echo "EXIT=$?"
|
|
72
|
+
node "$BIN" --package=${PACKAGE_NAME} --scope=project; echo "EXIT=$?"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Second call** — paths 4–8:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
DIR=/tmp/inject-smoke-${SHORTCUT:-target}
|
|
79
|
+
BIN="$PWD/packages/slats/claude-assets-sync/bin/inject-claude-settings.mjs"
|
|
80
|
+
cd "$DIR"
|
|
81
|
+
|
|
82
|
+
find .claude -name SKILL.md -exec sh -c 'echo tampered >> "$1"' _ {} \;
|
|
83
|
+
CI=true node "$BIN" --package=${PACKAGE_NAME} --scope=project; echo "EXIT=$?"
|
|
84
|
+
CI=true node "$BIN" --package=${PACKAGE_NAME} --scope=project --force; echo "EXIT=$?"
|
|
85
|
+
CI=true node "$BIN" --package=${PACKAGE_NAME}; echo "EXIT=$?"
|
|
86
|
+
node "$BIN"; echo "EXIT=$?"
|
|
87
|
+
node "$BIN" --package=@does/not-exist; echo "EXIT=$?"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Note: `$PWD` in the second call is the parent shell's cwd (monorepo
|
|
91
|
+
root), so `BIN` resolves correctly. `cd "$DIR"` then moves into the
|
|
92
|
+
smoke directory before invoking.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Failure Handling
|
|
97
|
+
|
|
98
|
+
| Observed | Meaning | Action |
|
|
99
|
+
|----------|-------------------------------------------------------------------------|--------------------------------------------------------------------|
|
|
100
|
+
| 1 ≠ 0 | Dry-run crashed. Likely an engine bug or bad `claude.assetPath`. | Stop, capture stderr, report. |
|
|
101
|
+
| 2 ≠ 0 | First write failed. Permissions, engine bug, or manifest issue. | Stop, inspect `dist/claude-hashes.json`, report. |
|
|
102
|
+
| 3 ≠ 0 | Idempotency broken — re-run should be no-op. | Stop, diff `$DIR/.claude` before/after, report. |
|
|
103
|
+
| 4 = 0 | CI mode did not refuse tampered files. Safety regression. | Stop — the engine's CI gate is broken. |
|
|
104
|
+
| 5 ≠ 0 | `--force` failed to override. Check engine. | Stop, report. |
|
|
105
|
+
| 6 = 0 | Engine defaulted a scope in non-TTY context. Should require `--scope`. | Stop, report. |
|
|
106
|
+
| 7 = 0 | Dispatcher accepted no `--package`. Violates contract. | Stop — dispatcher bug. |
|
|
107
|
+
| 8 = 0 | Dispatcher succeeded on unresolvable package. Violates contract. | Stop — dispatcher bug. |
|
|
108
|
+
|
|
109
|
+
Do not attempt to "make the tests pass" by altering expectations. The
|
|
110
|
+
matrix encodes invariants of the engine — a mismatch is a real
|
|
111
|
+
regression upstream.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Consumer Integration Template
|
|
2
|
+
|
|
3
|
+
How to make a package ship Claude Code assets through the `inject-claude-settings` dispatcher. Two fields in `package.json`; no stub code.
|
|
4
|
+
|
|
5
|
+
## 1. `package.json` additions
|
|
6
|
+
|
|
7
|
+
```jsonc
|
|
8
|
+
{
|
|
9
|
+
"name": "@your-scope/your-package",
|
|
10
|
+
"version": "…",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "… && yarn build:hashes",
|
|
13
|
+
"build:hashes": "claude-build-hashes"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@slats/claude-assets-sync": "workspace:^"
|
|
17
|
+
},
|
|
18
|
+
"files": ["dist", "docs", "README.md"],
|
|
19
|
+
"claude": {
|
|
20
|
+
"assetPath": "docs/claude"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- `@slats/claude-assets-sync` MUST be in `dependencies`, not `devDependencies` or `peerDependencies`.
|
|
26
|
+
- Do **not** add any `bin` field. Bin names collide across consumers under `node_modules/.bin/` and the engine is the sole CLI surface.
|
|
27
|
+
- Do **not** expose `./bin/*` or `./docs/*` in `exports`. Exposing them would let bundlers pull CLI code or the docs tree into app bundles.
|
|
28
|
+
- Do **not** create a `bin/` or `scripts/` directory in the consumer. The engine's `claude-build-hashes` bin (resolved via `node_modules/.bin/`) handles build-time hashing.
|
|
29
|
+
|
|
30
|
+
## 2. `docs/claude/` authoring
|
|
31
|
+
|
|
32
|
+
Any file tree works, but the recommended layout is:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
docs/claude/
|
|
36
|
+
├── skills/
|
|
37
|
+
│ └── <skill-name>/
|
|
38
|
+
│ ├── SKILL.md
|
|
39
|
+
│ └── knowledge/...
|
|
40
|
+
├── rules/...
|
|
41
|
+
└── commands/...
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The build step (`yarn build:hashes` → `claude-build-hashes`) hashes every file under `docs/claude/` relative to the asset root and writes `dist/claude-hashes.json`. On inject, the CLI copies `skills`/`rules`/`commands` into the matching subtree under `.claude/`.
|
|
45
|
+
|
|
46
|
+
## 3. Isolation guardrails (optional but recommended)
|
|
47
|
+
|
|
48
|
+
In a `.dependency-cruiser.cjs`:
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
{
|
|
52
|
+
name: 'src-no-docs',
|
|
53
|
+
severity: 'error',
|
|
54
|
+
comment:
|
|
55
|
+
'src/ must not import from docs/. docs/claude/** contains pure markdown ' +
|
|
56
|
+
'assets meant only for the engine dispatcher, not for the library runtime.',
|
|
57
|
+
from: { path: '^src/' },
|
|
58
|
+
to: { path: '^docs/' },
|
|
59
|
+
},
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Plus `"sideEffects": false` in `package.json`. These ensure the docs tree never leaks into consumer runtime bundles.
|
|
63
|
+
|
|
64
|
+
The legacy `src-no-bin` and `src-no-claude-assets-sync` rules are no longer load-bearing — the consumer owns no `bin/`, and the engine isn't referenced from `src/` anyway. Do not reintroduce them.
|
|
65
|
+
|
|
66
|
+
## 4. End-user invocations
|
|
67
|
+
|
|
68
|
+
| Install topology | Invocation |
|
|
69
|
+
|---|---|
|
|
70
|
+
| End user installs consumer as a **direct dep** on npm / yarn-classic | `npx inject-claude-settings --package=@your-scope/your-package --scope=user` |
|
|
71
|
+
| End user installs consumer as a **direct dep** on pnpm strict / yarn-berry PnP | `npx -p @slats/claude-assets-sync inject-claude-settings --package=@your-scope/your-package --scope=user` |
|
|
72
|
+
| End user has **no consumer installed** yet | `npx -p @slats/claude-assets-sync inject-claude-settings --package=@your-scope/your-package --scope=user` (resolves to whatever is on the registry under that exact name) |
|
|
73
|
+
| End user has **multiple consumers installed** | Call `inject-claude-settings --package=<one-name>` per target. There is no `--all`. |
|
|
74
|
+
|
|
75
|
+
### Scope resolution (project)
|
|
76
|
+
|
|
77
|
+
For `--scope=project`, the target `.claude` directory is resolved by walking up from `process.cwd()` and reusing the first existing `.claude` directory found. Only if no ancestor owns a `.claude` does the CLI fall back to `process.cwd()/.claude`. The CLI logs `(auto-located)` when this happens.
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
workspace/
|
|
81
|
+
.claude/ ← reused target (auto-located)
|
|
82
|
+
packages/
|
|
83
|
+
@your-scope/your-package/ ← cd here and run inject-claude-settings
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Running `inject-claude-settings --package=@your-scope/your-package --scope=project` from `packages/@your-scope/your-package/` injects into `workspace/.claude`, not `packages/@your-scope/your-package/.claude`.
|
|
87
|
+
|
|
88
|
+
## 5. Verification checklist
|
|
89
|
+
|
|
90
|
+
- [ ] `yarn build` succeeds and emits `dist/claude-hashes.json` alongside the rest of `dist/`.
|
|
91
|
+
- [ ] `node packages/slats/claude-assets-sync/bin/inject-claude-settings.mjs --help` prints the dispatcher usage.
|
|
92
|
+
- [ ] `node packages/slats/claude-assets-sync/bin/inject-claude-settings.mjs --package=@your-scope/your-package --scope=project --dry-run` emits a copy plan when run from `/tmp/...`.
|
|
93
|
+
- [ ] If you enabled Section 3's depcheck, `yarn depcheck` reports zero violations.
|
|
94
|
+
- [ ] Consumer bundler tree-shakes away docs — grep the built bundle for `@slats/claude-assets-sync`, `inject-claude-settings`, and `docs/claude`; all three should be absent.
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slats/claude-assets-sync",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "CLI
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Shared CLI engine that lets consumer packages inject their Claude docs (skills, rules, commands) into a user's .claude directory via a thin bin/inject-docs wrapper.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
|
7
7
|
"claude-code",
|
|
8
8
|
"cli",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
9
|
+
"inject",
|
|
10
|
+
"docs",
|
|
11
11
|
"skills",
|
|
12
12
|
"assets"
|
|
13
13
|
],
|
|
@@ -29,23 +29,34 @@
|
|
|
29
29
|
"source": "./src/index.ts",
|
|
30
30
|
"import": "./dist/index.mjs",
|
|
31
31
|
"require": "./dist/index.cjs"
|
|
32
|
+
},
|
|
33
|
+
"./buildHashes": {
|
|
34
|
+
"import": "./scripts/buildHashes.mjs"
|
|
32
35
|
}
|
|
33
36
|
},
|
|
34
37
|
"main": "dist/index.cjs",
|
|
35
38
|
"module": "dist/index.mjs",
|
|
36
39
|
"types": "dist/index.d.ts",
|
|
37
|
-
"bin":
|
|
40
|
+
"bin": {
|
|
41
|
+
"claude-build-hashes": "./scripts/claude-build-hashes.mjs",
|
|
42
|
+
"inject-claude-settings": "./bin/inject-claude-settings.mjs"
|
|
43
|
+
},
|
|
38
44
|
"files": [
|
|
39
45
|
"dist",
|
|
46
|
+
"docs",
|
|
47
|
+
"bin",
|
|
48
|
+
"scripts",
|
|
40
49
|
"README.md"
|
|
41
50
|
],
|
|
42
51
|
"scripts": {
|
|
43
|
-
"build": "node scripts/inject-version.js && rollup -c && yarn build:types",
|
|
52
|
+
"build": "node scripts/inject-version.js && rollup -c && yarn build:types && yarn build:hashes",
|
|
53
|
+
"build:hashes": "node scripts/build-hashes.mjs",
|
|
44
54
|
"build:publish:npm": "yarn build && yarn publish:npm",
|
|
45
55
|
"build:types": "node ../../aileron/script/build/buildTypes.mjs",
|
|
46
|
-
"dev": "node scripts/inject-version.js && tsx src/
|
|
56
|
+
"dev": "node scripts/inject-version.js && tsx src/main.ts",
|
|
47
57
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
48
58
|
"lint": "eslint \"src/**/*.ts\"",
|
|
59
|
+
"prepublishOnly": "yarn build",
|
|
49
60
|
"publish:npm": "yarn npm publish --access public",
|
|
50
61
|
"test": "vitest",
|
|
51
62
|
"version:major": "yarn version major",
|
|
@@ -53,17 +64,14 @@
|
|
|
53
64
|
"version:patch": "yarn version patch"
|
|
54
65
|
},
|
|
55
66
|
"dependencies": {
|
|
56
|
-
"@
|
|
67
|
+
"@inquirer/prompts": "^8.4.2",
|
|
57
68
|
"commander": "^12.1.0",
|
|
58
|
-
"
|
|
59
|
-
"ink-select-input": "^6.2.0",
|
|
60
|
-
"ink-spinner": "^5.0.0",
|
|
61
|
-
"picocolors": "^1.1.1",
|
|
62
|
-
"react": "^19.1.1",
|
|
63
|
-
"react-dom": "^19.1.1"
|
|
69
|
+
"picocolors": "^1.1.1"
|
|
64
70
|
},
|
|
65
71
|
"devDependencies": {
|
|
66
|
-
"@
|
|
67
|
-
|
|
72
|
+
"@inquirer/testing": "^3.3.5"
|
|
73
|
+
},
|
|
74
|
+
"claude": {
|
|
75
|
+
"assetPath": "docs/claude"
|
|
68
76
|
}
|
|
69
77
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Thin wrapper — parses this package's package.json and delegates to
|
|
3
|
+
// @slats/claude-assets-sync/buildHashes. The `claude.assetPath` convention
|
|
4
|
+
// lives here, in the consumer; the library is generic.
|
|
5
|
+
import { buildHashes } from '@slats/claude-assets-sync/buildHashes';
|
|
6
|
+
import { readFile } from 'node:fs/promises';
|
|
7
|
+
import { dirname, resolve } from 'node:path';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
|
|
10
|
+
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
11
|
+
const pkg = JSON.parse(
|
|
12
|
+
await readFile(resolve(packageRoot, 'package.json'), 'utf-8'),
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
if (typeof pkg.claude?.assetPath === 'string') {
|
|
16
|
+
try {
|
|
17
|
+
const { outPath, fileCount } = await buildHashes({
|
|
18
|
+
packageRoot,
|
|
19
|
+
packageName: pkg.name,
|
|
20
|
+
packageVersion: pkg.version,
|
|
21
|
+
assetPath: pkg.claude.assetPath,
|
|
22
|
+
});
|
|
23
|
+
console.log(
|
|
24
|
+
`✓ claude-hashes.json written: ${fileCount} file(s) → ${outPath}`,
|
|
25
|
+
);
|
|
26
|
+
} catch (err) {
|
|
27
|
+
console.error('❌ build-hashes failed:', err?.message ?? err);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface BuildHashesOptions {
|
|
2
|
+
packageRoot?: string;
|
|
3
|
+
packageName?: string;
|
|
4
|
+
packageVersion?: string;
|
|
5
|
+
assetPathRel?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface BuildHashesResult {
|
|
9
|
+
outPath: string;
|
|
10
|
+
fileCount: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function buildHashes(
|
|
14
|
+
opts?: BuildHashesOptions,
|
|
15
|
+
): Promise<BuildHashesResult>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Library + importable implementation for the hash manifest builder.
|
|
2
|
+
//
|
|
3
|
+
// Self-executing CLI behavior lives in `./claude-build-hashes.mjs` so this
|
|
4
|
+
// file stays free of top-level await and can be bundled into CJS/ESM outputs
|
|
5
|
+
// via Rollup without format errors.
|
|
6
|
+
//
|
|
7
|
+
// Exported for:
|
|
8
|
+
// - Consumer packages: `import { buildHashes } from '@slats/claude-assets-sync/buildHashes'`
|
|
9
|
+
// - Standalone bin: `./claude-build-hashes.mjs`
|
|
10
|
+
//
|
|
11
|
+
// The caller owns all package metadata. This function does not read
|
|
12
|
+
// package.json — consumers parse their own manifest and pass a ready-made
|
|
13
|
+
// set of values so the library stays free of field-shape assumptions.
|
|
14
|
+
|
|
15
|
+
import { createHash } from 'node:crypto';
|
|
16
|
+
import { mkdir, readFile, readdir, writeFile } from 'node:fs/promises';
|
|
17
|
+
import { isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
18
|
+
|
|
19
|
+
const MANIFEST_FILENAME = 'claude-hashes.json';
|
|
20
|
+
const NOISE = [/(^|\/)\.omc(\/|$)/, /(^|\/)\.DS_Store$/, /\.log$/];
|
|
21
|
+
|
|
22
|
+
const toPosix = (p) => (sep === '/' ? p : p.split(sep).join('/'));
|
|
23
|
+
|
|
24
|
+
async function* walk(root) {
|
|
25
|
+
let entries;
|
|
26
|
+
try {
|
|
27
|
+
entries = await readdir(root, { withFileTypes: true });
|
|
28
|
+
} catch (err) {
|
|
29
|
+
if (err.code === 'ENOENT') return;
|
|
30
|
+
throw err;
|
|
31
|
+
}
|
|
32
|
+
for (const entry of entries) {
|
|
33
|
+
const abs = join(root, entry.name);
|
|
34
|
+
if (entry.isDirectory()) yield* walk(abs);
|
|
35
|
+
else if (entry.isFile()) yield abs;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function buildHashes(opts) {
|
|
40
|
+
if (
|
|
41
|
+
!opts ||
|
|
42
|
+
typeof opts.packageRoot !== 'string' ||
|
|
43
|
+
typeof opts.packageName !== 'string' ||
|
|
44
|
+
typeof opts.packageVersion !== 'string' ||
|
|
45
|
+
typeof opts.assetPath !== 'string'
|
|
46
|
+
) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
'buildHashes requires { packageRoot, packageName, packageVersion, assetPath }.',
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
const { packageRoot, packageName, packageVersion, assetPath } = opts;
|
|
52
|
+
if (!isAbsolute(packageRoot)) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
`packageRoot must be an absolute path; received: ${packageRoot}`,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
const assetRoot = resolve(packageRoot, assetPath);
|
|
58
|
+
const files = {};
|
|
59
|
+
for await (const abs of walk(assetRoot)) {
|
|
60
|
+
const rel = toPosix(relative(assetRoot, abs));
|
|
61
|
+
if (NOISE.some((re) => re.test(rel))) continue;
|
|
62
|
+
const buf = await readFile(abs);
|
|
63
|
+
files[rel] = createHash('sha256').update(buf).digest('hex');
|
|
64
|
+
}
|
|
65
|
+
const sorted = Object.fromEntries(
|
|
66
|
+
Object.entries(files).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)),
|
|
67
|
+
);
|
|
68
|
+
const manifest = {
|
|
69
|
+
schemaVersion: 1,
|
|
70
|
+
package: { name: packageName, version: packageVersion },
|
|
71
|
+
generatedAt: new Date().toISOString(),
|
|
72
|
+
algorithm: 'sha256',
|
|
73
|
+
assetRoot: assetPath,
|
|
74
|
+
files: sorted,
|
|
75
|
+
previousVersions: {},
|
|
76
|
+
};
|
|
77
|
+
const distDir = resolve(packageRoot, 'dist');
|
|
78
|
+
await mkdir(distDir, { recursive: true });
|
|
79
|
+
const outPath = join(distDir, MANIFEST_FILENAME);
|
|
80
|
+
await writeFile(outPath, `${JSON.stringify(manifest, null, 2)}\n`, 'utf-8');
|
|
81
|
+
return { outPath, fileCount: Object.keys(sorted).length };
|
|
82
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Standalone CLI for `claude-build-hashes`.
|
|
3
|
+
//
|
|
4
|
+
// Reads the consumer's package.json at process.cwd() to extract the asset
|
|
5
|
+
// path, then delegates to `buildHashes`. Consumers who want a different
|
|
6
|
+
// manifest layout can skip this bin and ship a one-line
|
|
7
|
+
// `scripts/build-hashes.mjs` that calls `buildHashes` directly with their
|
|
8
|
+
// own parsed values.
|
|
9
|
+
//
|
|
10
|
+
// Convention: `pkg.claude?.assetPath` with a fallback of `'claude'`.
|
|
11
|
+
// This convention is purely consumer-side — the library itself enforces
|
|
12
|
+
// nothing about package.json shape.
|
|
13
|
+
import { readFile } from 'node:fs/promises';
|
|
14
|
+
import { resolve } from 'node:path';
|
|
15
|
+
|
|
16
|
+
import { buildHashes } from './buildHashes.mjs';
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
const packageRoot = process.cwd();
|
|
20
|
+
const pkg = JSON.parse(
|
|
21
|
+
await readFile(resolve(packageRoot, 'package.json'), 'utf-8'),
|
|
22
|
+
);
|
|
23
|
+
if (typeof pkg.name !== 'string' || typeof pkg.version !== 'string') {
|
|
24
|
+
throw new Error(
|
|
25
|
+
`${packageRoot}/package.json must define "name" and "version".`,
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
const assetPath =
|
|
29
|
+
typeof pkg.claude?.assetPath === 'string' && pkg.claude.assetPath.length > 0
|
|
30
|
+
? pkg.claude.assetPath
|
|
31
|
+
: 'claude';
|
|
32
|
+
const { outPath, fileCount } = await buildHashes({
|
|
33
|
+
packageRoot,
|
|
34
|
+
packageName: pkg.name,
|
|
35
|
+
packageVersion: pkg.version,
|
|
36
|
+
assetPath,
|
|
37
|
+
});
|
|
38
|
+
console.log(`✓ claude-hashes.json written: ${fileCount} file(s) → ${outPath}`);
|
|
39
|
+
} catch (err) {
|
|
40
|
+
console.error('❌ buildHashes failed:', err?.message ?? err);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { dirname, join } from 'node:path';
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Semantic version regex (https://semver.org/)
|
|
12
|
+
* Matches: 0.0.1, 1.2.3, 1.0.0-beta.1, 2.0.0+build.123, etc.
|
|
13
|
+
*/
|
|
14
|
+
const SEMVER_REGEX = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Read and validate package.json version
|
|
18
|
+
*/
|
|
19
|
+
function readPackageVersion() {
|
|
20
|
+
const packageJsonPath = join(__dirname, '..', 'package.json');
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const content = readFileSync(packageJsonPath, 'utf-8');
|
|
24
|
+
const pkg = JSON.parse(content);
|
|
25
|
+
|
|
26
|
+
if (!pkg.version) {
|
|
27
|
+
console.error('❌ Error: No version field found in package.json');
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!SEMVER_REGEX.test(pkg.version)) {
|
|
32
|
+
console.error(`❌ Error: Invalid semantic version "${pkg.version}" in package.json`);
|
|
33
|
+
console.error(' Expected format: MAJOR.MINOR.PATCH (e.g., 1.2.3, 1.0.0-beta.1)');
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return pkg.version;
|
|
38
|
+
} catch (error) {
|
|
39
|
+
if (error.code === 'ENOENT') {
|
|
40
|
+
console.error('❌ Error: package.json not found at', packageJsonPath);
|
|
41
|
+
} else if (error instanceof SyntaxError) {
|
|
42
|
+
console.error('❌ Error: Invalid JSON in package.json');
|
|
43
|
+
} else {
|
|
44
|
+
console.error('❌ Error reading package.json:', error.message);
|
|
45
|
+
}
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Generate src/version.ts with current version
|
|
52
|
+
*/
|
|
53
|
+
function generateVersionFile(version) {
|
|
54
|
+
const versionFilePath = join(__dirname, '..', 'src', 'utils', 'version.ts');
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
// Check if file exists and read current version
|
|
58
|
+
let currentVersion = null;
|
|
59
|
+
try {
|
|
60
|
+
const existingContent = readFileSync(versionFilePath, 'utf-8');
|
|
61
|
+
const match = existingContent.match(/VERSION = ['"]([^'"]+)['"]/);
|
|
62
|
+
if (match) {
|
|
63
|
+
currentVersion = match[1];
|
|
64
|
+
}
|
|
65
|
+
} catch {
|
|
66
|
+
// File doesn't exist yet, that's fine
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (currentVersion === version) {
|
|
70
|
+
console.log(`✓ Version file already up to date: ${version}`);
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Generate new version file
|
|
75
|
+
const content = `// Auto-generated by scripts/inject-version.js
|
|
76
|
+
// DO NOT EDIT MANUALLY - This file is generated during build
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Current package version from package.json
|
|
80
|
+
* Automatically synchronized during build process
|
|
81
|
+
*/
|
|
82
|
+
export const VERSION = '${version}';
|
|
83
|
+
`;
|
|
84
|
+
|
|
85
|
+
writeFileSync(versionFilePath, content, 'utf-8');
|
|
86
|
+
|
|
87
|
+
if (currentVersion) {
|
|
88
|
+
console.log(`✓ Version file updated: ${currentVersion} → ${version}`);
|
|
89
|
+
} else {
|
|
90
|
+
console.log(`✓ Version file created: ${version}`);
|
|
91
|
+
}
|
|
92
|
+
return true;
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.error('❌ Error generating version file:', error.message);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Main execution
|
|
100
|
+
try {
|
|
101
|
+
const version = readPackageVersion();
|
|
102
|
+
const updated = generateVersionFile(version);
|
|
103
|
+
|
|
104
|
+
if (!updated) {
|
|
105
|
+
console.log(`\n✅ Version is synchronized: ${version}`);
|
|
106
|
+
} else {
|
|
107
|
+
console.log(`\n✅ Version synchronization complete: ${version}`);
|
|
108
|
+
}
|
|
109
|
+
} catch (error) {
|
|
110
|
+
console.error('❌ Unexpected error:', error.message);
|
|
111
|
+
process.exit(1);
|
|
112
|
+
}
|
package/dist/cli.cjs
DELETED
package/dist/cli.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/cli.mjs
DELETED
package/dist/commands/add.cjs
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var ink = require('ink');
|
|
4
|
-
var React = require('react');
|
|
5
|
-
var AddCommand = require('../components/add/AddCommand.cjs');
|
|
6
|
-
var BulkAddView = require('../components/add/BulkAddView.cjs');
|
|
7
|
-
var sync = require('../core/sync.cjs');
|
|
8
|
-
|
|
9
|
-
async function runAddCommand(options, cwd) {
|
|
10
|
-
const workingDir = process.cwd();
|
|
11
|
-
if (options.pattern) {
|
|
12
|
-
try {
|
|
13
|
-
new RegExp(options.pattern);
|
|
14
|
-
}
|
|
15
|
-
catch (err) {
|
|
16
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
17
|
-
throw new Error(`Invalid regex pattern "${options.pattern}": ${msg}`);
|
|
18
|
-
}
|
|
19
|
-
const { waitUntilExit } = ink.render(React.createElement(BulkAddView.BulkAddView, {
|
|
20
|
-
pattern: options.pattern,
|
|
21
|
-
cwd: workingDir,
|
|
22
|
-
local: options.local ?? false,
|
|
23
|
-
ref: options.ref,
|
|
24
|
-
}));
|
|
25
|
-
await waitUntilExit();
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
if (!options.package) {
|
|
29
|
-
console.error('Error: either --package or --pattern must be provided');
|
|
30
|
-
console.error(' Usage: claude-assets-sync add -p <name>');
|
|
31
|
-
console.error(' claude-assets-sync add --pattern <regex>');
|
|
32
|
-
process.exit(1);
|
|
33
|
-
}
|
|
34
|
-
return new Promise((resolve, reject) => {
|
|
35
|
-
const { waitUntilExit } = ink.render(React.createElement(AddCommand.AddCommand, {
|
|
36
|
-
packageName: options.package,
|
|
37
|
-
local: options.local ?? false,
|
|
38
|
-
ref: options.ref,
|
|
39
|
-
onComplete: async (selection) => {
|
|
40
|
-
try {
|
|
41
|
-
await performSync(selection, workingDir);
|
|
42
|
-
resolve();
|
|
43
|
-
}
|
|
44
|
-
catch (error) {
|
|
45
|
-
reject(error);
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
onError: (error) => {
|
|
49
|
-
reject(error);
|
|
50
|
-
},
|
|
51
|
-
onCancel: () => {
|
|
52
|
-
console.log('\nSync cancelled');
|
|
53
|
-
resolve();
|
|
54
|
-
},
|
|
55
|
-
}));
|
|
56
|
-
waitUntilExit().catch(reject);
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
async function performSync(selection, cwd) {
|
|
60
|
-
const exclusions = {
|
|
61
|
-
directories: [],
|
|
62
|
-
files: [],
|
|
63
|
-
};
|
|
64
|
-
for (const assetType of Object.keys(selection.excludedAssets)) {
|
|
65
|
-
for (const excludedPath of selection.excludedAssets[assetType]) {
|
|
66
|
-
exclusions.files.push(excludedPath);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
await sync.syncPackage(selection.packageName, {
|
|
70
|
-
force: true,
|
|
71
|
-
dryRun: false,
|
|
72
|
-
local: selection.source === 'local',
|
|
73
|
-
ref: selection.ref,
|
|
74
|
-
flat: true,
|
|
75
|
-
}, cwd, exclusions.directories.length > 0 || exclusions.files.length > 0
|
|
76
|
-
? exclusions
|
|
77
|
-
: undefined, undefined);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
exports.runAddCommand = runAddCommand;
|