@bitcobblers/wod-wiki-engine 0.35.2128 → 0.36.2130

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 (74) hide show
  1. package/dist/bin/wod.cjs +758 -194
  2. package/dist/bin/wod.cjs.map +1 -1
  3. package/dist/bin/wod.d.cts +1 -1
  4. package/dist/bin/wod.d.ts +1 -1
  5. package/dist/bin/wod.mjs +5 -3
  6. package/dist/bin/wod.mjs.map +1 -1
  7. package/dist/chunk-6L5ZDZJ7.mjs +15 -0
  8. package/dist/chunk-6L5ZDZJ7.mjs.map +1 -0
  9. package/dist/{chunk-Y6WO6MXS.mjs → chunk-BMHE7DDG.mjs} +3 -9
  10. package/dist/chunk-BMHE7DDG.mjs.map +1 -0
  11. package/dist/chunk-EUQWEX6Z.mjs +253 -0
  12. package/dist/chunk-EUQWEX6Z.mjs.map +1 -0
  13. package/dist/{chunk-N4KFWY6Z.mjs → chunk-UKBQ36RW.mjs} +377 -193
  14. package/dist/chunk-UKBQ36RW.mjs.map +1 -0
  15. package/dist/{compiler-SXUCF7AU.mjs → compiler-NODHKWJJ.mjs} +4 -3
  16. package/dist/compiler-NODHKWJJ.mjs.map +1 -0
  17. package/dist/index.cjs +763 -199
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.cts +27 -8
  20. package/dist/index.d.ts +27 -8
  21. package/dist/index.mjs +10 -8
  22. package/dist/index.mjs.map +1 -1
  23. package/dist/server/app.cjs +299 -0
  24. package/dist/server/app.cjs.map +1 -0
  25. package/dist/server/app.d.cts +24 -0
  26. package/dist/server/app.d.ts +24 -0
  27. package/dist/server/app.mjs +301 -0
  28. package/dist/server/app.mjs.map +1 -0
  29. package/dist/server-4P6AJAGT.mjs +128 -0
  30. package/dist/server-4P6AJAGT.mjs.map +1 -0
  31. package/dist/web/playground/ai-skills/parse.md +656 -0
  32. package/dist/web/playground/assets/main-Bhn9NHgQ.css +2 -0
  33. package/dist/web/playground/assets/main-CGSJY1vM.js +212 -0
  34. package/dist/web/playground/assets/rolldown-runtime-C0FnF6B9.js +1 -0
  35. package/dist/web/playground/assets/statementBuilderFlow-PTgOOzz5.js +2 -0
  36. package/dist/web/playground/assets/vendor-BlJqgFME.js +201 -0
  37. package/dist/web/playground/assets/vendor-codemirror-BtJgoBjf.js +40 -0
  38. package/dist/web/playground/fonts/Inter-Regular.woff2 +0 -0
  39. package/dist/web/playground/fonts/Inter-SemiBold.woff2 +0 -0
  40. package/dist/web/playground/images/hero/editing.png +0 -0
  41. package/dist/web/playground/images/hero/journal.png +0 -0
  42. package/dist/web/playground/images/hero/results.png +0 -0
  43. package/dist/web/playground/images/hero/timer.png +0 -0
  44. package/dist/web/playground/images/wod-wiki-logo-dark.png +0 -0
  45. package/dist/web/playground/images/wod-wiki-logo-light.png +0 -0
  46. package/dist/web/playground/index.html +60 -0
  47. package/dist/web/playground/seed/core/chunks/canvas.e6c77ad0.json +1 -0
  48. package/dist/web/playground/seed/core/chunks/template.e5e0e82d.json +1 -0
  49. package/dist/web/playground/seed/core/manifest.json +24 -0
  50. package/dist/web/playground/seed/core/report.html +43 -0
  51. package/dist/web/server/ai-skills/parse.md +656 -0
  52. package/dist/web/server/assets/main-Bhn9NHgQ.css +2 -0
  53. package/dist/web/server/assets/main-DhN2J5Ax.js +211 -0
  54. package/dist/web/server/assets/rolldown-runtime-C0FnF6B9.js +1 -0
  55. package/dist/web/server/assets/statementBuilderFlow-Dj0o2Wpk.js +2 -0
  56. package/dist/web/server/assets/vendor-BlJqgFME.js +201 -0
  57. package/dist/web/server/assets/vendor-codemirror-BtJgoBjf.js +40 -0
  58. package/dist/web/server/fonts/Inter-Regular.woff2 +0 -0
  59. package/dist/web/server/fonts/Inter-SemiBold.woff2 +0 -0
  60. package/dist/web/server/images/hero/editing.png +0 -0
  61. package/dist/web/server/images/hero/journal.png +0 -0
  62. package/dist/web/server/images/hero/results.png +0 -0
  63. package/dist/web/server/images/hero/timer.png +0 -0
  64. package/dist/web/server/images/wod-wiki-logo-dark.png +0 -0
  65. package/dist/web/server/images/wod-wiki-logo-light.png +0 -0
  66. package/dist/web/server/index.html +60 -0
  67. package/dist/web/server/seed/core/chunks/canvas.e6c77ad0.json +1 -0
  68. package/dist/web/server/seed/core/chunks/template.e5e0e82d.json +1 -0
  69. package/dist/web/server/seed/core/manifest.json +24 -0
  70. package/dist/web/server/seed/core/report.html +43 -0
  71. package/package.json +11 -5
  72. package/dist/chunk-N4KFWY6Z.mjs.map +0 -1
  73. package/dist/chunk-Y6WO6MXS.mjs.map +0 -1
  74. package/dist/compiler-SXUCF7AU.mjs.map +0 -1
@@ -1,5 +1,7 @@
1
1
  import { createRequire } from 'module';
2
- import { SEED_SCHEMA, SEED_REGISTERED_WIDGETS, seedNoteSourceId, catalogForChunkId, DASHBOARDS_CHUNK_ID, EFFORTS_CHUNK_ID, parseEffortFile, __require, seedMetaKey, emptySeedMeta, CANVAS_CHUNK_ID } from './chunk-Y6WO6MXS.mjs';
2
+ import { SEED_SCHEMA, SEED_REGISTERED_WIDGETS, seedNoteSourceId, catalogForChunkId, DASHBOARDS_CHUNK_ID, EFFORTS_CHUNK_ID, parseEffortFile, seedMetaKey, emptySeedMeta, CANVAS_CHUNK_ID } from './chunk-BMHE7DDG.mjs';
3
+ import { openCliDb, nodeFs, sqliteIndexStore, sqliteEffortStore, sqliteBlockStore, sqliteNoteStore, sqliteEventStore, getNoteBundle, getSessionBundle, getEffortBySlug, listTagsByType, nodePath, loadSql, uuid5, CLI_UUID_NAMESPACE, stableNoteId, randomId } from './chunk-EUQWEX6Z.mjs';
4
+ import { __require } from './chunk-6L5ZDZJ7.mjs';
3
5
  import { dialectRegistry, realtimeProcessorRegistry, summaryProcessorRegistry, getHints, createParser, toStoredOutputStatement, frozenNow, createCompiler, createMockClock, RuntimeStack, EventBus, ScriptRuntime, createAnalyticsEngineForBlock, StartSessionAction, NextEvent, bundledEfforts, parseScript } from '@bitcobblers/wod-wiki-lang';
