diffwiki 0.5.0 → 0.6.0-rc.202607240049.586dcb6

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 (2) hide show
  1. package/dist/bin.js +80 -15
  2. package/package.json +2 -2
package/dist/bin.js CHANGED
@@ -3,14 +3,16 @@
3
3
  // src/cli.ts
4
4
  import { Command } from "commander";
5
5
  import {
6
+ addExternalCollection,
6
7
  addTags,
8
+ collectionGitStatus,
7
9
  createArticle,
8
10
  createCollection,
9
11
  doctor,
10
12
  getConfigValue,
11
13
  initRepoWiki,
12
14
  installPlugin,
13
- listCollections,
15
+ listCollections as listCollections2,
14
16
  listAvailablePlugins,
15
17
  listPlugins,
16
18
  listSearchModes,
@@ -20,6 +22,7 @@ import {
20
22
  removeArticle,
21
23
  removePlugin,
22
24
  removeTags,
25
+ resolveCwdCollection,
23
26
  setConfigValue,
24
27
  setTags,
25
28
  updateArticleBody
@@ -150,6 +153,44 @@ async function stopUi() {
150
153
  return state;
151
154
  }
152
155
 
156
+ // src/exporter.ts
157
+ import { spawn as spawn2 } from "child_process";
158
+ import fs2 from "fs";
159
+ import path2 from "path";
160
+ import { fileURLToPath as fileURLToPath2 } from "url";
161
+ import { listCollections, resolveCollectionSelection, InvalidExportSelectionError } from "diffwiki-core";
162
+ var splitGlobs = (v) => (v ?? "").split(",").map((s) => s.trim()).filter(Boolean);
163
+ function localAppExporter() {
164
+ const candidates = [
165
+ path2.resolve(path2.dirname(fileURLToPath2(import.meta.url)), "../../../apps/wiki/bin/export.mjs"),
166
+ path2.resolve(process.cwd(), "apps/wiki/bin/export.mjs")
167
+ ];
168
+ return candidates.find((p) => fs2.existsSync(p));
169
+ }
170
+ async function runExport(opts) {
171
+ const out = path2.resolve(opts.out);
172
+ const filter = splitGlobs(opts.filter);
173
+ const exclude = splitGlobs(opts.exclude);
174
+ if (filter.length > 0 || exclude.length > 0) {
175
+ const names = (await listCollections()).map((c) => c.name);
176
+ const { errors } = resolveCollectionSelection(names, { filter, exclude });
177
+ if (errors.length > 0) throw new InvalidExportSelectionError(errors);
178
+ }
179
+ const local = localAppExporter();
180
+ const override = process.env.DIFFWIKI_APP_CMD ?? (local ? `node ${local}` : void 0);
181
+ const [cmd, ...prefix] = override ? override.split(" ") : ["npx", "-y", "diffwiki-app@latest"];
182
+ const args = [...prefix, "export", "--out", out, "--base", opts.base];
183
+ if (opts.filter) args.push("--filter", opts.filter);
184
+ if (opts.exclude) args.push("--exclude", opts.exclude);
185
+ if (override) console.log(`Exporting via ${override}`);
186
+ await new Promise((resolve, reject) => {
187
+ const child = spawn2(cmd, args, { stdio: "inherit", env: process.env });
188
+ child.on("error", reject);
189
+ child.on("close", (code) => code === 0 ? resolve() : reject(new Error(`export failed (exit ${code})`)));
190
+ });
191
+ console.log(`Static site written to ${out}`);
192
+ }
193
+
153
194
  // src/cli.ts
154
195
  var icon = (level) => level === "ok" ? "\u2713" : level === "warn" ? "!" : "\u2716";
155
196
  function createProgram() {
@@ -160,23 +201,34 @@ function createProgram() {
160
201
  });
161
202
  program.command("list").description("List all collections").action(
162
203
  withErrors(async () => {
163
- const collections = await listCollections();
204
+ const collections = await listCollections2();
164
205
  if (collections.length === 0) {
165
206
  console.log("No collections yet. Create one with: diffwiki create <name>");
166
207
  return;
167
208
  }
168
209
  for (const c of collections) {
169
- console.log(`${c.name} [${c.type}] ${c.path}`);
210
+ const status = await collectionGitStatus(c);
211
+ const branch = status?.branch ? ` (${status.branch})` : "";
212
+ console.log(`${c.name} [${c.type}] ${c.path}${branch}`);
170
213
  }
171
214
  })
172
215
  );
216
+ program.command("add").description("Add the current git repo as an external collection (docs dir, no diffwiki.yaml)").option("-d, --docs <dir>", "content dir relative to repo root", "docs").action(
217
+ withErrors(async (opts) => {
218
+ const entry = await addExternalCollection({ cwd: process.cwd(), docsDir: opts.docs });
219
+ const status = await collectionGitStatus(entry);
220
+ const branch = status?.branch ? ` (${status.branch})` : "";
221
+ console.log(`Added "${entry.name}"${branch} \u2192 ${entry.path}`);
222
+ console.log("Registered globally \u2014 discoverable via: diffwiki list");
223
+ })
224
+ );
173
225
  program.command("create").description("Create a new global collection").argument("<name>", "collection name").action(
174
226
  withErrors(async (name) => {
175
227
  const entry = await createCollection(name);
176
228
  console.log(`Created collection "${entry.name}" at ${entry.path}`);
177
229
  })
178
230
  );
179
- program.command("add").description("Add an article to a collection").requiredOption("-p, --path <target>", '"[collection:]title"').option("-t, --tag <tag>", "tag (repeatable, comma-separated)", collect, []).argument("[body]", "markdown body").action(
231
+ program.command("add-article").description("Add an article to a collection").requiredOption("-p, --path <target>", '"[collection:]title"').option("-t, --tag <tag>", "tag (repeatable, comma-separated)", collect, []).argument("[body]", "markdown body").action(
180
232
  withErrors(async (body, opts) => {
181
233
  const article = await createArticle({
182
234
  target: opts.path,
@@ -186,13 +238,13 @@ function createProgram() {
186
238
  console.log(article.path);
187
239
  })
188
240
  );
189
- program.command("update").description("Replace an article's body").requiredOption("-p, --path <target>", '"collection:path"').argument("<body>", "new markdown body").action(
241
+ program.command("update-article").description("Replace an article's body").requiredOption("-p, --path <target>", '"collection:path"').argument("<body>", "new markdown body").action(
190
242
  withErrors(async (body, opts) => {
191
243
  const article = await updateArticleBody(opts.path, body);
192
244
  console.log(`Updated ${article.path}`);
193
245
  })
194
246
  );
195
- program.command("remove").description("Delete an article").requiredOption("-p, --path <target>", '"collection:path"').action(
247
+ program.command("remove-article").description("Delete an article").requiredOption("-p, --path <target>", '"collection:path"').action(
196
248
  withErrors(async (opts) => {
197
249
  const removed = await removeArticle(opts.path);
198
250
  console.log(`Removed ${removed}`);
@@ -219,7 +271,7 @@ function createProgram() {
219
271
  );
220
272
  return;
221
273
  }
222
- const indexed = await provider.reindex(await listCollections(), { embed: !!opts.embed });
274
+ const indexed = await provider.reindex(await listCollections2(), { embed: !!opts.embed });
223
275
  console.log(`Indexed ${indexed} document(s).`);
224
276
  })
225
277
  );
@@ -240,10 +292,11 @@ function createProgram() {
240
292
  })
241
293
  );
242
294
  const plugin = program.command("plugin").description("Manage search plugins");
243
- plugin.command("install").description("Install a search plugin from an npm spec and provision it (setup)").argument("<spec>", "npm package spec (name, name@version, or path)").option("--no-setup", "skip the end-to-end setup after install").option("--prefetch-models", "pre-download models during setup (heavy)").action(
295
+ plugin.command("install").description("Install a search plugin from an npm spec and provision it (setup)").argument("<spec>", "npm package spec (name, name@version, or path)").option("--no-setup", "skip the end-to-end setup after install").option("--no-default", "do not make this the default search engine").option("--prefetch-models", "pre-download models during setup (heavy)").action(
244
296
  withErrors(async (spec, opts) => {
245
- const { record, setup } = await installPlugin(spec, {
297
+ const { record, setup, defaulted } = await installPlugin(spec, {
246
298
  setup: opts.setup,
299
+ setDefault: opts.default,
247
300
  prefetchModels: opts.prefetchModels
248
301
  });
249
302
  console.log(`Installed "${record.name}"${record.version ? ` v${record.version}` : ""}`);
@@ -254,6 +307,11 @@ function createProgram() {
254
307
  console.log(`\u26A0 Not ready: ${reason}`);
255
308
  console.log(" \u2192 run: diffwiki doctor");
256
309
  }
310
+ if (defaulted) {
311
+ console.log(
312
+ `Set "${record.name}" as the default search engine (change: diffwiki config-set defaultSearch <engine[:type]>)`
313
+ );
314
+ }
257
315
  })
258
316
  );
259
317
  plugin.command("register").description("Register an existing executable as a search plugin").argument("<name>", "plugin name").requiredOption("--command <cmd...>", "command argv to spawn the plugin (e.g. node /abs/adapter.js)").action(
@@ -303,6 +361,11 @@ function createProgram() {
303
361
  console.log("Registered globally \u2014 discoverable via: diffwiki list");
304
362
  })
305
363
  );
364
+ program.command("export").description("Generate a static site (deployable to GitHub Pages)").requiredOption("-o, --out <dir>", "output directory").option("-b, --base <path>", "base URL path (e.g. /my-repo/ for GitHub Pages)", "/").option("-f, --filter <globs>", "only export collections matching these globs (comma-separated)").option("-e, --exclude <globs>", "exclude collections matching these globs (comma-separated)").action(
365
+ withErrors(async (opts) => {
366
+ await runExport({ out: opts.out, base: opts.base, filter: opts.filter, exclude: opts.exclude });
367
+ })
368
+ );
306
369
  program.command("config-set").description("Set a config value (e.g. defaultCollection, or defaultSearch <engine[:type]>)").argument("<key>", "config key").argument("<value>", "config value").action(
307
370
  withErrors(async (key, value) => {
308
371
  await setConfigValue(key, value);
@@ -363,8 +426,10 @@ function createProgram() {
363
426
  state = await startUi(Number(opts.port));
364
427
  await waitForServer(state.url);
365
428
  }
366
- openBrowser(state.url);
367
- console.log(`Opening ${state.url}`);
429
+ const coll = await resolveCwdCollection(process.cwd());
430
+ const target = coll ? `${state.url}/${encodeURIComponent(coll.name)}` : state.url;
431
+ openBrowser(target);
432
+ console.log(`Opening ${target}`);
368
433
  })
369
434
  );
370
435
  return program;
@@ -373,14 +438,14 @@ function createProgram() {
373
438
  // src/logging.ts
374
439
  import { mkdirSync } from "fs";
375
440
  import os from "os";
376
- import path2 from "path";
441
+ import path3 from "path";
377
442
  import { configureSync, getConfig } from "@logtape/logtape";
378
443
  import { getRotatingFileSink } from "@logtape/file";
379
444
  import { resolveLogLevel } from "diffwiki-core";
380
445
  var configured = false;
381
446
  function diffwikiHome() {
382
447
  const override = process.env.DIFFWIKI_HOME;
383
- return override && override.length > 0 ? override : path2.join(os.homedir(), ".diffwiki");
448
+ return override && override.length > 0 ? override : path3.join(os.homedir(), ".diffwiki");
384
449
  }
385
450
  function resolveCliLevel(argv) {
386
451
  if (argv.includes("-v") || argv.includes("--verbose")) return "debug";
@@ -397,9 +462,9 @@ function configureCliLogging(argv = process.argv) {
397
462
  if (configured || getConfig() != null) return;
398
463
  configured = true;
399
464
  const level = resolveCliLevel(argv);
400
- const logsDir = path2.join(diffwikiHome(), "logs");
465
+ const logsDir = path3.join(diffwikiHome(), "logs");
401
466
  mkdirSync(logsDir, { recursive: true });
402
- const logFile = path2.join(logsDir, "diffwiki.log");
467
+ const logFile = path3.join(logsDir, "diffwiki.log");
403
468
  const stderrSink = (record) => {
404
469
  process.stderr.write(formatLine(record) + "\n");
405
470
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "diffwiki",
3
- "version": "0.5.0",
3
+ "version": "0.6.0-rc.202607240049.586dcb6",
4
4
  "description": "diffwiki command-line interface",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -17,7 +17,7 @@
17
17
  "@logtape/logtape": "^2.2.4",
18
18
  "@logtape/file": "^2.2.4",
19
19
  "commander": "^13.0.0",
20
- "diffwiki-core": "0.5.0"
20
+ "diffwiki-core": "0.6.0-rc.202607240049.586dcb6"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@types/node": "^22.0.0"