@bitcobblers/wod-wiki-tools 0.39.2143 → 0.40.2144

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 (47) hide show
  1. package/dist/bin/wod.cjs +736 -2
  2. package/dist/bin/wod.cjs.map +1 -1
  3. package/dist/bin/wod.mjs +2 -2
  4. package/dist/{chunk-F5SIEOUC.mjs → chunk-464KHLHY.mjs} +737 -6
  5. package/dist/chunk-464KHLHY.mjs.map +1 -0
  6. package/dist/{chunk-FYTG3FQK.mjs → chunk-UNDCEABI.mjs} +3 -3
  7. package/dist/chunk-UNDCEABI.mjs.map +1 -0
  8. package/dist/index.cjs +736 -2
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +59 -1
  11. package/dist/index.d.ts +59 -1
  12. package/dist/index.mjs +2 -2
  13. package/dist/{scaffoldCatalog-QEHORBWG.mjs → scaffoldCatalog-APBMVJES.mjs} +3 -3
  14. package/dist/{scaffoldCatalog-QEHORBWG.mjs.map → scaffoldCatalog-APBMVJES.mjs.map} +1 -1
  15. package/dist/web/playground/assets/main-DXU49DmJ.css +2 -0
  16. package/dist/web/playground/assets/{main-DiEBwjOo.js → main-DpzRbHM9.js} +103 -103
  17. package/dist/web/playground/assets/{statementBuilderFlow-c29iM7QE.js → statementBuilderFlow-B0UjTiSn.js} +2 -2
  18. package/dist/web/playground/assets/{vendor-CiB7wDhT.js → vendor-Dk-k8gVh.js} +67 -67
  19. package/dist/web/playground/assets/{vendor-codemirror-D4vSrLkz.js → vendor-codemirror-2KNYvyJk.js} +2 -2
  20. package/dist/web/playground/index.html +4 -4
  21. package/dist/web/playground/seed/core/chunks/canvas.f625050a.json +1 -0
  22. package/dist/web/playground/seed/core/chunks/efforts.a58dbed3.json +1 -0
  23. package/dist/web/playground/seed/core/chunks/equipment.c45026fc.json +1 -0
  24. package/dist/web/playground/seed/core/manifest.json +14 -14
  25. package/dist/web/playground/seed/core/report.html +13 -13
  26. package/dist/web/server/assets/main-DXU49DmJ.css +2 -0
  27. package/dist/web/server/assets/{main-CIbYk-ix.js → main-imfCx0Nx.js} +73 -72
  28. package/dist/web/server/assets/{statementBuilderFlow-sXef05V7.js → statementBuilderFlow-BI4ttuZP.js} +2 -2
  29. package/dist/web/server/assets/{vendor-CiB7wDhT.js → vendor-Dk-k8gVh.js} +67 -67
  30. package/dist/web/server/assets/{vendor-codemirror-D4vSrLkz.js → vendor-codemirror-2KNYvyJk.js} +2 -2
  31. package/dist/web/server/index.html +4 -4
  32. package/dist/web/server/seed/core/chunks/canvas.f625050a.json +1 -0
  33. package/dist/web/server/seed/core/chunks/efforts.a58dbed3.json +1 -0
  34. package/dist/web/server/seed/core/chunks/equipment.c45026fc.json +1 -0
  35. package/dist/web/server/seed/core/manifest.json +14 -14
  36. package/dist/web/server/seed/core/report.html +13 -13
  37. package/package.json +8 -7
  38. package/dist/chunk-F5SIEOUC.mjs.map +0 -1
  39. package/dist/chunk-FYTG3FQK.mjs.map +0 -1
  40. package/dist/web/playground/assets/main-C5dNwq9b.css +0 -2
  41. package/dist/web/playground/seed/core/chunks/canvas.c86bbb5e.json +0 -1
  42. package/dist/web/playground/seed/core/chunks/efforts.071eefb8.json +0 -1
  43. package/dist/web/playground/seed/core/chunks/equipment.c4fb1d64.json +0 -1
  44. package/dist/web/server/assets/main-C5dNwq9b.css +0 -2
  45. package/dist/web/server/seed/core/chunks/canvas.c86bbb5e.json +0 -1
  46. package/dist/web/server/seed/core/chunks/efforts.071eefb8.json +0 -1
  47. package/dist/web/server/seed/core/chunks/equipment.c4fb1d64.json +0 -1
