@moku-labs/web 2.2.2 → 2.3.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.
- package/dist/browser.d.mts +176 -6
- package/dist/browser.mjs +115 -6
- package/dist/convention-Bs8SrQS9.mjs +109 -0
- package/dist/{convention-BpDfzX7e.cjs → convention-CLIDd9k-.cjs} +0 -43
- package/dist/convention-CsJw7CML.cjs +120 -0
- package/dist/index.cjs +390 -37
- package/dist/index.d.cts +195 -6
- package/dist/index.d.mts +195 -6
- package/dist/index.mjs +328 -16
- package/dist/writer-BBtgz9wt.cjs +90 -0
- package/dist/{writer-JdhX1Wld.cjs → writer-BEM-Pbgb.cjs} +4 -3
- package/dist/writer-C9BfpPio.mjs +87 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __exportAll = (all, no_symbols) => {
|
|
10
|
+
let target = {};
|
|
11
|
+
for (var name in all) __defProp(target, name, {
|
|
12
|
+
get: all[name],
|
|
13
|
+
enumerable: true
|
|
14
|
+
});
|
|
15
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
16
|
+
return target;
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
20
|
+
key = keys[i];
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
22
|
+
get: ((k) => from[k]).bind(null, key),
|
|
23
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return to;
|
|
27
|
+
};
|
|
28
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
29
|
+
value: mod,
|
|
30
|
+
enumerable: true
|
|
31
|
+
}) : target, mod));
|
|
32
|
+
//#endregion
|
|
33
|
+
const require_convention = require("./convention-CLIDd9k-.cjs");
|
|
34
|
+
const require_convention$1 = require("./convention-CsJw7CML.cjs");
|
|
3
35
|
let _moku_labs_common = require("@moku-labs/common");
|
|
4
36
|
let _moku_labs_core = require("@moku-labs/core");
|
|
5
37
|
let node_fs = require("node:fs");
|
|
@@ -7,8 +39,8 @@ let node_crypto = require("node:crypto");
|
|
|
7
39
|
let node_fs_promises = require("node:fs/promises");
|
|
8
40
|
let node_os = require("node:os");
|
|
9
41
|
let node_path = require("node:path");
|
|
10
|
-
let node_path$1 =
|
|
11
|
-
node_path =
|
|
42
|
+
let node_path$1 = __toESM(node_path, 1);
|
|
43
|
+
node_path = __toESM(node_path);
|
|
12
44
|
let feed = require("feed");
|
|
13
45
|
let preact = require("preact");
|
|
14
46
|
let preact_render_to_string = require("preact-render-to-string");
|
|
@@ -17,31 +49,31 @@ let node_readline = require("node:readline");
|
|
|
17
49
|
let node_url = require("node:url");
|
|
18
50
|
let _moku_labs_common_cli = require("@moku-labs/common/cli");
|
|
19
51
|
let gray_matter = require("gray-matter");
|
|
20
|
-
gray_matter =
|
|
52
|
+
gray_matter = __toESM(gray_matter, 1);
|
|
21
53
|
let _shikijs_rehype = require("@shikijs/rehype");
|
|
22
|
-
_shikijs_rehype =
|
|
54
|
+
_shikijs_rehype = __toESM(_shikijs_rehype, 1);
|
|
23
55
|
let rehype_sanitize = require("rehype-sanitize");
|
|
24
|
-
rehype_sanitize =
|
|
56
|
+
rehype_sanitize = __toESM(rehype_sanitize, 1);
|
|
25
57
|
let rehype_stringify = require("rehype-stringify");
|
|
26
|
-
rehype_stringify =
|
|
58
|
+
rehype_stringify = __toESM(rehype_stringify, 1);
|
|
27
59
|
let unified = require("unified");
|
|
28
60
|
let rehype_raw = require("rehype-raw");
|
|
29
|
-
rehype_raw =
|
|
61
|
+
rehype_raw = __toESM(rehype_raw, 1);
|
|
30
62
|
let remark_directive = require("remark-directive");
|
|
31
|
-
remark_directive =
|
|
63
|
+
remark_directive = __toESM(remark_directive, 1);
|
|
32
64
|
let remark_frontmatter = require("remark-frontmatter");
|
|
33
|
-
remark_frontmatter =
|
|
65
|
+
remark_frontmatter = __toESM(remark_frontmatter, 1);
|
|
34
66
|
let remark_gfm = require("remark-gfm");
|
|
35
|
-
remark_gfm =
|
|
67
|
+
remark_gfm = __toESM(remark_gfm, 1);
|
|
36
68
|
let remark_parse = require("remark-parse");
|
|
37
|
-
remark_parse =
|
|
69
|
+
remark_parse = __toESM(remark_parse, 1);
|
|
38
70
|
let remark_rehype = require("remark-rehype");
|
|
39
|
-
remark_rehype =
|
|
71
|
+
remark_rehype = __toESM(remark_rehype, 1);
|
|
40
72
|
let unist_util_visit = require("unist-util-visit");
|
|
41
73
|
let preact_jsx_runtime = require("preact/jsx-runtime");
|
|
42
74
|
let hast_util_sanitize = require("hast-util-sanitize");
|
|
43
75
|
let reading_time = require("reading-time");
|
|
44
|
-
reading_time =
|
|
76
|
+
reading_time = __toESM(reading_time, 1);
|
|
45
77
|
let node_process = require("node:process");
|
|
46
78
|
//#region src/config.ts
|
|
47
79
|
/**
|
|
@@ -2571,9 +2603,70 @@ function substituteAssetPlaceholders(ctx, html) {
|
|
|
2571
2603
|
return html.replaceAll(ASSETS_PLACEHOLDER, buildAssetTags(ctx)).replaceAll(CSS_ASSETS_PLACEHOLDER, buildAssetTags(ctx, "css")).replaceAll(JS_ASSETS_PLACEHOLDER, buildAssetTags(ctx, "js"));
|
|
2572
2604
|
}
|
|
2573
2605
|
/**
|
|
2574
|
-
*
|
|
2575
|
-
*
|
|
2576
|
-
*
|
|
2606
|
+
* Test whether `destination` is already an up-to-date copy of the `src` file: same
|
|
2607
|
+
* size and at least as new (mtime). A missing destination — or any stat failure —
|
|
2608
|
+
* reports stale: when in doubt, copy.
|
|
2609
|
+
*
|
|
2610
|
+
* @param src - The source file path.
|
|
2611
|
+
* @param destination - The candidate destination file path.
|
|
2612
|
+
* @returns `true` when the destination can be skipped.
|
|
2613
|
+
* @example
|
|
2614
|
+
* ```ts
|
|
2615
|
+
* if (await isFreshCopy(src, destination)) return;
|
|
2616
|
+
* ```
|
|
2617
|
+
*/
|
|
2618
|
+
async function isFreshCopy(src, destination) {
|
|
2619
|
+
try {
|
|
2620
|
+
const [srcStat, destinationStat] = await Promise.all([(0, node_fs_promises.stat)(src), (0, node_fs_promises.stat)(destination)]);
|
|
2621
|
+
return destinationStat.size === srcStat.size && destinationStat.mtimeMs >= srcStat.mtimeMs;
|
|
2622
|
+
} catch {
|
|
2623
|
+
return false;
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
/**
|
|
2627
|
+
* Recursively copy `from` into `to`, skipping every file whose destination is already
|
|
2628
|
+
* fresh. Skipping matters in dev rebuilds (which keep the previous outDir): re-copying
|
|
2629
|
+
* unchanged assets makes asset-watching dev servers (wrangler) reload on src-only
|
|
2630
|
+
* edits, and on macOS/APFS under Bun a large-file re-copy goes through clonefile(2),
|
|
2631
|
+
* whose FSEvents "ItemCloned" echo on the SOURCE path re-triggers `public/**` watchers
|
|
2632
|
+
* — a self-sustaining rebuild loop. Serial on purpose: public dirs can hold thousands
|
|
2633
|
+
* of assets and the skip path is stat-only, while an unbounded parallel copy risks fd
|
|
2634
|
+
* exhaustion.
|
|
2635
|
+
*
|
|
2636
|
+
* @param from - The source directory.
|
|
2637
|
+
* @param to - The destination directory (created when missing).
|
|
2638
|
+
* @returns The number of entries actually copied.
|
|
2639
|
+
* @example
|
|
2640
|
+
* ```ts
|
|
2641
|
+
* const copied = await copyDirIncremental("public", "dist");
|
|
2642
|
+
* ```
|
|
2643
|
+
*/
|
|
2644
|
+
async function copyDirIncremental(from, to) {
|
|
2645
|
+
await (0, node_fs_promises.mkdir)(to, { recursive: true });
|
|
2646
|
+
const entries = await (0, node_fs_promises.readdir)(from, { withFileTypes: true });
|
|
2647
|
+
let copied = 0;
|
|
2648
|
+
for (const entry of entries) {
|
|
2649
|
+
const src = node_path$1.default.join(from, entry.name);
|
|
2650
|
+
const destination = node_path$1.default.join(to, entry.name);
|
|
2651
|
+
if (entry.isDirectory()) copied += await copyDirIncremental(src, destination);
|
|
2652
|
+
else if (entry.isFile()) {
|
|
2653
|
+
if (await isFreshCopy(src, destination)) continue;
|
|
2654
|
+
await (0, node_fs_promises.copyFile)(src, destination);
|
|
2655
|
+
copied += 1;
|
|
2656
|
+
} else {
|
|
2657
|
+
await (0, node_fs_promises.cp)(src, destination, { recursive: true });
|
|
2658
|
+
copied += 1;
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
return copied;
|
|
2662
|
+
}
|
|
2663
|
+
/**
|
|
2664
|
+
* Copies the configured `publicDir` (default `"public"`) into `outDir`, preserving the
|
|
2665
|
+
* nested directory structure. The copy is incremental: a file whose destination already
|
|
2666
|
+
* exists with the same size and an mtime at least as new as the source is skipped. A
|
|
2667
|
+
* full build cleans outDir first, so every file misses the compare and the output is
|
|
2668
|
+
* identical to a verbatim copy; a dev rebuild (`skipClean`) rewrites only what changed.
|
|
2669
|
+
* Skips silently (returns `null`) when the source directory does not exist.
|
|
2577
2670
|
*
|
|
2578
2671
|
* @param ctx - Plugin context (provides `config`, `log`).
|
|
2579
2672
|
* @returns The copy result, or `null` when the public directory is absent.
|
|
@@ -2591,14 +2684,15 @@ async function copyPublic(ctx) {
|
|
|
2591
2684
|
});
|
|
2592
2685
|
return null;
|
|
2593
2686
|
}
|
|
2594
|
-
await (
|
|
2687
|
+
const copied = await copyDirIncremental(from, ctx.config.outDir);
|
|
2595
2688
|
ctx.log.debug("build:public", {
|
|
2596
2689
|
from,
|
|
2597
|
-
dest: ctx.config.outDir
|
|
2690
|
+
dest: ctx.config.outDir,
|
|
2691
|
+
copied
|
|
2598
2692
|
});
|
|
2599
2693
|
return {
|
|
2600
2694
|
from: node_path$1.default.normalize(from),
|
|
2601
|
-
copied
|
|
2695
|
+
copied
|
|
2602
2696
|
};
|
|
2603
2697
|
}
|
|
2604
2698
|
//#endregion
|
|
@@ -4460,7 +4554,7 @@ function dataApi(ctx) {
|
|
|
4460
4554
|
* ```
|
|
4461
4555
|
*/
|
|
4462
4556
|
async write(entries, options) {
|
|
4463
|
-
const { writeData } = await Promise.resolve().then(() => require("./writer-
|
|
4557
|
+
const { writeData } = await Promise.resolve().then(() => require("./writer-BEM-Pbgb.cjs"));
|
|
4464
4558
|
return writeData(ctx, entries, options);
|
|
4465
4559
|
},
|
|
4466
4560
|
/**
|
|
@@ -4544,7 +4638,7 @@ function createDataState(_ctx) {
|
|
|
4544
4638
|
* isInvalidBaseUrl("_data"); // true
|
|
4545
4639
|
* ```
|
|
4546
4640
|
*/
|
|
4547
|
-
function isInvalidBaseUrl(baseUrl) {
|
|
4641
|
+
function isInvalidBaseUrl$1(baseUrl) {
|
|
4548
4642
|
return typeof baseUrl !== "string" || !baseUrl.startsWith("/");
|
|
4549
4643
|
}
|
|
4550
4644
|
/**
|
|
@@ -4559,7 +4653,7 @@ function isInvalidBaseUrl(baseUrl) {
|
|
|
4559
4653
|
* ```
|
|
4560
4654
|
*/
|
|
4561
4655
|
function validateDataConfig(config) {
|
|
4562
|
-
if (isInvalidBaseUrl(config.baseUrl)) throw new Error(`[web] data.baseUrl: must be a site-root-relative URL path starting with "/" (e.g. "/_data/").`);
|
|
4656
|
+
if (isInvalidBaseUrl$1(config.baseUrl)) throw new Error(`[web] data.baseUrl: must be a site-root-relative URL path starting with "/" (e.g. "/_data/").`);
|
|
4563
4657
|
}
|
|
4564
4658
|
//#endregion
|
|
4565
4659
|
//#region src/plugins/data/index.ts
|
|
@@ -9181,6 +9275,252 @@ const cliPlugin = createPlugin$1("cli", {
|
|
|
9181
9275
|
api: createApi$1
|
|
9182
9276
|
});
|
|
9183
9277
|
//#endregion
|
|
9278
|
+
//#region src/plugins/collection/read.ts
|
|
9279
|
+
/**
|
|
9280
|
+
* @file `loadCollectionShard` — the collection plugin's standalone BROWSER read
|
|
9281
|
+
* primitive. Internal to the `collection` plugin AND exported for standalone
|
|
9282
|
+
* consumers: `collection.at(...)` wraps it, and a room-layer consumer can import it
|
|
9283
|
+
* directly from `@moku-labs/web/browser`.
|
|
9284
|
+
*
|
|
9285
|
+
* Unlike the `data` plugin's isomorphic `loadJson`, this uses the `fetch` global
|
|
9286
|
+
* DIRECTLY (no `node:fs` branch). Consumers — and tests — rely on `fetch` even
|
|
9287
|
+
* under Node test environments, so there is no document sniffing here: a shard is
|
|
9288
|
+
* always fetched over HTTP from the build-authored URL. This keeps the module
|
|
9289
|
+
* fully node-free.
|
|
9290
|
+
*/
|
|
9291
|
+
/**
|
|
9292
|
+
* Fetch + parse a build-authored collection shard over HTTP. Builds the shard URL
|
|
9293
|
+
* via {@link collectionUrl}, fetches it, and throws on a non-OK response so the
|
|
9294
|
+
* caller (`collection.at`) can decide whether to fall back.
|
|
9295
|
+
*
|
|
9296
|
+
* @template T - The expected shape of the parsed shard JSON.
|
|
9297
|
+
* @param baseUrl - The site-root URL prefix (ends with `/`, e.g. `"/"`).
|
|
9298
|
+
* @param collection - The collection name (e.g. `"bank"`).
|
|
9299
|
+
* @param shard - The shard key within the collection (e.g. `"en/animals"`).
|
|
9300
|
+
* @returns The parsed shard JSON, typed as `T`.
|
|
9301
|
+
* @throws {Error} If the fetch is not OK.
|
|
9302
|
+
* @example
|
|
9303
|
+
* ```ts
|
|
9304
|
+
* const animals = await loadCollectionShard<Animal[]>("/", "bank", "en/animals");
|
|
9305
|
+
* ```
|
|
9306
|
+
*/
|
|
9307
|
+
async function loadCollectionShard(baseUrl, collection, shard) {
|
|
9308
|
+
const url = require_convention$1.collectionUrl(baseUrl, collection, shard);
|
|
9309
|
+
const response = await fetch(url);
|
|
9310
|
+
if (!response.ok) throw new Error(`[web] collection: failed to fetch ${url} (${String(response.status)}).`);
|
|
9311
|
+
return response.json();
|
|
9312
|
+
}
|
|
9313
|
+
//#endregion
|
|
9314
|
+
//#region src/plugins/collection/api.ts
|
|
9315
|
+
/**
|
|
9316
|
+
* @file collection plugin — API factory (the collection provider surface).
|
|
9317
|
+
*
|
|
9318
|
+
* Node-free by construction: this module statically imports only types + the pure
|
|
9319
|
+
* convention + the node-free `read` primitive. The Node write side (`write()`)
|
|
9320
|
+
* reaches its `node:fs` writer through a lazy `await import("./writer")` at call
|
|
9321
|
+
* time, so a browser bundle that composes `collection` for the read side never
|
|
9322
|
+
* pulls `node:*`. The read side (`at()`) uses only the `fetch`-based
|
|
9323
|
+
* `loadCollectionShard`.
|
|
9324
|
+
*/
|
|
9325
|
+
/**
|
|
9326
|
+
* Builds the collection provider — the static-data bridge. `write()` is the Node
|
|
9327
|
+
* persist side; `at()` is the browser read side; `urlFor`/`fileFor` are the pure
|
|
9328
|
+
* convention. No `onStart`/`onStop` (holds no long-lived resource).
|
|
9329
|
+
*
|
|
9330
|
+
* @param ctx - The collection plugin context.
|
|
9331
|
+
* @returns The {@link CollectionProvider} mounted at `app.collection`.
|
|
9332
|
+
* @example
|
|
9333
|
+
* ```ts
|
|
9334
|
+
* const api = collectionApi(ctx);
|
|
9335
|
+
* await api.write([{ collection: "bank", shard: "en/animals", data }]); // Node build
|
|
9336
|
+
* await api.at("bank", "en/animals"); // browser
|
|
9337
|
+
* ```
|
|
9338
|
+
*/
|
|
9339
|
+
function collectionApi(ctx) {
|
|
9340
|
+
return {
|
|
9341
|
+
/**
|
|
9342
|
+
* READ (browser) — fetch (and cache) the persisted data for a `(collection,
|
|
9343
|
+
* shard)` key. Returns the raw JSON as `unknown`; returns `null` if the fetch
|
|
9344
|
+
* or JSON parse fails (so the consumer can fall back). Wraps the throwing
|
|
9345
|
+
* {@link loadCollectionShard} reader into a soft null-returning app read.
|
|
9346
|
+
*
|
|
9347
|
+
* @param collection - The collection name (e.g. `"bank"`).
|
|
9348
|
+
* @param shard - The shard key within the collection (e.g. `"en/animals"`).
|
|
9349
|
+
* @returns The shard's raw data, or `null` on failure.
|
|
9350
|
+
* @example
|
|
9351
|
+
* ```ts
|
|
9352
|
+
* const raw = await api.at("bank", "en/animals");
|
|
9353
|
+
* ```
|
|
9354
|
+
*/
|
|
9355
|
+
async at(collection, shard) {
|
|
9356
|
+
const key = `${collection}/${shard}`;
|
|
9357
|
+
if (ctx.state.cache.has(key)) return ctx.state.cache.get(key);
|
|
9358
|
+
try {
|
|
9359
|
+
const data = await loadCollectionShard(ctx.config.baseUrl, collection, shard);
|
|
9360
|
+
ctx.state.cache.set(key, data);
|
|
9361
|
+
return data;
|
|
9362
|
+
} catch {
|
|
9363
|
+
return null;
|
|
9364
|
+
}
|
|
9365
|
+
},
|
|
9366
|
+
/**
|
|
9367
|
+
* WRITE (Node) — persist one JSON file per entry, keyed by `(collection,
|
|
9368
|
+
* shard)`. Called by the build after it authors the shards. Lazily loads its
|
|
9369
|
+
* `node:fs` writer (keeping a browser bundle node-free).
|
|
9370
|
+
*
|
|
9371
|
+
* @param entries - The per-shard data to persist.
|
|
9372
|
+
* @param options - Optional `{ outDir }` override (defaults to `./dist`).
|
|
9373
|
+
* @param options.outDir - Build output directory the write happens under.
|
|
9374
|
+
* @returns A summary of the written files.
|
|
9375
|
+
* @example
|
|
9376
|
+
* ```ts
|
|
9377
|
+
* await api.write([{ collection: "bank", shard: "ru", data }], { outDir: "dist" });
|
|
9378
|
+
* ```
|
|
9379
|
+
*/
|
|
9380
|
+
async write(entries, options) {
|
|
9381
|
+
const { writeCollection } = await Promise.resolve().then(() => require("./writer-BBtgz9wt.cjs"));
|
|
9382
|
+
return writeCollection(ctx, entries, options);
|
|
9383
|
+
},
|
|
9384
|
+
/**
|
|
9385
|
+
* PURE — the browser fetch URL for a `(collection, shard)` key.
|
|
9386
|
+
*
|
|
9387
|
+
* @param collection - The collection name.
|
|
9388
|
+
* @param shard - The shard key within the collection.
|
|
9389
|
+
* @returns The site-root-relative shard URL.
|
|
9390
|
+
* @example
|
|
9391
|
+
* ```ts
|
|
9392
|
+
* api.urlFor("bank", "en/animals"); // "/bank/en/animals.json"
|
|
9393
|
+
* ```
|
|
9394
|
+
*/
|
|
9395
|
+
urlFor(collection, shard) {
|
|
9396
|
+
return require_convention$1.collectionUrl(ctx.config.baseUrl, collection, shard);
|
|
9397
|
+
},
|
|
9398
|
+
/**
|
|
9399
|
+
* PURE — the `outDir`-relative file path for a `(collection, shard)` key.
|
|
9400
|
+
*
|
|
9401
|
+
* @param collection - The collection name.
|
|
9402
|
+
* @param shard - The shard key within the collection.
|
|
9403
|
+
* @returns The output-relative file path.
|
|
9404
|
+
* @example
|
|
9405
|
+
* ```ts
|
|
9406
|
+
* api.fileFor("bank", "en/animals"); // "bank/en/animals.json"
|
|
9407
|
+
* ```
|
|
9408
|
+
*/
|
|
9409
|
+
fileFor(collection, shard) {
|
|
9410
|
+
return require_convention$1.relativeShardFile(collection, shard);
|
|
9411
|
+
}
|
|
9412
|
+
};
|
|
9413
|
+
}
|
|
9414
|
+
//#endregion
|
|
9415
|
+
//#region src/plugins/collection/config.ts
|
|
9416
|
+
/**
|
|
9417
|
+
* Typed default collection config (R6: no inline `as`). `baseUrl` is the READ-side
|
|
9418
|
+
* site-root URL prefix the browser fetches shards from; the collection name is the
|
|
9419
|
+
* top directory under it. The default `"/"` serves shards straight from the site
|
|
9420
|
+
* root (e.g. `/bank/en/animals.json`).
|
|
9421
|
+
*
|
|
9422
|
+
* @example
|
|
9423
|
+
* ```ts
|
|
9424
|
+
* createPlugin("collection", { config: defaultCollectionConfig });
|
|
9425
|
+
* ```
|
|
9426
|
+
*/
|
|
9427
|
+
const defaultCollectionConfig = { baseUrl: "/" };
|
|
9428
|
+
//#endregion
|
|
9429
|
+
//#region src/plugins/collection/state.ts
|
|
9430
|
+
/**
|
|
9431
|
+
* Creates initial collection state: a null `lastWrite` slot (populated by the Node
|
|
9432
|
+
* `write()` side) and an empty `cache` (populated lazily by the browser
|
|
9433
|
+
* `at(collection, shard)` side on first fetch).
|
|
9434
|
+
*
|
|
9435
|
+
* @param _ctx - Minimal context with global and config.
|
|
9436
|
+
* @param _ctx.global - Global framework configuration.
|
|
9437
|
+
* @param _ctx.config - Resolved plugin configuration.
|
|
9438
|
+
* @returns Fresh collection state with no recorded write and an empty per-shard cache.
|
|
9439
|
+
* @example
|
|
9440
|
+
* ```ts
|
|
9441
|
+
* const state = createCollectionState({ global: {}, config });
|
|
9442
|
+
* ```
|
|
9443
|
+
*/
|
|
9444
|
+
function createCollectionState(_ctx) {
|
|
9445
|
+
return {
|
|
9446
|
+
lastWrite: null,
|
|
9447
|
+
cache: /* @__PURE__ */ new Map()
|
|
9448
|
+
};
|
|
9449
|
+
}
|
|
9450
|
+
//#endregion
|
|
9451
|
+
//#region src/plugins/collection/validate.ts
|
|
9452
|
+
/**
|
|
9453
|
+
* Reports whether a `baseUrl` value is invalid: it must be a string that ends with
|
|
9454
|
+
* a `"/"` so the collection name appends cleanly (`baseUrl + collection + "/" + …`).
|
|
9455
|
+
*
|
|
9456
|
+
* @param baseUrl - The candidate `baseUrl` value to check.
|
|
9457
|
+
* @returns `true` when `baseUrl` is not a string or does not end with "/".
|
|
9458
|
+
* @example
|
|
9459
|
+
* ```ts
|
|
9460
|
+
* isInvalidBaseUrl("/"); // false
|
|
9461
|
+
* isInvalidBaseUrl("/cdn"); // true
|
|
9462
|
+
* ```
|
|
9463
|
+
*/
|
|
9464
|
+
function isInvalidBaseUrl(baseUrl) {
|
|
9465
|
+
return typeof baseUrl !== "string" || !baseUrl.endsWith("/");
|
|
9466
|
+
}
|
|
9467
|
+
/**
|
|
9468
|
+
* Validates the resolved collection config: the browser `baseUrl` must be a string
|
|
9469
|
+
* ending with `"/"` so the collection name appends cleanly.
|
|
9470
|
+
*
|
|
9471
|
+
* @param config - The resolved plugin configuration.
|
|
9472
|
+
* @throws {Error} If `baseUrl` is not a string ending with "/".
|
|
9473
|
+
* @example
|
|
9474
|
+
* ```ts
|
|
9475
|
+
* validateCollectionConfig({ baseUrl: "/" });
|
|
9476
|
+
* ```
|
|
9477
|
+
*/
|
|
9478
|
+
function validateCollectionConfig(config) {
|
|
9479
|
+
if (isInvalidBaseUrl(config.baseUrl)) throw new Error(`[web] collection.baseUrl: must be a URL prefix ending with "/" (e.g. "/" or "/cdn/").`);
|
|
9480
|
+
}
|
|
9481
|
+
//#endregion
|
|
9482
|
+
//#region src/plugins/collection/index.ts
|
|
9483
|
+
/**
|
|
9484
|
+
* @file collection — Standard tier plugin (wiring-only). The static-data
|
|
9485
|
+
* COLLECTION provider — the collection-keyed sibling of the page-path-keyed `data`
|
|
9486
|
+
* plugin.
|
|
9487
|
+
*
|
|
9488
|
+
* Owns ONE contract — `(collection, shard) → persisted JSON file` — and nothing
|
|
9489
|
+
* about what the data is: `write(entries)` persists per-shard JSON on Node (the
|
|
9490
|
+
* build supplies the shards it already authored); `at(collection, shard)` fetches +
|
|
9491
|
+
* caches it in the browser as `unknown`, read on demand by the consumer. NOT a
|
|
9492
|
+
* framework default — the consumer composes it where needed (Node build AND/OR
|
|
9493
|
+
* browser app).
|
|
9494
|
+
*
|
|
9495
|
+
* **No hard `depends`** — fully browser-composable; the `node:fs` writer is behind
|
|
9496
|
+
* a lazy `import()` inside `write()`. Build ordering is a call-site contract: the
|
|
9497
|
+
* build writes shards during/after its pages phase, via `app.collection.write`.
|
|
9498
|
+
* No `onStart`/`onStop`.
|
|
9499
|
+
* @see README.md
|
|
9500
|
+
*/
|
|
9501
|
+
/**
|
|
9502
|
+
* Collection plugin — the static-data collection provider. Mounts
|
|
9503
|
+
* `write(entries)` (Node persist), `at(collection, shard)` (browser read), and the
|
|
9504
|
+
* pure `urlFor`/`fileFor` convention at `app.collection`.
|
|
9505
|
+
*
|
|
9506
|
+
* @example
|
|
9507
|
+
* ```ts
|
|
9508
|
+
* // Node build: write build-authored shards during/after the build's pages phase.
|
|
9509
|
+
* const app = createApp({ plugins: [collectionPlugin, buildPlugin] });
|
|
9510
|
+
* await app.build.run();
|
|
9511
|
+
* await app.collection.write([{ collection: "bank", shard: "en/animals", data }]);
|
|
9512
|
+
*
|
|
9513
|
+
* // Browser app: compose `collectionPlugin` too; fetch a shard on demand.
|
|
9514
|
+
* const raw = await app.collection.at("bank", "en/animals"); // unknown | null
|
|
9515
|
+
* ```
|
|
9516
|
+
*/
|
|
9517
|
+
const collectionPlugin = createPlugin$1("collection", {
|
|
9518
|
+
config: defaultCollectionConfig,
|
|
9519
|
+
createState: createCollectionState,
|
|
9520
|
+
onInit: (ctx) => validateCollectionConfig(ctx.config),
|
|
9521
|
+
api: collectionApi
|
|
9522
|
+
});
|
|
9523
|
+
//#endregion
|
|
9184
9524
|
//#region src/plugins/spa/api.ts
|
|
9185
9525
|
/**
|
|
9186
9526
|
* Creates the spa plugin API surface (registration / control). All methods
|
|
@@ -9346,7 +9686,7 @@ function syncHead(_head, doc) {
|
|
|
9346
9686
|
}
|
|
9347
9687
|
//#endregion
|
|
9348
9688
|
//#region src/plugins/spa/types.ts
|
|
9349
|
-
var types_exports$
|
|
9689
|
+
var types_exports$8 = /* @__PURE__ */ __exportAll({ ISLAND_HOOK_NAMES: () => ISLAND_HOOK_NAMES });
|
|
9350
9690
|
/** Allowed hook names — single source of truth for fail-fast validation. */
|
|
9351
9691
|
const ISLAND_HOOK_NAMES = [
|
|
9352
9692
|
"onCreate",
|
|
@@ -11479,25 +11819,28 @@ const spaPlugin = createPlugin$1("spa", {
|
|
|
11479
11819
|
});
|
|
11480
11820
|
//#endregion
|
|
11481
11821
|
//#region src/plugins/build/types.ts
|
|
11482
|
-
var types_exports = /* @__PURE__ */
|
|
11822
|
+
var types_exports = /* @__PURE__ */ __exportAll({});
|
|
11483
11823
|
//#endregion
|
|
11484
11824
|
//#region src/plugins/cli/types.ts
|
|
11485
|
-
var types_exports$1 = /* @__PURE__ */
|
|
11825
|
+
var types_exports$1 = /* @__PURE__ */ __exportAll({});
|
|
11826
|
+
//#endregion
|
|
11827
|
+
//#region src/plugins/collection/types.ts
|
|
11828
|
+
var types_exports$2 = /* @__PURE__ */ __exportAll({});
|
|
11486
11829
|
//#endregion
|
|
11487
11830
|
//#region src/plugins/content/types.ts
|
|
11488
|
-
var types_exports$
|
|
11831
|
+
var types_exports$3 = /* @__PURE__ */ __exportAll({});
|
|
11489
11832
|
//#endregion
|
|
11490
11833
|
//#region src/plugins/data/types.ts
|
|
11491
|
-
var types_exports$
|
|
11834
|
+
var types_exports$4 = /* @__PURE__ */ __exportAll({});
|
|
11492
11835
|
//#endregion
|
|
11493
11836
|
//#region src/plugins/deploy/types.ts
|
|
11494
|
-
var types_exports$
|
|
11837
|
+
var types_exports$5 = /* @__PURE__ */ __exportAll({});
|
|
11495
11838
|
//#endregion
|
|
11496
11839
|
//#region src/plugins/head/types.ts
|
|
11497
|
-
var types_exports$
|
|
11840
|
+
var types_exports$6 = /* @__PURE__ */ __exportAll({});
|
|
11498
11841
|
//#endregion
|
|
11499
11842
|
//#region src/plugins/router/types.ts
|
|
11500
|
-
var types_exports$
|
|
11843
|
+
var types_exports$7 = /* @__PURE__ */ __exportAll({});
|
|
11501
11844
|
//#endregion
|
|
11502
11845
|
//#region node_modules/unist-util-stringify-position/lib/index.js
|
|
11503
11846
|
/**
|
|
@@ -13709,44 +14052,51 @@ Object.defineProperty(exports, "Cli", {
|
|
|
13709
14052
|
return types_exports$1;
|
|
13710
14053
|
}
|
|
13711
14054
|
});
|
|
13712
|
-
Object.defineProperty(exports, "
|
|
14055
|
+
Object.defineProperty(exports, "Collection", {
|
|
13713
14056
|
enumerable: true,
|
|
13714
14057
|
get: function() {
|
|
13715
14058
|
return types_exports$2;
|
|
13716
14059
|
}
|
|
13717
14060
|
});
|
|
13718
|
-
Object.defineProperty(exports, "
|
|
14061
|
+
Object.defineProperty(exports, "Content", {
|
|
13719
14062
|
enumerable: true,
|
|
13720
14063
|
get: function() {
|
|
13721
14064
|
return types_exports$3;
|
|
13722
14065
|
}
|
|
13723
14066
|
});
|
|
13724
|
-
Object.defineProperty(exports, "
|
|
14067
|
+
Object.defineProperty(exports, "Data", {
|
|
13725
14068
|
enumerable: true,
|
|
13726
14069
|
get: function() {
|
|
13727
14070
|
return types_exports$4;
|
|
13728
14071
|
}
|
|
13729
14072
|
});
|
|
14073
|
+
Object.defineProperty(exports, "Deploy", {
|
|
14074
|
+
enumerable: true,
|
|
14075
|
+
get: function() {
|
|
14076
|
+
return types_exports$5;
|
|
14077
|
+
}
|
|
14078
|
+
});
|
|
13730
14079
|
exports.EmbedFacadeButton = EmbedFacadeButton;
|
|
13731
14080
|
exports.GalleryTrack = GalleryTrack;
|
|
13732
14081
|
Object.defineProperty(exports, "Head", {
|
|
13733
14082
|
enumerable: true,
|
|
13734
14083
|
get: function() {
|
|
13735
|
-
return types_exports$
|
|
14084
|
+
return types_exports$6;
|
|
13736
14085
|
}
|
|
13737
14086
|
});
|
|
13738
14087
|
Object.defineProperty(exports, "Router", {
|
|
13739
14088
|
enumerable: true,
|
|
13740
14089
|
get: function() {
|
|
13741
|
-
return types_exports$
|
|
14090
|
+
return types_exports$7;
|
|
13742
14091
|
}
|
|
13743
14092
|
});
|
|
13744
14093
|
Object.defineProperty(exports, "Spa", {
|
|
13745
14094
|
enumerable: true,
|
|
13746
14095
|
get: function() {
|
|
13747
|
-
return types_exports$
|
|
14096
|
+
return types_exports$8;
|
|
13748
14097
|
}
|
|
13749
14098
|
});
|
|
14099
|
+
exports.__toESM = __toESM;
|
|
13750
14100
|
Object.defineProperty(exports, "browserEnv", {
|
|
13751
14101
|
enumerable: true,
|
|
13752
14102
|
get: function() {
|
|
@@ -13763,6 +14113,8 @@ Object.defineProperty(exports, "cloudflareBindings", {
|
|
|
13763
14113
|
return _moku_labs_common.cloudflareBindings;
|
|
13764
14114
|
}
|
|
13765
14115
|
});
|
|
14116
|
+
exports.collectionPlugin = collectionPlugin;
|
|
14117
|
+
exports.collectionUrl = require_convention$1.collectionUrl;
|
|
13766
14118
|
exports.contentPlugin = contentPlugin;
|
|
13767
14119
|
exports.createApp = createApp;
|
|
13768
14120
|
exports.createChannel = createChannel;
|
|
@@ -13792,6 +14144,7 @@ exports.hreflang = hreflang;
|
|
|
13792
14144
|
exports.i18nPlugin = i18nPlugin;
|
|
13793
14145
|
exports.jsonLd = jsonLd;
|
|
13794
14146
|
exports.lazyEmbed = lazyEmbed;
|
|
14147
|
+
exports.loadCollectionShard = loadCollectionShard;
|
|
13795
14148
|
Object.defineProperty(exports, "logPlugin", {
|
|
13796
14149
|
enumerable: true,
|
|
13797
14150
|
get: function() {
|