@slats/claude-assets-sync 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/README.md +15 -11
  2. package/dist/claude-hashes.json +7 -7
  3. package/dist/commands/runCli/runCli.d.ts +4 -2
  4. package/dist/commands/runCli/runCli.mjs +7 -2
  5. package/dist/commands/runCli/type.d.ts +1 -0
  6. package/dist/commands/runCli/utils/renderOrFallback.d.ts +6 -0
  7. package/dist/commands/runCli/utils/renderOrFallback.mjs +12 -0
  8. package/dist/commands/runCli/utils/renderPlain.d.ts +11 -0
  9. package/dist/commands/runCli/utils/renderPlain.mjs +89 -0
  10. package/dist/commands/runCli/utils/resolveScopeAlias.mjs +30 -33
  11. package/dist/commands/runCli/utils/resolveScopeFlag.d.ts +9 -1
  12. package/dist/commands/runCli/utils/resolveScopeFlag.mjs +5 -11
  13. package/dist/commands/runCli/utils/toConsumerPackages.d.ts +9 -0
  14. package/dist/commands/runCli/utils/toConsumerPackages.mjs +26 -0
  15. package/dist/core/index.d.ts +2 -2
  16. package/dist/core/injectDocs/index.d.ts +3 -2
  17. package/dist/core/injectDocs/type.d.ts +0 -19
  18. package/dist/core/scope/index.d.ts +1 -1
  19. package/dist/core/scope/scope.d.ts +0 -1
  20. package/dist/core/scope/scope.mjs +1 -4
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.mjs +2 -2
  23. package/dist/ui/InjectApp/InjectApp.d.ts +2 -0
  24. package/dist/ui/InjectApp/InjectApp.mjs +82 -0
  25. package/dist/ui/InjectApp/index.d.ts +2 -0
  26. package/dist/ui/InjectApp/utils/eventSelectors.d.ts +5 -0
  27. package/dist/ui/InjectApp/utils/eventSelectors.mjs +24 -0
  28. package/dist/ui/InjectApp/utils/phaseReducer.d.ts +2 -0
  29. package/dist/ui/InjectApp/utils/phaseReducer.mjs +133 -0
  30. package/dist/ui/InjectApp/utils/renderInjectApp.d.ts +2 -0
  31. package/dist/ui/InjectApp/utils/renderInjectApp.mjs +19 -0
  32. package/dist/ui/InjectApp/utils/type.d.ts +5 -0
  33. package/dist/ui/components/ActionRow.d.ts +7 -0
  34. package/dist/ui/components/ActionRow.mjs +45 -0
  35. package/dist/ui/components/Banner.d.ts +7 -0
  36. package/dist/ui/components/Banner.mjs +9 -0
  37. package/dist/ui/components/ConfirmForce.d.ts +8 -0
  38. package/dist/ui/components/ConfirmForce.mjs +35 -0
  39. package/dist/ui/components/ErrorPanel.d.ts +6 -0
  40. package/dist/ui/components/ErrorPanel.mjs +14 -0
  41. package/dist/ui/components/Footer.d.ts +8 -0
  42. package/dist/ui/components/Footer.mjs +27 -0
  43. package/dist/ui/components/PlanTable.d.ts +8 -0
  44. package/dist/ui/components/PlanTable.mjs +15 -0
  45. package/dist/ui/components/ProgressBar.d.ts +10 -0
  46. package/dist/ui/components/ProgressBar.mjs +28 -0
  47. package/dist/ui/components/ScopePicker.d.ts +7 -0
  48. package/dist/ui/components/ScopePicker.mjs +26 -0
  49. package/dist/ui/components/Spinner.d.ts +8 -0
  50. package/dist/ui/components/Spinner.mjs +10 -0
  51. package/dist/ui/components/StatusBadge.d.ts +8 -0
  52. package/dist/ui/components/StepTracker.d.ts +9 -0
  53. package/dist/ui/components/StepTracker.mjs +43 -0
  54. package/dist/ui/components/Summary.d.ts +9 -0
  55. package/dist/ui/components/Summary.mjs +30 -0
  56. package/dist/ui/components/TargetCard.d.ts +11 -0
  57. package/dist/ui/components/TargetCard.mjs +29 -0
  58. package/dist/ui/hooks/useApplyStep.d.ts +12 -0
  59. package/dist/ui/hooks/useApplyStep.mjs +30 -0
  60. package/dist/ui/hooks/useExitApp.d.ts +8 -0
  61. package/dist/ui/hooks/useExitApp.mjs +19 -0
  62. package/dist/ui/hooks/useForceConfirmStep.d.ts +9 -0
  63. package/dist/ui/hooks/useForceConfirmStep.mjs +24 -0
  64. package/dist/ui/hooks/useInjectSession.d.ts +10 -0
  65. package/dist/ui/hooks/useInjectSession.mjs +63 -0
  66. package/dist/ui/hooks/useInterval.d.ts +1 -0
  67. package/dist/ui/hooks/usePhase.d.ts +2 -0
  68. package/dist/ui/hooks/usePhase.mjs +9 -0
  69. package/dist/ui/hooks/usePlanStep.d.ts +13 -0
  70. package/dist/ui/hooks/usePlanStep.mjs +95 -0
  71. package/dist/ui/hooks/useResolveStep.d.ts +18 -0
  72. package/dist/ui/hooks/useResolveStep.mjs +21 -0
  73. package/dist/ui/hooks/useTerminalWidth.d.ts +1 -0
  74. package/dist/ui/index.d.ts +2 -0
  75. package/dist/ui/index.mjs +16 -0
  76. package/dist/ui/theme/colors.d.ts +12 -0
  77. package/dist/ui/theme/colors.mjs +9 -0
  78. package/dist/ui/theme/icons.d.ts +29 -0
  79. package/dist/ui/theme/icons.mjs +17 -0
  80. package/dist/ui/theme/layout.d.ts +20 -0
  81. package/dist/ui/theme/layout.mjs +9 -0
  82. package/dist/ui/types/event.d.ts +45 -0
  83. package/dist/ui/types/index.d.ts +4 -0
  84. package/dist/ui/types/phase.d.ts +44 -0
  85. package/dist/ui/types/render.d.ts +6 -0
  86. package/dist/ui/types/target.d.ts +25 -0
  87. package/dist/utils/version.d.ts +1 -1
  88. package/dist/utils/version.mjs +1 -1
  89. package/docs/claude/skills/claude-docs-asset-wiring/SKILL.md +1 -1
  90. package/docs/claude/skills/claude-docs-asset-wiring/knowledge/claude-md-template.md +4 -12
  91. package/docs/claude/skills/claude-docs-asset-wiring/knowledge/gotchas.md +17 -14
  92. package/docs/claude/skills/claude-docs-asset-wiring/knowledge/package-json-patches.md +18 -13
  93. package/docs/claude/skills/claude-docs-asset-wiring/knowledge/reference-files.md +4 -4
  94. package/docs/consumer-integration.md +9 -8
  95. package/package.json +12 -7
  96. package/scripts/dev-ui-fixtures.ts +288 -0
  97. package/scripts/dev-ui.tsx +288 -0
  98. package/dist/commands/runCli/runCli.cjs +0 -53
  99. package/dist/commands/runCli/utils/classifyTarget.cjs +0 -48
  100. package/dist/commands/runCli/utils/injectOne.cjs +0 -47
  101. package/dist/commands/runCli/utils/injectOne.d.ts +0 -3
  102. package/dist/commands/runCli/utils/injectOne.mjs +0 -45
  103. package/dist/commands/runCli/utils/resolvePackage.cjs +0 -77
  104. package/dist/commands/runCli/utils/resolveScopeAlias.cjs +0 -69
  105. package/dist/commands/runCli/utils/resolveScopeFlag.cjs +0 -28
  106. package/dist/commands/runCli/utils/resolveTargets.cjs +0 -40
  107. package/dist/commands/runCli/utils/runInject.cjs +0 -52
  108. package/dist/commands/runCli/utils/runInject.d.ts +0 -3
  109. package/dist/commands/runCli/utils/runInject.mjs +0 -50
  110. package/dist/core/buildPlan/buildPlan.cjs +0 -42
  111. package/dist/core/buildPlan/utils/toPosix.cjs +0 -9
  112. package/dist/core/buildPlan/utils/walkFiles.cjs +0 -25
  113. package/dist/core/hash/hash.cjs +0 -30
  114. package/dist/core/hashManifest/hashManifest.cjs +0 -27
  115. package/dist/core/injectDocs/injectDocs.cjs +0 -43
  116. package/dist/core/injectDocs/injectDocs.d.ts +0 -2
  117. package/dist/core/injectDocs/injectDocs.mjs +0 -41
  118. package/dist/core/injectDocs/utils/applyAction.cjs +0 -21
  119. package/dist/core/injectDocs/utils/emitCiForceList.cjs +0 -10
  120. package/dist/core/injectDocs/utils/emitCiForceList.d.ts +0 -2
  121. package/dist/core/injectDocs/utils/emitCiForceList.mjs +0 -8
  122. package/dist/core/injectDocs/utils/printPlan.cjs +0 -20
  123. package/dist/core/injectDocs/utils/printPlan.d.ts +0 -2
  124. package/dist/core/injectDocs/utils/printPlan.mjs +0 -18
  125. package/dist/core/injectDocs/utils/summarize.cjs +0 -27
  126. package/dist/core/scope/scope.cjs +0 -46
  127. package/dist/core/scope/utils/isDirectory.cjs +0 -14
  128. package/dist/index.cjs +0 -20
  129. package/dist/prompts/confirmForce.cjs +0 -27
  130. package/dist/prompts/confirmForce.d.ts +0 -1
  131. package/dist/prompts/confirmForce.mjs +0 -25
  132. package/dist/prompts/index.d.ts +0 -2
  133. package/dist/prompts/selectScope.cjs +0 -30
  134. package/dist/prompts/selectScope.d.ts +0 -2
  135. package/dist/prompts/selectScope.mjs +0 -28
  136. package/dist/utils/asyncPool.cjs +0 -26
  137. package/dist/utils/heartbeat.cjs +0 -25
  138. package/dist/utils/heartbeat.d.ts +0 -16
  139. package/dist/utils/heartbeat.mjs +0 -23
  140. package/dist/utils/logger.cjs +0 -74
  141. package/dist/utils/version.cjs +0 -5
