@kurajs/cli 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.
Files changed (3) hide show
  1. package/README.md +24 -0
  2. package/dist/cli.js +91 -0
  3. package/package.json +42 -0
package/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # @kurajs/cli
2
+
3
+ The `kura` command-line tool.
4
+
5
+ ```sh
6
+ kura index [--out app/_index.bin] [--model Xenova/bge-m3]
7
+ ```
8
+
9
+ **`kura index`** builds the search index for a Kura docs app: it reads the June-frozen
10
+ `app/_content.ts`, embeds every doc with bge-m3 (local, via `@kurajs/transformers`), and
11
+ writes a compact index (`app/_index.bin`) that the app loads at runtime — so search never
12
+ embeds the corpus on the request thread.
13
+
14
+ Typical use in a docs app's `package.json`:
15
+
16
+ ```json
17
+ { "scripts": { "gen": "june gen && kura index", "build": "june build && kura index" } }
18
+ ```
19
+
20
+ Run `june gen` first (it generates `app/_content.ts`), then `kura index`.
21
+
22
+ ## License
23
+
24
+ MIT
package/dist/cli.js ADDED
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env node
2
+ // Kura CLI.
3
+ // kura index [--out app/_index.bin] [--model Xenova/bge-m3]
4
+ // Build the search index for the current Kura docs app: embed every doc from the
5
+ // June-frozen app/_content.ts and write a compact index the app loads at runtime.
6
+ import { buildIndex } from "@kurajs/docs/search";
7
+ import { transformers } from "@kurajs/transformers";
8
+ import fs from "node:fs";
9
+ import path from "node:path";
10
+ import { pathToFileURL } from "node:url";
11
+ function arg(name, def) {
12
+ const i = process.argv.indexOf(`--${name}`);
13
+ return i >= 0 ? process.argv[i + 1] : def;
14
+ }
15
+ async function cmdIndex() {
16
+ const cwd = process.cwd();
17
+ const contentPath = path.join(cwd, "app", "_content.ts");
18
+ if (!fs.existsSync(contentPath)) {
19
+ console.error("kura index: app/_content.ts not found — run `june gen` first (in a Kura docs app).");
20
+ process.exit(1);
21
+ }
22
+ const out = arg("out", path.join("app", "_index.bin"));
23
+ const model = arg("model", "Xenova/bge-m3");
24
+ const mod = (await import(pathToFileURL(contentPath).href));
25
+ const DOCS = mod.DOCS ?? [];
26
+ if (!DOCS.length) {
27
+ console.error("kura index: no docs found in app/_content.ts");
28
+ process.exit(1);
29
+ }
30
+ // Discover locales from content/<col>/<locale>/ subdirs, then collect each locale's actual
31
+ // variants (entry.locale === locale; fallbacks stay in the default set). Both the search
32
+ // index and the MDX precompile cover default + every variant → cross-lingual by construction.
33
+ const LOCALE_DIR = /^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$/;
34
+ const contentRoot = path.join(cwd, "content");
35
+ const locales = new Set();
36
+ if (mod.docs && fs.existsSync(contentRoot)) {
37
+ for (const col of fs.readdirSync(contentRoot, { withFileTypes: true })) {
38
+ if (!col.isDirectory())
39
+ continue;
40
+ for (const sub of fs.readdirSync(path.join(contentRoot, col.name), { withFileTypes: true })) {
41
+ if (sub.isDirectory() && LOCALE_DIR.test(sub.name))
42
+ locales.add(sub.name);
43
+ }
44
+ }
45
+ }
46
+ const variants = [];
47
+ for (const locale of locales)
48
+ for (const e of mod.docs(locale))
49
+ if (e.locale === locale)
50
+ variants.push(e);
51
+ const allEntries = [...DOCS, ...variants];
52
+ const localeTag = locales.size ? ` (+${variants.length} variants across ${locales.size} locales)` : "";
53
+ console.log(`kura index: embedding ${DOCS.length} docs${localeTag} (model ${model})…`);
54
+ const t0 = Date.now();
55
+ const bytes = await buildIndex({ entries: allEntries, embedder: transformers({ model }) });
56
+ fs.mkdirSync(path.dirname(out), { recursive: true });
57
+ fs.writeFileSync(out, bytes);
58
+ console.log(`kura index: wrote ${out} (${(fs.statSync(out).size / 1024).toFixed(0)}KB) in ${((Date.now() - t0) / 1000).toFixed(1)}s`);
59
+ // Precompile MDX -> static HTML with curated components (build-time; Workers-safe at
60
+ // runtime). Bucketed by locale: "default" for the flat (default-locale) files, plus one
61
+ // bucket per variant locale. The app picks the bucket per entry.
62
+ const { mdxToHtml } = await import("@kurajs/docs/mdx");
63
+ const mdxOut = path.join(cwd, "app", "_mdx.json");
64
+ const map = { default: {} };
65
+ let ok = 0;
66
+ const render = async (bucket, e) => {
67
+ try {
68
+ (map[bucket] ??= {})[e.slug] = await mdxToHtml(e.body);
69
+ ok++;
70
+ }
71
+ catch {
72
+ /* leave out → the app falls back to the plain markdown html */
73
+ }
74
+ };
75
+ for (const d of DOCS)
76
+ await render("default", d);
77
+ for (const e of variants)
78
+ await render(e.locale, e);
79
+ fs.writeFileSync(mdxOut, JSON.stringify(map));
80
+ const total = Object.values(map).reduce((n, b) => n + Object.keys(b).length, 0);
81
+ const tag = locales.size ? ` across ${locales.size + 1} locales` : "";
82
+ console.log(`kura index: rendered ${ok}/${total} docs via MDX${tag} -> ${path.relative(cwd, mdxOut)}`);
83
+ }
84
+ const cmd = process.argv[2];
85
+ if (cmd === "index") {
86
+ await cmdIndex();
87
+ }
88
+ else {
89
+ console.log("Kura CLI\n kura index [--out app/_index.bin] [--model <hf-model>] build the docs search index");
90
+ process.exit(cmd ? 1 : 0);
91
+ }
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@kurajs/cli",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "description": "Kura CLI — build the docs search index (kura index).",
6
+ "bin": {
7
+ "kura": "dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc -p tsconfig.json"
14
+ },
15
+ "license": "MIT",
16
+ "dependencies": {
17
+ "@kurajs/core": "^0.0.1",
18
+ "@kurajs/docs": "^0.0.1",
19
+ "@kurajs/transformers": "^0.0.1"
20
+ },
21
+ "peerDependencies": {
22
+ "@huggingface/transformers": ">=3"
23
+ },
24
+ "devDependencies": {
25
+ "@huggingface/transformers": "3.8.1",
26
+ "typescript": "^5.7.0"
27
+ },
28
+ "author": "Yi-Ru Lin",
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "homepage": "https://kura.build",
33
+ "keywords": [
34
+ "kura",
35
+ "june",
36
+ "cli",
37
+ "docs",
38
+ "search",
39
+ "index",
40
+ "mcp"
41
+ ]
42
+ }