package/dist/index.d.cts CHANGED
@@ -109,6 +109,52 @@ declare class PackLoadError extends Error {
109
109
  */
110
110
  declare function loadLanguagePack(moduleSpec: string): Promise<LanguagePack>;
111
111
 
112
+ /**
113
+ * `wod db <action>` — native Turso lifecycle commands for the Storage UI:
114
+ *
115
+ * wod db create [--name <db>] --group <g> -o <pairing-file>
116
+ * Provision a fresh empty target (canonical name `wod-wiki-v<DB_VERSION>`)
117
+ * and pair it for the browser's first bootstrap.
118
+ * wod db backup <source> [--name <copy>] --writers-retired -o <file>
119
+ * wod db restore <source> [--name <copy>] --writers-retired -o <file>
120
+ * Native whole-database copy through the Control API seed
121
+ * (`seed.type = database`), proven row- and binary-identical before a
122
+ * client token is minted. Only a copy already at the current schema is
123
+ * paired; older-schema archives are reported as retained, unpairable
124
+ * copies. Restore refuses a target named like the source.
125
+ * wod db migrate <source> [--name <target>] --writers-retired -o <file>
126
+ * Logical conversion of a legacy/current older-schema source into a
127
+ * fresh target via the shared IndexedDB adapter (fake-indexeddb is
128
+ * loaded only in this trusted CLI runtime). The target is constructed
129
+ * at the non-legitimate marker schema 0 and stays unpairable until the
130
+ * full replay/pin/binary validation passes and the finalize CAS
131
+ * publishes the live schema. The source is never mutated (read-only
132
+ * token) and is retained on every outcome.
133
+ * wod db delete <name> --yes <name>
134
+ * Deletes the database — `--yes` must repeat the exact name.
135
+ * wod db pair <name> [--allow-empty] -o <file> [--write-env]
136
+ * Mint a database-scoped token and write the pairing file for the
137
+ * browser Data settings. Refuses unknown/legacy/newer and the schema-0
138
+ * constructing marker; `--allow-empty` pairs a fresh bootstrap target.
139
+ *
140
+ * Safety contract: management credentials come from the environment only
141
+ * (TURSO_API_TOKEN, TURSO_ORGANIZATION — never flags, never printed);
142
+ * pairing credentials are written only to the explicitly requested file
143
+ * (created 0600, exclusive); `--write-env` is opt-in, atomic (temp+rename)
144
+ * and refuses to replace existing database settings. A failed verification
145
+ * or config write never deletes the created database and never touches the
146
+ * source — the user decides.
147
+ */
148
+
149
+ interface DbAdminDeps {
150
+ fetchFn?: typeof fetch;
151
+ now?: () => Date;
152
+ /** Test seam: map a provisioned hostname to a client URL. */
153
+ databaseUrl?: (hostname: string) => string;
154
+ /** Test seam: runs after the Control API created a copy, before verification. */
155
+ midCopyHook?: (copyName: string) => Promise<void>;
156
+ }
157
+
112
158
  /**
113
159
  * CLI Output Formatters (JSON, ASCII Table, CSV)
114
160
  *
@@ -144,7 +190,7 @@ declare function formatQueryOutput(ir: WodWikiIRFile<QueryResult | RowsQueryResu
144
190
  */
145
191
 
146
192
  interface CliParsedArgs {
147
- subcommand?: 'parse' | 'run' | 'query' | 'download' | 'export' | 'import' | 'publish' | 'build' | 'seed' | 'reset' | 'init' | 'server' | 'serve' | 'playground' | 'init-catalog' | 'help' | 'version';
193
+ subcommand?: 'parse' | 'run' | 'query' | 'download' | 'export' | 'import' | 'publish' | 'build' | 'seed' | 'reset' | 'init' | 'db' | 'server' | 'serve' | 'playground' | 'init-catalog' | 'help' | 'version';
148
194
  target?: string;
149
195
  /** Second positional: the id (download) or file (import) after the kind. */
150
196
  target2?: string;
@@ -164,6 +210,15 @@ interface CliParsedArgs {
164
210
  db?: string;
165
211
  /** Backend driver override (--db-driver): sqlite | postgres | turso. */
166
212
  dbDriver?: string;
213
+ /** `wod db`: action (create|backup|restore|migrate|delete|pair) is the
214
+ * first positional (parsed.target) and the database name the second. */
215
+ group?: string;
216
+ dbName?: string;
217
+ yes?: string;
218
+ writersRetired?: boolean;
219
+ allowEmpty?: boolean;
220
+ writeEnv?: boolean;
221
+ force?: boolean;
167
222
  /** PostgreSQL connection URL (--database-url) or component flags below. */
168
223
  databaseUrl?: string;
169
224
  postgresHost?: string;
@@ -201,6 +256,9 @@ declare function cliMain(argv?: string[], io?: {
201
256
  stdout?: (text: string) => void;
202
257
  stderr?: (text: string) => void;
203
258
  readStdinFn?: () => Promise<string>;
259
+ /** Test seam for `wod db`: injectable fetch/URL mapping for the Turso
260
+ * management client (production resolves the real network). */
261
+ dbDeps?: DbAdminDeps;
204
262
  }): Promise<number>;
205
263
 
206
264
  /**
package/dist/index.d.ts CHANGED
@@ -109,6 +109,52 @@ declare class PackLoadError extends Error {
109
109
  */
110
110
  declare function loadLanguagePack(moduleSpec: string): Promise<LanguagePack>;
111
111
 
112
+ /**
113
+ * `wod db <action>` — native Turso lifecycle commands for the Storage UI:
114
+ *
115
+ * wod db create [--name <db>] --group <g> -o <pairing-file>
116
+ * Provision a fresh empty target (canonical name `wod-wiki-v<DB_VERSION>`)
117
+ * and pair it for the browser's first bootstrap.
118
+ * wod db backup <source> [--name <copy>] --writers-retired -o <file>
119
+ * wod db restore <source> [--name <copy>] --writers-retired -o <file>
120
+ * Native whole-database copy through the Control API seed
121
+ * (`seed.type = database`), proven row- and binary-identical before a
122
+ * client token is minted. Only a copy already at the current schema is
123
+ * paired; older-schema archives are reported as retained, unpairable
124
+ * copies. Restore refuses a target named like the source.
125
+ * wod db migrate <source> [--name <target>] --writers-retired -o <file>
126
+ * Logical conversion of a legacy/current older-schema source into a
127
+ * fresh target via the shared IndexedDB adapter (fake-indexeddb is
128
+ * loaded only in this trusted CLI runtime). The target is constructed
129
+ * at the non-legitimate marker schema 0 and stays unpairable until the
130
+ * full replay/pin/binary validation passes and the finalize CAS
131
+ * publishes the live schema. The source is never mutated (read-only
132
+ * token) and is retained on every outcome.
133
+ * wod db delete <name> --yes <name>
134
+ * Deletes the database — `--yes` must repeat the exact name.
135
+ * wod db pair <name> [--allow-empty] -o <file> [--write-env]
136
+ * Mint a database-scoped token and write the pairing file for the
137
+ * browser Data settings. Refuses unknown/legacy/newer and the schema-0
138
+ * constructing marker; `--allow-empty` pairs a fresh bootstrap target.
139
+ *
140
+ * Safety contract: management credentials come from the environment only
141
+ * (TURSO_API_TOKEN, TURSO_ORGANIZATION — never flags, never printed);
142
+ * pairing credentials are written only to the explicitly requested file
143
+ * (created 0600, exclusive); `--write-env` is opt-in, atomic (temp+rename)
144
+ * and refuses to replace existing database settings. A failed verification
145
+ * or config write never deletes the created database and never touches the
146
+ * source — the user decides.
147
+ */
148
+
149
+ interface DbAdminDeps {
150
+ fetchFn?: typeof fetch;
151
+ now?: () => Date;
152
+ /** Test seam: map a provisioned hostname to a client URL. */
153
+ databaseUrl?: (hostname: string) => string;
154
+ /** Test seam: runs after the Control API created a copy, before verification. */
155
+ midCopyHook?: (copyName: string) => Promise<void>;
156
+ }
157
+
112
158
  /**
113
159
  * CLI Output Formatters (JSON, ASCII Table, CSV)
114
160
  *
@@ -144,7 +190,7 @@ declare function formatQueryOutput(ir: WodWikiIRFile<QueryResult | RowsQueryResu
144
190
  */
145
191
 
146
192
  interface CliParsedArgs {
147
- subcommand?: 'parse' | 'run' | 'query' | 'download' | 'export' | 'import' | 'publish' | 'build' | 'seed' | 'reset' | 'init' | 'server' | 'serve' | 'playground' | 'init-catalog' | 'help' | 'version';
193
+ subcommand?: 'parse' | 'run' | 'query' | 'download' | 'export' | 'import' | 'publish' | 'build' | 'seed' | 'reset' | 'init' | 'db' | 'server' | 'serve' | 'playground' | 'init-catalog' | 'help' | 'version';
148
194
  target?: string;
149
195
  /** Second positional: the id (download) or file (import) after the kind. */
150
196
  target2?: string;
@@ -164,6 +210,15 @@ interface CliParsedArgs {
164
210
  db?: string;
165
211
  /** Backend driver override (--db-driver): sqlite | postgres | turso. */
166
212
  dbDriver?: string;
213
+ /** `wod db`: action (create|backup|restore|migrate|delete|pair) is the
214
+ * first positional (parsed.target) and the database name the second. */
215
+ group?: string;
216
+ dbName?: string;
217
+ yes?: string;
218
+ writersRetired?: boolean;
219
+ allowEmpty?: boolean;
220
+ writeEnv?: boolean;
221
+ force?: boolean;
167
222
  /** PostgreSQL connection URL (--database-url) or component flags below. */
168
223
  databaseUrl?: string;
169
224
  postgresHost?: string;
@@ -201,6 +256,9 @@ declare function cliMain(argv?: string[], io?: {
201
256
  stdout?: (text: string) => void;
202
257
  stderr?: (text: string) => void;
203
258
  readStdinFn?: () => Promise<string>;
259
+ /** Test seam for `wod db`: injectable fetch/URL mapping for the Turso
260
+ * management client (production resolves the real network). */
261
+ dbDeps?: DbAdminDeps;
204
262
  }): Promise<number>;
205
263
 
206
264
  /**
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createRequire } from 'module';
2
- export { PackLoadError, ParseSyntaxError, WqlSyntaxError, cliMain, formatExecutionOutput, formatParseOutput, formatQueryOutput, loadCliEnvironment, loadLanguagePack, loadQueryData, parseCliArgs, readStdin, resolveDatabaseConfig, runExecution, runParse, runQueryCli } from './chunk-F5SIEOUC.mjs';
2
+ export { PackLoadError, ParseSyntaxError, WqlSyntaxError, cliMain, formatExecutionOutput, formatParseOutput, formatQueryOutput, loadCliEnvironment, loadLanguagePack, loadQueryData, parseCliArgs, readStdin, resolveDatabaseConfig, runExecution, runParse, runQueryCli } from './chunk-464KHLHY.mjs';
3
3
  import './chunk-IEW74LUO.mjs';
4
- import './chunk-FYTG3FQK.mjs';
4
+ import './chunk-UNDCEABI.mjs';
5
5
  export { runCliServer } from './chunk-RWNL6APX.mjs';
6
6
  export { openCliDb } from './chunk-IWT7U3WX.mjs';
7
7
  import './chunk-V23POHG2.mjs';
@@ -1,5 +1,5 @@
1
1
  import { createRequire } from 'module';
2
- import { VERSION } from './chunk-FYTG3FQK.mjs';
2
+ import { VERSION } from './chunk-UNDCEABI.mjs';
3
3
  import './chunk-6L5ZDZJ7.mjs';
4
4
  import { mkdirSync, writeFileSync, rmSync } from 'fs';
5
5
  import { resolve, join, dirname } from 'path';
@@ -201,5 +201,5 @@ function scaffoldCatalog(name, opts = {}) {
201
201
  }
202
202
 
203
203
  export { scaffoldCatalog, validateCatalogName };
204
- //# sourceMappingURL=scaffoldCatalog-QEHORBWG.mjs.map
205
- //# sourceMappingURL=scaffoldCatalog-QEHORBWG.mjs.map
204
+ //# sourceMappingURL=scaffoldCatalog-APBMVJES.mjs.map
205
+ //# sourceMappingURL=scaffoldCatalog-APBMVJES.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/scaffoldCatalog.ts"],"names":[],"mappings":"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","file":"scaffoldCatalog-QEHORBWG.mjs","sourcesContent":["/**\n * `wod init-catalog <name>` — scaffold a ready-to-publish WOD Wiki catalog\n * repository skeleton (docs/catalogs-and-distributed-seed-model.html §repo-creation,\n * roadmap Phase 4): markdown collections example, package.json, GitHub Actions\n * Pages workflow, README. Creates a new directory only; refuses an existing\n * destination without touching it.\n *\n * Lazily imported by cli/runner.ts (dynamic import), so static node:fs/node:path\n * imports stay out of browser bundles.\n */\nimport { mkdirSync, rmSync, writeFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { VERSION } from '../version';\n\nexport interface ScaffoldCatalogResult {\n /** Absolute path of the created catalog root. */\n dir: string;\n /** Created files, POSIX-relative to the catalog root. */\n files: string[];\n}\n\n/** npm package name + single-directory-segment validation for `<name>`. */\nexport function validateCatalogName(name: string): string {\n if (name.length === 0 || name === '.' || name === '..') {\n throw new Error('Catalog name must be a single non-empty directory name');\n }\n if (name.includes('/') || name.includes('\\\\') || name.includes('\\0')) {\n throw new Error(`Invalid catalog name '${name}': must be a single directory name (no path separators or traversal)`);\n }\n if (/^(?:[A-Za-z]:)?[/\\\\]/.test(name)) {\n throw new Error(`Invalid catalog name '${name}': absolute paths are not allowed`);\n }\n if (name.length > 214 || !/^[a-z0-9][a-z0-9._-]*$/.test(name)) {\n throw new Error(\n `Invalid catalog name '${name}': must be a valid npm package name ` +\n '(lowercase letters, digits, dots, hyphens, underscores; no leading dot/hyphen)',\n );\n }\n return name;\n}\n\nconst publishWorkflow = (): string => `name: Publish catalog\n\n# Compile the catalog with the wod CLI and deploy dist/ to GitHub Pages.\n# Requires Pages enabled: repo Settings → Pages → Source: \"GitHub Actions\".\n\non:\n push:\n branches: [main]\n workflow_dispatch:\n\npermissions:\n contents: read\n pages: write\n id-token: write\n\nconcurrency:\n group: pages\n cancel-in-progress: true\n\njobs:\n publish:\n runs-on: ubuntu-latest\n environment:\n name: github-pages\n url: \\${{ steps.deployment.outputs.page_url }}\n steps:\n - uses: actions/checkout@v4\n with:\n # Full history: seed manifest version stamps derive from git commit count.\n fetch-depth: 0\n\n - name: Set up Bun\n uses: oven-sh/setup-bun@v2\n with:\n bun-version: 1.4.x\n\n - name: Install dependencies\n run: bun install\n\n - name: Build seed\n run: bunx wod build . --output dist\n\n - uses: actions/configure-pages@v5\n\n - name: Upload dist\n uses: actions/upload-pages-artifact@v3\n with:\n path: dist\n\n - id: deployment\n uses: actions/deploy-pages@v4\n`;\n\nconst collectionReadme = (name: string): string => `# ${name}\n\nExample benchmark collection. Each \\`.md\\` file in this directory becomes part of\nthe \\`example\\` collection chunk; \\`README.md\\` is the collection's landing page.\n\nAdd one file per workout:\n\n\\`\\`\\`\\`markdown\n---\ntitle: My workout\ndate: 2026-01-01\n---\n\n# My workout\n\n\\`\\`\\`time\n(21-15-9)\n Thrusters @95lb\n Pull-ups\n\\`\\`\\`\n\\`\\`\\`\\`\n\nThe \\`date:\\` frontmatter field sets the workout's chronological placement\n(regardless of filename or directory).\n`;\n\nconst exampleWorkout = (date: string): string => `---\ntitle: Morning session\ndate: ${date}\n---\n\n# Morning session\n\n\\`\\`\\`time\n(21-15-9)\n Thrusters @95lb\n Pull-ups\n\\`\\`\\`\n`;\n\nconst catalogReadme = (name: string): string => `# ${name}\n\nA [WOD Wiki](https://github.com/bitcobblers/wod-wiki) workout catalog: plain\nMarkdown workouts compiled to static, version-stamped seed chunks and published\nvia GitHub Pages.\n\n## Develop\n\n\\`\\`\\`sh\nbun install\nbunx wod build . --output dist\n\\`\\`\\`\n\nWorkouts live under \\`markdown/\\` — this scaffold starts with one example\ncollection. Validate everything with \\`bunx wod build\\`: it gates every file on\nthe Whiteboard grammar and corpus layout before writing \\`dist/\\`.\n\n## Publish\n\nPush to GitHub and enable Pages (**Settings → Pages → Source: GitHub\nActions**). The bundled workflow (\\`.github/workflows/publish-catalog.yml\\`)\nbuilds the catalog on every push to \\`main\\` and deploys \\`dist/\\`.\n\n## Share\n\nOnce published, anyone can subscribe to this catalog from a WOD Wiki instance\nat:\n\n\\`\\`\\`\n<app-url>/subscribe?source=<url-encoded published catalog URL>\n\\`\\`\\`\n\nFor \\`owner\\`/\\`repo\\` on GitHub Pages the catalog URL is the deployed\ndirectory, \\`https://owner.github.io/repo/\\`, e.g.\n\\`/subscribe?source=https%3A%2F%2Fowner.github.io%2Frepo%2F\\`.\n`;\n\n/**\n * Scaffold a new catalog repository at `<cwd>/<name>`. Throws when the name is\n * invalid or the destination already exists; partial failure removes created files.\n */\nexport function scaffoldCatalog(name: string, opts: { cwd?: string } = {}): ScaffoldCatalogResult {\n validateCatalogName(name);\n const dir = resolve(opts.cwd ?? process.cwd(), name);\n // Atomic acquire: EEXIST is the refusal signal — no exists-check/create race,\n // and an existing destination is never removed or written.\n try {\n mkdirSync(dir);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'EEXIST') {\n throw new Error(`Refusing to overwrite '${dir}': destination already exists`, { cause: error });\n }\n throw error;\n }\n\n const date = new Date().toISOString().slice(0, 10);\n const files: Array<[rel: string, content: string]> = [\n ['package.json', `${JSON.stringify(\n {\n name,\n version: '0.1.0',\n private: true,\n type: 'module',\n description: `WOD Wiki workout catalog: ${name}`,\n scripts: {\n build: 'wod build . --output dist',\n },\n devDependencies: {\n '@bitcobblers/wod-wiki-tools': `^${VERSION}`,\n },\n },\n null,\n 2,\n )}\\n`],\n ['.gitignore', 'node_modules/\\ndist/\\n'],\n ['.github/workflows/publish-catalog.yml', publishWorkflow()],\n ['markdown/collections/example/README.md', collectionReadme(name)],\n [`markdown/collections/example/morning-session.md`, exampleWorkout(date)],\n ['README.md', catalogReadme(name)],\n ];\n\n try {\n for (const [rel, content] of files) {\n const target = join(dir, rel);\n mkdirSync(dirname(target), { recursive: true });\n writeFileSync(target, content, 'utf-8');\n }\n } catch (error) {\n rmSync(dir, { recursive: true, force: true });\n throw error;\n }\n return { dir, files: files.map(([rel]) => rel) };\n}\n"]}
1
+ {"version":3,"sources":["../src/cli/scaffoldCatalog.ts"],"names":[],"mappings":"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","file":"scaffoldCatalog-APBMVJES.mjs","sourcesContent":["/**\n * `wod init-catalog <name>` — scaffold a ready-to-publish WOD Wiki catalog\n * repository skeleton (docs/catalogs-and-distributed-seed-model.html §repo-creation,\n * roadmap Phase 4): markdown collections example, package.json, GitHub Actions\n * Pages workflow, README. Creates a new directory only; refuses an existing\n * destination without touching it.\n *\n * Lazily imported by cli/runner.ts (dynamic import), so static node:fs/node:path\n * imports stay out of browser bundles.\n */\nimport { mkdirSync, rmSync, writeFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { VERSION } from '../version';\n\nexport interface ScaffoldCatalogResult {\n /** Absolute path of the created catalog root. */\n dir: string;\n /** Created files, POSIX-relative to the catalog root. */\n files: string[];\n}\n\n/** npm package name + single-directory-segment validation for `<name>`. */\nexport function validateCatalogName(name: string): string {\n if (name.length === 0 || name === '.' || name === '..') {\n throw new Error('Catalog name must be a single non-empty directory name');\n }\n if (name.includes('/') || name.includes('\\\\') || name.includes('\\0')) {\n throw new Error(`Invalid catalog name '${name}': must be a single directory name (no path separators or traversal)`);\n }\n if (/^(?:[A-Za-z]:)?[/\\\\]/.test(name)) {\n throw new Error(`Invalid catalog name '${name}': absolute paths are not allowed`);\n }\n if (name.length > 214 || !/^[a-z0-9][a-z0-9._-]*$/.test(name)) {\n throw new Error(\n `Invalid catalog name '${name}': must be a valid npm package name ` +\n '(lowercase letters, digits, dots, hyphens, underscores; no leading dot/hyphen)',\n );\n }\n return name;\n}\n\nconst publishWorkflow = (): string => `name: Publish catalog\n\n# Compile the catalog with the wod CLI and deploy dist/ to GitHub Pages.\n# Requires Pages enabled: repo Settings → Pages → Source: \"GitHub Actions\".\n\non:\n push:\n branches: [main]\n workflow_dispatch:\n\npermissions:\n contents: read\n pages: write\n id-token: write\n\nconcurrency:\n group: pages\n cancel-in-progress: true\n\njobs:\n publish:\n runs-on: ubuntu-latest\n environment:\n name: github-pages\n url: \\${{ steps.deployment.outputs.page_url }}\n steps:\n - uses: actions/checkout@v4\n with:\n # Full history: seed manifest version stamps derive from git commit count.\n fetch-depth: 0\n\n - name: Set up Bun\n uses: oven-sh/setup-bun@v2\n with:\n bun-version: 1.4.x\n\n - name: Install dependencies\n run: bun install\n\n - name: Build seed\n run: bunx wod build . --output dist\n\n - uses: actions/configure-pages@v5\n\n - name: Upload dist\n uses: actions/upload-pages-artifact@v3\n with:\n path: dist\n\n - id: deployment\n uses: actions/deploy-pages@v4\n`;\n\nconst collectionReadme = (name: string): string => `# ${name}\n\nExample benchmark collection. Each \\`.md\\` file in this directory becomes part of\nthe \\`example\\` collection chunk; \\`README.md\\` is the collection's landing page.\n\nAdd one file per workout:\n\n\\`\\`\\`\\`markdown\n---\ntitle: My workout\ndate: 2026-01-01\n---\n\n# My workout\n\n\\`\\`\\`time\n(21-15-9)\n Thrusters @95lb\n Pull-ups\n\\`\\`\\`\n\\`\\`\\`\\`\n\nThe \\`date:\\` frontmatter field sets the workout's chronological placement\n(regardless of filename or directory).\n`;\n\nconst exampleWorkout = (date: string): string => `---\ntitle: Morning session\ndate: ${date}\n---\n\n# Morning session\n\n\\`\\`\\`time\n(21-15-9)\n Thrusters @95lb\n Pull-ups\n\\`\\`\\`\n`;\n\nconst catalogReadme = (name: string): string => `# ${name}\n\nA [WOD Wiki](https://github.com/bitcobblers/wod-wiki) workout catalog: plain\nMarkdown workouts compiled to static, version-stamped seed chunks and published\nvia GitHub Pages.\n\n## Develop\n\n\\`\\`\\`sh\nbun install\nbunx wod build . --output dist\n\\`\\`\\`\n\nWorkouts live under \\`markdown/\\` — this scaffold starts with one example\ncollection. Validate everything with \\`bunx wod build\\`: it gates every file on\nthe Whiteboard grammar and corpus layout before writing \\`dist/\\`.\n\n## Publish\n\nPush to GitHub and enable Pages (**Settings → Pages → Source: GitHub\nActions**). The bundled workflow (\\`.github/workflows/publish-catalog.yml\\`)\nbuilds the catalog on every push to \\`main\\` and deploys \\`dist/\\`.\n\n## Share\n\nOnce published, anyone can subscribe to this catalog from a WOD Wiki instance\nat:\n\n\\`\\`\\`\n<app-url>/subscribe?source=<url-encoded published catalog URL>\n\\`\\`\\`\n\nFor \\`owner\\`/\\`repo\\` on GitHub Pages the catalog URL is the deployed\ndirectory, \\`https://owner.github.io/repo/\\`, e.g.\n\\`/subscribe?source=https%3A%2F%2Fowner.github.io%2Frepo%2F\\`.\n`;\n\n/**\n * Scaffold a new catalog repository at `<cwd>/<name>`. Throws when the name is\n * invalid or the destination already exists; partial failure removes created files.\n */\nexport function scaffoldCatalog(name: string, opts: { cwd?: string } = {}): ScaffoldCatalogResult {\n validateCatalogName(name);\n const dir = resolve(opts.cwd ?? process.cwd(), name);\n // Atomic acquire: EEXIST is the refusal signal — no exists-check/create race,\n // and an existing destination is never removed or written.\n try {\n mkdirSync(dir);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'EEXIST') {\n throw new Error(`Refusing to overwrite '${dir}': destination already exists`, { cause: error });\n }\n throw error;\n }\n\n const date = new Date().toISOString().slice(0, 10);\n const files: Array<[rel: string, content: string]> = [\n ['package.json', `${JSON.stringify(\n {\n name,\n version: '0.1.0',\n private: true,\n type: 'module',\n description: `WOD Wiki workout catalog: ${name}`,\n scripts: {\n build: 'wod build . --output dist',\n },\n devDependencies: {\n '@bitcobblers/wod-wiki-tools': `^${VERSION}`,\n },\n },\n null,\n 2,\n )}\\n`],\n ['.gitignore', 'node_modules/\\ndist/\\n'],\n ['.github/workflows/publish-catalog.yml', publishWorkflow()],\n ['markdown/collections/example/README.md', collectionReadme(name)],\n [`markdown/collections/example/morning-session.md`, exampleWorkout(date)],\n ['README.md', catalogReadme(name)],\n ];\n\n try {\n for (const [rel, content] of files) {\n const target = join(dir, rel);\n mkdirSync(dirname(target), { recursive: true });\n writeFileSync(target, content, 'utf-8');\n }\n } catch (error) {\n rmSync(dir, { recursive: true, force: true });\n throw error;\n }\n return { dir, files: files.map(([rel]) => rel) };\n}\n"]}