4
6
  import { MetricType, validateNoteBlocks, parseDocumentSections, blockContentId, reconcileNoteBlocks, mapNoteBlockChanges, KNOWN_SECTION_WIDGETS } from '@bitcobblers/wod-wiki-core';
5
7
  import { WQL_TYPED_TAG_KEYS, toEventRows, toSummaryEventRows, parseQuery, QueryService, isPipelineQuery, isFindQuery } from '@bitcobblers/wod-wiki-wql';
@@ -360,7 +362,7 @@ function loadQueryData(options) {
360
362
  } else if (obj.facts || obj.results || obj.notes || obj.blocks || obj.efforts || obj.tags || obj.logs) {
361
363
  const corpus = payload;
362
364
  if (corpus.facts) data.facts = corpus.facts;
363
- if (corpus.results) data.results = corpus.results;
365
+ if (Array.isArray(corpus.results)) data.results = corpus.results;
364
366
  if (corpus.notes) data.notes = corpus.notes;
365
367
  if (corpus.blocks) data.blocks = corpus.blocks;
366
368
  if (corpus.efforts) data.efforts = corpus.efforts;
@@ -1580,192 +1582,249 @@ ${escapeCsvField2(data.parsed.metric)},${data.scalar},${escapeCsvField2(data.uni
1580
1582
  }
1581
1583
  return lines.join("\n");
1582
1584
  }
1583
- var nodePath = () => nodeRequire()("node:path");
1584
- var nodeFs = () => nodeRequire()("node:fs");
1585
- var nodeCrypto = () => nodeRequire()("node:crypto");
1585
+
1586
+ // src/cli/config.ts
1586
1587
  function nodeRequire() {
1587
1588
  const g = globalThis;
1588
1589
  if (typeof g.process?.versions?.node === "undefined" && typeof g.Bun === "undefined") {
1589
- throw new Error("SQLite operations are only supported in Node / Bun environments");
1590
+ throw new Error("database configuration is only supported in Node / Bun environments");
1590
1591
  }
1591
1592
  const req = g.require ?? (typeof __require === "function" ? __require : void 0);
1592
- if (!req) throw new Error("SQLite operations require a CJS require shim (missing tsup banner?)");
1593
+ if (!req) throw new Error("database configuration requires a CJS require shim (missing tsup banner?)");
1593
1594
  return req;
1594
1595
  }
1595
- var sqlModulePromise;
1596
- function loadSql() {
1597
- sqlModulePromise ??= import(
1598
- /* @vite-ignore */
1599
- '@bitcobblers/wod-wiki-storage/sql'
1600
- );
1601
- return sqlModulePromise;
1602
- }
1603
- function resolveDbPath(dbPath) {
1604
- const chosen = dbPath ?? process.env.WOD_WIKI_DB ?? "./wodwiki.db";
1605
- return nodePath().resolve(process.cwd(), chosen);
1606
- }
1607
- async function openCliDb(dbPath) {
1608
- const [{ createClient }, sql] = await Promise.all([
1609
- import(
1610
- /* @vite-ignore */
1611
- '@libsql/client'
1612
- ),
1613
- loadSql()
1614
- ]);
1615
- const resolved = resolveDbPath(dbPath);
1616
- nodeFs().mkdirSync(nodePath().dirname(resolved), { recursive: true });
1617
- const db = sql.libsqlDatabase(createClient({ url: `file:${resolved}` }));
1596
+ var nodePath2 = () => nodeRequire()("node:path");
1597
+ var nodeFs2 = () => nodeRequire()("node:fs");
1598
+ function parseEnvFile(content) {
1599
+ return nodeRequire()("node:util").parseEnv(content);
1600
+ }
1601
+ function loadCliEnvironment(envFile) {
1602
+ const fs = nodeFs2();
1603
+ const path = nodePath2();
1604
+ let file;
1605
+ if (envFile !== void 0) {
1606
+ file = path.resolve(process.cwd(), envFile);
1607
+ if (!fs.existsSync(file)) throw new Error(`[wod] --env-file: file not found: ${envFile}`);
1608
+ } else {
1609
+ let dir = process.cwd();
1610
+ for (; ; ) {
1611
+ const candidate = path.join(dir, ".env");
1612
+ if (fs.existsSync(candidate)) {
1613
+ file = candidate;
1614
+ break;
1615
+ }
1616
+ const parent = path.dirname(dir);
1617
+ if (parent === dir) break;
1618
+ dir = parent;
1619
+ }
1620
+ }
1621
+ return file !== void 0 ? parseEnvFile(fs.readFileSync(file, "utf-8")) : {};
1622
+ }
1623
+ var SQLITE_URL_SCHEMES = /^(libsql|https?|wss?|file):\/\//;
1624
+ var PG_URL_SCHEMES = /^postgres(ql)?:\/\//;
1625
+ var TURSO_URL_SCHEMES = /^(libsql|https?|wss?):\/\//;
1626
+ var PG_FLAG_KEYS = [
1627
+ "postgresHost",
1628
+ "postgresPort",
1629
+ "postgresUser",
1630
+ "postgresPassword",
1631
+ "postgresDatabase",
1632
+ "postgresSsl"
1633
+ ];
1634
+ var PG_ENV_KEYS = [
1635
+ "POSTGRES_HOST",
1636
+ "POSTGRES_PORT",
1637
+ "POSTGRES_USER",
1638
+ "POSTGRES_PASSWORD",
1639
+ "POSTGRES_DATABASE",
1640
+ "POSTGRES_SSL"
1641
+ ];
1642
+ var isBackend = (v) => v === "sqlite" || v === "postgres" || v === "turso";
1643
+ function setEnv(v) {
1644
+ return v !== void 0 && v.trim() !== "" ? v : void 0;
1645
+ }
1646
+ function fail(message) {
1647
+ throw new Error(`[wod] ${message}`);
1648
+ }
1649
+ function parsePort(v, source) {
1650
+ if (!/^\d+$/.test(v)) fail(`${source} must be an integer 1..65535, got ${JSON.stringify(v)}`);
1651
+ const port = Number(v);
1652
+ if (port < 1 || port > 65535) fail(`${source} must be an integer 1..65535, got ${v}`);
1653
+ return port;
1654
+ }
1655
+ function sslMode(v, source) {
1656
+ if (v === void 0 || v === "") return "prefer";
1657
+ if (typeof v === "boolean") return v ? "require" : "disable";
1658
+ const s = v.trim().toLowerCase();
1659
+ if (["true", "1", "yes", "require"].includes(s)) return "require";
1660
+ if (["false", "0", "no", "disable", "disabled"].includes(s)) return "disable";
1661
+ if (s === "prefer" || s === "verify-ca" || s === "verify-full") return s;
1662
+ fail(`${source} must be disable|prefer|require|verify-ca|verify-full, got ${JSON.stringify(v)}`);
1663
+ }
1664
+ function safeUrlLabel(raw) {
1618
1665
  try {
1619
- await sql.initializeStore(db);
1620
- await sql.initializeDomain(db);
1621
- return { db, storage: new sql.SqlStorage(db), path: resolved, close: () => db.close() };
1622
- } catch (error) {
1623
- await db.close();
1624
- throw error;
1666
+ const u = new URL(raw);
1667
+ return `${u.protocol}//${u.host}${u.pathname}`;
1668
+ } catch {
1669
+ return "<unparsable-url>";
1625
1670
  }
1626
1671
  }
1627
- function formatV5Digest(digest) {
1628
- const bytes = digest.slice(0, 16);
1629
- bytes[6] = bytes[6] & 15 | 80;
1630
- bytes[8] = bytes[8] & 63 | 128;
1631
- const hex = [...bytes].map((b) => b.toString(16).padStart(2, "0"));
1632
- return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10, 16).join("")}`;
1633
- }
1634
- function uuid5(namespace, name) {
1635
- return formatV5Digest(nodeCrypto().createHash("sha1").update(namespace).update(name).digest());
1636
- }
1637
- var CLI_UUID_NAMESPACE = "c0ffee00-8b1a-4e2c-9d3f-5a6b7c8d9e0f";
1638
- function stableNoteId(sourceLabel, content) {
1639
- if (sourceLabel && sourceLabel !== "-") {
1640
- return uuid5(CLI_UUID_NAMESPACE, `wod-cli:${nodePath().resolve(process.cwd(), sourceLabel)}`);
1672
+ function postgresFromUrl(url, source) {
1673
+ if (!PG_URL_SCHEMES.test(url)) {
1674
+ fail(`${source} must start with postgres:// or postgresql://`);
1641
1675
  }
