@webjsdev/core 0.7.32 → 0.7.34
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/webjs-core-browser.js +3 -3
- package/dist/webjs-core-browser.js.map +2 -2
- package/dist/webjs-core.js +3 -3
- package/dist/webjs-core.js.map +2 -2
- package/package.json +1 -1
- package/src/component.js +1 -1
- package/src/context.js +1 -1
- package/src/metadata.d.ts +1 -1
- package/src/render-server.js +1 -1
- package/src/rich-fetch.js +2 -2
- package/src/router-client.js +95 -6
- package/src/routes.d.ts +2 -2
- package/src/serializable.d.ts +3 -3
- package/src/serialize.d.ts +1 -1
- package/src/serialize.js +1 -1
- package/src/signal.js +1 -1
- package/src/testing.js +1 -1
- package/src/webjs-config.d.ts +13 -2
- package/src/websocket-client.js +1 -1
package/package.json
CHANGED
package/src/component.js
CHANGED
|
@@ -159,7 +159,7 @@ function defaultHasChanged(a, b) {
|
|
|
159
159
|
* `attachInternals()` on hydration.
|
|
160
160
|
*
|
|
161
161
|
* Deliberate deviation from lit: lit's `checkValidity` / `reportValidity`
|
|
162
|
-
* THROW on the server.
|
|
162
|
+
* THROW on the server. WebJs returns `true` instead, to keep SSR
|
|
163
163
|
* progressive-enhancement-safe (a stray validity call in a constructor must
|
|
164
164
|
* not 500 the page); the browser does the real validation.
|
|
165
165
|
* @returns {any}
|
package/src/context.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Context Protocol: cross-component data sharing without prop drilling.
|
|
3
3
|
*
|
|
4
4
|
* Implements the W3C Community Group Context Protocol so any web component
|
|
5
|
-
* (not just
|
|
5
|
+
* (not just WebJs components) can participate as a provider or consumer.
|
|
6
6
|
*
|
|
7
7
|
* ## When to use
|
|
8
8
|
*
|
package/src/metadata.d.ts
CHANGED
|
@@ -259,7 +259,7 @@ export interface Metadata {
|
|
|
259
259
|
* `<link rel="preconnect">` hints: warm DNS + TLS + TCP to a cross-origin
|
|
260
260
|
* the page is about to talk to (an API host, a font / image CDN). Each
|
|
261
261
|
* entry is a URL string or `{ url, crossorigin? }` (a font CDN needs
|
|
262
|
-
* `crossorigin`). A single value or an array.
|
|
262
|
+
* `crossorigin`). A single value or an array. WebJs ALSO auto-emits one
|
|
263
263
|
* preconnect to the resolved vendor CDN origin for an unpinned app (deduped
|
|
264
264
|
* against an author-declared one).
|
|
265
265
|
*/
|
package/src/render-server.js
CHANGED
|
@@ -390,7 +390,7 @@ function isProd() {
|
|
|
390
390
|
* renders an empty (silent, isolated) element so no internal detail leaks.
|
|
391
391
|
*
|
|
392
392
|
* The prod-silence signal is the SERVER's `dev` flag, threaded through the SSR
|
|
393
|
-
* render context (#483).
|
|
393
|
+
* render context (#483). WebJs keys prod on the CLI `dev` flag, not `NODE_ENV`,
|
|
394
394
|
* and `webjs start` does not export `NODE_ENV=production`, so a bare prod launch
|
|
395
395
|
* would otherwise leak the message. When `dev` is undefined (a context-free
|
|
396
396
|
* `renderToString` with no server signal, e.g. a bare unit test) it falls back
|
package/src/rich-fetch.js
CHANGED
|
@@ -8,14 +8,14 @@ const RPC_CONTENT_TYPE = 'application/vnd.webjs+json';
|
|
|
8
8
|
* `TypedArray`, `Blob`, `File`, `FormData`, cycles).
|
|
9
9
|
*
|
|
10
10
|
* - Adds `Accept: application/vnd.webjs+json` to the request so a
|
|
11
|
-
* server-side `json(data)` helper encodes with the
|
|
11
|
+
* server-side `json(data)` helper encodes with the WebJs serializer.
|
|
12
12
|
* - If the response content-type matches, decodes with the webjs
|
|
13
13
|
* serializer and returns the rich value.
|
|
14
14
|
* - Otherwise decodes with plain `.json()` (so any route you haven't
|
|
15
15
|
* opted in on still works).
|
|
16
16
|
* - Request bodies: if `init.body` is a plain object (not a string,
|
|
17
17
|
* FormData/Blob/ArrayBuffer/ReadableStream/URLSearchParams), it is
|
|
18
|
-
* encoded with the
|
|
18
|
+
* encoded with the WebJs serializer and the request content-type is
|
|
19
19
|
* set to our vendor type.
|
|
20
20
|
*
|
|
21
21
|
* ```js
|
package/src/router-client.js
CHANGED
|
@@ -153,7 +153,7 @@ let currentPageUrl = null;
|
|
|
153
153
|
* Previous value of `history.scrollRestoration` (so we can restore it
|
|
154
154
|
* when the router is disabled). The browser's default behavior of
|
|
155
155
|
* auto-restoring scroll on popstate races with the SPA's own scroll
|
|
156
|
-
* restoration: disabled here so
|
|
156
|
+
* restoration: disabled here so WebJs is the sole authority on scroll
|
|
157
157
|
* during navigation. Same pattern as Turbo Drive's
|
|
158
158
|
* `assumeControlOfScrollRestoration()` (turbo/src/core/drive/history.js).
|
|
159
159
|
*
|
|
@@ -1189,7 +1189,7 @@ function prefetchSuppressed(anchor) {
|
|
|
1189
1189
|
|
|
1190
1190
|
/**
|
|
1191
1191
|
* Resolve the prefetch strategy for an anchor from a `data-prefetch`
|
|
1192
|
-
* attribute.
|
|
1192
|
+
* attribute. WebJs has no Link component (links are plain `<a href>`), so
|
|
1193
1193
|
* the knob is a valid-HTML `data-*` attribute, the same shape SvelteKit
|
|
1194
1194
|
* (`data-sveltekit-preload-data`) and Astro (`data-astro-prefetch`) use.
|
|
1195
1195
|
* Next.js / Nuxt / Remix express the same choice as a component PROP
|
|
@@ -1284,9 +1284,34 @@ function prefetch(href) {
|
|
|
1284
1284
|
if (!/^text\/html\b/i.test(ctype)) return;
|
|
1285
1285
|
if (resp.status >= 400) return;
|
|
1286
1286
|
const build = resp.headers.get('x-webjs-build');
|
|
1287
|
+
const src = resp.headers.get('x-webjs-src');
|
|
1288
|
+
// Deploy detected at PREFETCH time (#899). A prefetch fetch carries the
|
|
1289
|
+
// server's current build id AND app-source id. If EITHER differs from what
|
|
1290
|
+
// the page booted with, a deploy landed, so every earlier snapshot/prefetch
|
|
1291
|
+
// is pre-deploy and stale. Evict them here, well before the click (a
|
|
1292
|
+
// hover/viewport prefetch fires early), so a click on a previously-
|
|
1293
|
+
// prefetched link re-fetches fresh (then applySwap hard-reloads on a build
|
|
1294
|
+
// change or soft-applies on a src-only change). This shrinks the window
|
|
1295
|
+
// where a pre-deploy prefetch, whose stored ids equal the still-old page
|
|
1296
|
+
// ids so applySwap alone cannot tell it is stale, is served. Both ids of a
|
|
1297
|
+
// pair must be present: an empty id is the warmup "version unknown", never
|
|
1298
|
+
// a deploy signal.
|
|
1299
|
+
const pageTag = typeof document !== 'undefined' ? document.querySelector('script[type="importmap"]') : null;
|
|
1300
|
+
const pageBuild = pageTag ? pageTag.getAttribute('data-webjs-build') : null;
|
|
1301
|
+
const pageSrc = pageTag ? pageTag.getAttribute('data-webjs-src') : null;
|
|
1302
|
+
if ((build && pageBuild && build !== pageBuild) || (src && pageSrc && src !== pageSrc)) {
|
|
1303
|
+
snapshotCache.clear();
|
|
1304
|
+
prefetchCache.clear();
|
|
1305
|
+
// Deliberately do NOT advance the page's data-webjs-src here (only the
|
|
1306
|
+
// foreground `applySwap` does). A prefetch is speculative; leaving the
|
|
1307
|
+
// reference id on the old deploy keeps applySwap the single authority
|
|
1308
|
+
// that settles the page on the first real navigation. The cost is small:
|
|
1309
|
+
// repeated prefetches in the pre-first-nav window each re-clear the
|
|
1310
|
+
// (already tiny) caches, which converges the instant the user navigates.
|
|
1311
|
+
}
|
|
1287
1312
|
const finalUrl = resp.redirected && resp.url ? resp.url : href;
|
|
1288
1313
|
const html = await resp.text();
|
|
1289
|
-
prefetchStore(key, { html, build, finalUrl, at: nowMs() });
|
|
1314
|
+
prefetchStore(key, { html, build, src, finalUrl, at: nowMs() });
|
|
1290
1315
|
})
|
|
1291
1316
|
.catch(() => { /* speculative: swallow */ })
|
|
1292
1317
|
.finally(() => {
|
|
@@ -1608,6 +1633,7 @@ async function fetchAndApply(href, frameId, recordHistory, optimisticState, meth
|
|
|
1608
1633
|
// shell swap. Null for a buffered (non-streaming) or prefetched response.
|
|
1609
1634
|
let streamCtx = null;
|
|
1610
1635
|
let incomingBuild = null;
|
|
1636
|
+
let incomingSrc = null;
|
|
1611
1637
|
/** @type {number | null} */
|
|
1612
1638
|
let respStatus = null;
|
|
1613
1639
|
/** @type {boolean} */
|
|
@@ -1633,6 +1659,7 @@ async function fetchAndApply(href, frameId, recordHistory, optimisticState, meth
|
|
|
1633
1659
|
if (prefetched) {
|
|
1634
1660
|
html = prefetched.html;
|
|
1635
1661
|
incomingBuild = prefetched.build;
|
|
1662
|
+
incomingSrc = prefetched.src;
|
|
1636
1663
|
finalUrl = prefetched.finalUrl;
|
|
1637
1664
|
// A consumed prefetch is a successful 200 GET fragment.
|
|
1638
1665
|
respStatus = 200;
|
|
@@ -1725,6 +1752,7 @@ async function fetchAndApply(href, frameId, recordHistory, optimisticState, meth
|
|
|
1725
1752
|
// tag to compare. The applySwap importmap-mismatch guard reads
|
|
1726
1753
|
// this to detect deploys that bumped the vendor pin.
|
|
1727
1754
|
incomingBuild = resp.headers.get('x-webjs-build');
|
|
1755
|
+
incomingSrc = resp.headers.get('x-webjs-src');
|
|
1728
1756
|
// Progressive streaming (#473): read only up to the first streamed Suspense
|
|
1729
1757
|
// boundary so the shell (with fallbacks) swaps in immediately; the rest
|
|
1730
1758
|
// streams in after the swap. A body with no boundaries reads to completion,
|
|
@@ -1763,7 +1791,7 @@ async function fetchAndApply(href, frameId, recordHistory, optimisticState, meth
|
|
|
1763
1791
|
// recover in place rather than a destructive full reload.
|
|
1764
1792
|
if (!doc) { restoreOptimistic(optimisticState); handleNavigationError(href, null, new Error('navigation response did not parse as HTML')); return { ok: false, status: respStatus, aborted: false }; }
|
|
1765
1793
|
|
|
1766
|
-
applySwap(doc, frameId, false, finalUrl, incomingBuild);
|
|
1794
|
+
applySwap(doc, frameId, false, finalUrl, incomingBuild, incomingSrc);
|
|
1767
1795
|
|
|
1768
1796
|
if (recordHistory) history.pushState(null, '', finalUrl);
|
|
1769
1797
|
|
|
@@ -2234,7 +2262,7 @@ function upgradeCustomElementsInRange(range) {
|
|
|
2234
2262
|
}
|
|
2235
2263
|
}
|
|
2236
2264
|
|
|
2237
|
-
function applySwap(doc, frameId, revalidating, href, incomingBuild) {
|
|
2265
|
+
function applySwap(doc, frameId, revalidating, href, incomingBuild, incomingSrc) {
|
|
2238
2266
|
// SSR action seeding (#472): ingest any seed payload the incoming page
|
|
2239
2267
|
// carries BEFORE its components are grafted into the live DOM and upgrade, so
|
|
2240
2268
|
// a soft-navigated async component resolves from the seed instead of
|
|
@@ -2308,6 +2336,14 @@ function applySwap(doc, frameId, revalidating, href, incomingBuild) {
|
|
|
2308
2336
|
if (currentSig !== incomingSig) mismatch = true;
|
|
2309
2337
|
}
|
|
2310
2338
|
if (mismatch && typeof location !== 'undefined') {
|
|
2339
|
+
// A detected cross-deploy mismatch means every URL-keyed snapshot and
|
|
2340
|
+
// speculative prefetch was captured on the OLD deploy, so it is stale
|
|
2341
|
+
// pre-deploy HTML (#899). Evict both caches so no stale entry is applied
|
|
2342
|
+
// on a later soft nav, even when the infinite-reload guard below bails to
|
|
2343
|
+
// a partial swap instead of a full reload (that partial swap must not then
|
|
2344
|
+
// pull a pre-deploy fragment out of the cache).
|
|
2345
|
+
snapshotCache.clear();
|
|
2346
|
+
prefetchCache.clear();
|
|
2311
2347
|
// Infinite-reload guard: if the importmap appears to genuinely
|
|
2312
2348
|
// change EVERY navigation (e.g. a developer is live-editing the
|
|
2313
2349
|
// pin file in dev, or a misbehaving CDN returns different
|
|
@@ -2336,6 +2372,27 @@ function applySwap(doc, frameId, revalidating, href, incomingBuild) {
|
|
|
2336
2372
|
return;
|
|
2337
2373
|
}
|
|
2338
2374
|
} else if (!mismatch) {
|
|
2375
|
+
// No importmap/build mismatch, so no hard reload. But the app-source
|
|
2376
|
+
// signal (#899) is the SECOND tier: if `data-webjs-src` differs, an
|
|
2377
|
+
// app-source or server-framework deploy changed the SSR output while the
|
|
2378
|
+
// running page's browser code is unchanged. A hard reload would be an
|
|
2379
|
+
// over-correction; instead EVICT the URL-keyed snapshot + prefetch caches
|
|
2380
|
+
// (all captured on the OLD deploy) so a later soft nav re-fetches fresh.
|
|
2381
|
+
// The current nav's already-fetched `doc` still applies normally. Both ids
|
|
2382
|
+
// must be present (an empty id is the warmup "unknown", never a signal),
|
|
2383
|
+
// exactly like the build guard.
|
|
2384
|
+
const currentSrc = currentTag ? currentTag.getAttribute('data-webjs-src') : null;
|
|
2385
|
+
if (incomingSrc && currentSrc && incomingSrc !== currentSrc) {
|
|
2386
|
+
snapshotCache.clear();
|
|
2387
|
+
prefetchCache.clear();
|
|
2388
|
+
// Advance the page's reference id. The importmap <script> is preserved
|
|
2389
|
+
// across soft navs (an importmap cannot be re-registered), so without
|
|
2390
|
+
// this the tag would keep its OLD id and EVERY later nav in the new
|
|
2391
|
+
// deploy would re-detect the same mismatch and evict again, defeating
|
|
2392
|
+
// the caches. Updating the attribute (not the importmap body) settles
|
|
2393
|
+
// the page onto the new deploy: evict once, then cache normally.
|
|
2394
|
+
if (currentTag) currentTag.setAttribute('data-webjs-src', incomingSrc);
|
|
2395
|
+
}
|
|
2339
2396
|
// A clean swap (no importmap mismatch) means we're back to
|
|
2340
2397
|
// matching client/server importmaps. Clear the reload flag so
|
|
2341
2398
|
// a future LEGITIMATE mismatch (e.g. a later deploy) gets a
|
|
@@ -2609,12 +2666,42 @@ function diffElementInPlace(dst, src) {
|
|
|
2609
2666
|
// The attribute version is skipped above; we deliberately do nothing
|
|
2610
2667
|
// here so the user's typing / checking is never blown away.
|
|
2611
2668
|
|
|
2669
|
+
// A hydrated component OWNS its rendered subtree. The client renderer
|
|
2670
|
+
// stashes the live template instance (lit-html parts holding DIRECT
|
|
2671
|
+
// references to the rendered nodes) on the host under
|
|
2672
|
+
// `Symbol.for('webjs.instance')`. Recursing into those children would
|
|
2673
|
+
// import/remove/reorder the very nodes the parts still point at, so the
|
|
2674
|
+
// component's next reactive update would write into detached nodes and
|
|
2675
|
+
// silently do nothing (a dead click after a soft nav, #906). Treat the
|
|
2676
|
+
// component as opaque: the attribute sync above already drove any reactive
|
|
2677
|
+
// property change through `attributeChangedCallback`, so the component
|
|
2678
|
+
// re-renders ITSELF; the router must not touch its internals. This mirrors
|
|
2679
|
+
// Turbo/morphdom, which leave custom elements alone by default.
|
|
2680
|
+
if (isHydratedComponent(dst)) return;
|
|
2681
|
+
|
|
2612
2682
|
// Recurse into children: collect both sides, run reconcileSiblings on
|
|
2613
2683
|
// them with synthetic boundary markers. Cheap implementation: use
|
|
2614
2684
|
// virtual ranges instead of inserting real comment markers.
|
|
2615
2685
|
reconcileChildren(dst, src);
|
|
2616
2686
|
}
|
|
2617
2687
|
|
|
2688
|
+
/**
|
|
2689
|
+
* True when `el` carries a live client-side render instance, i.e. a webjs
|
|
2690
|
+
* component whose `render()` produced the current children and owns them via
|
|
2691
|
+
* lit-html parts. The router must not reconcile INTO such an element (#906).
|
|
2692
|
+
*
|
|
2693
|
+
* Detected via the render-client instance symbol rather than a `customElements`
|
|
2694
|
+
* lookup so it fires only for elements that have actually rendered client-side:
|
|
2695
|
+
* a not-yet-upgraded or purely display-only custom element (no client render,
|
|
2696
|
+
* no parts to corrupt) stays fully reconcilable.
|
|
2697
|
+
*
|
|
2698
|
+
* @param {Element} el
|
|
2699
|
+
* @returns {boolean}
|
|
2700
|
+
*/
|
|
2701
|
+
function isHydratedComponent(el) {
|
|
2702
|
+
return /** @type {any} */ (el)[Symbol.for('webjs.instance')] != null;
|
|
2703
|
+
}
|
|
2704
|
+
|
|
2618
2705
|
/**
|
|
2619
2706
|
* Reconcile dst's children to match src's children, in-place.
|
|
2620
2707
|
*
|
|
@@ -2839,7 +2926,7 @@ function getCspNonce() {
|
|
|
2839
2926
|
// because it can be called against script/link elements (where
|
|
2840
2927
|
// browsers DO expose `.nonce` and additionally clear the
|
|
2841
2928
|
// `nonce` attribute on document load). The `<meta name="csp-nonce">`
|
|
2842
|
-
// element
|
|
2929
|
+
// element WebJs targets has no `.nonce` IDL (only script + link
|
|
2843
2930
|
// elements do per HTML spec), so the only viable source is the
|
|
2844
2931
|
// `content` attribute.
|
|
2845
2932
|
return meta ? meta.getAttribute('content') || '' : '';
|
|
@@ -3220,7 +3307,9 @@ export {
|
|
|
3220
3307
|
diffElementInPlace as _diffElementInPlace,
|
|
3221
3308
|
reconcileChildren as _reconcileChildren,
|
|
3222
3309
|
onPopState as _onPopState,
|
|
3310
|
+
applySwap as _applySwap,
|
|
3223
3311
|
snapshotCache as _snapshotCache,
|
|
3312
|
+
prefetchCache as _prefetchCache,
|
|
3224
3313
|
LIVE_ATTRS as _LIVE_ATTRS,
|
|
3225
3314
|
blurOutgoingFocus as _blurOutgoingFocus,
|
|
3226
3315
|
onSubmit as _onSubmit,
|
package/src/routes.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* opt-in, generated route union that types `navigate()` and catches bad
|
|
4
4
|
* hrefs at tsserver time (#258).
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* WebJs identity holds: NO build step, NO runtime cost, types-only, opt-in
|
|
7
7
|
* for JSDoc apps. The mechanism mirrors Next 15's `typedRoutes` but via
|
|
8
8
|
* interface declaration-merging instead of a bundler.
|
|
9
9
|
*
|
|
@@ -86,7 +86,7 @@ export type RouteParams<R extends string> = R extends keyof RouteParamMap
|
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
88
|
* A value that is BOTH synchronously usable as `T` and `await`-able to `T`
|
|
89
|
-
* (#848). The
|
|
89
|
+
* (#848). The WebJs runtime hands `params` / `searchParams` as a plain object
|
|
90
90
|
* carrying a non-enumerable `then`, so `params.id` and `await params` both
|
|
91
91
|
* work; this type expresses that dual nature to TypeScript.
|
|
92
92
|
*/
|
package/src/serializable.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Compile-time serializability typing for server actions (#488).
|
|
3
3
|
*
|
|
4
4
|
* A `'use server'` action's arguments and result cross the RPC wire through the
|
|
5
|
-
*
|
|
5
|
+
* WebJs serializer, which round-trips a SPECIFIC set of rich types (`Date`,
|
|
6
6
|
* `Map`, `Set`, `BigInt`, `Error`, `RegExp`, `URL`, typed arrays, `ArrayBuffer`,
|
|
7
7
|
* `Blob`, `File`, `FormData`, registered `Symbol`s, plain objects / arrays, and
|
|
8
8
|
* cycles). It does NOT round-trip a FUNCTION or a class instance's METHODS: a
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* / `SerializableResult` apply it across an action's parameter tuple and its
|
|
18
18
|
* (possibly promised) return.
|
|
19
19
|
*
|
|
20
|
-
* This is OPT-IN by design:
|
|
20
|
+
* This is OPT-IN by design: WebJs actions stay plain `export async function`s
|
|
21
21
|
* with no wrapper (the framework rewrites the client import to an RPC stub at
|
|
22
22
|
* runtime, it does not wrap the authored function). An author who wants the
|
|
23
23
|
* guard annotates the action with `SerializableActionFn`, e.g.
|
|
@@ -40,7 +40,7 @@ export type NonSerializable<Reason extends string = 'this value is not serializa
|
|
|
40
40
|
type SerializablePrimitive = string | number | boolean | bigint | null | undefined;
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
* Built-in rich types the
|
|
43
|
+
* Built-in rich types the WebJs serializer round-trips as themselves (their
|
|
44
44
|
* identity / methods survive because the serializer reconstructs the instance).
|
|
45
45
|
* `Map` / `Set` recurse into their members via the top-level mapper.
|
|
46
46
|
*/
|
package/src/serialize.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
2
|
+
* The WebJs wire serializer (rich-type round-trip: Date / Map / Set / BigInt /
|
|
3
3
|
* Error / typed arrays / Blob / File / FormData / Symbols / cycles).
|
|
4
4
|
*/
|
|
5
5
|
export function stringify(value: unknown): Promise<string>;
|
package/src/serialize.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* WebJs serializer: JSON-friendly encoding for rich JS types.
|
|
3
3
|
*
|
|
4
4
|
* Replaces superjson with a pure-ESM, dependency-free implementation
|
|
5
5
|
* tuned to the wire surface that React Server Actions support, plus a
|
package/src/signal.js
CHANGED
|
@@ -493,7 +493,7 @@ class SignalWatcher {
|
|
|
493
493
|
* to the watcher's producer set automatically. Re-arms on every call.
|
|
494
494
|
*
|
|
495
495
|
* Used by the WebComponent integration and the `watch()` directive
|
|
496
|
-
* because the natural
|
|
496
|
+
* because the natural WebJs pattern is "watch everything this render
|
|
497
497
|
* touches" rather than enumerating signals up front.
|
|
498
498
|
*
|
|
499
499
|
* @param {() => unknown} fn
|
package/src/testing.js
CHANGED
package/src/webjs-config.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* TypeScript overlay for the `webjs` config block in a
|
|
2
|
+
* TypeScript overlay for the `webjs` config block in a WebJs app's
|
|
3
3
|
* package.json.
|
|
4
4
|
*
|
|
5
5
|
* // package.json is JSON, so author it there, but a typed reference
|
|
@@ -95,6 +95,17 @@ export interface WebjsDevTasks {
|
|
|
95
95
|
* the parent and torn down on exit, so a watcher cannot leak past the server.
|
|
96
96
|
*/
|
|
97
97
|
parallel?: string[];
|
|
98
|
+
/**
|
|
99
|
+
* Extra directories the dev live-reload watcher follows IN ADDITION to the
|
|
100
|
+
* appDir (#894). The dev server watches its appDir recursively, but an app
|
|
101
|
+
* that reads content from OUTSIDE its tree (e.g. blog markdown in a repo-root
|
|
102
|
+
* `blog/` dir, a sibling of the app) sees no reload when that content changes.
|
|
103
|
+
* Each entry is resolved relative to the app root and MAY escape it
|
|
104
|
+
* (`"../blog"`); a change under one triggers the same rebuild + browser reload
|
|
105
|
+
* as an in-tree edit. Missing / overlapping (ancestor or descendant of the
|
|
106
|
+
* appDir) entries are skipped. Read by the server (`readDevWatchPathsFromApp`).
|
|
107
|
+
*/
|
|
108
|
+
watch?: string[];
|
|
98
109
|
}
|
|
99
110
|
|
|
100
111
|
/** Start task orchestration in `webjs.start` (#550). Read by the CLI, not the server. */
|
|
@@ -124,7 +135,7 @@ export interface WebjsCspConfig {
|
|
|
124
135
|
}
|
|
125
136
|
|
|
126
137
|
/**
|
|
127
|
-
* The `webjs` object in a
|
|
138
|
+
* The `webjs` object in a WebJs app's package.json. Every key is
|
|
128
139
|
* optional. Mirrors what the server readers actually consume, NOT a
|
|
129
140
|
* Next.js superset.
|
|
130
141
|
*/
|
package/src/websocket-client.js
CHANGED