@raven.js/cli 1.1.2 → 1.2.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 +10 -7
- package/dist/raven +33 -109
- package/dist/raven.map +3 -3
- package/dist/registry.json +1 -9
- package/dist/source/core/GUIDE.md +14 -0
- package/dist/source/core/PLUGIN.md +225 -0
- package/dist/source/core/README.md +427 -0
- package/dist/source/core/index.ts +624 -0
- package/dist/source/core/router.ts +128 -0
- package/dist/source/schema-validator/GUIDE.md +12 -0
- package/dist/source/schema-validator/README.md +229 -0
- package/dist/source/schema-validator/index.ts +139 -0
- package/dist/source/schema-validator/standard-schema.ts +76 -0
- package/dist/source/sql/GUIDE.md +12 -0
- package/dist/source/sql/README.md +271 -0
- package/dist/source/sql/index.ts +14 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# RavenJS CLI
|
|
2
2
|
|
|
3
|
-
The RavenJS CLI is designed for **Agent consumption**. AI skills (raven-setup, raven-add, raven-learn, raven-use) invoke it via `bunx raven`.
|
|
3
|
+
The RavenJS CLI is designed for **Agent consumption**. AI skills (raven-setup, raven-add, raven-learn, raven-use) invoke it via `bunx raven`. To get skills into your project, use **install-raven** (e.g. `npx install-raven`); then run `bunx raven init` to create the raven root, or let raven-setup do it.
|
|
4
4
|
|
|
5
|
-
**Install
|
|
5
|
+
**Install** (project-local, recommended). Requires Bun `>=1.0`:
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
bun add -d @raven.js/cli
|
|
@@ -12,16 +12,19 @@ bun add -d @raven.js/cli
|
|
|
12
12
|
|
|
13
13
|
| Command | Description |
|
|
14
14
|
|---------|-------------|
|
|
15
|
-
| `bunx raven init` | Initialize
|
|
16
|
-
| `bunx raven add <module>` | Add a module.
|
|
17
|
-
| `bunx raven status` |
|
|
15
|
+
| `bunx raven init` | Initialize raven root (directory and `raven.yaml`). Install AI skills with install-raven first. |
|
|
16
|
+
| `bunx raven add <module>` | Add a module (e.g. `core`). Reads from **embedded source** (no network). Installs `dependsOn` in topological order, copies files, and rewrites `@ravenjs/*` / `@raven.js/*` imports to relative paths. |
|
|
17
|
+
| `bunx raven status` | Show RavenJS installation status (core, modules). Output is JSON for Agent consumption. |
|
|
18
18
|
|
|
19
19
|
## Options
|
|
20
20
|
|
|
21
21
|
| Option | Description |
|
|
22
22
|
|--------|-------------|
|
|
23
23
|
| `--root <dir>` | RavenJS root directory (default: `raven`). Overridable via `RAVEN_ROOT`. |
|
|
24
|
-
| `--
|
|
25
|
-
| `--registry <path>` | Path to registry JSON (default: bundled with CLI). Overridable via `RAVEN_DEFAULT_REGISTRY_PATH`. |
|
|
24
|
+
| `--registry <path>` | Path to registry JSON (default: same dir as CLI). Overridable via `RAVEN_DEFAULT_REGISTRY_PATH`. |
|
|
26
25
|
| `--verbose, -v` | Verbose output. |
|
|
27
26
|
|
|
27
|
+
## Offline behavior
|
|
28
|
+
|
|
29
|
+
The CLI embeds module source at build time (`dist/source/<module>/`). `raven add <module>` reads from this embedded source and does not perform any network requests.
|
|
30
|
+
|
package/dist/raven
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// @bun
|
|
2
3
|
|
|
3
4
|
// index.ts
|
|
4
|
-
import {
|
|
5
|
+
import { Command } from "commander";
|
|
5
6
|
import { mkdir, readdir, stat, readFile, writeFile, access } from "fs/promises";
|
|
6
7
|
import { join, dirname, resolve, isAbsolute } from "path";
|
|
7
8
|
import { cwd } from "process";
|
|
@@ -14,8 +15,6 @@ var __dirname2 = dirname(fileURLToPath(import.meta.url));
|
|
|
14
15
|
function loadCliVersion() {
|
|
15
16
|
return process.env.RAVEN_CLI_VERSION ?? "0.0.0";
|
|
16
17
|
}
|
|
17
|
-
var GITHUB_REPO = "myWsq/RavenJS";
|
|
18
|
-
var GITHUB_RAW_URL = `https://raw.githubusercontent.com/${GITHUB_REPO}`;
|
|
19
18
|
var DEFAULT_ROOT = "raven";
|
|
20
19
|
async function fileExists(path) {
|
|
21
20
|
try {
|
|
@@ -41,20 +40,12 @@ async function loadRegistry(options) {
|
|
|
41
40
|
return JSON.parse(content);
|
|
42
41
|
}
|
|
43
42
|
}
|
|
44
|
-
console.error("registry.json not found. Run 'bun run build' in packages/cli first
|
|
43
|
+
console.error("registry.json not found. Run 'bun run build' in packages/cli first.");
|
|
45
44
|
process.exit(1);
|
|
46
45
|
}
|
|
47
46
|
function getRoot(options) {
|
|
48
47
|
return options.root || process.env.RAVEN_ROOT || DEFAULT_ROOT;
|
|
49
48
|
}
|
|
50
|
-
function getSource(options) {
|
|
51
|
-
return options.source || process.env.RAVEN_SOURCE;
|
|
52
|
-
}
|
|
53
|
-
function resolveSourcePath(source) {
|
|
54
|
-
if (!source || source === "github")
|
|
55
|
-
return;
|
|
56
|
-
return isAbsolute(source) ? source : resolve(cwd(), source);
|
|
57
|
-
}
|
|
58
49
|
async function verboseLog(message, options) {
|
|
59
50
|
if (options?.verbose) {
|
|
60
51
|
console.log(message);
|
|
@@ -174,64 +165,34 @@ function replaceRavenImports(content, fromModuleDir, registry) {
|
|
|
174
165
|
}
|
|
175
166
|
return out;
|
|
176
167
|
}
|
|
177
|
-
async function downloadFile(url, destPath) {
|
|
178
|
-
const response = await fetch(url);
|
|
179
|
-
if (!response.ok) {
|
|
180
|
-
throw new Error(`Failed to download ${url}: ${response.status}`);
|
|
181
|
-
}
|
|
182
|
-
const content = await response.text();
|
|
183
|
-
await ensureDir(dirname(destPath));
|
|
184
|
-
await writeFile(destPath, content);
|
|
185
|
-
}
|
|
186
|
-
async function copyLocalFile(srcPath, destPath) {
|
|
187
|
-
if (!await fileExists(srcPath)) {
|
|
188
|
-
throw new Error(`Missing local file: ${srcPath}`);
|
|
189
|
-
}
|
|
190
|
-
await ensureDir(dirname(destPath));
|
|
191
|
-
const content = await readFile(srcPath);
|
|
192
|
-
await writeFile(destPath, content);
|
|
193
|
-
}
|
|
194
168
|
var SOURCE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx"];
|
|
195
169
|
function isSourceFile(file) {
|
|
196
170
|
return SOURCE_EXTENSIONS.some((ext) => file.endsWith(ext));
|
|
197
171
|
}
|
|
198
|
-
async function
|
|
172
|
+
async function installModule(registry, moduleName, destDir, options, targetSubdir) {
|
|
199
173
|
const module = registry.modules[moduleName];
|
|
200
174
|
if (!module) {
|
|
201
175
|
throw new Error(`Module ${moduleName} not found in registry`);
|
|
202
176
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
verboseLog(`Using local source: ${sourcePath}`, options);
|
|
206
|
-
}
|
|
207
|
-
verboseLog(`Downloading ${moduleName} files...`, options);
|
|
177
|
+
verboseLog(`Installing ${moduleName} files...`, options);
|
|
178
|
+
const embeddedSourceDir = join(__dirname2, "source");
|
|
208
179
|
const fromModuleDir = targetSubdir ?? moduleName;
|
|
209
180
|
const modifiedFiles = [];
|
|
210
|
-
const
|
|
181
|
+
const copies = module.files.map(async (file) => {
|
|
211
182
|
let destPath;
|
|
212
|
-
if (module.fileMapping
|
|
183
|
+
if (module.fileMapping?.[file]) {
|
|
213
184
|
destPath = join(destDir, module.fileMapping[file]);
|
|
214
185
|
} else if (targetSubdir) {
|
|
215
186
|
destPath = join(destDir, targetSubdir, file);
|
|
216
187
|
} else {
|
|
217
188
|
destPath = join(destDir, moduleName, file);
|
|
218
189
|
}
|
|
219
|
-
verboseLog(`
|
|
220
|
-
|
|
221
|
-
if (
|
|
222
|
-
|
|
223
|
-
const fallbackPath = join(sourcePath, moduleName, file);
|
|
224
|
-
const src = await fileExists(primaryPath) ? primaryPath : await fileExists(fallbackPath) ? fallbackPath : "";
|
|
225
|
-
if (!src)
|
|
226
|
-
throw new Error(`Missing local file: ${primaryPath}`);
|
|
227
|
-
content = await readFile(src, "utf-8");
|
|
228
|
-
} else {
|
|
229
|
-
const url = `${GITHUB_RAW_URL}/v${version}/modules/${moduleName}/${file}`;
|
|
230
|
-
const response = await fetch(url);
|
|
231
|
-
if (!response.ok)
|
|
232
|
-
throw new Error(`Failed to download ${url}: ${response.status}`);
|
|
233
|
-
content = await response.text();
|
|
190
|
+
verboseLog(` Copying ${file}...`, options);
|
|
191
|
+
const srcPath = join(embeddedSourceDir, moduleName, file);
|
|
192
|
+
if (!await fileExists(srcPath)) {
|
|
193
|
+
throw new Error(`Missing embedded source file: ${srcPath}`);
|
|
234
194
|
}
|
|
195
|
+
let content = await readFile(srcPath, "utf-8");
|
|
235
196
|
if (isSourceFile(file)) {
|
|
236
197
|
content = replaceRavenImports(content, fromModuleDir, registry);
|
|
237
198
|
}
|
|
@@ -239,35 +200,7 @@ async function downloadModule(registry, moduleName, version, destDir, options, t
|
|
|
239
200
|
await writeFile(destPath, content);
|
|
240
201
|
modifiedFiles.push(destPath);
|
|
241
202
|
});
|
|
242
|
-
await Promise.all(
|
|
243
|
-
return modifiedFiles;
|
|
244
|
-
}
|
|
245
|
-
async function downloadAiResources(registry, version, destDir, options) {
|
|
246
|
-
const ai = registry.ai;
|
|
247
|
-
if (!ai?.claude) {
|
|
248
|
-
throw new Error("AI resources not found in registry");
|
|
249
|
-
}
|
|
250
|
-
const mapping = ai.claude;
|
|
251
|
-
const entries = Object.entries(mapping);
|
|
252
|
-
const sourcePath = resolveSourcePath(getSource(options || {}));
|
|
253
|
-
if (sourcePath) {
|
|
254
|
-
verboseLog(`Using local source: ${sourcePath}`, options);
|
|
255
|
-
}
|
|
256
|
-
verboseLog("Downloading AI resources...", options);
|
|
257
|
-
const modifiedFiles = [];
|
|
258
|
-
const downloads = entries.map(async ([file, destRel]) => {
|
|
259
|
-
const destPath = join(destDir, destRel);
|
|
260
|
-
verboseLog(` Downloading ${file}...`, options);
|
|
261
|
-
if (sourcePath) {
|
|
262
|
-
const sourceFile = join(sourcePath, "packages", "ai", file);
|
|
263
|
-
await copyLocalFile(sourceFile, destPath);
|
|
264
|
-
} else {
|
|
265
|
-
const url = `${GITHUB_RAW_URL}/v${version}/packages/ai/${file}`;
|
|
266
|
-
await downloadFile(url, destPath);
|
|
267
|
-
}
|
|
268
|
-
modifiedFiles.push(destPath);
|
|
269
|
-
});
|
|
270
|
-
await Promise.all(downloads);
|
|
203
|
+
await Promise.all(copies);
|
|
271
204
|
return modifiedFiles;
|
|
272
205
|
}
|
|
273
206
|
async function cmdInit(options) {
|
|
@@ -287,29 +220,28 @@ async function cmdInit(options) {
|
|
|
287
220
|
await createRavenYaml(ravenDir, version);
|
|
288
221
|
modifiedFiles.push(ravenYamlPath);
|
|
289
222
|
}
|
|
290
|
-
const dotClaudeDir = join(targetDir, ".claude");
|
|
291
|
-
await ensureDir(dotClaudeDir);
|
|
292
|
-
const aiFiles = await downloadAiResources(registry, version, targetDir, options);
|
|
293
|
-
modifiedFiles.push(...aiFiles);
|
|
294
223
|
};
|
|
295
224
|
if (options?.verbose) {
|
|
296
225
|
await doInit();
|
|
297
226
|
} else {
|
|
298
227
|
const s = makeSpinner();
|
|
299
|
-
s.start("Initializing
|
|
228
|
+
s.start("Initializing raven root...");
|
|
300
229
|
try {
|
|
301
230
|
await doInit();
|
|
302
231
|
} catch (e) {
|
|
303
232
|
s.stop("Initialization failed");
|
|
304
233
|
error(e.message);
|
|
305
234
|
}
|
|
306
|
-
s.stop("Initializing
|
|
235
|
+
s.stop("Initializing raven root...");
|
|
307
236
|
}
|
|
308
|
-
success("RavenJS initialized
|
|
237
|
+
success("RavenJS raven root initialized. Install AI skills with: install-raven (or npx install-raven).");
|
|
309
238
|
printSectionHeader("Modified Files");
|
|
310
239
|
for (const file of modifiedFiles) {
|
|
311
240
|
printListItem(file);
|
|
312
241
|
}
|
|
242
|
+
printSectionHeader("Status");
|
|
243
|
+
const status = await getStatus(registry, options);
|
|
244
|
+
console.log(JSON.stringify(status));
|
|
313
245
|
}
|
|
314
246
|
async function createRavenYaml(destDir, version) {
|
|
315
247
|
const content = stringify({ version });
|
|
@@ -334,14 +266,14 @@ async function cmdAdd(moduleName, options) {
|
|
|
334
266
|
if (!available.includes(moduleName)) {
|
|
335
267
|
error(`Unknown module: ${moduleName}`);
|
|
336
268
|
}
|
|
337
|
-
const { ravenDir
|
|
269
|
+
const { ravenDir } = await ensureRavenInstalled(options);
|
|
338
270
|
const installed = await getInstalledModules(ravenDir, registry);
|
|
339
271
|
const order = getInstallOrder(moduleName, registry, installed);
|
|
340
272
|
try {
|
|
341
273
|
const modifiedFiles = [];
|
|
342
274
|
const allDependencies = {};
|
|
343
275
|
for (const name of order) {
|
|
344
|
-
const files = await
|
|
276
|
+
const files = await installModule(registry, name, ravenDir, options);
|
|
345
277
|
modifiedFiles.push(...files);
|
|
346
278
|
const mod = registry.modules[name];
|
|
347
279
|
if (mod?.dependencies) {
|
|
@@ -354,6 +286,8 @@ async function cmdAdd(moduleName, options) {
|
|
|
354
286
|
modifiedFiles,
|
|
355
287
|
dependencies: allDependencies
|
|
356
288
|
}));
|
|
289
|
+
const status = await getStatus(registry, options);
|
|
290
|
+
console.log(JSON.stringify(status));
|
|
357
291
|
} catch (e) {
|
|
358
292
|
error(e.message);
|
|
359
293
|
}
|
|
@@ -407,15 +341,6 @@ async function getStatus(registry, options) {
|
|
|
407
341
|
}
|
|
408
342
|
await traverseDir(ravenDir, ravenDir);
|
|
409
343
|
}
|
|
410
|
-
let latestVersion;
|
|
411
|
-
try {
|
|
412
|
-
const response = await fetch(`https://api.github.com/repos/${GITHUB_REPO}/releases/latest`);
|
|
413
|
-
if (response.ok) {
|
|
414
|
-
const data = await response.json();
|
|
415
|
-
latestVersion = data.tag_name.replace(/^v/, "");
|
|
416
|
-
}
|
|
417
|
-
} catch (e) {
|
|
418
|
-
}
|
|
419
344
|
if (moduleStatus.length === 0) {
|
|
420
345
|
for (const name of knownModules) {
|
|
421
346
|
const mod = registry.modules[name];
|
|
@@ -431,7 +356,6 @@ async function getStatus(registry, options) {
|
|
|
431
356
|
return {
|
|
432
357
|
modules: moduleStatus,
|
|
433
358
|
version: currentVersion,
|
|
434
|
-
latestVersion,
|
|
435
359
|
modifiedFiles,
|
|
436
360
|
fileHashes
|
|
437
361
|
};
|
|
@@ -441,13 +365,13 @@ async function cmdStatus(options) {
|
|
|
441
365
|
const status = await getStatus(registry, options);
|
|
442
366
|
console.log(JSON.stringify(status));
|
|
443
367
|
}
|
|
444
|
-
var
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
368
|
+
var program = new Command("raven");
|
|
369
|
+
program.version(loadCliVersion());
|
|
370
|
+
program.option("--registry <path>", "Registry json path (default: same dir as CLI)").option("--root <dir>", "RavenJS root directory (default: raven)").option("-v, --verbose", "Verbose output");
|
|
371
|
+
program.command("init").description("Initialize raven root (directory and raven.yaml). Install AI skills with install-raven.").action(() => cmdInit(program.opts()));
|
|
372
|
+
program.command("add <module>").description("Add a module (e.g., core)").action((module) => cmdAdd(module, program.opts()));
|
|
373
|
+
program.command("status").description("Show RavenJS installation status (core, modules)").action(() => cmdStatus(program.opts()));
|
|
374
|
+
program.parse();
|
|
451
375
|
|
|
452
|
-
//# debugId=
|
|
376
|
+
//# debugId=18CE5936F1B83A4764756E2164756E21
|
|
453
377
|
//# sourceMappingURL=raven.map
|
package/dist/raven.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"#!/usr/bin/env node\n\nimport { cac } from \"cac\";\nimport { mkdir, readdir, stat, readFile, writeFile, access } from \"fs/promises\";\nimport { join, dirname, resolve, isAbsolute } from \"path\";\nimport { cwd } from \"process\";\nimport { createHash } from \"crypto\";\nimport { fileURLToPath } from \"url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nimport pc from \"picocolors\";\nimport { spinner as makeSpinner, log } from \"@clack/prompts\";\nimport { parse, stringify } from \"yaml\";\n\nfunction loadCliVersion(): string {\n return process.env.RAVEN_CLI_VERSION ?? \"0.0.0\";\n}\n\nconst GITHUB_REPO = \"myWsq/RavenJS\";\nconst GITHUB_RAW_URL = `https://raw.githubusercontent.com/${GITHUB_REPO}`;\nconst DEFAULT_ROOT = \"raven\";\n\ninterface CLIOptions {\n verbose?: boolean;\n root?: string;\n source?: string;\n prerelease?: boolean;\n registry?: string;\n}\n\ninterface RegistryModule {\n files: string[];\n fileMapping?: Record<string, string>;\n dependencies?: Record<string, string>;\n dependsOn?: string[];\n description?: string;\n}\n\ninterface RegistryAi {\n claude: Record<string, string>;\n}\n\ninterface Registry {\n version: string;\n modules: Record<string, RegistryModule>;\n ai: RegistryAi;\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function loadRegistry(options?: {\n registry?: string;\n}): Promise<Registry> {\n const candidates: string[] = [];\n if (options?.registry) {\n candidates.push(\n isAbsolute(options.registry)\n ? options.registry\n : resolve(cwd(), options.registry),\n );\n }\n if (process.env.RAVEN_DEFAULT_REGISTRY_PATH) {\n const p = process.env.RAVEN_DEFAULT_REGISTRY_PATH;\n candidates.push(isAbsolute(p) ? p : resolve(cwd(), p));\n }\n candidates.push(join(__dirname, \"registry.json\"));\n\n for (const p of candidates) {\n if (await fileExists(p)) {\n const content = await readFile(p, \"utf-8\");\n return JSON.parse(content) as Registry;\n }\n }\n console.error(\n \"registry.json not found. Run 'bun run build' in packages/cli first, or use --registry <path>.\",\n );\n process.exit(1);\n}\n\nfunction getRoot(options: CLIOptions): string {\n return options.root || process.env.RAVEN_ROOT || DEFAULT_ROOT;\n}\n\nfunction getSource(options: CLIOptions): string | undefined {\n return options.source || process.env.RAVEN_SOURCE;\n}\n\nfunction resolveSourcePath(source?: string): string | undefined {\n if (!source || source === \"github\") return undefined;\n return isAbsolute(source) ? source : resolve(cwd(), source);\n}\n\nasync function verboseLog(message: string, options?: CLIOptions) {\n if (options?.verbose) {\n console.log(message);\n }\n}\n\nfunction error(message: string): never {\n // Use stderr for programmatic consumption (e.g. tests, piping). @clack/prompts\n // log.error writes to stdout which breaks stderr-based assertions.\n console.error(message);\n process.exit(1);\n}\n\nfunction success(message: string) {\n log.success(message);\n}\n\nfunction printSectionHeader(title: string) {\n log.step(title);\n}\n\nfunction printListItem(item: string) {\n log.message(item, { symbol: pc.dim(\"-\") });\n}\n\nasync function ensureDir(path: string) {\n try {\n await mkdir(path, { recursive: true });\n } catch (e: any) {\n if (e.code !== \"EEXIST\") throw e;\n }\n}\n\nasync function isDirEmpty(path: string): Promise<boolean> {\n try {\n const entries = await readdir(path);\n return entries.length === 0;\n } catch (e: any) {\n if (e.code === \"ENOENT\") return true;\n throw e;\n }\n}\n\nasync function pathExists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch (e: any) {\n if (e.code === \"ENOENT\") return false;\n throw e;\n }\n}\n\nasync function ensureRavenInstalled(\n options: CLIOptions,\n): Promise<{ ravenDir: string; version: string }> {\n const targetDir = cwd();\n const root = getRoot(options);\n const ravenDir = join(targetDir, root);\n\n if (!(await pathExists(ravenDir))) {\n error(`RavenJS not installed at ${root}/. Run 'raven init' first.`);\n }\n\n const yamlPath = join(ravenDir, \"raven.yaml\");\n try {\n const content = await readFile(yamlPath, \"utf-8\");\n const config = parse(content) as RavenYamlConfig;\n if (!config?.version) {\n error(\"Invalid raven.yaml: version field is missing\");\n }\n return { ravenDir, version: config.version };\n } catch (e: any) {\n error(`Failed to load raven.yaml: ${e.message}`);\n }\n}\n\nfunction getModuleNames(registry: Registry): string[] {\n return Object.keys(registry.modules);\n}\n\nfunction getInstallOrder(\n moduleName: string,\n registry: Registry,\n installed: Set<string>,\n): string[] {\n const result: string[] = [];\n const visited = new Set<string>();\n const recStack = new Set<string>();\n const path: string[] = [];\n let cycle: string[] | null = null;\n\n function visit(name: string) {\n if (recStack.has(name)) {\n const idx = path.indexOf(name);\n cycle = path.slice(idx).concat(name);\n return;\n }\n if (visited.has(name)) return;\n visited.add(name);\n recStack.add(name);\n path.push(name);\n\n const mod = registry.modules[name];\n if (mod?.dependsOn) {\n for (const dep of mod.dependsOn) {\n if (registry.modules[dep]) visit(dep);\n }\n }\n if (!installed.has(name)) {\n result.push(name);\n }\n path.pop();\n recStack.delete(name);\n }\n\n visit(moduleName);\n if (cycle !== null) {\n error(`Circular dependency: ${(cycle as string[]).join(\" -> \")}`);\n }\n return result;\n}\n\nconst RAVENJS_PREFIX = \"@raven.js/\";\n\nfunction replaceRavenImports(\n content: string,\n fromModuleDir: string,\n registry: Registry,\n): string {\n const moduleNames = Object.keys(registry.modules);\n let out = content;\n const depth = fromModuleDir.split(\"/\").filter(Boolean).length;\n const prefix = depth > 0 ? \"../\".repeat(depth) : \"./\";\n for (const modName of moduleNames) {\n const pkg = `${RAVENJS_PREFIX}${modName}`;\n const rel = prefix + modName;\n\n const dq = new RegExp(\n `from\\\\s+\"${pkg.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}\"`,\n \"g\",\n );\n const sq = new RegExp(\n `from\\\\s+'${pkg.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}'`,\n \"g\",\n );\n out = out.replace(dq, `from \"${rel}\"`).replace(sq, `from '${rel}'`);\n }\n return out;\n}\n\nasync function downloadFile(url: string, destPath: string): Promise<void> {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to download ${url}: ${response.status}`);\n }\n const content = await response.text();\n await ensureDir(dirname(destPath));\n await writeFile(destPath, content);\n}\n\nasync function copyLocalFile(srcPath: string, destPath: string): Promise<void> {\n if (!(await fileExists(srcPath))) {\n throw new Error(`Missing local file: ${srcPath}`);\n }\n await ensureDir(dirname(destPath));\n const content = await readFile(srcPath);\n await writeFile(destPath, content);\n}\n\nconst SOURCE_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\"];\n\nfunction isSourceFile(file: string): boolean {\n return SOURCE_EXTENSIONS.some((ext) => file.endsWith(ext));\n}\n\nasync function downloadModule(\n registry: Registry,\n moduleName: string,\n version: string,\n destDir: string,\n options?: CLIOptions,\n targetSubdir?: string,\n): Promise<string[]> {\n const module = registry.modules[moduleName];\n if (!module) {\n throw new Error(`Module ${moduleName} not found in registry`);\n }\n\n const sourcePath = resolveSourcePath(getSource(options || {}));\n if (sourcePath) {\n verboseLog(`Using local source: ${sourcePath}`, options);\n }\n verboseLog(`Downloading ${moduleName} files...`, options);\n\n const fromModuleDir = targetSubdir ?? moduleName;\n\n const modifiedFiles: string[] = [];\n const downloads = module.files.map(async (file: string) => {\n let destPath: string;\n\n if (module.fileMapping && module.fileMapping[file]) {\n destPath = join(destDir, module.fileMapping[file]);\n } else if (targetSubdir) {\n destPath = join(destDir, targetSubdir, file);\n } else {\n destPath = join(destDir, moduleName, file);\n }\n\n verboseLog(` Downloading ${file}...`, options);\n\n let content: string;\n if (sourcePath) {\n const primaryPath = join(sourcePath, \"modules\", moduleName, file);\n const fallbackPath = join(sourcePath, moduleName, file);\n const src = (await fileExists(primaryPath))\n ? primaryPath\n : (await fileExists(fallbackPath))\n ? fallbackPath\n : \"\";\n if (!src) throw new Error(`Missing local file: ${primaryPath}`);\n content = await readFile(src, \"utf-8\");\n } else {\n const url = `${GITHUB_RAW_URL}/v${version}/modules/${moduleName}/${file}`;\n const response = await fetch(url);\n if (!response.ok)\n throw new Error(`Failed to download ${url}: ${response.status}`);\n content = await response.text();\n }\n\n if (isSourceFile(file)) {\n content = replaceRavenImports(content, fromModuleDir, registry);\n }\n\n await ensureDir(dirname(destPath));\n await writeFile(destPath, content);\n modifiedFiles.push(destPath);\n });\n\n await Promise.all(downloads);\n return modifiedFiles;\n}\n\nasync function downloadAiResources(\n registry: Registry,\n version: string,\n destDir: string,\n options?: CLIOptions,\n): Promise<string[]> {\n const ai = registry.ai;\n if (!ai?.claude) {\n throw new Error(\"AI resources not found in registry\");\n }\n\n const mapping = ai.claude;\n const entries = Object.entries(mapping);\n\n const sourcePath = resolveSourcePath(getSource(options || {}));\n if (sourcePath) {\n verboseLog(`Using local source: ${sourcePath}`, options);\n }\n verboseLog(\"Downloading AI resources...\", options);\n\n const modifiedFiles: string[] = [];\n const downloads = entries.map(async ([file, destRel]) => {\n const destPath = join(destDir, destRel);\n verboseLog(` Downloading ${file}...`, options);\n\n if (sourcePath) {\n const sourceFile = join(sourcePath, \"packages\", \"ai\", file);\n await copyLocalFile(sourceFile, destPath);\n } else {\n const url = `${GITHUB_RAW_URL}/v${version}/packages/ai/${file}`;\n await downloadFile(url, destPath);\n }\n modifiedFiles.push(destPath);\n });\n\n await Promise.all(downloads);\n return modifiedFiles;\n}\n\nasync function cmdInit(options: CLIOptions) {\n const registry = await loadRegistry(options);\n const targetDir = cwd();\n const root = getRoot(options);\n const ravenDir = join(targetDir, root);\n\n verboseLog(`Initializing RavenJS in ${targetDir}`, options);\n\n const version = registry.version;\n const modifiedFiles: string[] = [];\n\n const ravenRootExists = await pathExists(ravenDir);\n const ravenYamlPath = join(ravenDir, \"raven.yaml\");\n const ravenYamlExists = await pathExists(ravenYamlPath);\n\n const doInit = async () => {\n if (!ravenRootExists || !ravenYamlExists) {\n await ensureDir(ravenDir);\n await createRavenYaml(ravenDir, version);\n modifiedFiles.push(ravenYamlPath);\n }\n\n const dotClaudeDir = join(targetDir, \".claude\");\n await ensureDir(dotClaudeDir);\n const aiFiles = await downloadAiResources(\n registry,\n version,\n targetDir,\n options,\n );\n modifiedFiles.push(...aiFiles);\n };\n\n if (options?.verbose) {\n await doInit();\n } else {\n const s = makeSpinner();\n s.start(\"Initializing RavenJS...\");\n try {\n await doInit();\n } catch (e: any) {\n s.stop(\"Initialization failed\");\n error(e.message);\n }\n s.stop(\"Initializing RavenJS...\");\n }\n\n success(\"RavenJS initialized successfully!\");\n\n printSectionHeader(\"Modified Files\");\n for (const file of modifiedFiles) {\n printListItem(file);\n }\n}\n\ninterface RavenYamlConfig {\n version: string;\n}\n\nasync function createRavenYaml(destDir: string, version: string) {\n const content = stringify({ version });\n await writeFile(join(destDir, \"raven.yaml\"), content);\n}\n\nasync function getInstalledModules(\n ravenDir: string,\n registry: Registry,\n): Promise<Set<string>> {\n const installed = new Set<string>();\n for (const name of getModuleNames(registry)) {\n const modDir = join(ravenDir, name);\n if ((await pathExists(modDir)) && !(await isDirEmpty(modDir))) {\n installed.add(name);\n }\n }\n return installed;\n}\n\nasync function cmdAdd(moduleName: string, options: CLIOptions) {\n const registry = await loadRegistry(options);\n if (!moduleName) {\n error(\n `Please specify a module to add. Available: ${getModuleNames(registry).join(\", \")}`,\n );\n }\n\n const available = getModuleNames(registry);\n\n if (!available.includes(moduleName)) {\n error(`Unknown module: ${moduleName}`);\n }\n\n const { ravenDir, version } = await ensureRavenInstalled(options);\n\n const installed = await getInstalledModules(ravenDir, registry);\n const order = getInstallOrder(moduleName, registry, installed);\n\n try {\n const modifiedFiles: string[] = [];\n const allDependencies: Record<string, string> = {};\n for (const name of order) {\n const files = await downloadModule(\n registry,\n name,\n version,\n ravenDir,\n options,\n );\n modifiedFiles.push(...files);\n const mod = registry.modules[name];\n if (mod?.dependencies) {\n Object.assign(allDependencies, mod.dependencies);\n }\n }\n\n console.log(\n JSON.stringify({\n success: true,\n moduleName,\n modifiedFiles,\n dependencies: allDependencies,\n }),\n );\n } catch (e: any) {\n error(e.message);\n }\n}\n\n// === SECTION: Status ===\n\ninterface ModuleInfo {\n name: string;\n description?: string;\n installed: boolean;\n /** 模块目录的绝对路径 */\n installDir?: string;\n}\n\ninterface StatusResult {\n modules: ModuleInfo[];\n version?: string;\n latestVersion?: string;\n modifiedFiles?: string[];\n fileHashes?: Record<string, string>;\n}\n\nasync function computeFileHash(filePath: string): Promise<string> {\n const content = await readFile(filePath);\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\nasync function getStatus(\n registry: Registry,\n options: CLIOptions,\n): Promise<StatusResult> {\n const targetDir = cwd();\n const root = getRoot(options);\n const ravenDir = join(targetDir, root);\n\n let currentVersion: string | undefined;\n const modifiedFiles: string[] = [];\n const fileHashes: Record<string, string> = {};\n\n const knownModules = getModuleNames(registry).sort();\n const moduleStatus: ModuleInfo[] = [];\n\n if (await pathExists(ravenDir)) {\n const yamlPath = join(ravenDir, \"raven.yaml\");\n try {\n const content = await readFile(yamlPath, \"utf-8\");\n const config = parse(content) as RavenYamlConfig;\n if (config?.version) {\n currentVersion = config.version;\n }\n } catch (_e) {\n // raven.yaml missing or invalid\n }\n\n for (const name of knownModules) {\n const modDir = join(ravenDir, name);\n const installed =\n (await pathExists(modDir)) && !(await isDirEmpty(modDir));\n const mod = registry.modules[name];\n moduleStatus.push({\n name,\n description: mod?.description,\n installed,\n installDir: resolve(modDir),\n });\n }\n\n // Compute file hashes for all files in raven/\n async function traverseDir(dir: string, baseDir: string) {\n const dirEntries = await readdir(dir, { withFileTypes: true });\n for (const e of dirEntries) {\n const fullPath = join(dir, e.name);\n const relPath = fullPath.slice(baseDir.length + 1);\n if (e.isDirectory()) {\n await traverseDir(fullPath, baseDir);\n } else {\n const hash = await computeFileHash(fullPath);\n fileHashes[relPath] = hash;\n }\n }\n }\n await traverseDir(ravenDir, ravenDir);\n }\n\n // Try to get latest version from GitHub\n let latestVersion: string | undefined;\n try {\n const response = await fetch(\n `https://api.github.com/repos/${GITHUB_REPO}/releases/latest`,\n );\n if (response.ok) {\n const data = await response.json();\n latestVersion = data.tag_name.replace(/^v/, \"\");\n }\n } catch (e) {\n // ignore if can't fetch latest version\n }\n\n if (moduleStatus.length === 0) {\n for (const name of knownModules) {\n const mod = registry.modules[name];\n const modDir = join(ravenDir, name);\n moduleStatus.push({\n name,\n description: mod?.description,\n installed: false,\n installDir: resolve(modDir),\n });\n }\n }\n\n return {\n modules: moduleStatus,\n version: currentVersion,\n latestVersion,\n modifiedFiles,\n fileHashes,\n };\n}\n\ninterface StatusCLIOptions extends CLIOptions {}\n\nasync function cmdStatus(options: StatusCLIOptions) {\n const registry = await loadRegistry(options);\n const status = await getStatus(registry, options);\n console.log(JSON.stringify(status));\n}\n\nconst cli = cac(\"raven\");\ncli.version(loadCliVersion()).help();\n\ncli\n .option(\"--registry <path>\", \"Registry json path (default: same dir as CLI)\")\n .option(\"--root <dir>\", \"RavenJS root directory (default: raven)\")\n .option(\"--source <path>\", \"Local module source path (default: github)\")\n .option(\"--verbose, -v\", \"Verbose output\");\n\ncli\n .command(\"init\", \"Initialize RavenJS AI resources\")\n .action((options) => cmdInit(options as CLIOptions));\n\ncli\n .command(\"add <module>\", \"Add a module (e.g., core)\")\n .action((module, options) => cmdAdd(module, options as CLIOptions));\n\ncli\n .command(\"status\", \"Show RavenJS installation status (core, modules)\")\n .action((options) => cmdStatus(options as StatusCLIOptions));\n\ncli.parse();\n"
|
|
5
|
+
"#!/usr/bin/env bun\n\nimport { Command } from \"commander\";\nimport { mkdir, readdir, stat, readFile, writeFile, access } from \"fs/promises\";\nimport { join, dirname, resolve, isAbsolute } from \"path\";\nimport { cwd } from \"process\";\nimport { createHash } from \"crypto\";\nimport { fileURLToPath } from \"url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nimport pc from \"picocolors\";\nimport { spinner as makeSpinner, log } from \"@clack/prompts\";\nimport { parse, stringify } from \"yaml\";\n\nfunction loadCliVersion(): string {\n return process.env.RAVEN_CLI_VERSION ?? \"0.0.0\";\n}\n\nconst DEFAULT_ROOT = \"raven\";\n\ninterface CLIOptions {\n verbose?: boolean;\n root?: string;\n prerelease?: boolean;\n registry?: string;\n}\n\ninterface RegistryModule {\n files: string[];\n fileMapping?: Record<string, string>;\n dependencies?: Record<string, string>;\n dependsOn?: string[];\n description?: string;\n}\n\ninterface Registry {\n version: string;\n modules: Record<string, RegistryModule>;\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function loadRegistry(options?: {\n registry?: string;\n}): Promise<Registry> {\n const candidates: string[] = [];\n if (options?.registry) {\n candidates.push(\n isAbsolute(options.registry)\n ? options.registry\n : resolve(cwd(), options.registry),\n );\n }\n if (process.env.RAVEN_DEFAULT_REGISTRY_PATH) {\n const p = process.env.RAVEN_DEFAULT_REGISTRY_PATH;\n candidates.push(isAbsolute(p) ? p : resolve(cwd(), p));\n }\n candidates.push(join(__dirname, \"registry.json\"));\n\n for (const p of candidates) {\n if (await fileExists(p)) {\n const content = await readFile(p, \"utf-8\");\n return JSON.parse(content) as Registry;\n }\n }\n console.error(\n \"registry.json not found. Run 'bun run build' in packages/cli first.\",\n );\n process.exit(1);\n}\n\nfunction getRoot(options: CLIOptions): string {\n return options.root || process.env.RAVEN_ROOT || DEFAULT_ROOT;\n}\n\nasync function verboseLog(message: string, options?: CLIOptions) {\n if (options?.verbose) {\n console.log(message);\n }\n}\n\nfunction error(message: string): never {\n // Use stderr for programmatic consumption (e.g. tests, piping). @clack/prompts\n // log.error writes to stdout which breaks stderr-based assertions.\n console.error(message);\n process.exit(1);\n}\n\nfunction success(message: string) {\n log.success(message);\n}\n\nfunction printSectionHeader(title: string) {\n log.step(title);\n}\n\nfunction printListItem(item: string) {\n log.message(item, { symbol: pc.dim(\"-\") });\n}\n\nasync function ensureDir(path: string) {\n try {\n await mkdir(path, { recursive: true });\n } catch (e: any) {\n if (e.code !== \"EEXIST\") throw e;\n }\n}\n\nasync function isDirEmpty(path: string): Promise<boolean> {\n try {\n const entries = await readdir(path);\n return entries.length === 0;\n } catch (e: any) {\n if (e.code === \"ENOENT\") return true;\n throw e;\n }\n}\n\nasync function pathExists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch (e: any) {\n if (e.code === \"ENOENT\") return false;\n throw e;\n }\n}\n\nasync function ensureRavenInstalled(\n options: CLIOptions,\n): Promise<{ ravenDir: string; version: string }> {\n const targetDir = cwd();\n const root = getRoot(options);\n const ravenDir = join(targetDir, root);\n\n if (!(await pathExists(ravenDir))) {\n error(`RavenJS not installed at ${root}/. Run 'raven init' first.`);\n }\n\n const yamlPath = join(ravenDir, \"raven.yaml\");\n try {\n const content = await readFile(yamlPath, \"utf-8\");\n const config = parse(content) as RavenYamlConfig;\n if (!config?.version) {\n error(\"Invalid raven.yaml: version field is missing\");\n }\n return { ravenDir, version: config.version };\n } catch (e: any) {\n error(`Failed to load raven.yaml: ${e.message}`);\n }\n}\n\nfunction getModuleNames(registry: Registry): string[] {\n return Object.keys(registry.modules);\n}\n\nfunction getInstallOrder(\n moduleName: string,\n registry: Registry,\n installed: Set<string>,\n): string[] {\n const result: string[] = [];\n const visited = new Set<string>();\n const recStack = new Set<string>();\n const path: string[] = [];\n let cycle: string[] | null = null;\n\n function visit(name: string) {\n if (recStack.has(name)) {\n const idx = path.indexOf(name);\n cycle = path.slice(idx).concat(name);\n return;\n }\n if (visited.has(name)) return;\n visited.add(name);\n recStack.add(name);\n path.push(name);\n\n const mod = registry.modules[name];\n if (mod?.dependsOn) {\n for (const dep of mod.dependsOn) {\n if (registry.modules[dep]) visit(dep);\n }\n }\n if (!installed.has(name)) {\n result.push(name);\n }\n path.pop();\n recStack.delete(name);\n }\n\n visit(moduleName);\n if (cycle !== null) {\n error(`Circular dependency: ${(cycle as string[]).join(\" -> \")}`);\n }\n return result;\n}\n\nconst RAVENJS_PREFIX = \"@raven.js/\";\n\nfunction replaceRavenImports(\n content: string,\n fromModuleDir: string,\n registry: Registry,\n): string {\n const moduleNames = Object.keys(registry.modules);\n let out = content;\n const depth = fromModuleDir.split(\"/\").filter(Boolean).length;\n const prefix = depth > 0 ? \"../\".repeat(depth) : \"./\";\n for (const modName of moduleNames) {\n const pkg = `${RAVENJS_PREFIX}${modName}`;\n const rel = prefix + modName;\n\n const dq = new RegExp(\n `from\\\\s+\"${pkg.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}\"`,\n \"g\",\n );\n const sq = new RegExp(\n `from\\\\s+'${pkg.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}'`,\n \"g\",\n );\n out = out.replace(dq, `from \"${rel}\"`).replace(sq, `from '${rel}'`);\n }\n return out;\n}\n\nconst SOURCE_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\"];\n\nfunction isSourceFile(file: string): boolean {\n return SOURCE_EXTENSIONS.some((ext) => file.endsWith(ext));\n}\n\nasync function installModule(\n registry: Registry,\n moduleName: string,\n destDir: string,\n options?: CLIOptions,\n targetSubdir?: string,\n): Promise<string[]> {\n const module = registry.modules[moduleName];\n if (!module) {\n throw new Error(`Module ${moduleName} not found in registry`);\n }\n\n verboseLog(`Installing ${moduleName} files...`, options);\n\n const embeddedSourceDir = join(__dirname, \"source\");\n const fromModuleDir = targetSubdir ?? moduleName;\n\n const modifiedFiles: string[] = [];\n const copies = module.files.map(async (file: string) => {\n let destPath: string;\n\n if (module.fileMapping?.[file]) {\n destPath = join(destDir, module.fileMapping[file]);\n } else if (targetSubdir) {\n destPath = join(destDir, targetSubdir, file);\n } else {\n destPath = join(destDir, moduleName, file);\n }\n\n verboseLog(` Copying ${file}...`, options);\n\n const srcPath = join(embeddedSourceDir, moduleName, file);\n if (!(await fileExists(srcPath))) {\n throw new Error(`Missing embedded source file: ${srcPath}`);\n }\n\n let content = await readFile(srcPath, \"utf-8\");\n\n if (isSourceFile(file)) {\n content = replaceRavenImports(content, fromModuleDir, registry);\n }\n\n await ensureDir(dirname(destPath));\n await writeFile(destPath, content);\n modifiedFiles.push(destPath);\n });\n\n await Promise.all(copies);\n return modifiedFiles;\n}\n\nasync function cmdInit(options: CLIOptions) {\n const registry = await loadRegistry(options);\n const targetDir = cwd();\n const root = getRoot(options);\n const ravenDir = join(targetDir, root);\n\n verboseLog(`Initializing RavenJS in ${targetDir}`, options);\n\n const version = registry.version;\n const modifiedFiles: string[] = [];\n\n const ravenRootExists = await pathExists(ravenDir);\n const ravenYamlPath = join(ravenDir, \"raven.yaml\");\n const ravenYamlExists = await pathExists(ravenYamlPath);\n\n const doInit = async () => {\n if (!ravenRootExists || !ravenYamlExists) {\n await ensureDir(ravenDir);\n await createRavenYaml(ravenDir, version);\n modifiedFiles.push(ravenYamlPath);\n }\n };\n\n if (options?.verbose) {\n await doInit();\n } else {\n const s = makeSpinner();\n s.start(\"Initializing raven root...\");\n try {\n await doInit();\n } catch (e: any) {\n s.stop(\"Initialization failed\");\n error(e.message);\n }\n s.stop(\"Initializing raven root...\");\n }\n\n success(\"RavenJS raven root initialized. Install AI skills with: install-raven (or npx install-raven).\");\n\n printSectionHeader(\"Modified Files\");\n for (const file of modifiedFiles) {\n printListItem(file);\n }\n\n printSectionHeader(\"Status\");\n const status = await getStatus(registry, options);\n console.log(JSON.stringify(status));\n}\n\ninterface RavenYamlConfig {\n version: string;\n}\n\nasync function createRavenYaml(destDir: string, version: string) {\n const content = stringify({ version });\n await writeFile(join(destDir, \"raven.yaml\"), content);\n}\n\nasync function getInstalledModules(\n ravenDir: string,\n registry: Registry,\n): Promise<Set<string>> {\n const installed = new Set<string>();\n for (const name of getModuleNames(registry)) {\n const modDir = join(ravenDir, name);\n if ((await pathExists(modDir)) && !(await isDirEmpty(modDir))) {\n installed.add(name);\n }\n }\n return installed;\n}\n\nasync function cmdAdd(moduleName: string, options: CLIOptions) {\n const registry = await loadRegistry(options);\n if (!moduleName) {\n error(\n `Please specify a module to add. Available: ${getModuleNames(registry).join(\", \")}`,\n );\n }\n\n const available = getModuleNames(registry);\n\n if (!available.includes(moduleName)) {\n error(`Unknown module: ${moduleName}`);\n }\n\n const { ravenDir } = await ensureRavenInstalled(options);\n\n const installed = await getInstalledModules(ravenDir, registry);\n const order = getInstallOrder(moduleName, registry, installed);\n\n try {\n const modifiedFiles: string[] = [];\n const allDependencies: Record<string, string> = {};\n for (const name of order) {\n const files = await installModule(\n registry,\n name,\n ravenDir,\n options,\n );\n modifiedFiles.push(...files);\n const mod = registry.modules[name];\n if (mod?.dependencies) {\n Object.assign(allDependencies, mod.dependencies);\n }\n }\n\n // Two JSON lines for Agent: add result + status in one call to save tokens.\n console.log(\n JSON.stringify({\n success: true,\n moduleName,\n modifiedFiles,\n dependencies: allDependencies,\n }),\n );\n const status = await getStatus(registry, options);\n console.log(JSON.stringify(status));\n } catch (e: any) {\n error(e.message);\n }\n}\n\n// === SECTION: Status ===\n\ninterface ModuleInfo {\n name: string;\n description?: string;\n installed: boolean;\n /** 模块目录的绝对路径 */\n installDir?: string;\n}\n\ninterface StatusResult {\n modules: ModuleInfo[];\n version?: string;\n modifiedFiles?: string[];\n fileHashes?: Record<string, string>;\n}\n\nasync function computeFileHash(filePath: string): Promise<string> {\n const content = await readFile(filePath);\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\nasync function getStatus(\n registry: Registry,\n options: CLIOptions,\n): Promise<StatusResult> {\n const targetDir = cwd();\n const root = getRoot(options);\n const ravenDir = join(targetDir, root);\n\n let currentVersion: string | undefined;\n const modifiedFiles: string[] = [];\n const fileHashes: Record<string, string> = {};\n\n const knownModules = getModuleNames(registry).sort();\n const moduleStatus: ModuleInfo[] = [];\n\n if (await pathExists(ravenDir)) {\n const yamlPath = join(ravenDir, \"raven.yaml\");\n try {\n const content = await readFile(yamlPath, \"utf-8\");\n const config = parse(content) as RavenYamlConfig;\n if (config?.version) {\n currentVersion = config.version;\n }\n } catch (_e) {\n // raven.yaml missing or invalid\n }\n\n for (const name of knownModules) {\n const modDir = join(ravenDir, name);\n const installed =\n (await pathExists(modDir)) && !(await isDirEmpty(modDir));\n const mod = registry.modules[name];\n moduleStatus.push({\n name,\n description: mod?.description,\n installed,\n installDir: resolve(modDir),\n });\n }\n\n // Compute file hashes for all files in raven/\n async function traverseDir(dir: string, baseDir: string) {\n const dirEntries = await readdir(dir, { withFileTypes: true });\n for (const e of dirEntries) {\n const fullPath = join(dir, e.name);\n const relPath = fullPath.slice(baseDir.length + 1);\n if (e.isDirectory()) {\n await traverseDir(fullPath, baseDir);\n } else {\n const hash = await computeFileHash(fullPath);\n fileHashes[relPath] = hash;\n }\n }\n }\n await traverseDir(ravenDir, ravenDir);\n }\n\n if (moduleStatus.length === 0) {\n for (const name of knownModules) {\n const mod = registry.modules[name];\n const modDir = join(ravenDir, name);\n moduleStatus.push({\n name,\n description: mod?.description,\n installed: false,\n installDir: resolve(modDir),\n });\n }\n }\n\n return {\n modules: moduleStatus,\n version: currentVersion,\n modifiedFiles,\n fileHashes,\n };\n}\n\ninterface StatusCLIOptions extends CLIOptions {}\n\nasync function cmdStatus(options: StatusCLIOptions) {\n const registry = await loadRegistry(options);\n const status = await getStatus(registry, options);\n console.log(JSON.stringify(status));\n}\n\nconst program = new Command(\"raven\");\nprogram.version(loadCliVersion());\n\nprogram\n .option(\"--registry <path>\", \"Registry json path (default: same dir as CLI)\")\n .option(\"--root <dir>\", \"RavenJS root directory (default: raven)\")\n .option(\"-v, --verbose\", \"Verbose output\");\n\nprogram\n .command(\"init\")\n .description(\"Initialize raven root (directory and raven.yaml). Install AI skills with install-raven.\")\n .action(() => cmdInit(program.opts() as CLIOptions));\n\nprogram\n .command(\"add <module>\")\n .description(\"Add a module (e.g., core)\")\n .action((module: string) => cmdAdd(module, program.opts() as CLIOptions));\n\nprogram\n .command(\"status\")\n .description(\"Show RavenJS installation status (core, modules)\")\n .action(() => cmdStatus(program.opts() as StatusCLIOptions));\n\nprogram.parse();\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "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",
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "18CE5936F1B83A4764756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/registry.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.2.0",
|
|
3
3
|
"modules": {
|
|
4
4
|
"sql": {
|
|
5
5
|
"files": [
|
|
@@ -38,13 +38,5 @@
|
|
|
38
38
|
"dependsOn": [],
|
|
39
39
|
"description": "RavenJS core framework providing HTTP services, routing, hooks, and state management. Designed for building web services and handling request/response cycles."
|
|
40
40
|
}
|
|
41
|
-
},
|
|
42
|
-
"ai": {
|
|
43
|
-
"claude": {
|
|
44
|
-
"raven-add/skill.md": ".claude/skills/raven-add/SKILL.md",
|
|
45
|
-
"raven-learn/skill.md": ".claude/skills/raven-learn/SKILL.md",
|
|
46
|
-
"raven-setup/skill.md": ".claude/skills/raven-setup/SKILL.md",
|
|
47
|
-
"raven-use/skill.md": ".claude/skills/raven-use/SKILL.md"
|
|
48
|
-
}
|
|
49
41
|
}
|
|
50
42
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# REQUIRED READING
|
|
2
|
+
|
|
3
|
+
To understand the architecture, concepts, API, and usage, read:
|
|
4
|
+
|
|
5
|
+
- [README.md](./README.md)
|
|
6
|
+
- [index.ts](./index.ts)
|
|
7
|
+
|
|
8
|
+
# OPTIONAL READING
|
|
9
|
+
|
|
10
|
+
| Document | Read when… |
|
|
11
|
+
|----------|------------|
|
|
12
|
+
| [PLUGIN.md](./PLUGIN.md) | You are creating a plugin — covers `definePlugin`, all three state patterns, and plugin-specific gotchas. |
|
|
13
|
+
| [router.ts](./router.ts) | You need to understand or extend route matching (Radix tree, path params, wildcards). |
|
|
14
|
+
| [standard-schema.ts](./standard-schema.ts) | You need to integrate validation (Zod, Valibot) or implement Standard Schema–compatible validation. |
|