@@ -0,0 +1,288 @@
1
+ #!/usr/bin/env node
2
+ import { render, Box, Text, useApp, useInput } from 'ink';
3
+ import React, { useEffect, useState } from 'react';
4
+
5
+ import { Banner } from '../src/ui/components/Banner.js';
6
+ import { ConfirmForce } from '../src/ui/components/ConfirmForce.js';
7
+ import { ErrorPanel } from '../src/ui/components/ErrorPanel.js';
8
+ import { Footer } from '../src/ui/components/Footer.js';
9
+ import { ProgressBar } from '../src/ui/components/ProgressBar.js';
10
+ import { ScopePicker } from '../src/ui/components/ScopePicker.js';
11
+ import { Spinner } from '../src/ui/components/Spinner.js';
12
+ import { StepTracker } from '../src/ui/components/StepTracker.js';
13
+ import { Summary } from '../src/ui/components/Summary.js';
14
+ import { TargetCard } from '../src/ui/components/TargetCard.js';
15
+ import { colors } from '../src/ui/theme/colors.js';
16
+ import { icons } from '../src/ui/theme/icons.js';
17
+ import type { Phase } from '../src/ui/types/index.js';
18
+ import { VERSION } from '../src/utils/version.js';
19
+
20
+ import { buildPhase, PHASES, type PhaseKey } from './dev-ui-fixtures.js';
21
+
22
+ interface CliArgs {
23
+ mode: 'usage' | 'phase' | 'tour';
24
+ phase?: PhaseKey;
25
+ tourMs?: number;
26
+ }
27
+
28
+ function parseArgs(argv: readonly string[]): CliArgs {
29
+ if (argv.includes('--tour')) {
30
+ const msArg = argv.find((a) => a.startsWith('--ms='));
31
+ const tourMs = msArg ? Number(msArg.slice(5)) : 2500;
32
+ return { mode: 'tour', tourMs };
33
+ }
34
+ const phaseArg = argv.find((a) => a.startsWith('--phase='));
35
+ if (phaseArg) {
36
+ const phaseKey = phaseArg.slice(8);
37
+ if (!PHASES.includes(phaseKey as PhaseKey)) {
38
+ console.error(
39
+ `Unknown phase: ${phaseKey}. Available: ${PHASES.join(', ')}`,
40
+ );
41
+ process.exit(2);
42
+ }
43
+ return { mode: 'phase', phase: phaseKey as PhaseKey };
44
+ }
45
+ return { mode: 'usage' };
46
+ }
47
+
48
+ function Usage(): React.ReactElement {
49
+ return (
50
+ <Box flexDirection="column">
51
+ <Text bold color={colors.primary}>
52
+ {icons.triangleRight} claude-assets-sync — dev UI runner
53
+ </Text>
54
+ <Box marginLeft={2} marginTop={1} flexDirection="column">
55
+ <Text color={colors.muted}>Preview individual Ink screens or tour them all.</Text>
56
+ <Box marginTop={1} flexDirection="column">
57
+ <Text>
58
+ <Text color={colors.success} bold>yarn dev:ui</Text>
59
+ <Text color={colors.muted}>{' --phase=<name> '}</Text>
60
+ <Text dimColor>single phase preview</Text>
61
+ </Text>
62
+ <Text>
63
+ <Text color={colors.success} bold>yarn dev:ui</Text>
64
+ <Text color={colors.muted}>{' --tour [--ms=2500] '}</Text>
65
+ <Text dimColor>cycle through all phases</Text>
66
+ </Text>
67
+ <Text>
68
+ <Text color={colors.success} bold>yarn dev:cli</Text>
69
+ <Text color={colors.muted}>{' <args> '}</Text>
70
+ <Text dimColor>run the actual CLI against real packages</Text>
71
+ </Text>
72
+ </Box>
73
+ <Box marginTop={1} flexDirection="column">
74
+ <Text bold>Available phases:</Text>
75
+ {PHASES.map((p) => (
76
+ <Text key={p} color={colors.muted}>
77
+ {' '}·{' '}
78
+ <Text color={colors.accent}>{p}</Text>
79
+ </Text>
80
+ ))}
81
+ </Box>
82
+ <Box marginTop={1} flexDirection="column">
83
+ <Text bold>Examples:</Text>
84
+ <Text color={colors.muted}>
85
+ {' '}yarn dev:ui --phase=diff-review
86
+ </Text>
87
+ <Text color={colors.muted}>
88
+ {' '}yarn dev:ui --phase=applying
89
+ </Text>
90
+ <Text color={colors.muted}>
91
+ {' '}yarn dev:ui --tour --ms=1800
92
+ </Text>
93
+ <Text color={colors.muted}>
94
+ {' '}yarn dev:cli --package @canard/schema-form --scope=project --dry-run
95
+ </Text>
96
+ </Box>
97
+ </Box>
98
+ </Box>
99
+ );
100
+ }
101
+
102
+ interface FixtureViewProps {
103
+ readonly phase: Phase;
104
+ readonly targetCount: number;
105
+ }
106
+
107
+ function FixtureView({ phase, targetCount }: FixtureViewProps): React.ReactElement {
108
+ return (
109
+ <Box flexDirection="column">
110
+ <Banner version={VERSION} scope="user" />
111
+ <Box marginTop={1}>
112
+ <StepTracker phase={phase} targetCount={targetCount} scope="user" />
113
+ </Box>
114
+ <Box flexDirection="column" marginTop={1}>
115
+ {renderPhaseBody(phase)}
116
+ </Box>
117
+ <Footer phase={phase} version={VERSION} />
118
+ </Box>
119
+ );
120
+ }
121
+
122
+ function renderPhaseBody(phase: Phase): React.ReactNode {
123
+ switch (phase.kind) {
124
+ case 'booting':
125
+ case 'resolving':
126
+ return <Spinner label="resolving targets…" />;
127
+ case 'scope-select':
128
+ return <ScopePicker onSelect={phase.pending} />;
129
+ case 'planning':
130
+ return (
131
+ <Box flexDirection="column">
132
+ <Spinner label="building plans…" />
133
+ <Box flexDirection="column" marginLeft={2} marginTop={1}>
134
+ {[...phase.progress.values()].map((step) => (
135
+ <Box key={step.packageName}>
136
+ <Text
137
+ color={
138
+ step.status === 'done'
139
+ ? colors.success
140
+ : step.status === 'running'
141
+ ? colors.warn
142
+ : step.status === 'failed'
143
+ ? colors.danger
144
+ : colors.muted
145
+ }
146
+ bold={step.status === 'running'}
147
+ >
148
+ {step.status === 'done'
149
+ ? icons.check
150
+ : step.status === 'failed'
151
+ ? icons.cross
152
+ : step.status === 'running'
153
+ ? icons.bulletActive
154
+ : icons.bulletPending}{' '}
155
+ </Text>
156
+ <Text>{step.packageName}</Text>
157
+ </Box>
158
+ ))}
159
+ </Box>
160
+ </Box>
161
+ );
162
+ case 'diff-review':
163
+ return (
164
+ <Box flexDirection="column">
165
+ {phase.plans.map((tp, idx) => (
166
+ <TargetCard
167
+ key={tp.target.name}
168
+ target={tp.target}
169
+ plan={tp.plan}
170
+ expanded
171
+ highlighted={idx === phase.focusedIndex}
172
+ />
173
+ ))}
174
+ </Box>
175
+ );
176
+ case 'force-confirm':
177
+ return <ConfirmForce warnings={phase.warnings} onAnswer={phase.pending} />;
178
+ case 'applying': {
179
+ const elapsedMs = Math.max(Date.now() - phase.progress.startedAt, 1);
180
+ const rate = phase.progress.done / elapsedMs;
181
+ const remaining = phase.progress.total - phase.progress.done;
182
+ const eta = rate > 0 ? remaining / rate / 1000 : undefined;
183
+ return (
184
+ <Box flexDirection="column">
185
+ <ProgressBar
186
+ done={phase.progress.done}
187
+ total={phase.progress.total}
188
+ etaSeconds={eta}
189
+ label={phase.progress.current}
190
+ />
191
+ <Box flexDirection="column" marginLeft={2} marginTop={1}>
192
+ {phase.plans.map((tp) => (
193
+ <TargetCard
194
+ key={tp.target.name}
195
+ target={tp.target}
196
+ plan={tp.plan}
197
+ expanded={false}
198
+ />
199
+ ))}
200
+ </Box>
201
+ </Box>
202
+ );
203
+ }
204
+ case 'summary':
205
+ return (
206
+ <Box flexDirection="column">
207
+ {phase.plans.map((tp) => (
208
+ <TargetCard
209
+ key={tp.target.name}
210
+ target={tp.target}
211
+ plan={tp.plan}
212
+ expanded={false}
213
+ />
214
+ ))}
215
+ <Summary
216
+ reports={phase.reports}
217
+ exitCode={phase.exitCode}
218
+ dryRun={phase.dryRun}
219
+ />
220
+ </Box>
221
+ );
222
+ case 'error':
223
+ return <ErrorPanel error={phase.error} />;
224
+ default: {
225
+ const _exhaustive: never = phase;
226
+ void _exhaustive;
227
+ return null;
228
+ }
229
+ }
230
+ }
231
+
232
+ function PhaseApp({ phaseKey }: { phaseKey: PhaseKey }): React.ReactElement {
233
+ const { exit } = useApp();
234
+ const phase = buildPhase(phaseKey);
235
+ useInput((input) => {
236
+ if (input === 'q' || input === '') exit();
237
+ });
238
+ return <FixtureView phase={phase} targetCount={3} />;
239
+ }
240
+
241
+ function TourApp({ intervalMs }: { intervalMs: number }): React.ReactElement {
242
+ const { exit } = useApp();
243
+ const [idx, setIdx] = useState(0);
244
+ useEffect(() => {
245
+ const handle = setInterval(() => {
246
+ setIdx((current) => {
247
+ if (current + 1 >= PHASES.length) {
248
+ setTimeout(() => exit(), 300);
249
+ return current;
250
+ }
251
+ return current + 1;
252
+ });
253
+ }, intervalMs);
254
+ return () => clearInterval(handle);
255
+ }, [intervalMs, exit]);
256
+ useInput((input) => {
257
+ if (input === 'q' || input === '') exit();
258
+ if (input === ' ')
259
+ setIdx((current) =>
260
+ current + 1 >= PHASES.length ? current : current + 1,
261
+ );
262
+ });
263
+ const phaseKey = PHASES[idx];
264
+ const phase = buildPhase(phaseKey);
265
+ return (
266
+ <Box flexDirection="column">
267
+ <Box>
268
+ <Text color={colors.accent} bold>
269
+ [tour {idx + 1}/{PHASES.length}]
270
+ </Text>
271
+ <Text color={colors.muted} dimColor>
272
+ {' '}
273
+ {phaseKey} · space:next · q/esc:exit
274
+ </Text>
275
+ </Box>
276
+ <FixtureView phase={phase} targetCount={3} />
277
+ </Box>
278
+ );
279
+ }
280
+
281
+ const args = parseArgs(process.argv.slice(2));
282
+ if (args.mode === 'usage') {
283
+ render(<Usage />);
284
+ } else if (args.mode === 'phase') {
285
+ render(<PhaseApp phaseKey={args.phase!} />);
286
+ } else if (args.mode === 'tour') {
287
+ render(<TourApp intervalMs={args.tourMs ?? 2500} />);
288
+ }
@@ -1,53 +0,0 @@
1
- 'use strict';
2
-
3
- var commander = require('commander');
4
- var logger = require('../../utils/logger.cjs');
5
- var version = require('../../utils/version.cjs');
6
- var resolveTargets = require('./utils/resolveTargets.cjs');
7
- var runInject = require('./utils/runInject.cjs');
8
-
9
- async function runCli(argv = process.argv) {
10
- const cmd = new commander.Command();
11
- cmd
12
- .name('inject-claude-settings')
13
- .description("Inject target consumer(s)' Claude assets into the selected .claude directory")
14
- .version(version.VERSION)
15
- .option('--package <name...>', 'Target(s). "@<scope>" = whole npm scope; "@<scope>/<name>" or "<name>" = one package. Repeat the flag or comma-separate values.', collectPackageValues, [])
16
- .option('--scope <scope>', 'Target scope: user (~/.claude) | project (nearest ancestor .claude or <cwd>/.claude)')
17
- .option('--dry-run', 'Preview without writing', false)
18
- .option('--force', 'Overwrite user modifications', false)
19
- .option('--root <path>', 'Override scope resolution cwd (default: cwd)')
20
- .action(async (flags) => {
21
- const targets = flags.package ?? [];
22
- if (targets.length === 0) {
23
- logger.logger.error('missing required flag: --package <name> (e.g. --package=@canard/schema-form or --package=@canard)');
24
- process.exit(2);
25
- }
26
- const originCwd = flags.root ?? process.cwd();
27
- const metadataList = await resolveTargets.resolveTargets(targets, originCwd);
28
- if (metadataList.length === 0) {
29
- logger.logger.warn(`no packages resolved from --package target(s): ${targets.join(', ')}`);
30
- return;
31
- }
32
- await runInject.runInject(flags, metadataList);
33
- });
34
- try {
35
- await cmd.parseAsync([...argv]);
36
- }
37
- catch (err) {
38
- const msg = err instanceof Error ? err.message : String(err);
39
- logger.logger.error(msg);
40
- process.exit(1);
41
- }
42
- }
43
- function collectPackageValues(value, previous = []) {
44
- return [
45
- ...previous,
46
- ...value
47
- .split(',')
48
- .map((s) => s.trim())
49
- .filter(Boolean),
50
- ];
51
- }
52
-
53
- exports.runCli = runCli;
@@ -1,48 +0,0 @@
1
- 'use strict';
2
-
3
- const NPM_NAME_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
4
- function classifyTarget(target) {
5
- if (typeof target !== 'string' || target.length === 0) {
6
- return { kind: 'invalid', reason: 'empty --package value' };
7
- }
8
- if (target.startsWith('@')) {
9
- const body = target.slice(1);
10
- const slashIndex = body.indexOf('/');
11
- if (slashIndex === -1) {
12
- if (!NPM_NAME_PATTERN.test(body)) {
13
- return {
14
- kind: 'invalid',
15
- reason: `invalid scope alias "${target}" — expected "@<scope>" with lowercase alphanumerics, ".", "-", or "_"`,
16
- };
17
- }
18
- return { kind: 'scope', scope: body };
19
- }
20
- const scopePart = body.slice(0, slashIndex);
21
- const namePart = body.slice(slashIndex + 1);
22
- if (!NPM_NAME_PATTERN.test(scopePart) ||
23
- namePart.length === 0 ||
24
- namePart.includes('/') ||
25
- !NPM_NAME_PATTERN.test(namePart)) {
26
- return {
27
- kind: 'invalid',
28
- reason: `invalid scoped package "${target}" — expected "@<scope>/<name>"`,
29
- };
30
- }
31
- return { kind: 'package', name: target };
32
- }
33
- if (target.includes('/')) {
34
- return {
35
- kind: 'invalid',
36
- reason: `invalid target "${target}" — unscoped package names cannot contain "/"`,
37
- };
38
- }
39
- if (!NPM_NAME_PATTERN.test(target)) {
40
- return {
41
- kind: 'invalid',
42
- reason: `invalid package name "${target}" — expected lowercase alphanumerics, ".", "-", or "_"`,
43
- };
44
- }
45
- return { kind: 'package', name: target };
46
- }
47
-
48
- exports.classifyTarget = classifyTarget;
@@ -1,47 +0,0 @@
1
- 'use strict';
2
-
3
- require('node:crypto');
4
- require('node:fs/promises');
5
- require('node:path');
6
- var injectDocs = require('../../../core/injectDocs/injectDocs.cjs');
7
- require('node:os');
8
- require('node:fs');
9
- require('@inquirer/prompts');
10
- require('picocolors');
11
- var confirmForce = require('../../../prompts/confirmForce.cjs');
12
- var heartbeat = require('../../../utils/heartbeat.cjs');
13
- var logger = require('../../../utils/logger.cjs');
14
-
15
- async function injectOne(target, scope, flags, originCwd) {
16
- if (!target.hashesPresent) {
17
- logger.logger.warn(`${target.name}: dist/claude-hashes.json missing — build the package (e.g. yarn build) to regenerate the hash manifest first.`);
18
- return 0;
19
- }
20
- logger.logger.heading(`${target.name}@${target.version}`);
21
- const stopHeartbeat = heartbeat.startHeartbeat({
22
- label: `injecting ${target.name}`,
23
- });
24
- try {
25
- const report = await injectDocs.injectDocs({
26
- packageName: target.name,
27
- packageVersion: target.version,
28
- packageRoot: target.packageRoot,
29
- assetRoot: target.assetRoot,
30
- scope,
31
- originCwd,
32
- dryRun: flags.dryRun ?? false,
33
- force: flags.force ?? false,
34
- confirmForce: async (plan) => {
35
- const diverged = plan.actions.filter((a) => a.kind === 'warn-diverged');
36
- const orphans = plan.actions.filter((a) => a.kind === 'warn-orphan');
37
- return confirmForce.confirmForceAsync(diverged.length, orphans.length, [...diverged, ...orphans].map((a) => a.relPath).slice(0, 3));
38
- },
39
- });
40
- return report.exitCode;
41
- }
42
- finally {
43
- stopHeartbeat();
44
- }
45
- }
46
-
47
- exports.injectOne = injectOne;
@@ -1,3 +0,0 @@
1
- import { type Scope } from '../../../core/index.js';
2
- import type { ConsumerPackage, DefaultFlags } from '../type.js';
3
- export declare function injectOne(target: ConsumerPackage, scope: Scope, flags: DefaultFlags, originCwd: string): Promise<number>;
@@ -1,45 +0,0 @@
1
- import 'node:crypto';
2
- import 'node:fs/promises';
3
- import 'node:path';
4
- import { injectDocs } from '../../../core/injectDocs/injectDocs.mjs';
5
- import 'node:os';
6
- import 'node:fs';
7
- import '@inquirer/prompts';
8
- import 'picocolors';
9
- import { confirmForceAsync } from '../../../prompts/confirmForce.mjs';
10
- import { startHeartbeat } from '../../../utils/heartbeat.mjs';
11
- import { logger } from '../../../utils/logger.mjs';
12
-
13
- async function injectOne(target, scope, flags, originCwd) {
14
- if (!target.hashesPresent) {
15
- logger.warn(`${target.name}: dist/claude-hashes.json missing — build the package (e.g. yarn build) to regenerate the hash manifest first.`);
16
- return 0;
17
- }
18
- logger.heading(`${target.name}@${target.version}`);
19
- const stopHeartbeat = startHeartbeat({
20
- label: `injecting ${target.name}`,
21
- });
22
- try {
23
- const report = await injectDocs({
24
- packageName: target.name,
25
- packageVersion: target.version,
26
- packageRoot: target.packageRoot,
27
- assetRoot: target.assetRoot,
28
- scope,
29
- originCwd,
30
- dryRun: flags.dryRun ?? false,
31
- force: flags.force ?? false,
32
- confirmForce: async (plan) => {
33
- const diverged = plan.actions.filter((a) => a.kind === 'warn-diverged');
34
- const orphans = plan.actions.filter((a) => a.kind === 'warn-orphan');
35
- return confirmForceAsync(diverged.length, orphans.length, [...diverged, ...orphans].map((a) => a.relPath).slice(0, 3));
36
- },
37
- });
38
- return report.exitCode;
39
- }
40
- finally {
41
- stopHeartbeat();
42
- }
43
- }
44
-
45
- export { injectOne };
@@ -1,77 +0,0 @@
1
- 'use strict';
2
-
3
- var node_fs = require('node:fs');
4
- var promises = require('node:fs/promises');
5
- var node_module = require('node:module');
6
- var node_path = require('node:path');
7
- var logger = require('../../../utils/logger.cjs');
8
-
9
- var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
10
- async function resolvePackage(name, options = {}) {
11
- const pkgJsonPath = resolvePackageJsonPath(name);
12
- if (!pkgJsonPath) {
13
- logger.logger.error(`cannot resolve package "${name}". Install it in the current project or pass the correct name.`);
14
- process.exit(2);
15
- }
16
- const packageRoot = node_path.dirname(pkgJsonPath);
17
- const raw = await promises.readFile(pkgJsonPath, 'utf-8');
18
- const pkg = JSON.parse(raw);
19
- if (typeof pkg.name !== 'string' || typeof pkg.version !== 'string') {
20
- if (options.skipMissingAsset) {
21
- logger.logger.warn(`"${name}" package.json is missing a string "name" or "version" — skipping.`);
22
- return null;
23
- }
24
- logger.logger.error(`${pkgJsonPath} must define string "name" and "version".`);
25
- process.exit(2);
26
- }
27
- const assetPath = pkg.claude?.assetPath;
28
- if (typeof assetPath !== 'string' || assetPath.length === 0) {
29
- if (options.skipMissingAsset) {
30
- logger.logger.warn(`"${name}" is missing "claude.assetPath" — skipping (the package does not ship Claude assets).`);
31
- return null;
32
- }
33
- logger.logger.error(`"${name}" is missing "claude.assetPath" in its package.json — the package does not ship Claude assets.`);
34
- process.exit(2);
35
- }
36
- return {
37
- packageRoot,
38
- packageName: pkg.name,
39
- packageVersion: pkg.version,
40
- assetPath,
41
- };
42
- }
43
- function resolvePackageJsonPath(name) {
44
- const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('commands/runCli/utils/resolvePackage.cjs', document.baseURI).href)));
45
- try {
46
- return require$1.resolve(`${name}/package.json`);
47
- }
48
- catch (err) {
49
- const code = err?.code;
50
- if (code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED')
51
- return null;
52
- }
53
- let mainEntry;
54
- try {
55
- mainEntry = require$1.resolve(name);
56
- }
57
- catch {
58
- return null;
59
- }
60
- let dir = node_path.dirname(mainEntry);
61
- while (dir && dir !== node_path.dirname(dir)) {
62
- const candidate = node_path.resolve(dir, 'package.json');
63
- if (node_fs.existsSync(candidate)) {
64
- try {
65
- const pkg = JSON.parse(node_fs.readFileSync(candidate, 'utf-8'));
66
- if (pkg.name === name)
67
- return candidate;
68
- }
69
- catch {
70
- }
71
- }
72
- dir = node_path.dirname(dir);
73
- }
74
- return null;
75
- }
76
-
77
- exports.resolvePackage = resolvePackage;
@@ -1,69 +0,0 @@
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;
@@ -1,28 +0,0 @@
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;