@slats/claude-assets-sync 0.0.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.
- package/LICENSE +21 -0
- package/README.md +144 -0
- package/dist/@aileron/declare/function.d.ts +16 -0
- package/dist/@aileron/declare/index.d.ts +4 -0
- package/dist/@aileron/declare/object.d.ts +11 -0
- package/dist/@aileron/declare/unit.d.ts +19 -0
- package/dist/@aileron/declare/utility.d.ts +45 -0
- package/dist/cli/index.cjs +56 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.mjs +53 -0
- package/dist/core/filesystem.cjs +81 -0
- package/dist/core/filesystem.d.ts +73 -0
- package/dist/core/filesystem.mjs +70 -0
- package/dist/core/github.cjs +90 -0
- package/dist/core/github.d.ts +50 -0
- package/dist/core/github.mjs +83 -0
- package/dist/core/sync.cjs +150 -0
- package/dist/core/sync.d.ts +17 -0
- package/dist/core/sync.mjs +147 -0
- package/dist/index.cjs +15 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.mjs +11 -0
- package/dist/utils/logger.cjs +67 -0
- package/dist/utils/logger.d.ts +57 -0
- package/dist/utils/logger.mjs +65 -0
- package/dist/utils/package.cjs +143 -0
- package/dist/utils/package.d.ts +66 -0
- package/dist/utils/package.mjs +133 -0
- package/dist/utils/types.d.ts +88 -0
- package/package.json +59 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger utility with colored output
|
|
3
|
+
*/
|
|
4
|
+
export declare const logger: {
|
|
5
|
+
/**
|
|
6
|
+
* Log info message
|
|
7
|
+
*/
|
|
8
|
+
info(message: string): void;
|
|
9
|
+
/**
|
|
10
|
+
* Log success message
|
|
11
|
+
*/
|
|
12
|
+
success(message: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* Log warning message
|
|
15
|
+
*/
|
|
16
|
+
warn(message: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Log error message
|
|
19
|
+
*/
|
|
20
|
+
error(message: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Log debug message (only in verbose mode)
|
|
23
|
+
*/
|
|
24
|
+
debug(message: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* Log a step in the sync process
|
|
27
|
+
*/
|
|
28
|
+
step(step: string, detail?: string): void;
|
|
29
|
+
/**
|
|
30
|
+
* Log file operation
|
|
31
|
+
*/
|
|
32
|
+
file(operation: "create" | "update" | "skip", path: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* Log package sync start
|
|
35
|
+
*/
|
|
36
|
+
packageStart(packageName: string): void;
|
|
37
|
+
/**
|
|
38
|
+
* Log package sync result
|
|
39
|
+
*/
|
|
40
|
+
packageEnd(_packageName: string, result: {
|
|
41
|
+
success: boolean;
|
|
42
|
+
skipped: boolean;
|
|
43
|
+
reason?: string;
|
|
44
|
+
}): void;
|
|
45
|
+
/**
|
|
46
|
+
* Log summary at the end
|
|
47
|
+
*/
|
|
48
|
+
summary(results: {
|
|
49
|
+
success: number;
|
|
50
|
+
skipped: number;
|
|
51
|
+
failed: number;
|
|
52
|
+
}): void;
|
|
53
|
+
/**
|
|
54
|
+
* Log dry-run notice
|
|
55
|
+
*/
|
|
56
|
+
dryRunNotice(): void;
|
|
57
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import pc from 'picocolors';
|
|
2
|
+
|
|
3
|
+
const logger = {
|
|
4
|
+
info(message) {
|
|
5
|
+
console.log(pc.blue('info'), message);
|
|
6
|
+
},
|
|
7
|
+
success(message) {
|
|
8
|
+
console.log(pc.green('success'), message);
|
|
9
|
+
},
|
|
10
|
+
warn(message) {
|
|
11
|
+
console.log(pc.yellow('warn'), message);
|
|
12
|
+
},
|
|
13
|
+
error(message) {
|
|
14
|
+
console.log(pc.red('error'), message);
|
|
15
|
+
},
|
|
16
|
+
debug(message) {
|
|
17
|
+
if (process.env.VERBOSE) {
|
|
18
|
+
console.log(pc.gray('debug'), message);
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
step(step, detail) {
|
|
22
|
+
const stepText = pc.cyan(`[${step}]`);
|
|
23
|
+
console.log(stepText, detail || '');
|
|
24
|
+
},
|
|
25
|
+
file(operation, path) {
|
|
26
|
+
const colors = {
|
|
27
|
+
create: pc.green,
|
|
28
|
+
update: pc.yellow,
|
|
29
|
+
skip: pc.gray,
|
|
30
|
+
};
|
|
31
|
+
const symbols = {
|
|
32
|
+
create: '+',
|
|
33
|
+
update: '~',
|
|
34
|
+
skip: '-',
|
|
35
|
+
};
|
|
36
|
+
console.log(` ${colors[operation](symbols[operation])} ${path}`);
|
|
37
|
+
},
|
|
38
|
+
packageStart(packageName) {
|
|
39
|
+
console.log();
|
|
40
|
+
console.log(pc.bold(pc.cyan(`Syncing ${packageName}...`)));
|
|
41
|
+
},
|
|
42
|
+
packageEnd(_packageName, result) {
|
|
43
|
+
if (result.skipped)
|
|
44
|
+
console.log(pc.gray(` Skipped: ${result.reason || 'Unknown reason'}`));
|
|
45
|
+
else if (result.success)
|
|
46
|
+
console.log(pc.green(` Completed successfully`));
|
|
47
|
+
else
|
|
48
|
+
console.log(pc.red(` Failed: ${result.reason || 'Unknown error'}`));
|
|
49
|
+
},
|
|
50
|
+
summary(results) {
|
|
51
|
+
console.log();
|
|
52
|
+
console.log(pc.bold('Summary:'));
|
|
53
|
+
console.log(` ${pc.green('Success:')} ${results.success}`);
|
|
54
|
+
console.log(` ${pc.gray('Skipped:')} ${results.skipped}`);
|
|
55
|
+
if (results.failed > 0)
|
|
56
|
+
console.log(` ${pc.red('Failed:')} ${results.failed}`);
|
|
57
|
+
},
|
|
58
|
+
dryRunNotice() {
|
|
59
|
+
console.log();
|
|
60
|
+
console.log(pc.yellow(pc.bold('[DRY RUN] No files will be created or modified.')));
|
|
61
|
+
console.log();
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export { logger };
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var node_child_process = require('node:child_process');
|
|
4
|
+
var node_fs = require('node:fs');
|
|
5
|
+
var node_path = require('node:path');
|
|
6
|
+
|
|
7
|
+
const GITHUB_HTTPS_URL_PATTERN = /https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/;
|
|
8
|
+
const GITHUB_SSH_URL_PATTERN = /git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/;
|
|
9
|
+
const GITHUB_SHORTHAND_PATTERN = /^github:([^/]+)\/([^/]+)$/;
|
|
10
|
+
const readPackageJson = (packageName, cwd = process.cwd()) => {
|
|
11
|
+
try {
|
|
12
|
+
const packageJsonPath = node_path.join(cwd, 'node_modules', packageName, 'package.json');
|
|
13
|
+
const content = node_fs.readFileSync(packageJsonPath, 'utf-8');
|
|
14
|
+
const json = JSON.parse(content);
|
|
15
|
+
if (!json.name || !json.version || !json.repository)
|
|
16
|
+
return null;
|
|
17
|
+
return {
|
|
18
|
+
name: json.name,
|
|
19
|
+
version: json.version,
|
|
20
|
+
repository: json.repository,
|
|
21
|
+
claude: json.claude,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const parseGitHubRepo = (repository) => {
|
|
29
|
+
if (!repository || typeof repository.url !== 'string')
|
|
30
|
+
return null;
|
|
31
|
+
const url = repository.url;
|
|
32
|
+
const httpsMatch = url.match(GITHUB_HTTPS_URL_PATTERN);
|
|
33
|
+
if (httpsMatch)
|
|
34
|
+
return {
|
|
35
|
+
owner: httpsMatch[1],
|
|
36
|
+
repo: httpsMatch[2],
|
|
37
|
+
directory: repository.directory,
|
|
38
|
+
};
|
|
39
|
+
const sshMatch = url.match(GITHUB_SSH_URL_PATTERN);
|
|
40
|
+
if (sshMatch)
|
|
41
|
+
return {
|
|
42
|
+
owner: sshMatch[1],
|
|
43
|
+
repo: sshMatch[2],
|
|
44
|
+
directory: repository.directory,
|
|
45
|
+
};
|
|
46
|
+
const shorthandMatch = url.match(GITHUB_SHORTHAND_PATTERN);
|
|
47
|
+
if (shorthandMatch)
|
|
48
|
+
return {
|
|
49
|
+
owner: shorthandMatch[1],
|
|
50
|
+
repo: shorthandMatch[2],
|
|
51
|
+
directory: repository.directory,
|
|
52
|
+
};
|
|
53
|
+
return null;
|
|
54
|
+
};
|
|
55
|
+
const buildVersionTag = (packageName, version) => `${packageName}@${version}`;
|
|
56
|
+
const buildAssetPath = (assetPath, directory) => (assetPath);
|
|
57
|
+
const findGitRoot = (cwd = process.cwd()) => {
|
|
58
|
+
try {
|
|
59
|
+
const gitRoot = node_child_process.execSync('git rev-parse --show-toplevel', {
|
|
60
|
+
cwd,
|
|
61
|
+
encoding: 'utf-8',
|
|
62
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
63
|
+
}).trim();
|
|
64
|
+
return gitRoot;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
const findWorkspaceRoot = (startDir = process.cwd()) => {
|
|
71
|
+
let currentDir = startDir;
|
|
72
|
+
while (currentDir !== '/') {
|
|
73
|
+
const packageJsonPath = node_path.join(currentDir, 'package.json');
|
|
74
|
+
if (node_fs.existsSync(packageJsonPath)) {
|
|
75
|
+
try {
|
|
76
|
+
const content = node_fs.readFileSync(packageJsonPath, 'utf-8');
|
|
77
|
+
const json = JSON.parse(content);
|
|
78
|
+
if (json.workspaces)
|
|
79
|
+
return currentDir;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
currentDir = node_path.dirname(currentDir);
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
};
|
|
88
|
+
const getWorkspaceList = (workspaceRoot) => {
|
|
89
|
+
try {
|
|
90
|
+
const output = node_child_process.execSync('yarn workspaces list --json', {
|
|
91
|
+
cwd: workspaceRoot,
|
|
92
|
+
encoding: 'utf-8',
|
|
93
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
94
|
+
});
|
|
95
|
+
return output
|
|
96
|
+
.trim()
|
|
97
|
+
.split('\n')
|
|
98
|
+
.filter(Boolean)
|
|
99
|
+
.map((line) => JSON.parse(line));
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
const findWorkspaceLocation = (packageName, workspaceRoot) => {
|
|
106
|
+
const workspaces = getWorkspaceList(workspaceRoot);
|
|
107
|
+
const workspace = workspaces.find((ws) => ws.name === packageName);
|
|
108
|
+
return workspace ? node_path.join(workspaceRoot, workspace.location) : null;
|
|
109
|
+
};
|
|
110
|
+
const readLocalPackageJson = (packageName, cwd = process.cwd()) => {
|
|
111
|
+
try {
|
|
112
|
+
const workspaceRoot = findWorkspaceRoot(cwd);
|
|
113
|
+
if (!workspaceRoot)
|
|
114
|
+
return null;
|
|
115
|
+
const packageLocation = findWorkspaceLocation(packageName, workspaceRoot);
|
|
116
|
+
if (!packageLocation)
|
|
117
|
+
return null;
|
|
118
|
+
const packageJsonPath = node_path.join(packageLocation, 'package.json');
|
|
119
|
+
const content = node_fs.readFileSync(packageJsonPath, 'utf-8');
|
|
120
|
+
const json = JSON.parse(content);
|
|
121
|
+
if (!json.name || !json.version || !json.repository)
|
|
122
|
+
return null;
|
|
123
|
+
return {
|
|
124
|
+
name: json.name,
|
|
125
|
+
version: json.version,
|
|
126
|
+
repository: json.repository,
|
|
127
|
+
claude: json.claude,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
exports.buildAssetPath = buildAssetPath;
|
|
136
|
+
exports.buildVersionTag = buildVersionTag;
|
|
137
|
+
exports.findGitRoot = findGitRoot;
|
|
138
|
+
exports.findWorkspaceLocation = findWorkspaceLocation;
|
|
139
|
+
exports.findWorkspaceRoot = findWorkspaceRoot;
|
|
140
|
+
exports.getWorkspaceList = getWorkspaceList;
|
|
141
|
+
exports.parseGitHubRepo = parseGitHubRepo;
|
|
142
|
+
exports.readLocalPackageJson = readLocalPackageJson;
|
|
143
|
+
exports.readPackageJson = readPackageJson;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { GitHubRepoInfo, PackageInfo, WorkspaceInfo } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Read package.json from node_modules
|
|
4
|
+
* @param packageName - Package name (e.g., "@canard/schema-form")
|
|
5
|
+
* @param cwd - Current working directory
|
|
6
|
+
* @returns PackageInfo or null if not found
|
|
7
|
+
*/
|
|
8
|
+
export declare const readPackageJson: (packageName: string, cwd?: string) => PackageInfo | null;
|
|
9
|
+
/**
|
|
10
|
+
* Parse GitHub repository URL to extract owner and repo
|
|
11
|
+
* Supports formats:
|
|
12
|
+
* - https://github.com/owner/repo.git
|
|
13
|
+
* - https://github.com/owner/repo
|
|
14
|
+
* - git@github.com:owner/repo.git
|
|
15
|
+
* - github:owner/repo
|
|
16
|
+
*
|
|
17
|
+
* @param repository - Repository info from package.json
|
|
18
|
+
* @returns GitHubRepoInfo or null if parsing failed
|
|
19
|
+
*/
|
|
20
|
+
export declare const parseGitHubRepo: (repository: PackageInfo["repository"]) => GitHubRepoInfo | null;
|
|
21
|
+
/**
|
|
22
|
+
* Build version tag for GitHub
|
|
23
|
+
* @param packageName - Package name (e.g., "@canard/schema-form")
|
|
24
|
+
* @param version - Package version (e.g., "0.10.0")
|
|
25
|
+
* @returns Version tag (e.g., "@canard/schema-form@0.10.0")
|
|
26
|
+
*/
|
|
27
|
+
export declare const buildVersionTag: (packageName: string, version: string) => string;
|
|
28
|
+
/**
|
|
29
|
+
* Build asset path for a package
|
|
30
|
+
* @param assetPath - Base asset path (e.g., "docs/claude")
|
|
31
|
+
* @param directory - Repository directory (optional)
|
|
32
|
+
* @returns Full asset path
|
|
33
|
+
*/
|
|
34
|
+
export declare const buildAssetPath: (assetPath: string, directory?: string) => string;
|
|
35
|
+
/**
|
|
36
|
+
* Find git repository root directory
|
|
37
|
+
* @param cwd - Current working directory
|
|
38
|
+
* @returns Git root path or null if not in a git repository
|
|
39
|
+
*/
|
|
40
|
+
export declare const findGitRoot: (cwd?: string) => string | null;
|
|
41
|
+
/**
|
|
42
|
+
* Find the workspace root directory by looking for package.json with workspaces
|
|
43
|
+
* @param startDir - Directory to start searching from
|
|
44
|
+
* @returns Workspace root path or null if not found
|
|
45
|
+
*/
|
|
46
|
+
export declare const findWorkspaceRoot: (startDir?: string) => string | null;
|
|
47
|
+
/**
|
|
48
|
+
* Get list of workspaces using yarn workspaces list
|
|
49
|
+
* @param workspaceRoot - Workspace root directory
|
|
50
|
+
* @returns Array of WorkspaceInfo
|
|
51
|
+
*/
|
|
52
|
+
export declare const getWorkspaceList: (workspaceRoot: string) => WorkspaceInfo[];
|
|
53
|
+
/**
|
|
54
|
+
* Find workspace location by package name
|
|
55
|
+
* @param packageName - Package name to find
|
|
56
|
+
* @param workspaceRoot - Workspace root directory
|
|
57
|
+
* @returns Workspace location path or null if not found
|
|
58
|
+
*/
|
|
59
|
+
export declare const findWorkspaceLocation: (packageName: string, workspaceRoot: string) => string | null;
|
|
60
|
+
/**
|
|
61
|
+
* Read package.json from local workspace
|
|
62
|
+
* @param packageName - Package name (e.g., "@canard/schema-form")
|
|
63
|
+
* @param cwd - Current working directory
|
|
64
|
+
* @returns PackageInfo or null if not found
|
|
65
|
+
*/
|
|
66
|
+
export declare const readLocalPackageJson: (packageName: string, cwd?: string) => PackageInfo | null;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
3
|
+
import { join, dirname } from 'node:path';
|
|
4
|
+
|
|
5
|
+
const GITHUB_HTTPS_URL_PATTERN = /https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/;
|
|
6
|
+
const GITHUB_SSH_URL_PATTERN = /git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/;
|
|
7
|
+
const GITHUB_SHORTHAND_PATTERN = /^github:([^/]+)\/([^/]+)$/;
|
|
8
|
+
const readPackageJson = (packageName, cwd = process.cwd()) => {
|
|
9
|
+
try {
|
|
10
|
+
const packageJsonPath = join(cwd, 'node_modules', packageName, 'package.json');
|
|
11
|
+
const content = readFileSync(packageJsonPath, 'utf-8');
|
|
12
|
+
const json = JSON.parse(content);
|
|
13
|
+
if (!json.name || !json.version || !json.repository)
|
|
14
|
+
return null;
|
|
15
|
+
return {
|
|
16
|
+
name: json.name,
|
|
17
|
+
version: json.version,
|
|
18
|
+
repository: json.repository,
|
|
19
|
+
claude: json.claude,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const parseGitHubRepo = (repository) => {
|
|
27
|
+
if (!repository || typeof repository.url !== 'string')
|
|
28
|
+
return null;
|
|
29
|
+
const url = repository.url;
|
|
30
|
+
const httpsMatch = url.match(GITHUB_HTTPS_URL_PATTERN);
|
|
31
|
+
if (httpsMatch)
|
|
32
|
+
return {
|
|
33
|
+
owner: httpsMatch[1],
|
|
34
|
+
repo: httpsMatch[2],
|
|
35
|
+
directory: repository.directory,
|
|
36
|
+
};
|
|
37
|
+
const sshMatch = url.match(GITHUB_SSH_URL_PATTERN);
|
|
38
|
+
if (sshMatch)
|
|
39
|
+
return {
|
|
40
|
+
owner: sshMatch[1],
|
|
41
|
+
repo: sshMatch[2],
|
|
42
|
+
directory: repository.directory,
|
|
43
|
+
};
|
|
44
|
+
const shorthandMatch = url.match(GITHUB_SHORTHAND_PATTERN);
|
|
45
|
+
if (shorthandMatch)
|
|
46
|
+
return {
|
|
47
|
+
owner: shorthandMatch[1],
|
|
48
|
+
repo: shorthandMatch[2],
|
|
49
|
+
directory: repository.directory,
|
|
50
|
+
};
|
|
51
|
+
return null;
|
|
52
|
+
};
|
|
53
|
+
const buildVersionTag = (packageName, version) => `${packageName}@${version}`;
|
|
54
|
+
const buildAssetPath = (assetPath, directory) => (assetPath);
|
|
55
|
+
const findGitRoot = (cwd = process.cwd()) => {
|
|
56
|
+
try {
|
|
57
|
+
const gitRoot = execSync('git rev-parse --show-toplevel', {
|
|
58
|
+
cwd,
|
|
59
|
+
encoding: 'utf-8',
|
|
60
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
61
|
+
}).trim();
|
|
62
|
+
return gitRoot;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
const findWorkspaceRoot = (startDir = process.cwd()) => {
|
|
69
|
+
let currentDir = startDir;
|
|
70
|
+
while (currentDir !== '/') {
|
|
71
|
+
const packageJsonPath = join(currentDir, 'package.json');
|
|
72
|
+
if (existsSync(packageJsonPath)) {
|
|
73
|
+
try {
|
|
74
|
+
const content = readFileSync(packageJsonPath, 'utf-8');
|
|
75
|
+
const json = JSON.parse(content);
|
|
76
|
+
if (json.workspaces)
|
|
77
|
+
return currentDir;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
currentDir = dirname(currentDir);
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
};
|
|
86
|
+
const getWorkspaceList = (workspaceRoot) => {
|
|
87
|
+
try {
|
|
88
|
+
const output = execSync('yarn workspaces list --json', {
|
|
89
|
+
cwd: workspaceRoot,
|
|
90
|
+
encoding: 'utf-8',
|
|
91
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
92
|
+
});
|
|
93
|
+
return output
|
|
94
|
+
.trim()
|
|
95
|
+
.split('\n')
|
|
96
|
+
.filter(Boolean)
|
|
97
|
+
.map((line) => JSON.parse(line));
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const findWorkspaceLocation = (packageName, workspaceRoot) => {
|
|
104
|
+
const workspaces = getWorkspaceList(workspaceRoot);
|
|
105
|
+
const workspace = workspaces.find((ws) => ws.name === packageName);
|
|
106
|
+
return workspace ? join(workspaceRoot, workspace.location) : null;
|
|
107
|
+
};
|
|
108
|
+
const readLocalPackageJson = (packageName, cwd = process.cwd()) => {
|
|
109
|
+
try {
|
|
110
|
+
const workspaceRoot = findWorkspaceRoot(cwd);
|
|
111
|
+
if (!workspaceRoot)
|
|
112
|
+
return null;
|
|
113
|
+
const packageLocation = findWorkspaceLocation(packageName, workspaceRoot);
|
|
114
|
+
if (!packageLocation)
|
|
115
|
+
return null;
|
|
116
|
+
const packageJsonPath = join(packageLocation, 'package.json');
|
|
117
|
+
const content = readFileSync(packageJsonPath, 'utf-8');
|
|
118
|
+
const json = JSON.parse(content);
|
|
119
|
+
if (!json.name || !json.version || !json.repository)
|
|
120
|
+
return null;
|
|
121
|
+
return {
|
|
122
|
+
name: json.name,
|
|
123
|
+
version: json.version,
|
|
124
|
+
repository: json.repository,
|
|
125
|
+
claude: json.claude,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export { buildAssetPath, buildVersionTag, findGitRoot, findWorkspaceLocation, findWorkspaceRoot, getWorkspaceList, parseGitHubRepo, readLocalPackageJson, readPackageJson };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude configuration in package.json
|
|
3
|
+
*/
|
|
4
|
+
export interface ClaudeConfig {
|
|
5
|
+
/** Path to Claude assets directory (e.g., "docs/claude") */
|
|
6
|
+
assetPath: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Repository information from package.json
|
|
10
|
+
*/
|
|
11
|
+
export interface RepositoryInfo {
|
|
12
|
+
type: string;
|
|
13
|
+
url: string;
|
|
14
|
+
directory?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Parsed package information
|
|
18
|
+
*/
|
|
19
|
+
export interface PackageInfo {
|
|
20
|
+
name: string;
|
|
21
|
+
version: string;
|
|
22
|
+
repository: RepositoryInfo;
|
|
23
|
+
claude?: ClaudeConfig;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Parsed GitHub repository details
|
|
27
|
+
*/
|
|
28
|
+
export interface GitHubRepoInfo {
|
|
29
|
+
owner: string;
|
|
30
|
+
repo: string;
|
|
31
|
+
directory?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* GitHub API file/directory entry
|
|
35
|
+
*/
|
|
36
|
+
export interface GitHubEntry {
|
|
37
|
+
name: string;
|
|
38
|
+
path: string;
|
|
39
|
+
type: 'file' | 'dir';
|
|
40
|
+
download_url: string | null;
|
|
41
|
+
sha: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Sync metadata stored in .sync-meta.json
|
|
45
|
+
*/
|
|
46
|
+
export interface SyncMeta {
|
|
47
|
+
/** Package version at sync time */
|
|
48
|
+
version: string;
|
|
49
|
+
/** ISO timestamp of last sync */
|
|
50
|
+
syncedAt: string;
|
|
51
|
+
/** List of synced file names */
|
|
52
|
+
files: string[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Asset type (commands or skills)
|
|
56
|
+
*/
|
|
57
|
+
export type AssetType = 'commands' | 'skills';
|
|
58
|
+
/**
|
|
59
|
+
* Sync result for a single package
|
|
60
|
+
*/
|
|
61
|
+
export interface SyncResult {
|
|
62
|
+
packageName: string;
|
|
63
|
+
success: boolean;
|
|
64
|
+
skipped: boolean;
|
|
65
|
+
reason?: string;
|
|
66
|
+
syncedFiles?: {
|
|
67
|
+
commands: string[];
|
|
68
|
+
skills: string[];
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* CLI options
|
|
73
|
+
*/
|
|
74
|
+
export interface CliOptions {
|
|
75
|
+
package: string[];
|
|
76
|
+
force: boolean;
|
|
77
|
+
dryRun: boolean;
|
|
78
|
+
local: boolean;
|
|
79
|
+
/** Custom git ref (branch, tag, or commit) to fetch from */
|
|
80
|
+
ref?: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Workspace info from yarn workspaces
|
|
84
|
+
*/
|
|
85
|
+
export interface WorkspaceInfo {
|
|
86
|
+
name: string;
|
|
87
|
+
location: string;
|
|
88
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@slats/claude-assets-sync",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "CLI tool to sync Claude commands and skills from npm packages to your project's .claude directory",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"claude",
|
|
7
|
+
"claude-code",
|
|
8
|
+
"cli",
|
|
9
|
+
"sync",
|
|
10
|
+
"commands",
|
|
11
|
+
"skills",
|
|
12
|
+
"assets"
|
|
13
|
+
],
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/vincent-kk/albatrion.git",
|
|
17
|
+
"directory": "packages/slats/claude-assets-sync"
|
|
18
|
+
},
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"author": {
|
|
21
|
+
"name": "Vincent K. Kelvin",
|
|
22
|
+
"email": "lunox273@gmail.com"
|
|
23
|
+
},
|
|
24
|
+
"sideEffects": false,
|
|
25
|
+
"type": "module",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"source": "./src/index.ts",
|
|
30
|
+
"import": "./dist/index.mjs",
|
|
31
|
+
"require": "./dist/index.cjs"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"main": "dist/index.cjs",
|
|
35
|
+
"module": "dist/index.mjs",
|
|
36
|
+
"types": "dist/index.d.ts",
|
|
37
|
+
"bin": "./dist/index.mjs",
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"README.md"
|
|
41
|
+
],
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "rollup -c && yarn build:types",
|
|
44
|
+
"build:publish:npm": "yarn build && yarn publish:npm",
|
|
45
|
+
"build:types": "tsc -p ./tsconfig.declarations.json && tsc-alias -p ./tsconfig.declarations.json",
|
|
46
|
+
"dev": "tsx src/index.ts",
|
|
47
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
48
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
49
|
+
"publish:npm": "npm publish --access public",
|
|
50
|
+
"test": "vitest",
|
|
51
|
+
"version:major": "yarn version major",
|
|
52
|
+
"version:minor": "yarn version minor",
|
|
53
|
+
"version:patch": "yarn version patch"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"commander": "^12.1.0",
|
|
57
|
+
"picocolors": "^1.1.1"
|
|
58
|
+
}
|
|
59
|
+
}
|