@moku-labs/web 2.4.12 → 2.4.13
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 +6 -0
- package/dist/browser.mjs +35 -11
- package/dist/index.cjs +35 -11
- package/dist/index.d.cts +6 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.mjs +35 -11
- package/package.json +1 -1
package/dist/browser.d.mts
CHANGED
|
@@ -1998,6 +1998,12 @@ interface DataState {
|
|
|
1998
1998
|
lastWrite: DataWriteSummary | null;
|
|
1999
1999
|
/** Per-path fetched data, cached after the first `at(path)` (browser). */
|
|
2000
2000
|
cache: Map<string, unknown>;
|
|
2001
|
+
/**
|
|
2002
|
+
* Per-path fetches still in flight (browser). A second `at(path)` awaits the
|
|
2003
|
+
* same promise instead of starting another request. The entry is removed when
|
|
2004
|
+
* the fetch settles, on success and on failure, so a failure is never cached.
|
|
2005
|
+
*/
|
|
2006
|
+
pending: Map<string, Promise<unknown | null>>;
|
|
2001
2007
|
}
|
|
2002
2008
|
/**
|
|
2003
2009
|
* Public API mounted at `app.data` — the agnostic data provider. `write()` is the
|
package/dist/browser.mjs
CHANGED
|
@@ -2367,6 +2367,30 @@ async function loadJson(pathOrUrl) {
|
|
|
2367
2367
|
* the isomorphic `loadJson` (whose Node branch is itself lazy).
|
|
2368
2368
|
*/
|
|
2369
2369
|
/**
|
|
2370
|
+
* Fetches one path's data, caches it on success, and always clears the path's
|
|
2371
|
+
* in-flight entry. Never rejects: a failed fetch or JSON parse resolves `null`
|
|
2372
|
+
* and caches nothing, so a later `at(path)` retries.
|
|
2373
|
+
*
|
|
2374
|
+
* @param ctx - The data plugin context.
|
|
2375
|
+
* @param path - The page URL path (e.g. `/en/hello/`).
|
|
2376
|
+
* @returns The page's raw data, or `null` on failure.
|
|
2377
|
+
* @example
|
|
2378
|
+
* ```ts
|
|
2379
|
+
* const raw = await fetchAndCache(ctx, "/en/hello/");
|
|
2380
|
+
* ```
|
|
2381
|
+
*/
|
|
2382
|
+
async function fetchAndCache(ctx, path) {
|
|
2383
|
+
try {
|
|
2384
|
+
const data = await loadJson(`${ctx.config.baseUrl}${dataSuffix(path)}`);
|
|
2385
|
+
ctx.state.cache.set(path, data);
|
|
2386
|
+
return data;
|
|
2387
|
+
} catch {
|
|
2388
|
+
return null;
|
|
2389
|
+
} finally {
|
|
2390
|
+
ctx.state.pending.delete(path);
|
|
2391
|
+
}
|
|
2392
|
+
}
|
|
2393
|
+
/**
|
|
2370
2394
|
* Builds the data provider — the agnostic bridge. `write()` is the Node persist
|
|
2371
2395
|
* side; `at()` is the browser read side; `urlFor`/`fileFor` are the pure
|
|
2372
2396
|
* convention. No `onStart`/`onStop` (holds no long-lived resource).
|
|
@@ -2384,6 +2408,7 @@ function dataApi(ctx) {
|
|
|
2384
2408
|
return {
|
|
2385
2409
|
/**
|
|
2386
2410
|
* READ (browser) — fetch (and cache) the persisted data for a page path.
|
|
2411
|
+
* Concurrent calls for one path share one in-flight request.
|
|
2387
2412
|
* Returns the raw JSON as `unknown`, which the route uses directly as `ctx.data`
|
|
2388
2413
|
* (no route `.parse()`); returns `null` if the fetch or JSON parse fails (so
|
|
2389
2414
|
* `spa` can fall back to HTML).
|
|
@@ -2397,13 +2422,11 @@ function dataApi(ctx) {
|
|
|
2397
2422
|
*/
|
|
2398
2423
|
async at(path) {
|
|
2399
2424
|
if (ctx.state.cache.has(path)) return ctx.state.cache.get(path);
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
return null;
|
|
2406
|
-
}
|
|
2425
|
+
const inFlight = ctx.state.pending.get(path);
|
|
2426
|
+
if (inFlight) return inFlight;
|
|
2427
|
+
const request = fetchAndCache(ctx, path);
|
|
2428
|
+
ctx.state.pending.set(path, request);
|
|
2429
|
+
return request;
|
|
2407
2430
|
},
|
|
2408
2431
|
/**
|
|
2409
2432
|
* WRITE (Node) — persist one JSON file per entry, keyed by page path. Called by
|
|
@@ -2472,13 +2495,13 @@ const defaultDataConfig = {
|
|
|
2472
2495
|
//#region src/plugins/data/state.ts
|
|
2473
2496
|
/**
|
|
2474
2497
|
* Creates initial data state: a null `lastWrite` slot (populated by the Node
|
|
2475
|
-
* `write()` side)
|
|
2476
|
-
* side on first fetch).
|
|
2498
|
+
* `write()` side), an empty `cache` (populated lazily by the browser `at(path)`
|
|
2499
|
+
* side on first fetch) and an empty `pending` map of in-flight fetches.
|
|
2477
2500
|
*
|
|
2478
2501
|
* @param _ctx - Minimal context with global and config.
|
|
2479
2502
|
* @param _ctx.global - Global framework configuration.
|
|
2480
2503
|
* @param _ctx.config - Resolved plugin configuration.
|
|
2481
|
-
* @returns Fresh data state with no recorded write and an empty per-path cache.
|
|
2504
|
+
* @returns Fresh data state with no recorded write and an empty per-path cache and no pending fetch.
|
|
2482
2505
|
* @example
|
|
2483
2506
|
* ```ts
|
|
2484
2507
|
* const state = createDataState({ global: {}, config });
|
|
@@ -2487,7 +2510,8 @@ const defaultDataConfig = {
|
|
|
2487
2510
|
function createDataState(_ctx) {
|
|
2488
2511
|
return {
|
|
2489
2512
|
lastWrite: null,
|
|
2490
|
-
cache: /* @__PURE__ */ new Map()
|
|
2513
|
+
cache: /* @__PURE__ */ new Map(),
|
|
2514
|
+
pending: /* @__PURE__ */ new Map()
|
|
2491
2515
|
};
|
|
2492
2516
|
}
|
|
2493
2517
|
//#endregion
|
package/dist/index.cjs
CHANGED
|
@@ -4625,6 +4625,30 @@ async function loadJson(pathOrUrl) {
|
|
|
4625
4625
|
* the isomorphic `loadJson` (whose Node branch is itself lazy).
|
|
4626
4626
|
*/
|
|
4627
4627
|
/**
|
|
4628
|
+
* Fetches one path's data, caches it on success, and always clears the path's
|
|
4629
|
+
* in-flight entry. Never rejects: a failed fetch or JSON parse resolves `null`
|
|
4630
|
+
* and caches nothing, so a later `at(path)` retries.
|
|
4631
|
+
*
|
|
4632
|
+
* @param ctx - The data plugin context.
|
|
4633
|
+
* @param path - The page URL path (e.g. `/en/hello/`).
|
|
4634
|
+
* @returns The page's raw data, or `null` on failure.
|
|
4635
|
+
* @example
|
|
4636
|
+
* ```ts
|
|
4637
|
+
* const raw = await fetchAndCache(ctx, "/en/hello/");
|
|
4638
|
+
* ```
|
|
4639
|
+
*/
|
|
4640
|
+
async function fetchAndCache(ctx, path) {
|
|
4641
|
+
try {
|
|
4642
|
+
const data = await loadJson(`${ctx.config.baseUrl}${require_convention.dataSuffix(path)}`);
|
|
4643
|
+
ctx.state.cache.set(path, data);
|
|
4644
|
+
return data;
|
|
4645
|
+
} catch {
|
|
4646
|
+
return null;
|
|
4647
|
+
} finally {
|
|
4648
|
+
ctx.state.pending.delete(path);
|
|
4649
|
+
}
|
|
4650
|
+
}
|
|
4651
|
+
/**
|
|
4628
4652
|
* Builds the data provider — the agnostic bridge. `write()` is the Node persist
|
|
4629
4653
|
* side; `at()` is the browser read side; `urlFor`/`fileFor` are the pure
|
|
4630
4654
|
* convention. No `onStart`/`onStop` (holds no long-lived resource).
|
|
@@ -4642,6 +4666,7 @@ function dataApi(ctx) {
|
|
|
4642
4666
|
return {
|
|
4643
4667
|
/**
|
|
4644
4668
|
* READ (browser) — fetch (and cache) the persisted data for a page path.
|
|
4669
|
+
* Concurrent calls for one path share one in-flight request.
|
|
4645
4670
|
* Returns the raw JSON as `unknown`, which the route uses directly as `ctx.data`
|
|
4646
4671
|
* (no route `.parse()`); returns `null` if the fetch or JSON parse fails (so
|
|
4647
4672
|
* `spa` can fall back to HTML).
|
|
@@ -4655,13 +4680,11 @@ function dataApi(ctx) {
|
|
|
4655
4680
|
*/
|
|
4656
4681
|
async at(path) {
|
|
4657
4682
|
if (ctx.state.cache.has(path)) return ctx.state.cache.get(path);
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
return null;
|
|
4664
|
-
}
|
|
4683
|
+
const inFlight = ctx.state.pending.get(path);
|
|
4684
|
+
if (inFlight) return inFlight;
|
|
4685
|
+
const request = fetchAndCache(ctx, path);
|
|
4686
|
+
ctx.state.pending.set(path, request);
|
|
4687
|
+
return request;
|
|
4665
4688
|
},
|
|
4666
4689
|
/**
|
|
4667
4690
|
* WRITE (Node) — persist one JSON file per entry, keyed by page path. Called by
|
|
@@ -4730,13 +4753,13 @@ const defaultDataConfig = {
|
|
|
4730
4753
|
//#region src/plugins/data/state.ts
|
|
4731
4754
|
/**
|
|
4732
4755
|
* Creates initial data state: a null `lastWrite` slot (populated by the Node
|
|
4733
|
-
* `write()` side)
|
|
4734
|
-
* side on first fetch).
|
|
4756
|
+
* `write()` side), an empty `cache` (populated lazily by the browser `at(path)`
|
|
4757
|
+
* side on first fetch) and an empty `pending` map of in-flight fetches.
|
|
4735
4758
|
*
|
|
4736
4759
|
* @param _ctx - Minimal context with global and config.
|
|
4737
4760
|
* @param _ctx.global - Global framework configuration.
|
|
4738
4761
|
* @param _ctx.config - Resolved plugin configuration.
|
|
4739
|
-
* @returns Fresh data state with no recorded write and an empty per-path cache.
|
|
4762
|
+
* @returns Fresh data state with no recorded write and an empty per-path cache and no pending fetch.
|
|
4740
4763
|
* @example
|
|
4741
4764
|
* ```ts
|
|
4742
4765
|
* const state = createDataState({ global: {}, config });
|
|
@@ -4745,7 +4768,8 @@ const defaultDataConfig = {
|
|
|
4745
4768
|
function createDataState(_ctx) {
|
|
4746
4769
|
return {
|
|
4747
4770
|
lastWrite: null,
|
|
4748
|
-
cache: /* @__PURE__ */ new Map()
|
|
4771
|
+
cache: /* @__PURE__ */ new Map(),
|
|
4772
|
+
pending: /* @__PURE__ */ new Map()
|
|
4749
4773
|
};
|
|
4750
4774
|
}
|
|
4751
4775
|
//#endregion
|
package/dist/index.d.cts
CHANGED
|
@@ -3467,6 +3467,12 @@ interface DataState {
|
|
|
3467
3467
|
lastWrite: DataWriteSummary | null;
|
|
3468
3468
|
/** Per-path fetched data, cached after the first `at(path)` (browser). */
|
|
3469
3469
|
cache: Map<string, unknown>;
|
|
3470
|
+
/**
|
|
3471
|
+
* Per-path fetches still in flight (browser). A second `at(path)` awaits the
|
|
3472
|
+
* same promise instead of starting another request. The entry is removed when
|
|
3473
|
+
* the fetch settles, on success and on failure, so a failure is never cached.
|
|
3474
|
+
*/
|
|
3475
|
+
pending: Map<string, Promise<unknown | null>>;
|
|
3470
3476
|
}
|
|
3471
3477
|
/**
|
|
3472
3478
|
* Public API mounted at `app.data` — the agnostic data provider. `write()` is the
|
package/dist/index.d.mts
CHANGED
|
@@ -3465,6 +3465,12 @@ interface DataState {
|
|
|
3465
3465
|
lastWrite: DataWriteSummary | null;
|
|
3466
3466
|
/** Per-path fetched data, cached after the first `at(path)` (browser). */
|
|
3467
3467
|
cache: Map<string, unknown>;
|
|
3468
|
+
/**
|
|
3469
|
+
* Per-path fetches still in flight (browser). A second `at(path)` awaits the
|
|
3470
|
+
* same promise instead of starting another request. The entry is removed when
|
|
3471
|
+
* the fetch settles, on success and on failure, so a failure is never cached.
|
|
3472
|
+
*/
|
|
3473
|
+
pending: Map<string, Promise<unknown | null>>;
|
|
3468
3474
|
}
|
|
3469
3475
|
/**
|
|
3470
3476
|
* Public API mounted at `app.data` — the agnostic data provider. `write()` is the
|
package/dist/index.mjs
CHANGED
|
@@ -4581,6 +4581,30 @@ async function loadJson(pathOrUrl) {
|
|
|
4581
4581
|
* the isomorphic `loadJson` (whose Node branch is itself lazy).
|
|
4582
4582
|
*/
|
|
4583
4583
|
/**
|
|
4584
|
+
* Fetches one path's data, caches it on success, and always clears the path's
|
|
4585
|
+
* in-flight entry. Never rejects: a failed fetch or JSON parse resolves `null`
|
|
4586
|
+
* and caches nothing, so a later `at(path)` retries.
|
|
4587
|
+
*
|
|
4588
|
+
* @param ctx - The data plugin context.
|
|
4589
|
+
* @param path - The page URL path (e.g. `/en/hello/`).
|
|
4590
|
+
* @returns The page's raw data, or `null` on failure.
|
|
4591
|
+
* @example
|
|
4592
|
+
* ```ts
|
|
4593
|
+
* const raw = await fetchAndCache(ctx, "/en/hello/");
|
|
4594
|
+
* ```
|
|
4595
|
+
*/
|
|
4596
|
+
async function fetchAndCache(ctx, path) {
|
|
4597
|
+
try {
|
|
4598
|
+
const data = await loadJson(`${ctx.config.baseUrl}${dataSuffix(path)}`);
|
|
4599
|
+
ctx.state.cache.set(path, data);
|
|
4600
|
+
return data;
|
|
4601
|
+
} catch {
|
|
4602
|
+
return null;
|
|
4603
|
+
} finally {
|
|
4604
|
+
ctx.state.pending.delete(path);
|
|
4605
|
+
}
|
|
4606
|
+
}
|
|
4607
|
+
/**
|
|
4584
4608
|
* Builds the data provider — the agnostic bridge. `write()` is the Node persist
|
|
4585
4609
|
* side; `at()` is the browser read side; `urlFor`/`fileFor` are the pure
|
|
4586
4610
|
* convention. No `onStart`/`onStop` (holds no long-lived resource).
|
|
@@ -4598,6 +4622,7 @@ function dataApi(ctx) {
|
|
|
4598
4622
|
return {
|
|
4599
4623
|
/**
|
|
4600
4624
|
* READ (browser) — fetch (and cache) the persisted data for a page path.
|
|
4625
|
+
* Concurrent calls for one path share one in-flight request.
|
|
4601
4626
|
* Returns the raw JSON as `unknown`, which the route uses directly as `ctx.data`
|
|
4602
4627
|
* (no route `.parse()`); returns `null` if the fetch or JSON parse fails (so
|
|
4603
4628
|
* `spa` can fall back to HTML).
|
|
@@ -4611,13 +4636,11 @@ function dataApi(ctx) {
|
|
|
4611
4636
|
*/
|
|
4612
4637
|
async at(path) {
|
|
4613
4638
|
if (ctx.state.cache.has(path)) return ctx.state.cache.get(path);
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
return null;
|
|
4620
|
-
}
|
|
4639
|
+
const inFlight = ctx.state.pending.get(path);
|
|
4640
|
+
if (inFlight) return inFlight;
|
|
4641
|
+
const request = fetchAndCache(ctx, path);
|
|
4642
|
+
ctx.state.pending.set(path, request);
|
|
4643
|
+
return request;
|
|
4621
4644
|
},
|
|
4622
4645
|
/**
|
|
4623
4646
|
* WRITE (Node) — persist one JSON file per entry, keyed by page path. Called by
|
|
@@ -4686,13 +4709,13 @@ const defaultDataConfig = {
|
|
|
4686
4709
|
//#region src/plugins/data/state.ts
|
|
4687
4710
|
/**
|
|
4688
4711
|
* Creates initial data state: a null `lastWrite` slot (populated by the Node
|
|
4689
|
-
* `write()` side)
|
|
4690
|
-
* side on first fetch).
|
|
4712
|
+
* `write()` side), an empty `cache` (populated lazily by the browser `at(path)`
|
|
4713
|
+
* side on first fetch) and an empty `pending` map of in-flight fetches.
|
|
4691
4714
|
*
|
|
4692
4715
|
* @param _ctx - Minimal context with global and config.
|
|
4693
4716
|
* @param _ctx.global - Global framework configuration.
|
|
4694
4717
|
* @param _ctx.config - Resolved plugin configuration.
|
|
4695
|
-
* @returns Fresh data state with no recorded write and an empty per-path cache.
|
|
4718
|
+
* @returns Fresh data state with no recorded write and an empty per-path cache and no pending fetch.
|
|
4696
4719
|
* @example
|
|
4697
4720
|
* ```ts
|
|
4698
4721
|
* const state = createDataState({ global: {}, config });
|
|
@@ -4701,7 +4724,8 @@ const defaultDataConfig = {
|
|
|
4701
4724
|
function createDataState(_ctx) {
|
|
4702
4725
|
return {
|
|
4703
4726
|
lastWrite: null,
|
|
4704
|
-
cache: /* @__PURE__ */ new Map()
|
|
4727
|
+
cache: /* @__PURE__ */ new Map(),
|
|
4728
|
+
pending: /* @__PURE__ */ new Map()
|
|
4705
4729
|
};
|
|
4706
4730
|
}
|
|
4707
4731
|
//#endregion
|
package/package.json
CHANGED