1642
- return uuid5(CLI_UUID_NAMESPACE, `wod-cli:stdin:${content.length}:${content.slice(0, 256)}`);
1643
- }
1644
- function randomId() {
1645
- return nodeCrypto().randomUUID();
1646
- }
1647
- async function allRows(sql, db, store) {
1648
- return sql.listRows(db, sql.storeDefinition(store));
1649
- }
1650
- async function rowsByIndex(sql, db, store, index, only) {
1651
- return sql.listRows(db, sql.storeDefinition(store), { only }, void 0, index);
1652
- }
1653
- function sqliteEventStore(db) {
1654
- const all = async () => await allRows(await loadSql(), db, "events");
1676
+ let u;
1677
+ try {
1678
+ u = new URL(url);
1679
+ } catch {
1680
+ fail(`${source} is not a parseable URL`);
1681
+ }
1682
+ const database = decodeURIComponent(u.pathname.replace(/^\/+|\/+$/g, ""));
1683
+ if (database === "") fail(`${source} has no database name`);
1655
1684
  return {
1656
- getEventsByTimeRange: async (start, end) => (await all()).filter((r) => r.timestamp >= start && r.timestamp <= end),
1657
- getEventsByResult: async (resultId) => (await all()).filter((r) => r.resultId === resultId),
1658
- getEventsForNote: async (noteId) => (await all()).filter((r) => r.noteId === noteId),
1659
- getEventsByContent: async (blockContentId4) => (await all()).filter((r) => r.blockContentId === blockContentId4),
1660
- scanAll: all,
1661
- appendEvents: async (appended) => {
1662
- const sql = await loadSql();
1663
- await db.transaction(async (tx) => {
1664
- const eventsDef = sql.storeDefinition("events");
1665
- for (const row of appended) await sql.putRow(tx, eventsDef, row);
1666
- });
1667
- },
1668
- finalizeSummaries: async (resultId, finals) => {
1669
- const sql = await loadSql();
1670
- await db.transaction(async (tx) => {
1671
- const eventsDef = sql.storeDefinition("events");
1672
- const existing = (await sql.listRows(tx, eventsDef)).filter(
1673
- (r) => r.resultId === resultId && r.grain === "summary" && r.origin !== "user"
1674
- );
1675
- for (const row of existing) await sql.deleteRows(tx, eventsDef, row.id);
1676
- for (const row of finals) await sql.putRow(tx, eventsDef, row);
1677
- });
1678
- },
1679
- deleteEvents: async (ids) => {
1680
- const sql = await loadSql();
1681
- await db.transaction(async (tx) => {
1682
- const eventsDef = sql.storeDefinition("events");
1683
- for (const id of ids) await sql.deleteRows(tx, eventsDef, id);
1684
- });
1685
- }
1685
+ kind: "postgres",
1686
+ label: safeUrlLabel(url),
1687
+ url,
1688
+ host: u.hostname,
1689
+ port: u.port !== "" ? parsePort(u.port, `${source} port`) : 5432,
1690
+ database,
1691
+ user: u.username !== "" ? decodeURIComponent(u.username) : void 0,
1692
+ password: u.password !== "" ? decodeURIComponent(u.password) : void 0,
1693
+ ssl: sslMode(u.searchParams.get("sslmode") ?? u.searchParams.get("ssl") ?? void 0, `${source} ssl parameter`)
1686
1694
  };
1687
1695
  }
