@askrjs/askr 0.0.84 → 0.0.86
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/{access-ePqdQqkV.js → access-Dpfoi4cA.js} +7 -1
- package/dist/actions/index.d.ts +1 -1
- package/dist/actions/index.js +3 -3
- package/dist/{activity-pySy9t7Y.d.ts → activity-B1I5HJQI.d.ts} +1 -1
- package/dist/{activity-CZiPgZy0.js → activity-BvgvaMZA.js} +53 -16
- package/dist/benchmark.js +8 -8
- package/dist/boot/index.d.ts +3 -3
- package/dist/boot/index.js +1 -1
- package/dist/{boot-D28lesMw.js → boot-CViTpUiB.js} +22 -20
- package/dist/{cleanup-ARiXproi.js → cleanup-c837KVij.js} +16 -6
- package/dist/{component-cleanup-Bug5tSiG.js → component-cleanup-BUfUleGZ.js} +2 -2
- package/dist/{component-internal-Bw4Mf9fd.js → component-internal-DcrLymUJ.js} +5 -5
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +1 -1
- package/dist/control/index.d.ts +1 -1
- package/dist/control/index.js +1 -1
- package/dist/{control-Y8F73Uln.d.ts → control-DhUZU4_V.d.ts} +2 -1
- package/dist/{control-nrS65oG3.js → control-oLADku43.js} +4 -4
- package/dist/{csp-nonce-ZTlD_EnK.js → csp-nonce-Bc52OIVc.js} +19 -2
- package/dist/data/index.js +3 -3
- package/dist/{data-BRS5woEh.js → data-DGrD3-qA.js} +5 -5
- package/dist/{data-runtime-D68YOo9L.js → data-runtime-Ck3tJDDQ.js} +1 -1
- package/dist/default-portal-runtime-DvMvWJVp.js +20 -0
- package/dist/{authoring-DQPG0VAm.js → deferred-nleQtdfY.js} +85 -5
- package/dist/{effect-B487asyz.js → effect-lnxQIpJG.js} +2 -2
- package/dist/{fastlane-BOr4lSLl.js → fastlane-CrfB3QG0.js} +2 -2
- package/dist/{for-internal-DjpV8ioj.js → for-internal-B_mnQhan.js} +18 -6
- package/dist/foundations/index.d.ts +1 -1
- package/dist/foundations/index.js +1 -2
- package/dist/foundations/state/index.d.ts +1 -1
- package/dist/foundations/state/index.js +1 -1
- package/dist/foundations/structures/index.d.ts +2 -2
- package/dist/foundations/structures/index.js +2 -3
- package/dist/fx/index.js +1 -1
- package/dist/{index-BApH3laU.d.ts → index-DflhL1h8.d.ts} +20 -16
- package/dist/{index-_UN08Pg1.d.ts → index-pIgGaXvS.d.ts} +19 -3
- package/dist/{index-DUXXZ31H.d.ts → index-r-nt13FE.d.ts} +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +12 -12
- package/dist/{lifecycle-batch-CFI4NKpJ.js → lifecycle-batch-Dfpid9-A.js} +39 -20
- package/dist/{lifecycle-operations-KYOIcM5R.js → lifecycle-operations-BrYrBsXY.js} +1 -1
- package/dist/manifest-D1P9uTlz.js +53 -0
- package/dist/{navigate-Dr3cjOSz.js → navigate-BwAPbpCb.js} +17 -16
- package/dist/{navigate-CgVIrrSs.d.ts → navigate-NyIjQUwI.d.ts} +1 -1
- package/dist/{query-registry-BL6rjGsO.js → query-registry-CPW_6nwF.js} +1 -1
- package/dist/{readable-_GQGe_St.js → readable-B5NtV7V0.js} +1 -1
- package/dist/render-context-D0Hoj9dW.js +161 -0
- package/dist/{renderer-B9j5IV1q.js → renderer-D9DL9R2D.js} +58 -17
- package/dist/{deferred-oqtAJ4iH.js → resolution-YHwi4Bav.js} +234 -222
- package/dist/resource-operation-ys6eDoRJ.js +304 -0
- package/dist/resources/index.d.ts +2 -2
- package/dist/resources/index.js +5 -5
- package/dist/{route-matching-IfQZmqkN.js → route-matching-DqULzZtC.js} +46 -277
- package/dist/router/index.d.ts +12 -10
- package/dist/router/index.js +10 -7
- package/dist/{selector-DJ1-N1K-.js → selector-Ck_Pp9av.js} +2 -2
- package/dist/ssg/index.d.ts +9 -3
- package/dist/ssg/index.js +31 -15
- package/dist/ssr/index.d.ts +7 -3
- package/dist/ssr/index.js +2 -2
- package/dist/{ssr-CtC4lChT.js → ssr-B98593qJ.js} +53 -27
- package/dist/ssr-DSHd_Q9K.js +25 -0
- package/dist/{state-BzIMC6-i.js → state-DCjONcHK.js} +4 -3
- package/dist/{portal-pHBoqwYd.js → structures-DsOm-clq.js} +236 -7
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +4 -4
- package/dist/{verify-hydration-BguOSco9.js → verify-hydration-ww1dgwea.js} +5 -4
- package/package.json +2 -2
- package/dist/render-context-D-DFk2WN.js +0 -73
- package/dist/ssr-CbQO5xd3.js +0 -12
- package/dist/structures-D3vO-WMN.js +0 -221
package/dist/ssr/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { f as DocumentRenderArgs, g as SSRStyleRegistration, h as SSRData, m as DocumentRenderer, p as DocumentRenderContext } from "../control-
|
|
1
|
+
import { _ as SSRStyleRegistrationValidation, f as DocumentRenderArgs, g as SSRStyleRegistration, h as SSRData, m as DocumentRenderer, p as DocumentRenderContext } from "../control-DhUZU4_V.js";
|
|
2
2
|
import { r as JSXElement, s as Props } from "../jsx-Dvr2SGRG.js";
|
|
3
|
-
import { A as RouteHandler, C as Route, J as RouteRequestResult, V as RouteRecord, W as RouteRegistry, g as AccessRedirectDecision, l as DeferredBoundaryRegistration, m as AccessDenyDecision, u as SSRPortalState, w as RouteAuthOptions } from "../index-
|
|
3
|
+
import { A as RouteHandler, C as Route, J as RouteRequestResult, V as RouteRecord, W as RouteRegistry, g as AccessRedirectDecision, l as DeferredBoundaryRegistration, m as AccessDenyDecision, u as SSRPortalState, w as RouteAuthOptions } from "../index-pIgGaXvS.js";
|
|
4
4
|
import { D as QueryPrefetchContext, _ as CoreTelemetry, n as ServerQueryRegistry, v as DataRuntime } from "../index-5S-fi2xy.js";
|
|
5
5
|
import { AuthContext } from "@askrjs/auth";
|
|
6
6
|
//#region src/common/page-render-envelope.d.ts
|
|
@@ -29,6 +29,7 @@ interface RenderContext {
|
|
|
29
29
|
params?: Record<string, string>;
|
|
30
30
|
routes?: readonly Route[];
|
|
31
31
|
routeAuth?: RouteAuthOptions;
|
|
32
|
+
basePath?: string;
|
|
32
33
|
authContext?: AuthContext;
|
|
33
34
|
signal?: AbortSignal;
|
|
34
35
|
dataRuntime?: unknown;
|
|
@@ -51,6 +52,7 @@ declare function createRenderContext(seed?: number, opts?: {
|
|
|
51
52
|
params?: Record<string, string>;
|
|
52
53
|
routes?: readonly Route[];
|
|
53
54
|
routeAuth?: RouteAuthOptions;
|
|
55
|
+
basePath?: string;
|
|
54
56
|
signal?: AbortSignal;
|
|
55
57
|
dataRuntime?: unknown;
|
|
56
58
|
mode?: 'ssr' | 'spa';
|
|
@@ -92,6 +94,8 @@ type RouteRenderOptions = SSRRouteSource & {
|
|
|
92
94
|
/** @internal Precomposed page state used by hydration verification. */
|
|
93
95
|
envelope?: PageRenderEnvelope;
|
|
94
96
|
cspNonce?: string;
|
|
97
|
+
/** Diagnose document renderers that omit request-local SSR style registrations. */
|
|
98
|
+
styleRegistrationValidation?: SSRStyleRegistrationValidation;
|
|
95
99
|
};
|
|
96
100
|
type RouteStreamOptions = RouteRenderOptions & {
|
|
97
101
|
onChunk(html: string): void;
|
|
@@ -185,4 +189,4 @@ declare function renderToString(component: (props?: Record<string, unknown>) =>
|
|
|
185
189
|
declare function renderToString(opts: RouteRenderOptions): string;
|
|
186
190
|
declare function renderToStream(opts: RouteStreamOptions): void;
|
|
187
191
|
//#endregion
|
|
188
|
-
export { type DocumentRenderArgs, type DocumentRenderContext, type DocumentRenderer, type RenderRouteRequestOptions, type RenderRouteRequestResult, type SSRComponent, SSRDataMissingError, type SSRRoute, type SSRStyleRegistration, type VNode, createRenderContext, getRenderContext, renderResolvedToStringSync, renderRouteRequest, renderRouteRequestToString, renderToStream, renderToString, renderToStringSync, resolveRequest, withRenderContext, withRenderContextAsync };
|
|
192
|
+
export { type DocumentRenderArgs, type DocumentRenderContext, type DocumentRenderer, type RenderRouteRequestOptions, type RenderRouteRequestResult, type SSRComponent, SSRDataMissingError, type SSRRoute, type SSRStyleRegistration, type SSRStyleRegistrationValidation, type VNode, createRenderContext, getRenderContext, renderResolvedToStringSync, renderRouteRequest, renderRouteRequestToString, renderToStream, renderToString, renderToStringSync, resolveRequest, withRenderContext, withRenderContextAsync };
|
package/dist/ssr/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as renderResolvedToStringSync, c as createRenderContext, d as withRenderContextAsync, i as renderRouteRequestToString, l as getRenderContext, n as renderToString, o as renderToStringSync, r as renderRouteRequest, s as resolveRequest, t as renderToStream, u as withRenderContext } from "../ssr-
|
|
1
|
+
import { x as SSRDataMissingError } from "../render-context-D0Hoj9dW.js";
|
|
2
|
+
import { a as renderResolvedToStringSync, c as createRenderContext, d as withRenderContextAsync, i as renderRouteRequestToString, l as getRenderContext, n as renderToString, o as renderToStringSync, r as renderRouteRequest, s as resolveRequest, t as renderToStream, u as withRenderContext } from "../ssr-B98593qJ.js";
|
|
3
3
|
export { SSRDataMissingError, createRenderContext, getRenderContext, renderResolvedToStringSync, renderRouteRequest, renderRouteRequestToString, renderToStream, renderToString, renderToStringSync, resolveRequest, withRenderContext, withRenderContextAsync };
|
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import { t as __CONTROL_BOUNDARY__ } from "./control-C-ApnFs1.js";
|
|
2
2
|
import { t as __ERROR_BOUNDARY__ } from "./vnode-D24p6IW2.js";
|
|
3
|
-
import { v as logger } from "./access-
|
|
4
|
-
import { i as isFragmentType, n as Fragment, t as ELEMENT_TYPE } from "./jsx-C3IECePB.js";
|
|
5
|
-
import { f as getExecutionContextFrame, h as markVNodeTreeWithContextFrame, l as callWithContext, n as createComponentInstance, p as getVNodeContextFrame } from "./component-internal-Bw4Mf9fd.js";
|
|
3
|
+
import { v as logger } from "./access-Dpfoi4cA.js";
|
|
6
4
|
import { f as getCurrentComponentInstance, w as setCurrentComponentInstance } from "./component-scope-DzJEbYGE.js";
|
|
7
|
-
import { t as
|
|
8
|
-
import { p as
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { n as SSR_PORTAL_HOST, t as SSR_PORTAL_ANCHOR } from "./portal-w3oQ6oQU.js";
|
|
14
|
-
import { a as disposeDefaultPortalScope, t as DefaultPortal } from "./portal-pHBoqwYd.js";
|
|
5
|
+
import { i as isFragmentType, n as Fragment, t as ELEMENT_TYPE } from "./jsx-C3IECePB.js";
|
|
6
|
+
import { f as getExecutionContextFrame, h as markVNodeTreeWithContextFrame, l as callWithContext, n as createComponentInstance, p as getVNodeContextFrame } from "./component-internal-DcrLymUJ.js";
|
|
7
|
+
import { t as cleanupComponent } from "./component-cleanup-BUfUleGZ.js";
|
|
8
|
+
import { p as isPromiseLike } from "./lifecycle-batch-Dfpid9-A.js";
|
|
9
|
+
import { _ as setControlBoundaryContextFrame, g as evaluateShowState, h as evaluateCaseState, i as evaluateForState, o as rollbackForStateTransaction, r as commitForStateTransaction } from "./for-internal-B_mnQhan.js";
|
|
10
|
+
import { _ as isPageRenderEnvelope, f as stopRenderPhase$1, g as isEmptyPageRenderEnvelope, h as createPageRenderEnvelope, t as configureRenderContextProvider, u as startRenderPhase$1, x as SSRDataMissingError } from "./render-context-D0Hoj9dW.js";
|
|
15
11
|
import { n as getPublicAttributeName, t as sanitizeCssValue } from "./css-BuPaTOfe.js";
|
|
16
|
-
import {
|
|
17
|
-
import { t as
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
12
|
+
import { o as isUnsafeUrlAttribute, r as validateCspNonce, t as CspNonceScope } from "./csp-nonce-Bc52OIVc.js";
|
|
13
|
+
import { n as SSR_PORTAL_HOST, t as SSR_PORTAL_ANCHOR } from "./portal-w3oQ6oQU.js";
|
|
14
|
+
import { t as createDataRuntime } from "./data-runtime-Ck3tJDDQ.js";
|
|
15
|
+
import { c as withTelemetry, i as dehydrateDataRuntime, t as createQueryPrefetchContext } from "./query-registry-CPW_6nwF.js";
|
|
16
|
+
import { a as resolveRouteFromRoutes, c as removeRouteBasePath, s as normalizeRouteBasePath, t as _resolveRouteMatchFromRoutes } from "./route-matching-DqULzZtC.js";
|
|
17
|
+
import { a as resolveRouteRequest, d as DEFERRED_BOUNDARY, l as validateRouteHydrationData, o as getRouteHydrationMetadata, p as isDeferred } from "./resolution-YHwi4Bav.js";
|
|
18
|
+
import { n as disposeRegisteredDefaultPortalScope, r as getDefaultPortalHost } from "./default-portal-runtime-DvMvWJVp.js";
|
|
19
|
+
import { n as renderDocument, t as SSR_RENDER_DATA_ATTR } from "./ssr-DSHd_Q9K.js";
|
|
21
20
|
//#region src/ssr/escape.ts
|
|
22
21
|
/**
|
|
23
22
|
* HTML escaping utilities for SSR
|
|
@@ -197,6 +196,7 @@ function createRenderContext(seed = 12345, opts = {}) {
|
|
|
197
196
|
params: opts.params,
|
|
198
197
|
routes: opts.routes,
|
|
199
198
|
routeAuth: opts.routeAuth,
|
|
199
|
+
basePath: opts.basePath,
|
|
200
200
|
signal: opts.signal,
|
|
201
201
|
dataRuntime: opts.dataRuntime ?? createDataRuntime({ queryCache }),
|
|
202
202
|
mode: opts.mode ?? "ssr",
|
|
@@ -307,7 +307,9 @@ function resolvePolicyAwareSSRRoute(opts, routeTable) {
|
|
|
307
307
|
let href = opts.url;
|
|
308
308
|
const visited = /* @__PURE__ */ new Set();
|
|
309
309
|
for (let redirects = 0; redirects <= MAX_SSR_REDIRECTS; redirects += 1) {
|
|
310
|
-
const
|
|
310
|
+
const logicalHref = removeRouteBasePath(href, normalizeRouteBasePath(manifest.basePath));
|
|
311
|
+
if (logicalHref === void 0) throw new Error(`SSR: no route found for url: ${href}`);
|
|
312
|
+
const matched = _resolveRouteMatchFromRoutes(new URL(logicalHref, "http://localhost").pathname, routeTable);
|
|
311
313
|
if (!matched) throw new Error(`SSR: no route found for url: ${href}`);
|
|
312
314
|
const resolved = getRouteRequestResultSync(resolveRouteRequest(href, {
|
|
313
315
|
registry: opts.registry,
|
|
@@ -446,13 +448,14 @@ function resolveSSRRouteSource(source) {
|
|
|
446
448
|
}));
|
|
447
449
|
}
|
|
448
450
|
function resolveSSRRouteRender(opts) {
|
|
449
|
-
const { seed = 12345, data, document } = opts;
|
|
451
|
+
const { seed = 12345, data, document, styleRegistrationValidation = "warn" } = opts;
|
|
450
452
|
const cspNonce = validateCspNonce(opts.cspNonce);
|
|
451
453
|
const routeTable = resolveSSRRouteSource(opts);
|
|
452
454
|
const resolvedRoute = resolvePolicyAwareSSRRoute(opts, routeTable);
|
|
453
455
|
const requestUrl = new URL(resolvedRoute.url, "http://localhost");
|
|
454
456
|
const ctx = createRenderContext(seed, {
|
|
455
457
|
url: resolvedRoute.url,
|
|
458
|
+
basePath: opts.registry.manifest.basePath,
|
|
456
459
|
data,
|
|
457
460
|
params: resolvedRoute.params,
|
|
458
461
|
routes: routeTable,
|
|
@@ -470,7 +473,8 @@ function resolveSSRRouteRender(opts) {
|
|
|
470
473
|
data,
|
|
471
474
|
ctx,
|
|
472
475
|
document,
|
|
473
|
-
cspNonce
|
|
476
|
+
cspNonce,
|
|
477
|
+
styleRegistrationValidation
|
|
474
478
|
};
|
|
475
479
|
}
|
|
476
480
|
function buildDocumentRenderArgs(resolved, appHtml) {
|
|
@@ -514,7 +518,7 @@ function renderToSinkInternal(opts, host) {
|
|
|
514
518
|
const appSink = new StringSink();
|
|
515
519
|
renderResolvedRouteAppToSink(resolved, appSink, host);
|
|
516
520
|
appSink.end();
|
|
517
|
-
sink.write(renderDocument(resolved.document, buildDocumentRenderArgs(resolved, appSink.toString()), "renderToString()/renderToStream()"));
|
|
521
|
+
sink.write(renderDocument(resolved.document, buildDocumentRenderArgs(resolved, appSink.toString()), "renderToString()/renderToStream()", resolved.styleRegistrationValidation));
|
|
518
522
|
});
|
|
519
523
|
}
|
|
520
524
|
function renderRouteToString(opts, host) {
|
|
@@ -551,7 +555,7 @@ function executeComponentSync(component, props, ctx, ownerFrame = null) {
|
|
|
551
555
|
cleanupError = error;
|
|
552
556
|
}
|
|
553
557
|
try {
|
|
554
|
-
|
|
558
|
+
disposeRegisteredDefaultPortalScope(temp);
|
|
555
559
|
} catch (error) {
|
|
556
560
|
if (cleanupError) throw new AggregateError([cleanupError, error], "SSR temporary owner cleanup failed");
|
|
557
561
|
throw error;
|
|
@@ -592,7 +596,7 @@ function wrapWithDefaultPortal(out) {
|
|
|
592
596
|
if (isPromiseLike(out)) throwSSRDataMissing();
|
|
593
597
|
const portalVNode = {
|
|
594
598
|
$$typeof: ELEMENT_TYPE,
|
|
595
|
-
type:
|
|
599
|
+
type: getDefaultPortalHost(),
|
|
596
600
|
props: { __askrAutoDefaultPortal: true },
|
|
597
601
|
key: "__default_portal"
|
|
598
602
|
};
|
|
@@ -781,7 +785,7 @@ function renderAttrsDirect(props, sink) {
|
|
|
781
785
|
}
|
|
782
786
|
if (value === false || value === null || value === void 0) continue;
|
|
783
787
|
const strValue = String(value);
|
|
784
|
-
if (attrName
|
|
788
|
+
if (isUnsafeUrlAttribute(attrName, strValue)) continue;
|
|
785
789
|
sink.write(" ");
|
|
786
790
|
sink.write(attrName);
|
|
787
791
|
sink.write("=\"");
|
|
@@ -816,7 +820,7 @@ function renderAttrs(props, opts) {
|
|
|
816
820
|
else if (value === false || value === null || value === void 0) continue;
|
|
817
821
|
else {
|
|
818
822
|
const strValue = String(value);
|
|
819
|
-
if (attrName
|
|
823
|
+
if (isUnsafeUrlAttribute(attrName, strValue)) continue;
|
|
820
824
|
attrParts.push(` ${attrName}="${getEscapedAttrValue(strValue)}"`);
|
|
821
825
|
}
|
|
822
826
|
}
|
|
@@ -853,6 +857,8 @@ function serializeHydrationRenderData(data, runtime) {
|
|
|
853
857
|
route: current.route,
|
|
854
858
|
framework: current.framework
|
|
855
859
|
});
|
|
860
|
+
const routeHydration = getRouteHydrationMetadata(payload.framework);
|
|
861
|
+
if (routeHydration) validateRouteHydrationData(payload.route, routeHydration.r);
|
|
856
862
|
if (isEmptyPageRenderEnvelope(payload)) return "";
|
|
857
863
|
return `<script type="application/json" ${SSR_RENDER_DATA_ATTR}="true">${JSON.stringify(payload, hydrationReplacer).replace(/</g, "\\u003C").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029")}<\/script>`;
|
|
858
864
|
}
|
|
@@ -1251,11 +1257,27 @@ function renderResolvedToStringSync(opts) {
|
|
|
1251
1257
|
...route,
|
|
1252
1258
|
handler
|
|
1253
1259
|
} : route);
|
|
1260
|
+
const matchedRoute = routes[matchedIndex];
|
|
1254
1261
|
return renderToString({
|
|
1255
1262
|
url,
|
|
1256
|
-
registry:
|
|
1257
|
-
|
|
1258
|
-
|
|
1263
|
+
registry: {
|
|
1264
|
+
manifest: {
|
|
1265
|
+
records: registry.manifest.records.map((record) => {
|
|
1266
|
+
const effectiveHandler = record.path === matchedRoute.path && record.handler === matchedRoute.handler && record.options.namespace === matchedRoute.namespace ? handler : record.handler;
|
|
1267
|
+
return {
|
|
1268
|
+
...record,
|
|
1269
|
+
component: effectiveHandler,
|
|
1270
|
+
handler: effectiveHandler,
|
|
1271
|
+
layoutChain: [],
|
|
1272
|
+
pageChain: [],
|
|
1273
|
+
options: record.options.namespace ? { namespace: record.options.namespace } : {},
|
|
1274
|
+
metaChain: void 0
|
|
1275
|
+
};
|
|
1276
|
+
}),
|
|
1277
|
+
...registry.manifest.basePath ? { basePath: registry.manifest.basePath } : {}
|
|
1278
|
+
},
|
|
1279
|
+
routes: effectiveRoutes
|
|
1280
|
+
},
|
|
1259
1281
|
seed: options?.seed,
|
|
1260
1282
|
data: options?.data,
|
|
1261
1283
|
dataRuntime: options?.dataRuntime,
|
|
@@ -1401,6 +1423,9 @@ async function renderRouteRequestInternal(options) {
|
|
|
1401
1423
|
});
|
|
1402
1424
|
const context = createRenderContext(options.seed, {
|
|
1403
1425
|
url: options.url,
|
|
1426
|
+
basePath: manifest.basePath,
|
|
1427
|
+
routes: options.registry.routes,
|
|
1428
|
+
routeAuth: options.auth ?? manifest.auth,
|
|
1404
1429
|
data: options.data,
|
|
1405
1430
|
framework: options.framework,
|
|
1406
1431
|
signal,
|
|
@@ -1421,6 +1446,7 @@ async function renderRouteRequestInternal(options) {
|
|
|
1421
1446
|
});
|
|
1422
1447
|
if (!resolved) return { kind: "no-match" };
|
|
1423
1448
|
if (resolved.kind !== "render") return resolved;
|
|
1449
|
+
context.params = resolved.params;
|
|
1424
1450
|
const sink = new StringSink();
|
|
1425
1451
|
renderSSRRouteAppToSink({
|
|
1426
1452
|
route: {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/common/ssr.ts
|
|
2
|
+
function escapedStyleRawText(value) {
|
|
3
|
+
return value.replace(/<\//gi, "<\\/");
|
|
4
|
+
}
|
|
5
|
+
function validateDocumentStyleRegistrations(html, styles, apiName, validation) {
|
|
6
|
+
if (validation === "off" || !styles || styles.length === 0) return;
|
|
7
|
+
const dropped = styles.filter(({ cssText }) => !html.includes(cssText) && !html.includes(escapedStyleRawText(cssText)));
|
|
8
|
+
if (dropped.length === 0) return;
|
|
9
|
+
const registrations = dropped.map(({ id }) => JSON.stringify(id)).join(", ");
|
|
10
|
+
const message = `${apiName} document() dropped ${dropped.length} registered SSR style${dropped.length === 1 ? "" : "s"}: ${registrations}. Serialize context.styles into the returned document, or set styleRegistrationValidation to "off" when omission is intentional.`;
|
|
11
|
+
if (validation === "error") throw new Error(message);
|
|
12
|
+
console.warn(message);
|
|
13
|
+
}
|
|
14
|
+
function renderDocument(document, args, apiName, styleRegistrationValidation = "warn") {
|
|
15
|
+
const html = document(args);
|
|
16
|
+
if (typeof html !== "string") {
|
|
17
|
+
const received = typeof html === "object" && html !== null && "then" in html && typeof html.then === "function" ? "a Promise-like value" : html === null ? "null" : Array.isArray(html) ? "an array" : typeof html;
|
|
18
|
+
throw new Error(`${apiName} document() must synchronously return a string; received ${received}.`);
|
|
19
|
+
}
|
|
20
|
+
validateDocumentStyleRegistrations(html, args.context.styles, apiName, styleRegistrationValidation);
|
|
21
|
+
return html;
|
|
22
|
+
}
|
|
23
|
+
const SSR_RENDER_DATA_ATTR = "data-askr-render-data";
|
|
24
|
+
//#endregion
|
|
25
|
+
export { renderDocument as n, SSR_RENDER_DATA_ATTR as t };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { x as isProductionEnvironment } from "./access-
|
|
2
|
-
import { t as isBulkCommitActive } from "./fastlane-
|
|
3
|
-
import { l as notifyReadableReaders, o as markReactivePropsDirtySource, s as markReadableDerivedSubscribersDirty, u as recordReadableRead } from "./readable-_GQGe_St.js";
|
|
1
|
+
import { v as logger, x as isProductionEnvironment } from "./access-Dpfoi4cA.js";
|
|
2
|
+
import { t as isBulkCommitActive } from "./fastlane-CrfB3QG0.js";
|
|
4
3
|
import { i as claimHookIndex, p as getCurrentInstance } from "./component-scope-DzJEbYGE.js";
|
|
4
|
+
import { l as notifyReadableReaders, o as markReactivePropsDirtySource, s as markReadableDerivedSubscribersDirty, u as recordReadableRead } from "./readable-B5NtV7V0.js";
|
|
5
5
|
//#region src/runtime/state.ts
|
|
6
6
|
/**
|
|
7
7
|
* State primitive for Askr components
|
|
@@ -77,6 +77,7 @@ function createStateCell(initialValue, instance) {
|
|
|
77
77
|
else newValue = newValueOrUpdater;
|
|
78
78
|
if (Object.is(value, newValue)) return;
|
|
79
79
|
if (isBulkCommitActive()) {
|
|
80
|
+
if (!isProductionEnvironment()) logger.warn("[Askr] state.set() was called while a bulk commit (fast-lane reorder) was in progress. The value updated, but subscribers were not notified, so this change will not be reflected in the UI until an unrelated update triggers a re-render. This usually happens from a ref callback or a native focus/blur event fired synchronously during a large keyed-list reorder.");
|
|
80
81
|
value = newValue;
|
|
81
82
|
return;
|
|
82
83
|
}
|
|
@@ -1,11 +1,107 @@
|
|
|
1
|
-
import { o as getRuntimeRenderer } from "./access-
|
|
2
|
-
import { t as ELEMENT_TYPE } from "./jsx-C3IECePB.js";
|
|
3
|
-
import { l as notifyReadableReaders, o as markReactivePropsDirtySource, s as markReadableDerivedSubscribersDirty, u as recordReadableRead } from "./readable-_GQGe_St.js";
|
|
1
|
+
import { o as getRuntimeRenderer } from "./access-Dpfoi4cA.js";
|
|
4
2
|
import { f as getCurrentComponentInstance, m as getCurrentPortalScope } from "./component-scope-DzJEbYGE.js";
|
|
5
|
-
import { t as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
3
|
+
import { n as Fragment, t as ELEMENT_TYPE } from "./jsx-C3IECePB.js";
|
|
4
|
+
import { l as notifyReadableReaders, o as markReactivePropsDirtySource, s as markReadableDerivedSubscribersDirty, u as recordReadableRead } from "./readable-B5NtV7V0.js";
|
|
5
|
+
import { t as cleanupComponent } from "./component-cleanup-BUfUleGZ.js";
|
|
6
|
+
import { c as getCurrentLifecycleCommitBatch, u as registerLifecycleTransaction } from "./lifecycle-batch-Dfpid9-A.js";
|
|
7
|
+
import { n as getActiveRenderContext } from "./render-context-D0Hoj9dW.js";
|
|
8
8
|
import { i as createSSRPortalHostToken, n as SSR_PORTAL_HOST, r as createSSRPortalAnchorToken, t as SSR_PORTAL_ANCHOR } from "./portal-w3oQ6oQU.js";
|
|
9
|
+
import { i as registerDefaultPortalRuntime } from "./default-portal-runtime-DvMvWJVp.js";
|
|
10
|
+
//#region src/jsx/utils.ts
|
|
11
|
+
function isElement(value) {
|
|
12
|
+
return typeof value === "object" && value !== null && value.$$typeof === ELEMENT_TYPE;
|
|
13
|
+
}
|
|
14
|
+
function cloneElement(element, props) {
|
|
15
|
+
return {
|
|
16
|
+
$$typeof: element.$$typeof,
|
|
17
|
+
type: element.type,
|
|
18
|
+
key: element.key,
|
|
19
|
+
props: {
|
|
20
|
+
...element.props,
|
|
21
|
+
...props
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/foundations/structures/layout.tsx
|
|
27
|
+
function layout(Layout) {
|
|
28
|
+
return (children, props) => {
|
|
29
|
+
return Layout({
|
|
30
|
+
...props,
|
|
31
|
+
children
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/foundations/structures/slot.tsx
|
|
37
|
+
/**
|
|
38
|
+
* Slot
|
|
39
|
+
*
|
|
40
|
+
* Structural primitive for prop forwarding patterns.
|
|
41
|
+
*
|
|
42
|
+
* POLICY DECISIONS (LOCKED):
|
|
43
|
+
*
|
|
44
|
+
* 1. asChild Pattern
|
|
45
|
+
* When asChild=true, merges props into the single child element.
|
|
46
|
+
* Child must be a valid JSXElement; non-element children return null.
|
|
47
|
+
* **Slot props override child props** (injection pattern).
|
|
48
|
+
*
|
|
49
|
+
* 2. Fallback Behavior
|
|
50
|
+
* When asChild=false, returns a Fragment (structural no-op).
|
|
51
|
+
* No DOM element is introduced.
|
|
52
|
+
*
|
|
53
|
+
* 3. Type Safety
|
|
54
|
+
* asChild=true requires exactly one JSXElement child (enforced by type).
|
|
55
|
+
* Runtime validates with isElement() check.
|
|
56
|
+
*/
|
|
57
|
+
function Slot(props) {
|
|
58
|
+
if (props.asChild) {
|
|
59
|
+
const { children, asChild: _asChild, ...rest } = props;
|
|
60
|
+
if (isElement(children)) return cloneElement(children, rest);
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
$$typeof: ELEMENT_TYPE,
|
|
65
|
+
type: Fragment,
|
|
66
|
+
props: { children: props.children },
|
|
67
|
+
key: null
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/foundations/structures/presence.ts
|
|
72
|
+
/**
|
|
73
|
+
* Presence
|
|
74
|
+
*
|
|
75
|
+
* Structural policy primitive for conditional mount/unmount.
|
|
76
|
+
* - No timers
|
|
77
|
+
* - No animation coupling
|
|
78
|
+
* - No DOM side-effects
|
|
79
|
+
*
|
|
80
|
+
* POLICY DECISIONS (LOCKED):
|
|
81
|
+
*
|
|
82
|
+
* 1. Present as Function
|
|
83
|
+
* Accepts boolean OR function to support lazy evaluation patterns.
|
|
84
|
+
* Function is called once per render. Use boolean form for static values.
|
|
85
|
+
*
|
|
86
|
+
* 2. Children Type
|
|
87
|
+
* Presence forwards normal renderable child content only.
|
|
88
|
+
* Imperative DOM nodes are not part of the public contract.
|
|
89
|
+
*
|
|
90
|
+
* 3. Immediate Mount/Unmount
|
|
91
|
+
* No exit animations or transitions. When `present` becomes false,
|
|
92
|
+
* children are removed immediately. Animation must be layered above
|
|
93
|
+
* this primitive.
|
|
94
|
+
*/
|
|
95
|
+
function Presence({ present, children }) {
|
|
96
|
+
if (!(typeof present === "function" ? present() : Boolean(present))) return null;
|
|
97
|
+
return {
|
|
98
|
+
$$typeof: ELEMENT_TYPE,
|
|
99
|
+
type: Fragment,
|
|
100
|
+
props: { children },
|
|
101
|
+
key: null
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
9
105
|
//#region src/runtime/portal.ts
|
|
10
106
|
const DEFAULT_SSR_PORTAL_KEY = {};
|
|
11
107
|
function getSSRPortalSlot(key) {
|
|
@@ -391,5 +487,138 @@ function Portal(props) {
|
|
|
391
487
|
writeDefaultPortal(props, owner);
|
|
392
488
|
return null;
|
|
393
489
|
}
|
|
490
|
+
registerDefaultPortalRuntime({
|
|
491
|
+
host: DefaultPortal,
|
|
492
|
+
clearForInstance(instance) {
|
|
493
|
+
clearDefaultPortalForInstance(instance);
|
|
494
|
+
},
|
|
495
|
+
disposeScope: disposeDefaultPortalScope
|
|
496
|
+
});
|
|
497
|
+
//#endregion
|
|
498
|
+
//#region src/foundations/structures/collection.ts
|
|
499
|
+
function createCollection() {
|
|
500
|
+
const registry = /* @__PURE__ */ new Map();
|
|
501
|
+
function register(node, metadata) {
|
|
502
|
+
const item = {
|
|
503
|
+
node,
|
|
504
|
+
metadata
|
|
505
|
+
};
|
|
506
|
+
registry.set(node, item);
|
|
507
|
+
return () => {
|
|
508
|
+
registry.delete(node);
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
function items() {
|
|
512
|
+
return Array.from(registry.values());
|
|
513
|
+
}
|
|
514
|
+
function clear() {
|
|
515
|
+
registry.clear();
|
|
516
|
+
}
|
|
517
|
+
function size() {
|
|
518
|
+
return registry.size;
|
|
519
|
+
}
|
|
520
|
+
return {
|
|
521
|
+
register,
|
|
522
|
+
items,
|
|
523
|
+
clear,
|
|
524
|
+
size
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* USAGE EXAMPLE:
|
|
529
|
+
*
|
|
530
|
+
* // Create a collection for menu items
|
|
531
|
+
* const menuItems = createCollection<HTMLElement, { disabled: boolean }>();
|
|
532
|
+
*
|
|
533
|
+
* // Register items
|
|
534
|
+
* const unregister1 = menuItems.register(element1, { disabled: false });
|
|
535
|
+
* const unregister2 = menuItems.register(element2, { disabled: true });
|
|
536
|
+
*
|
|
537
|
+
* // Query items
|
|
538
|
+
* const allItems = menuItems.items();
|
|
539
|
+
* const enabledItems = allItems.filter(item => !item.metadata.disabled);
|
|
540
|
+
*
|
|
541
|
+
* // Cleanup
|
|
542
|
+
* unregister1();
|
|
543
|
+
* unregister2();
|
|
544
|
+
*/
|
|
545
|
+
//#endregion
|
|
546
|
+
//#region src/foundations/structures/layer.ts
|
|
547
|
+
function createLayer() {
|
|
548
|
+
const stack = [];
|
|
549
|
+
let nextId = 1;
|
|
550
|
+
function register(options) {
|
|
551
|
+
const id = nextId++;
|
|
552
|
+
const entry = {
|
|
553
|
+
id,
|
|
554
|
+
options
|
|
555
|
+
};
|
|
556
|
+
stack.push(entry);
|
|
557
|
+
function isTop() {
|
|
558
|
+
return stack[stack.length - 1]?.id === id;
|
|
559
|
+
}
|
|
560
|
+
function unregister() {
|
|
561
|
+
const index = stack.findIndex((e) => e.id === id);
|
|
562
|
+
if (index !== -1) stack.splice(index, 1);
|
|
563
|
+
}
|
|
564
|
+
return {
|
|
565
|
+
id,
|
|
566
|
+
isTop,
|
|
567
|
+
unregister
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
function layers() {
|
|
571
|
+
return stack.map((entry) => ({
|
|
572
|
+
id: entry.id,
|
|
573
|
+
isTop: () => stack[stack.length - 1]?.id === entry.id,
|
|
574
|
+
unregister: () => {
|
|
575
|
+
const index = stack.findIndex((e) => e.id === entry.id);
|
|
576
|
+
if (index !== -1) stack.splice(index, 1);
|
|
577
|
+
}
|
|
578
|
+
}));
|
|
579
|
+
}
|
|
580
|
+
function handleEscape() {
|
|
581
|
+
const top = stack[stack.length - 1];
|
|
582
|
+
if (top) top.options.onEscape?.();
|
|
583
|
+
}
|
|
584
|
+
function handleOutsidePointer(e) {
|
|
585
|
+
const top = stack[stack.length - 1];
|
|
586
|
+
if (!top) return;
|
|
587
|
+
const node = top.options.node;
|
|
588
|
+
if (node && e.target instanceof Node) {
|
|
589
|
+
if (!node.contains(e.target)) top.options.onOutsidePointer?.(e);
|
|
590
|
+
} else top.options.onOutsidePointer?.(e);
|
|
591
|
+
}
|
|
592
|
+
return {
|
|
593
|
+
register,
|
|
594
|
+
layers,
|
|
595
|
+
handleEscape,
|
|
596
|
+
handleOutsidePointer
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* USAGE EXAMPLE:
|
|
601
|
+
*
|
|
602
|
+
* const layerManager = createLayer();
|
|
603
|
+
*
|
|
604
|
+
* function Modal({ onClose }) {
|
|
605
|
+
* const modalRef = ref<HTMLDivElement>();
|
|
606
|
+
*
|
|
607
|
+
* const layer = layerManager.register({
|
|
608
|
+
* node: modalRef.current,
|
|
609
|
+
* onEscape: onClose,
|
|
610
|
+
* onOutsidePointer: onClose,
|
|
611
|
+
* });
|
|
612
|
+
*
|
|
613
|
+
* onUnmount(() => layer.unregister());
|
|
614
|
+
*
|
|
615
|
+
* return (
|
|
616
|
+
* <div ref={modalRef}>
|
|
617
|
+
* <h1>Modal</h1>
|
|
618
|
+
* {layer.isTop() && <p>I am on top!</p>}
|
|
619
|
+
* </div>
|
|
620
|
+
* );
|
|
621
|
+
* }
|
|
622
|
+
*/
|
|
394
623
|
//#endregion
|
|
395
|
-
export {
|
|
624
|
+
export { definePortal as a, layout as c, Portal as i, cloneElement as l, createCollection as n, Presence as o, DefaultPortal as r, Slot as s, createLayer as t, isElement as u };
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { l as ComponentFunction } from "../control-
|
|
2
|
-
import { M as RouteMatch, W as RouteRegistry, w as RouteAuthOptions } from "../index-
|
|
1
|
+
import { l as ComponentFunction } from "../control-DhUZU4_V.js";
|
|
2
|
+
import { M as RouteMatch, W as RouteRegistry, w as RouteAuthOptions } from "../index-pIgGaXvS.js";
|
|
3
3
|
import { C as Query, k as QueryStaleReason } from "../index-5S-fi2xy.js";
|
|
4
4
|
//#region src/testing/render.d.ts
|
|
5
5
|
interface RenderOptions {
|
package/dist/testing/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { r as flushRuntimeScheduler } from "../access-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { a as cleanupApp, r as createSPA, t as createIsland } from "../boot-
|
|
1
|
+
import { r as flushRuntimeScheduler } from "../access-Dpfoi4cA.js";
|
|
2
|
+
import { l as addInvalidationListener } from "../data-runtime-Ck3tJDDQ.js";
|
|
3
|
+
import { r as computeRouteActivityMatches } from "../route-matching-DqULzZtC.js";
|
|
4
|
+
import { a as cleanupApp, r as createSPA, t as createIsland } from "../boot-CViTpUiB.js";
|
|
5
5
|
//#region src/testing/render.ts
|
|
6
6
|
const renderStates = /* @__PURE__ */ new WeakMap();
|
|
7
7
|
const eventConstructorNames = {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { m as withHydrationVerificationRender } from "./render-context-D0Hoj9dW.js";
|
|
2
|
+
import { t as SSR_RENDER_DATA_ATTR } from "./ssr-DSHd_Q9K.js";
|
|
3
|
+
import { a as renderResolvedToStringSync } from "./ssr-B98593qJ.js";
|
|
3
4
|
//#region src/ssr/verify-hydration.ts
|
|
4
5
|
function normalizeHydrationHtml(html) {
|
|
5
6
|
const template = document.createElement("template");
|
|
@@ -9,13 +10,13 @@ function normalizeHydrationHtml(html) {
|
|
|
9
10
|
}
|
|
10
11
|
function verifyHydrationSyncForUrl(opts) {
|
|
11
12
|
const { root, url, registry, resolved, options } = opts;
|
|
12
|
-
const expected = renderResolvedToStringSync({
|
|
13
|
+
const expected = withHydrationVerificationRender(() => renderResolvedToStringSync({
|
|
13
14
|
url,
|
|
14
15
|
registry,
|
|
15
16
|
handler: resolved.handler,
|
|
16
17
|
params: resolved.params,
|
|
17
18
|
options
|
|
18
|
-
});
|
|
19
|
+
}));
|
|
19
20
|
return normalizeHydrationHtml(root.innerHTML) === normalizeHydrationHtml(expected);
|
|
20
21
|
}
|
|
21
22
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askrjs/askr",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.86",
|
|
4
4
|
"description": "Actor-backed deterministic UI framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"askr",
|
|
@@ -170,7 +170,7 @@
|
|
|
170
170
|
}
|
|
171
171
|
},
|
|
172
172
|
"engines": {
|
|
173
|
-
"node": ">=24.
|
|
173
|
+
"node": ">=24.0.0"
|
|
174
174
|
},
|
|
175
175
|
"packageManager": "npm@12.0.1",
|
|
176
176
|
"allowScripts": {
|