@slats/claude-assets-sync 0.1.0 → 0.1.1

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 (61) hide show
  1. package/dist/commands/add.cjs +24 -0
  2. package/dist/commands/add.d.ts +2 -6
  3. package/dist/commands/add.mjs +24 -0
  4. package/dist/commands/index.d.ts +1 -2
  5. package/dist/commands/list.cjs +12 -1
  6. package/dist/commands/list.d.ts +10 -1
  7. package/dist/commands/list.mjs +12 -2
  8. package/dist/commands/remove.cjs +49 -31
  9. package/dist/commands/remove.mjs +49 -30
  10. package/dist/commands/types.d.ts +9 -0
  11. package/dist/commands/update.cjs +27 -0
  12. package/dist/commands/update.d.ts +16 -0
  13. package/dist/commands/update.mjs +27 -1
  14. package/dist/components/add/BulkAddView.cjs +169 -0
  15. package/dist/components/add/BulkAddView.d.ts +11 -0
  16. package/dist/components/add/BulkAddView.mjs +167 -0
  17. package/dist/components/list/ListCommand.cjs +585 -392
  18. package/dist/components/list/ListCommand.d.ts +0 -3
  19. package/dist/components/list/ListCommand.mjs +590 -377
  20. package/dist/components/list/index.d.ts +1 -0
  21. package/dist/components/list/types.d.ts +14 -0
  22. package/dist/components/remove/RemoveConfirm.cjs +18 -0
  23. package/dist/components/remove/RemoveConfirm.d.ts +11 -0
  24. package/dist/components/remove/RemoveConfirm.mjs +16 -0
  25. package/dist/components/shared/Confirm.cjs +30 -0
  26. package/dist/components/shared/Confirm.d.ts +8 -0
  27. package/dist/components/shared/Confirm.mjs +28 -0
  28. package/dist/components/shared/MenuItem.cjs +18 -0
  29. package/dist/components/shared/MenuItem.d.ts +7 -0
  30. package/dist/components/shared/MenuItem.mjs +16 -0
  31. package/dist/components/shared/ProgressBar.d.ts +7 -0
  32. package/dist/components/shared/StepRunner.cjs +58 -0
  33. package/dist/components/shared/StepRunner.d.ts +15 -0
  34. package/dist/components/shared/StepRunner.mjs +56 -0
  35. package/dist/components/shared/Table.cjs +19 -0
  36. package/dist/components/shared/Table.d.ts +8 -0
  37. package/dist/components/shared/Table.mjs +17 -0
  38. package/dist/components/shared/index.d.ts +6 -0
  39. package/dist/core/cli.cjs +4 -8
  40. package/dist/core/cli.mjs +5 -9
  41. package/dist/core/constants.cjs +2 -0
  42. package/dist/core/constants.d.ts +4 -0
  43. package/dist/core/constants.mjs +2 -1
  44. package/dist/core/io.mjs +1 -1
  45. package/dist/core/listOperations.cjs +228 -0
  46. package/dist/core/listOperations.d.ts +43 -0
  47. package/dist/core/listOperations.mjs +205 -0
  48. package/dist/core/packageScanner.cjs +8 -6
  49. package/dist/core/packageScanner.mjs +9 -7
  50. package/dist/core/sync.cjs +9 -15
  51. package/dist/core/sync.mjs +10 -16
  52. package/dist/utils/asyncPool.cjs +26 -0
  53. package/dist/utils/asyncPool.d.ts +5 -0
  54. package/dist/utils/asyncPool.mjs +24 -0
  55. package/dist/utils/dependencies.cjs +57 -0
  56. package/dist/utils/dependencies.d.ts +10 -0
  57. package/dist/utils/dependencies.mjs +34 -0
  58. package/dist/utils/package.cjs +5 -0
  59. package/dist/utils/package.d.ts +6 -1
  60. package/dist/utils/package.mjs +6 -2
  61. package/package.json +2 -1
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ export interface BulkAddViewProps {
3
+ pattern: string;
4
+ cwd: string;
5
+ local?: boolean;
6
+ ref?: string;
7
+ }
8
+ /**
9
+ * Bulk add view — scans dependencies by regex, scans assets, and syncs all found assets.
10
+ */
11
+ export declare const BulkAddView: React.FC<BulkAddViewProps>;
@@ -0,0 +1,167 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { Box, Text } from 'ink';
3
+ import Spinner from 'ink-spinner';
4
+ import { useState, useEffect } from 'react';
5
+ import { scanPackageAssets } from '../../core/packageScanner.mjs';
6
+ import { syncPackage } from '../../core/sync.mjs';
7
+ import { asyncPool } from '../../utils/asyncPool.mjs';
8
+ import { readProjectDependencies, filterByPattern } from '../../utils/dependencies.mjs';
9
+ import { StepRunner } from '../shared/StepRunner.mjs';
10
+ import { Table } from '../shared/Table.mjs';
11
+
12
+ const BulkAddView = ({ pattern, cwd, local = false, ref, }) => {
13
+ const [phase, setPhase] = useState('scanning-deps');
14
+ const [matches, setMatches] = useState([]);
15
+ const [scanSteps, setScanSteps] = useState([]);
16
+ const [syncSteps, setSyncSteps] = useState([]);
17
+ const [results, setResults] = useState([]);
18
+ const [errorMessage, setErrorMessage] = useState('');
19
+ useEffect(() => {
20
+ const run = async () => {
21
+ setPhase('scanning-deps');
22
+ let matched;
23
+ try {
24
+ const deps = readProjectDependencies(cwd);
25
+ matched = filterByPattern(deps, pattern);
26
+ }
27
+ catch (err) {
28
+ setErrorMessage(err instanceof Error ? err.message : String(err));
29
+ setPhase('error');
30
+ return;
31
+ }
32
+ setMatches(matched);
33
+ if (matched.length === 0) {
34
+ setResults([]);
35
+ setPhase('done');
36
+ return;
37
+ }
38
+ setPhase('scanning-assets');
39
+ const initialScanSteps = matched.map((name) => ({
40
+ name,
41
+ status: 'pending',
42
+ }));
43
+ setScanSteps(initialScanSteps);
44
+ const packagesWithAssets = [];
45
+ const scanResults = [];
46
+ await asyncPool(3, matched, async (pkgName) => {
47
+ setScanSteps((prev) => prev.map((s) => s.name === pkgName ? { ...s, status: 'running' } : s));
48
+ try {
49
+ const trees = await scanPackageAssets(pkgName, {
50
+ local,
51
+ ref,
52
+ cwd,
53
+ });
54
+ const hasAssets = trees.length > 0;
55
+ if (hasAssets) {
56
+ packagesWithAssets.push(pkgName);
57
+ setScanSteps((prev) => prev.map((s) => s.name === pkgName
58
+ ? { ...s, status: 'success', output: `${trees.length} asset type(s)` }
59
+ : s));
60
+ }
61
+ else {
62
+ scanResults.push({ name: pkgName, status: 'skipped', assetCount: 0 });
63
+ setScanSteps((prev) => prev.map((s) => s.name === pkgName ? { ...s, status: 'skipped' } : s));
64
+ }
65
+ }
66
+ catch (err) {
67
+ const msg = err instanceof Error ? err.message : String(err);
68
+ const isNoAssets = /no repository|asset path.*does not exist|not found in (local workspace|node_modules)/i.test(msg);
69
+ if (isNoAssets) {
70
+ scanResults.push({ name: pkgName, status: 'skipped', assetCount: 0 });
71
+ setScanSteps((prev) => prev.map((s) => s.name === pkgName ? { ...s, status: 'skipped' } : s));
72
+ }
73
+ else {
74
+ scanResults.push({ name: pkgName, status: 'error', assetCount: 0, error: msg });
75
+ setScanSteps((prev) => prev.map((s) => s.name === pkgName
76
+ ? { ...s, status: 'failed', error: msg }
77
+ : s));
78
+ }
79
+ }
80
+ });
81
+ if (packagesWithAssets.length === 0) {
82
+ setResults(scanResults);
83
+ setPhase('done');
84
+ return;
85
+ }
86
+ setPhase('syncing');
87
+ const initialSyncSteps = packagesWithAssets.map((name) => ({
88
+ name,
89
+ status: 'pending',
90
+ }));
91
+ setSyncSteps(initialSyncSteps);
92
+ await asyncPool(3, packagesWithAssets, async (pkgName) => {
93
+ setSyncSteps((prev) => prev.map((s) => s.name === pkgName ? { ...s, status: 'running' } : s));
94
+ try {
95
+ const result = await syncPackage(pkgName, {
96
+ force: true,
97
+ dryRun: false,
98
+ local,
99
+ ref,
100
+ flat: true,
101
+ }, cwd, undefined, undefined);
102
+ if (result.success && !result.skipped) {
103
+ const assetCount = Object.values(result.syncedFiles ?? {}).reduce((sum, files) => sum + files.length, 0);
104
+ scanResults.push({ name: pkgName, status: 'synced', assetCount });
105
+ setSyncSteps((prev) => prev.map((s) => s.name === pkgName
106
+ ? { ...s, status: 'success', output: `${assetCount} file(s)` }
107
+ : s));
108
+ }
109
+ else if (result.skipped) {
110
+ scanResults.push({ name: pkgName, status: 'skipped', assetCount: 0 });
111
+ setSyncSteps((prev) => prev.map((s) => s.name === pkgName ? { ...s, status: 'skipped' } : s));
112
+ }
113
+ else {
114
+ const msg = result.reason ?? 'Sync failed';
115
+ scanResults.push({ name: pkgName, status: 'error', assetCount: 0, error: msg });
116
+ setSyncSteps((prev) => prev.map((s) => s.name === pkgName
117
+ ? { ...s, status: 'failed', error: msg }
118
+ : s));
119
+ }
120
+ }
121
+ catch (err) {
122
+ const msg = err instanceof Error ? err.message : String(err);
123
+ scanResults.push({ name: pkgName, status: 'error', assetCount: 0, error: msg });
124
+ setSyncSteps((prev) => prev.map((s) => s.name === pkgName
125
+ ? { ...s, status: 'failed', error: msg }
126
+ : s));
127
+ }
128
+ });
129
+ setResults(scanResults);
130
+ setPhase('done');
131
+ };
132
+ run();
133
+ }, []);
134
+ if (phase === 'scanning-deps') {
135
+ return (jsx(Box, { children: jsxs(Text, { color: "cyan", children: [jsx(Spinner, { type: "dots" }), " Scanning dependencies matching /", pattern, "/..."] }) }));
136
+ }
137
+ if (phase === 'error') {
138
+ return (jsx(Box, { flexDirection: "column", children: jsxs(Text, { color: "red", children: ["Error: ", errorMessage] }) }));
139
+ }
140
+ if (phase === 'scanning-assets') {
141
+ return (jsxs(Box, { flexDirection: "column", children: [jsx(Box, { marginBottom: 1, children: jsxs(Text, { children: ["Found ", jsx(Text, { bold: true, children: matches.length }), " matching package(s). Scanning assets..."] }) }), jsx(StepRunner, { steps: scanSteps, currentStep: scanSteps.findIndex((s) => s.status === 'running'), total: scanSteps.length })] }));
142
+ }
143
+ if (phase === 'syncing') {
144
+ return (jsxs(Box, { flexDirection: "column", children: [jsx(Box, { marginBottom: 1, children: jsx(Text, { children: "Syncing packages..." }) }), jsx(StepRunner, { steps: syncSteps, currentStep: syncSteps.findIndex((s) => s.status === 'running'), total: syncSteps.length })] }));
145
+ }
146
+ if (phase === 'done') {
147
+ const synced = results.filter((r) => r.status === 'synced').length;
148
+ const skipped = results.filter((r) => r.status === 'skipped').length;
149
+ const errors = results.filter((r) => r.status === 'error').length;
150
+ if (results.length === 0) {
151
+ return (jsx(Box, { flexDirection: "column", children: jsxs(Text, { color: "yellow", children: ["No packages matched pattern /", pattern, "/"] }) }));
152
+ }
153
+ const rows = results.map((r) => {
154
+ const statusCell = r.status === 'synced'
155
+ ? '✓ synced'
156
+ : r.status === 'skipped'
157
+ ? '⏭ skipped'
158
+ : `✗ error`;
159
+ const assetsCell = r.status === 'synced' ? String(r.assetCount) : r.error ?? '-';
160
+ return [r.name, statusCell, assetsCell];
161
+ });
162
+ return (jsxs(Box, { flexDirection: "column", children: [jsx(Table, { headers: ['Package', 'Status', 'Assets'], rows: rows }), jsx(Box, { marginTop: 1, children: jsxs(Text, { children: [jsxs(Text, { color: "green", children: [synced, " synced"] }), jsx(Text, { children: ", " }), jsxs(Text, { color: "blue", children: [skipped, " skipped"] }), jsx(Text, { children: ", " }), jsxs(Text, { color: errors > 0 ? 'red' : 'gray', children: [errors, " errors"] })] }) })] }));
163
+ }
164
+ return null;
165
+ };
166
+
167
+ export { BulkAddView };