1688
- function sqliteNoteStore(db) {
1689
- return {
1690
- getAllNotes: async () => await allRows(await loadSql(), db, "notes"),
1691
- getNotesByIds: async (noteIds) => {
1692
- const sql = await loadSql();
1693
- const rows = await sql.getRows(db, sql.storeDefinition("notes"), [...noteIds]);
1694
- return rows.filter((row) => row !== void 0);
1695
- },
1696
- getNoteIdsForTag: async (label) => {
1697
- const sql = await loadSql();
1698
- const tags = (await allRows(sql, db, "tags")).filter((t) => t.label === label);
1699
- const ids = {};
1700
- for (const tag of tags) {
1701
- for (const row of await rowsByIndex(sql, db, "note_tags", "by-tag", tag.id)) {
1702
- ids[row.noteId] = true;
1703
- }
1704
- }
1705
- return new Set(Object.keys(ids));
1706
- },
1707
- getNoteTagLabels: async (noteId) => {
1708
- const sql = await loadSql();
1709
- const tagRows = await allRows(sql, db, "tags");
1710
- const labelById = {};
1711
- for (const t of tagRows) labelById[t.id] = t.label;
1712
- const links = await rowsByIndex(sql, db, "note_tags", "by-note", noteId);
1713
- return links.map((l) => labelById[l.tagId]).filter((l) => typeof l === "string");
1714
- },
1715
- queryDomain: async (request) => {
1716
- const result = await (await loadSql()).handleDomainQuery(db, request);
1717
- return result;
1696
+ function resolvePostgres(options, e, databaseUrl) {
1697
+ const flagProps = PG_FLAG_KEYS.some((k) => options[k] !== void 0);
1698
+ const envProps = PG_ENV_KEYS.some((k) => setEnv(e[k]) !== void 0);
1699
+ if (flagProps || envProps && databaseUrl === void 0) {
1700
+ const host = options.postgresHost ?? setEnv(e.POSTGRES_HOST) ?? "127.0.0.1";
1701
+ const port = parsePort(options.postgresPort ?? setEnv(e.POSTGRES_PORT) ?? "5432", "--postgres-port/POSTGRES_PORT");
1702
+ const database = options.postgresDatabase ?? setEnv(e.POSTGRES_DATABASE);
1703
+ if (database === void 0) {
1704
+ fail("--postgres-database (or POSTGRES_DATABASE) is required for per-property PostgreSQL configuration");
1705
+ }
1706
+ const user = options.postgresUser ?? setEnv(e.POSTGRES_USER);
1707
+ const password = options.postgresPassword ?? setEnv(e.POSTGRES_PASSWORD);
1708
+ const ssl = sslMode(options.postgresSsl ?? setEnv(e.POSTGRES_SSL), "--postgres-ssl/POSTGRES_SSL");
1709
+ try {
1710
+ const u = new URL(`postgresql://${host}`);
1711
+ u.port = String(port);
1712
+ u.pathname = `/${database}`;
1713
+ if (user !== void 0) u.username = user;
1714
+ if (password !== void 0) u.password = password;
1715
+ u.searchParams.set("sslmode", ssl);
1716
+ return {
1717
+ kind: "postgres",
1718
+ label: `postgresql://${u.host}${u.pathname}`,
1719
+ url: u.toString(),
1720
+ host,
1721
+ port,
1722
+ database,
1723
+ user,
1724
+ password,
1725
+ ssl
1726
+ };
1727
+ } catch {
1728
+ fail("invalid PostgreSQL host/database in per-property configuration");
1718
1729
  }
1719
- };
1730
+ }
1731
+ if (databaseUrl !== void 0) return postgresFromUrl(databaseUrl, "DB_DRIVER=postgres DATABASE_URL");
1732
+ fail("DB_DRIVER=postgres requires DATABASE_URL starting with postgres:// or postgresql:// \u2014 or per-property --postgres-host/--postgres-database flags");
1720
1733
  }
1721
- function sqliteBlockStore(db) {
1734
+ function resolveTurso(options, e, databaseUrl) {
1735
+ const url = options.tursoUrl ?? setEnv(e.TURSO_DATABASE_URL) ?? databaseUrl;
1736
+ if (url === void 0) {
1737
+ fail("DB_DRIVER=turso requires --turso-url / TURSO_DATABASE_URL or DATABASE_URL (libsql:// or https://)");
1738
+ }
1739
+ if (PG_URL_SCHEMES.test(url)) fail("DB_DRIVER=turso cannot use a postgres:// URL");
1740
+ if (!TURSO_URL_SCHEMES.test(url)) fail("DB_DRIVER=turso requires a libsql://, https://, http:// or wss:// URL");
1722
1741
  return {
1723
- getAllBlocks: async () => await allRows(await loadSql(), db, "block_index"),
1724
- queryDomain: async (request) => {
1725
- const result = await (await loadSql()).handleDomainQuery(db, { ...request, plan: "blocks" });
1726
- return result;
1727
- }
1742
+ kind: "turso",
1743
+ label: safeUrlLabel(url),
1744
+ url,
1745
+ authToken: options.tursoAuthToken ?? setEnv(e.TURSO_AUTH_TOKEN) ?? setEnv(e.LIBSQL_AUTH_TOKEN)
1728
1746
  };
1729
1747
  }
1730
- function sqliteEffortStore(db) {
1731
- return {
1732
- getAllEfforts: async () => {
1733
- const stored = await allRows(await loadSql(), db, "efforts");
1734
- const bySlug = {};
1735
- for (const effort of stored) bySlug[effort.slug] = effort;
1736
- for (const effort of bundledEfforts) {
1737
- bySlug[effort.slug] ??= effort;
1748
+ function resolveSqlite(options, e, databaseUrl) {
1749
+ if (options.db !== void 0) {
1750
+ const path2 = nodePath2().resolve(process.cwd(), options.db);
1751
+ return { kind: "sqlite", label: path2, path: path2 };
1752
+ }
1753
+ if (databaseUrl !== void 0) {
1754
+ if (PG_URL_SCHEMES.test(databaseUrl)) fail("DB_DRIVER=sqlite cannot use a postgres:// DATABASE_URL");
1755
+ if (databaseUrl.startsWith("file:")) {
1756
+ const path2 = nodePath2().resolve(process.cwd(), decodeURIComponent(databaseUrl.slice("file:".length).split("?")[0]));
1757
+ return { kind: "sqlite", label: path2, path: path2 };
1758
+ }
1759
+ if (!SQLITE_URL_SCHEMES.test(databaseUrl)) {
1760
+ fail("DB_DRIVER=sqlite requires a libsql://, https://, http://, wss:// or file:// DATABASE_URL");
1761
+ }
1762
+ return { kind: "turso", label: safeUrlLabel(databaseUrl), url: databaseUrl, authToken: setEnv(e.LIBSQL_AUTH_TOKEN) };
1763
+ }
1764
+ const path = nodePath2().resolve(process.cwd(), setEnv(e.WOD_WIKI_DB) ?? setEnv(e.SQLITE_PATH) ?? "./wodwiki.db");
1765
+ return { kind: "sqlite", label: path, path };
1766
+ }
1767
+ function envBackend(e) {
1768
+ const kinds = /* @__PURE__ */ new Set();
1769
+ if (setEnv(e.WOD_WIKI_DB) !== void 0 || setEnv(e.SQLITE_PATH) !== void 0) kinds.add("sqlite");
1770
+ const dbUrl = setEnv(e.DATABASE_URL);
1771
+ if (PG_ENV_KEYS.some((k) => setEnv(e[k]) !== void 0) || dbUrl !== void 0 && PG_URL_SCHEMES.test(dbUrl)) {
1772
+ kinds.add("postgres");
1773
+ } else if (dbUrl !== void 0 && SQLITE_URL_SCHEMES.test(dbUrl)) {
1774
+ kinds.add("sqlite");
1775
+ }
1776
+ if (setEnv(e.TURSO_DATABASE_URL) !== void 0) kinds.add("turso");
1777
+ if (kinds.size > 1) {
1778
+ fail(`ambiguous database configuration: ${[...kinds].join(" + ")} env vars are both set \u2014 set DB_DRIVER (or pass explicit flags) to choose`);
1779
+ }
1780
+ return kinds.values().next().value ?? "sqlite";
1781
+ }
1782
+ function resolveDatabaseConfig(options = {}, env) {
1783
+ const e = env ?? { ...loadCliEnvironment(options.envFile), ...process.env };
1784
+ const driverFlag = options.dbDriver;
1785
+ if (driverFlag !== void 0 && !isBackend(driverFlag)) {
1786
+ fail(`--db-driver must be sqlite|postgres|turso, got ${JSON.stringify(driverFlag)}`);
1787
+ }
1788
+ const pinned = [];
1789
+ if (options.db !== void 0) pinned.push(["--db", "sqlite"]);
1790
+ if (driverFlag !== void 0) pinned.push([`--db-driver ${driverFlag}`, driverFlag]);
1791
+ if (options.tursoUrl !== void 0) pinned.push(["--turso-url", "turso"]);
1792
+ if (options.tursoAuthToken !== void 0) pinned.push(["--turso-auth-token", "turso"]);
1793
+ if (PG_FLAG_KEYS.some((k) => options[k] !== void 0)) pinned.push(["--postgres-*", "postgres"]);
1794
+ const kinds = new Set(pinned.map(([, kind]) => kind));
1795
+ if (kinds.size > 1) {
1796
+ fail(`conflicting database selectors: ${pinned.map(([flag, kind]) => `${flag} (${kind})`).join(", ")}`);
1797
+ }
1798
+ if (options.databaseUrl !== void 0) {
1799
+ if (options.db !== void 0) fail("conflicting database selectors: --db and --database-url are both set");
1800
+ if (options.tursoUrl !== void 0) fail("conflicting database selectors: --turso-url and --database-url are both set");
1801
+ if (PG_FLAG_KEYS.some((k) => options[k] !== void 0)) {
1802
+ fail("conflicting database selectors: --database-url and --postgres-* flags are both set");
1803
+ }
1804
+ }
1805
+ let backend;
1806
+ if (pinned.length > 0) {
1807
+ backend = pinned[0][1];
1808
+ } else {
1809
+ const envDriver = setEnv(e.DB_DRIVER);
1810
+ if (envDriver !== void 0) {
1811
+ if (!isBackend(envDriver)) {
1812
+ fail(`Unsupported DB_DRIVER: ${envDriver} (expected sqlite|turso|postgres)`);
1738
1813
  }
1739
- return Object.values(bySlug);
1814
+ backend = envDriver;
1815
+ } else {
1816
+ backend = envBackend(e);
1740
1817
  }
1741
- };
1742
- }
1743
- function sqliteIndexStore(db, store) {
1744
- return {
1745
- getAllFromIndex: async (index, key) => rowsByIndex(await loadSql(), db, store, index, key)
1746
- };
1747
- }
1748
- async function getNoteBundle(db, noteId) {
1749
- const sql = await loadSql();
1750
- const note = await sql.getRow(db, sql.storeDefinition("notes"), noteId);
1751
- return { note };
1752
- }
1753
- async function getSessionBundle(db, resultId) {
1754
- const sql = await loadSql();
1755
- const session = await sql.getRow(db, sql.storeDefinition("sessions"), resultId);
1756
- if (!session) return void 0;
1757
- const events = await sql.listRows(db, sql.storeDefinition("events"), { only: resultId }, void 0, "by-result-grain");
1758
- return { session, events };
1759
- }
1760
- async function getEffortBySlug(db, slug) {
1761
- const sql = await loadSql();
1762
- const efforts = await allRows(sql, db, "efforts");
1763
- return efforts.find((e) => e.slug === slug);
1764
- }
1765
- async function listTagsByType(db, type) {
1766
- const sql = await loadSql();
1767
- const tags = await allRows(sql, db, "tags");
1768
- return tags.filter((t) => t.type === type);
1818
+ }
1819
+ const databaseUrl = options.databaseUrl ?? setEnv(e.DATABASE_URL);
1820
+ switch (backend) {
1821
+ case "postgres":
1822
+ return resolvePostgres(options, e, databaseUrl);
1823
+ case "turso":
1824
+ return resolveTurso(options, e, databaseUrl);
1825
+ case "sqlite":
1826
+ return resolveSqlite(options, e, databaseUrl);
1827
+ }
1769
1828
  }
1770
1829
  var registeredWidgets = KNOWN_SECTION_WIDGETS;
1771
1830
  var saveStores = ["notes", "block_revisions", "block_index", "block_efforts", "tags", "note_tags", "sessions"];
@@ -2103,16 +2162,53 @@ ${source}
2103
2162
  ${fence}
2104
2163
  `;
2105
2164
  }
2165
+ var VALUE_FLAGS = [
2166
+ ["--db", "db"],
2167
+ ["--db-driver", "dbDriver"],
2168
+ ["--database-url", "databaseUrl"],
2169
+ ["--postgres-host", "postgresHost"],
2170
+ ["--postgres-port", "postgresPort"],
2171
+ ["--postgres-user", "postgresUser"],
2172
+ ["--postgres-password", "postgresPassword"],
2173
+ ["--postgres-database", "postgresDatabase"],
2174
+ ["--postgres-ssl", "postgresSsl"],
2175
+ ["--turso-url", "tursoUrl"],
2176
+ ["--turso-auth-token", "tursoAuthToken"],
2177
+ ["--env-file", "envFile"],
2178
+ ["--host", "host"],
2179
+ ["--port", "port"],
2180
+ ["--dist", "dist"]
2181
+ ];
2182
+ function readValueFlag(args, i, flag) {
2183
+ const inline = args[i].startsWith(`${flag}=`);
2184
+ if (inline) {
2185
+ const value2 = args[i].slice(flag.length + 1);
2186
+ if (!value2) throw new Error(`Missing value for ${flag}`);
2187
+ return { value: value2, next: i + 1 };
2188
+ }
2189
+ const value = args[i + 1];
2190
+ if (value === void 0 || value === "" || value.startsWith("--")) throw new Error(`Missing value for ${flag}`);
2191
+ return { value, next: i + 2 };
2192
+ }
2106
2193
  function parseCliArgs(args) {
2107
2194
  const result = {
2108
2195
  format: "json",
2109
2196
  packs: [],
2110
2197
  sources: []
2111
2198
  };
2199
+ const valueArgs = result;
2112
2200
  let i = 0;
2113
2201
  while (i < args.length) {
2114
2202
  const arg = args[i];
2115
2203
  if (arg === "--at" || arg.startsWith("--at=")) throw new Error("Unknown option --at; whole Note exports have no as-of version");
2204
+ const valueFlag = VALUE_FLAGS.find(([flag]) => arg === flag || arg.startsWith(`${flag}=`));
2205
+ if (valueFlag) {
2206
+ const [flag, key] = valueFlag;
2207
+ const { value, next } = readValueFlag(args, i, flag);
2208
+ valueArgs[key] = value;
2209
+ i = next;
2210
+ continue;
2211
+ }
2116
2212
  if (arg === "--help" || arg === "-h") {
2117
2213
  result.help = true;
2118
2214
  i++;
@@ -2159,12 +2255,6 @@ function parseCliArgs(args) {
2159
2255
  } else if (arg === "--unit") {
2160
2256
  result.unit = args[++i];
2161
2257
  i++;
2162
- } else if (arg === "--db") {
2163
- result.db = args[++i];
2164
- i++;
2165
- } else if (arg.startsWith("--db=")) {
2166
- result.db = arg.slice("--db=".length);
2167
- i++;
2168
2258
  } else if (arg === "--debug") {
2169
2259
  result.debug = "";
2170
2260
  i++;
@@ -2200,7 +2290,7 @@ function parseCliArgs(args) {
2200
2290
  result.dir = arg.slice("--dir=".length);
2201
2291
  i++;
2202
2292
  } else if (!result.subcommand) {
2203
- if (arg === "parse" || arg === "run" || arg === "query" || arg === "download" || arg === "import" || arg === "build" || arg === "seed" || arg === "reset" || arg === "help" || arg === "version") {
2293
+ if (arg === "parse" || arg === "run" || arg === "query" || arg === "download" || arg === "import" || arg === "build" || arg === "seed" || arg === "reset" || arg === "init" || arg === "server" || arg === "serve" || arg === "playground" || arg === "help" || arg === "version") {
2204
2294
  result.subcommand = arg;
2205
2295
  } else {
2206
2296
  result.target = arg;
@@ -2216,6 +2306,11 @@ function parseCliArgs(args) {
2216
2306
  i++;
2217
2307
  }
2218
2308
  }
2309
+ for (const [flag, value] of [["--port", result.port], ["--postgres-port", result.postgresPort]]) {
2310
+ if (value !== void 0 && (!/^\d+$/.test(value) || Number(value) < 1 || Number(value) > 65535)) {
2311
+ throw new Error(`Invalid value for ${flag}: "${value}" is not a TCP port (1-65535)`);
2312
+ }
2313
+ }
2219
2314
  return result;
2220
2315
  }
2221
2316
  function readBunStdinText() {
@@ -2261,6 +2356,11 @@ USAGE:
2261
2356
  wod build [dir] [options]
2262
2357
  wod seed [options]
2263
2358
  wod reset [options]
2359
+ wod init Initialize the configured database (idempotent)
2360
+ wod server [options]
2361
+ Serve the app (HTTP API + packaged frontend; alias: serve)
2362
+ wod playground [options]
2363
+ Serve the local playground (browser IndexedDB build)
2264
2364
 
2265
2365
  SUBCOMMANDS:
2266
2366
  parse <file | -> Parse Whiteboard Script, create a note in the database
@@ -2314,9 +2414,47 @@ INPUT SOURCING (for 'query'; without these, the database is queried):
2314
2414
  --stdin-log Read kind: 'execution-log' JSON payload from stdin
2315
2415
  --stdin-facts Read raw kind: 'fact-set' JSON payload from stdin
2316
2416
 
2317
- DATABASE (parse / run / query / download / import / seed / reset):
2318
- --db <path> SQLite database file (default: $WOD_WIKI_DB or
2319
- ./wodwiki.db). Created on demand by parse/run/seed.
2417
+ DATABASE (init / parse / run / query / download / import / seed / reset / server):
2418
+ Pick one backend; explicit flags win over the process environment, the
2419
+ process environment wins over .env files. Run 'wod init' once first: it
2420
+ creates the SQLite file + schema, creates the PostgreSQL database when
2421
+ your role is authorized to (otherwise use an existing/provisioned one),
2422
+ or installs the schema in your provisioned Turso database \u2014 idempotently,
2423
+ preserving existing notes. 'wod server' refuses an uninitialized database.
2424
+ --db <path> Local SQLite database file (default: $WOD_WIKI_DB
2425
+ or ./wodwiki.db). Passing --db always selects SQLite,
2426
+ even when the environment names a remote backend.
2427
+ Created on demand by parse/run/seed.
2428
+ --db-driver <name> Backend driver: sqlite (default), postgres, or
2429
+ turso ($DB_DRIVER)
2430
+ --database-url <url> Database connection URL ($DATABASE_URL); accepts
2431
+ PostgreSQL, local SQLite, and remote libSQL URLs.
2432
+ --postgres-host <host> PostgreSQL host ($POSTGRES_HOST)
2433
+ --postgres-port <port> PostgreSQL port ($POSTGRES_PORT)
2434
+ --postgres-user <user> PostgreSQL user ($POSTGRES_USER)
2435
+ --postgres-password <pw> PostgreSQL password ($POSTGRES_PASSWORD)
2436
+ --postgres-database <db> PostgreSQL database name ($POSTGRES_DATABASE)
2437
+ --postgres-ssl <mode> PostgreSQL SSL mode, e.g. disable/prefer/require
2438
+ ($POSTGRES_SSL)
2439
+ --turso-url <url> Turso/libSQL database URL (libsql://\u2026). The
2440
+ hosted database must already exist (provisioned on
2441
+ Turso); only its schema is installed.
2442
+ --turso-auth-token <token> Turso authentication token (never printed)
2443
+ --env-file <path> Load variables from this file; a missing file is
2444
+ an error. Without it: ./.env when present, otherwise
2445
+ the workspace-root .env. Credentials are never logged.
2446
+
2447
+ HOSTING (for 'server' / 'playground'; requires the Bun runtime):
2448
+ server HTTP API over the configured database plus the frontend
2449
+ packaged inside the engine module. Requires an
2450
+ initialized database. ('serve' is an accepted alias.)
2451
+ playground Serves the playground app backed by browser IndexedDB;
2452
+ the configured database is not touched.
2453
+ --host <host> Bind address (default 127.0.0.1, $HOST)
2454
+ --port <port> TCP port (default 3000, $PORT)
2455
+ --dist <dir> Serve this prebuilt frontend directory instead of the
2456
+ packaged one ($PLAYGROUND_DIST); must already contain
2457
+ index.html.
2320
2458
 
2321
2459
  SEED SOURCING (for 'seed'):
2322
2460
  --source <dir> Extra compiled seed directory (manifest.json + chunks);
@@ -2336,6 +2474,15 @@ OPTIONS:
2336
2474
  -h, --help Show help message
2337
2475
  -v, --version Show version number
2338
2476
 
2477
+ ENVIRONMENT (flags > process env > .env):
2478
+ WOD_WIKI_DB, SQLITE_PATH SQLite file path
2479
+ DB_DRIVER sqlite | postgres | turso
2480
+ DATABASE_URL PostgreSQL connection URL
2481
+ POSTGRES_HOST, POSTGRES_PORT, POSTGRES_USER,
2482
+ POSTGRES_PASSWORD, POSTGRES_DATABASE, POSTGRES_SSL
2483
+ TURSO_DATABASE_URL, TURSO_AUTH_TOKEN, LIBSQL_AUTH_TOKEN
2484
+ HOST, PORT, PLAYGROUND_DIST server / playground defaults
2485
+
2339
2486
  EXIT CODES:
2340
2487
  0 - OK / Success
2341
2488
  1 - General / Runtime error
@@ -2355,6 +2502,10 @@ async function cliMain(argv = process.argv.slice(2), io = {}) {
2355
2502
  const writeOut = io.stdout ?? ((t) => process.stdout.write(t + "\n"));
2356
2503
  const writeErr = io.stderr ?? ((t) => process.stderr.write(t + "\n"));
2357
2504
  const getStdin = io.readStdinFn ?? readStdin;
2505
+ let envLoaded;
2506
+ const cliEnv = () => envLoaded ??= { ...loadCliEnvironment(parsed.envFile), ...process.env };
2507
+ let dbResolved;
2508
+ const cliDb = () => dbResolved ??= resolveDatabaseConfig(parsed, cliEnv());
2358
2509
  let parsed;
2359
2510
  try {
2360
2511
  parsed = parseCliArgs(argv);
@@ -2421,7 +2572,7 @@ async function cliMain(argv = process.argv.slice(2), io = {}) {
2421
2572
  const ir = runParse(source, { sport: parsed.sport, sourceLabel: `cli:wod parse ${parsed.target}` });
2422
2573
  const identity = extractNoteIdentity(source);
2423
2574
  const tags = extractTypedTags(source);
2424
- const db = await openCliDb(parsed.db);
2575
+ const db = await openCliDb(cliDb());
2425
2576
  try {
2426
2577
  const persisted = await persistNote(db, {
2427
2578
  source: noteSource,
@@ -2460,7 +2611,7 @@ async function cliMain(argv = process.argv.slice(2), io = {}) {
2460
2611
  source = fs.readFileSync(parsed.target, "utf-8");
2461
2612
  }
2462
2613
  const identity = extractNoteIdentity(source);
2463
- const db = await openCliDb(parsed.db);
2614
+ const db = await openCliDb(cliDb());
2464
2615
  let ir;
2465
2616
  try {
2466
2617
  const started = await startRun(db, {
@@ -2511,14 +2662,14 @@ async function cliMain(argv = process.argv.slice(2), io = {}) {
2511
2662
  }
2512
2663
  let ir;
2513
2664
  if (useDb) {
2514
- const dbPath = resolveDbPath(parsed.db);
2515
- if (!nodeFs().existsSync(dbPath)) {
2665
+ const config = cliDb();
2666
+ if (config.kind === "sqlite" && !nodeFs().existsSync(config.path)) {
2516
2667
  writeErr(
2517
- `[wod query] No input dataset and no database at ${dbPath}. Specify --corpus <file>, --stdin-log, --stdin-facts, or run \`wod seed\` first.`
2668
+ `[wod query] No input dataset and no database at ${config.path}. Specify --corpus <file>, --stdin-log, --stdin-facts, or run \`wod seed\` first.`
2518
2669
  );
2519
2670
  return 1;
2520
2671
  }
2521
- const db = await openCliDb(parsed.db);
2672
+ const db = await openCliDb(config, config.kind === "sqlite" ? void 0 : { initialize: false });
2522
2673
  try {
2523
2674
  ir = await runQueryCli(parsed.target, {
2524
2675
  preferredUnit: parsed.unit,
@@ -2564,7 +2715,7 @@ async function cliMain(argv = process.argv.slice(2), io = {}) {
2564
2715
  return 1;
2565
2716
  }
2566
2717
  const targetId = id;
2567
- const db = await openCliDb(parsed.db);
2718
+ const db = await openCliDb(cliDb());
2568
2719
  try {
2569
2720
  if (kind === "note") {
2570
2721
  const bundle = await getNoteBundle(db.db, targetId);
@@ -2641,7 +2792,7 @@ async function cliMain(argv = process.argv.slice(2), io = {}) {
2641
2792
  const source = fs.readFileSync(file, "utf-8");
2642
2793
  const identity = extractNoteIdentity(source);
2643
2794
  const tags = extractTypedTags(source);
2644
- const db2 = await openCliDb(parsed.db);
2795
+ const db2 = await openCliDb(cliDb());
2645
2796
  try {
2646
2797
  const persisted = await persistNote(db2, {
2647
2798
  source,
@@ -2664,7 +2815,7 @@ async function cliMain(argv = process.argv.slice(2), io = {}) {
2664
2815
  writeErr(`[wod import] Unparseable effort file (need frontmatter id/slug/label + numeric baseAttributes.met): ${file}`);
2665
2816
  return 1;
2666
2817
  }
2667
- const db2 = await openCliDb(parsed.db);
2818
+ const db2 = await openCliDb(cliDb());
2668
2819
  try {
2669
2820
  await persistEffort(db2, { ...effort, registrySource: "user" });
2670
2821
  writeOut(`[wod import] effort ${effort.slug} \u2014 ${effort.label} \u2192 ${db2.path}`);
@@ -2679,7 +2830,7 @@ async function cliMain(argv = process.argv.slice(2), io = {}) {
2679
2830
  writeErr(`[wod import] No equipment labels found in ${file}`);
2680
2831
  return 1;
2681
2832
  }
2682
- const db2 = await openCliDb(parsed.db);
2833
+ const db2 = await openCliDb(cliDb());
2683
2834
  try {
2684
2835
  const added = await persistTypedTags(db2, labels, "equipment");
2685
2836
  writeOut(`[wod import] equipment \u2014 ${labels.length} labels (${added} new) \u2192 ${db2.path}`);
@@ -2689,7 +2840,7 @@ async function cliMain(argv = process.argv.slice(2), io = {}) {
2689
2840
  return 0;
2690
2841
  }
2691
2842
  const { session, events } = csvToSessionRows(fs.readFileSync(file, "utf-8"));
2692
- const db = await openCliDb(parsed.db);
2843
+ const db = await openCliDb(cliDb());
2693
2844
  try {
2694
2845
  const result = await persistSessionBundle(db, session, events);
2695
2846
  writeOut(
@@ -2707,7 +2858,7 @@ async function cliMain(argv = process.argv.slice(2), io = {}) {
2707
2858
  writeErr(`[wod build] No markdown/ corpus under ${root} \u2014 run from the content repo root (or pass its directory).`);
2708
2859
  return 1;
2709
2860
  }
2710
- const { generateSeed } = await import('./compiler-SXUCF7AU.mjs');
2861
+ const { generateSeed } = await import('./compiler-NODHKWJJ.mjs');
2711
2862
  try {
2712
2863
  const result = generateSeed({
2713
2864
  corpusRoot: root,
@@ -2736,7 +2887,7 @@ async function cliMain(argv = process.argv.slice(2), io = {}) {
2736
2887
  );
2737
2888
  return 1;
2738
2889
  }
2739
- const db = await openCliDb(parsed.db);
2890
+ const db = await openCliDb(cliDb());
2740
2891
  try {
2741
2892
  for (const dir of dirs) {
2742
2893
  const summary = await importSeedDir(db, dir, "");
@@ -2750,7 +2901,14 @@ async function cliMain(argv = process.argv.slice(2), io = {}) {
2750
2901
  return 0;
2751
2902
  }
2752
2903
  if (parsed.subcommand === "reset") {
2753
- const target = resolveDbPath(parsed.db);
2904
+ const config = cliDb();
2905
+ if (config.kind !== "sqlite") {
2906
+ writeErr(
2907
+ `[wod reset] refusing to reset the configured ${config.kind} database \u2014 reset only removes a local SQLite file. Clear remote databases through their provider.`
2908
+ );
2909
+ return 1;
2910
+ }
2911
+ const target = config.path;
2754
2912
  if (nodeFs().existsSync(target)) {
2755
2913
  nodeFs().unlinkSync(target);
2756
2914
  writeOut(`[wod reset] removed ${target}`);
@@ -2759,6 +2917,32 @@ async function cliMain(argv = process.argv.slice(2), io = {}) {
2759
2917
  }
2760
2918
  return 0;
2761
2919
  }
2920
+ if (parsed.subcommand === "init") {
2921
+ const db = await openCliDb(cliDb(), { create: true });
2922
+ try {
2923
+ writeOut(`[wod init] database ready at ${db.path}`);
2924
+ } finally {
2925
+ await db.close();
2926
+ }
2927
+ return 0;
2928
+ }
2929
+ if (parsed.subcommand === "server" || parsed.subcommand === "serve" || parsed.subcommand === "playground") {
2930
+ if (!("Bun" in globalThis)) {
2931
+ writeErr(
2932
+ `[wod ${parsed.subcommand}] Error: hosting requires the Bun runtime (https://bun.sh) \u2014 run \`bun wod server\` / \`bun wod playground\`.`
2933
+ );
2934
+ return 1;
2935
+ }
2936
+ const mode = parsed.subcommand === "playground" ? "playground" : "server";
2937
+ const { runCliServer } = await import('./server-4P6AJAGT.mjs');
2938
+ const options = { env: cliEnv() };
2939
+ if (mode === "server") options.database = cliDb();
2940
+ if (parsed.host !== void 0) options.host = parsed.host;
2941
+ if (parsed.port !== void 0) options.port = parsed.port;
2942
+ if (parsed.dist !== void 0) options.dist = parsed.dist;
2943
+ await runCliServer(mode, options, writeOut);
2944
+ return 0;
2945
+ }
2762
2946
  writeErr(`[wod] Unknown subcommand "${parsed.subcommand}"`);
2763
2947
  return 1;
2764
2948
  } catch (error) {
@@ -2776,5 +2960,5 @@ async function cliMain(argv = process.argv.slice(2), io = {}) {
2776
2960
  }
2777
2961
 
2778
2962
  export { NOTE_ID_FRONTMATTER_KEY, PackLoadError, ParseSyntaxError, SESSION_CSV_HEADER, WqlSyntaxError, applySeedChunk, assertSeedManifest, assertSeedRows, buildStatementTree, buildWorkoutResults, cliMain, composeNoteMarkdown, createIRFile, csvToEquipmentLabels, csvToSessionRows, defineLanguagePack, effortToMarkdown, equipmentToCsv, extractNoteIdentity, extractTypedTags, formatExecutionOutput, formatParseOutput, formatQueryOutput, getRegisteredLanguagePacks, inMemoryEventStore, injectIdentityFrontmatter, isIRFile, listLanguagePacks, loadLanguagePack, loadQueryData, markdownToEffort, parseCliArgs, parseCsvLine, readFrontmatterMeta, readStdin, registerLanguagePack, runExecution, runParse, runQueryCli, seedNoteId, sessionToCsv, splitCsvRecords, statementToNode, unregisterLanguagePack };
2779
- //# sourceMappingURL=chunk-N4KFWY6Z.mjs.map
2780
- //# sourceMappingURL=chunk-N4KFWY6Z.mjs.map
2963
+ //# sourceMappingURL=chunk-UKBQ36RW.mjs.map
2964
+ //# sourceMappingURL=chunk-UKBQ36RW.mjs.map