@askrjs/askr 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +55 -1
  2. package/dist/actions/index.js +4 -4
  3. package/dist/benchmark.js +6 -6
  4. package/dist/boot/index.js +1 -1
  5. package/dist/{boot-DaoTYoCw.js → boot-DUJkrqGs.js} +79 -36
  6. package/dist/{browser-activity-CB8e-V4f.js → browser-activity-2r5gA1Cb.js} +6 -4
  7. package/dist/components/index.js +1 -1
  8. package/dist/{compose-ref-DWzdbxsD.js → compose-ref-ccRU59BM.js} +7 -1
  9. package/dist/control/index.js +1 -1
  10. package/dist/{control-nfpT2fbK.js → control-hr3B0QaD.js} +4 -2
  11. package/dist/{csp-nonce-DwGw1A6Q.js → csp-nonce-D-XM_uuJ.js} +1 -1
  12. package/dist/data/index.js +3 -3
  13. package/dist/{data-BCwClJiF.js → data-BsnOUpQ6.js} +18 -8
  14. package/dist/{data-runtime-C1bFAlba.js → data-runtime-i-RD0Ffm.js} +1 -1
  15. package/dist/{deferred-bEEHHvic.js → deferred-nGZglpj6.js} +5 -5
  16. package/dist/{error-boundary-Bpwofwps.js → error-boundary-ChXoIFVl.js} +2 -2
  17. package/dist/foundations/index.js +2 -2
  18. package/dist/foundations/interactions/index.js +1 -1
  19. package/dist/foundations/state/index.js +1 -1
  20. package/dist/foundations/structures/index.js +2 -2
  21. package/dist/foundations/utilities/index.js +1 -1
  22. package/dist/fx/index.js +2 -2
  23. package/dist/{hooks-BimKStr4.js → hooks-kjLigwDJ.js} +1 -1
  24. package/dist/index.js +5 -5
  25. package/dist/{instance-BAnfmXOR.js → instance-DL-YKrj6.js} +6 -2
  26. package/dist/{interactions-D2BoREb-.js → interactions-B_wfsDQg.js} +5 -1
  27. package/dist/{manifest-CW9gyNBY.js → manifest-BNupb86f.js} +1 -1
  28. package/dist/{navigate-CP_0Zy5U.js → navigate-DsfO12hB.js} +95 -79
  29. package/dist/{portal-DuOKfnLa.js → portal-LYf4cbHd.js} +3 -3
  30. package/dist/{query-registry-WMCN0BJL.js → query-registry-tzSiVrV_.js} +7 -2
  31. package/dist/{render-sync-IC5lMFpq.js → render-sync-Qz-9Hcqw.js} +187 -29
  32. package/dist/{resolution-Cx82-xjW.js → resolution-CF1BqHLm.js} +22 -8
  33. package/dist/{resource-CLjB7RBQ.js → resource-BhcaFqdB.js} +2 -2
  34. package/dist/resources/index.js +25 -27
  35. package/dist/router/index.js +8 -8
  36. package/dist/{scope-CwpVSHVf.js → scope-ila_zaId.js} +2 -2
  37. package/dist/ssg/index.js +43 -14
  38. package/dist/ssr/index.js +2 -2
  39. package/dist/{ssr-DoV-vJ-5.js → ssr-DPfdcq0e.js} +1 -1
  40. package/dist/{ssr-BJ8ug7zH.js → ssr-DueDLmhp.js} +6 -6
  41. package/dist/{state-DWO1KzkX.js → state-i9D4EtY6.js} +19 -1
  42. package/dist/{structures-D4dDMqHX.js → structures-CkehlOT3.js} +1 -1
  43. package/dist/testing/index.js +6 -6
  44. package/dist/{url-CnbfpX0K.js → url-C9xMpMMv.js} +6 -6
  45. package/dist/{verify-hydration-DpVaDnqz.js → verify-hydration-Jh5rnm_w.js} +4 -4
  46. package/package.json +1 -1
package/dist/ssg/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import { mt as prepareRouteHydrationData, nt as getRenderHandler, ot as RouteDataLoadError, rt as _preloadRouteHandler, t as bindResolvedRouteData, x as addRouteBasePath } from "../resolution-Cx82-xjW.js";
2
- import { n as createRouteRegistry } from "../manifest-CW9gyNBY.js";
3
- import { c as route, n as resolveDeferredValues } from "../deferred-bEEHHvic.js";
4
- import { n as renderDocument } from "../ssr-DoV-vJ-5.js";
5
- import { n as renderToString } from "../ssr-BJ8ug7zH.js";
1
+ import { ct as encodePathSegment, mt as prepareRouteHydrationData, nt as getRenderHandler, ot as RouteDataLoadError, rt as _preloadRouteHandler, t as bindResolvedRouteData, x as addRouteBasePath } from "../resolution-CF1BqHLm.js";
2
+ import { n as createRouteRegistry } from "../manifest-BNupb86f.js";
3
+ import { c as route, n as resolveDeferredValues } from "../deferred-nGZglpj6.js";
4
+ import { n as renderDocument } from "../ssr-DPfdcq0e.js";
5
+ import { n as renderToString } from "../ssr-DueDLmhp.js";
6
6
  import * as fs$1 from "node:fs/promises";
7
7
  import * as os from "node:os";
8
8
  import * as pathModule from "node:path";
@@ -128,9 +128,33 @@ function getOutputFilePath(pathStr) {
128
128
  if (pathStr === "/") return "index.html";
129
129
  return `${pathStr.replace(/^\/|\/$/g, "")}/index.html`;
130
130
  }
131
+ /** Prefer normalized names while accepting legacy raw template keys. */
132
+ function readRouteParameter(params, key) {
133
+ const normalized = key.trim();
134
+ const splat = normalized.startsWith("*");
135
+ const name = splat ? normalized.slice(1).trim() : normalized;
136
+ const canonical = params[name];
137
+ return {
138
+ name,
139
+ splat,
140
+ value: key === name || typeof canonical === "string" || Object.prototype.hasOwnProperty.call(params, name) ? canonical : params[key]
141
+ };
142
+ }
131
143
  function interpolateRoutePath(routePath, params) {
132
144
  if (!params) return routePath;
133
- return routePath.replace(/\{([^}]+)\}/g, (_, key) => params[key] ?? "");
145
+ return routePath.replace(/\{([^}]+)\}/g, (_, key) => {
146
+ return readRouteParameter(params, key).value ?? "";
147
+ });
148
+ }
149
+ /** Encode the render URL while retaining the existing concrete output path. */
150
+ function interpolateRouteUrl(routePath, params) {
151
+ assertSafeRoutePath(interpolateRoutePath(routePath, params));
152
+ if (!params) return routePath;
153
+ return routePath.replace(/\{([^}]+)\}/g, (_, key) => {
154
+ const { splat, value: parameterValue } = readRouteParameter(params, key);
155
+ const value = parameterValue ?? "";
156
+ return splat ? value.split("/").map(encodePathSegment).join("/") : encodePathSegment(value);
157
+ });
134
158
  }
135
159
  function resolveRouteDescriptor(route) {
136
160
  const path = interpolateRoutePath(route.path, route.params);
@@ -238,9 +262,12 @@ function validateRoutes(routes) {
238
262
  if (seen.has(key)) throw new Error(`duplicate route entry detected for path "${route.path}"`);
239
263
  seen.add(key);
240
264
  if (route.path.includes("{")) {
241
- const paramNames = Array.from(route.path.matchAll(/\{([^}]+)\}/g)).map((m) => m[1]);
265
+ const paramKeys = route.path.split("/").filter((segment) => segment.startsWith("{") && segment.endsWith("}")).map((segment) => segment.slice(1, -1));
242
266
  if (!route.params) throw new Error(`route "${route.path}" uses path parameters and requires params`);
243
- for (const name of paramNames) if (!(name in route.params)) throw new Error(`route "${route.path}" missing required param "${name}"`);
267
+ for (const paramKey of paramKeys) {
268
+ const { name, value } = readRouteParameter(route.params, paramKey);
269
+ if (typeof value !== "string") throw new Error(`route "${route.path}" missing required param "${name}"`);
270
+ }
244
271
  }
245
272
  }
246
273
  }
@@ -266,10 +293,11 @@ async function batchRenderRoutes(routes, options = {}) {
266
293
  }, { basePath: sharedBasePath }) : void 0;
267
294
  const renderOne = async (route$2) => {
268
295
  const startTime = performance.now();
269
- const url = interpolateRoutePath(route$2.path, route$2.params);
296
+ const path = interpolateRoutePath(route$2.path, route$2.params);
297
+ const url = interpolateRouteUrl(route$2.path, route$2.params);
270
298
  const publicUrl = addRouteBasePath(url, route$2.basePath ?? "");
271
299
  const requestUrl = new URL(url, "http://localhost");
272
- const resolvedData = resolveSsgRouteData(dataMap, route$2.path, url);
300
+ const resolvedData = resolveSsgRouteData(dataMap, route$2.path, path);
273
301
  const baseData = resolvedData.hasData ? resolvedData.data : void 0;
274
302
  const resourceCount = resolvedData.hasData && baseData ? Object.keys(baseData).length : 0;
275
303
  const mergedHandler = route$2.handler;
@@ -342,8 +370,8 @@ async function batchRenderRoutes(routes, options = {}) {
342
370
  });
343
371
  const duration = performance.now() - startTime;
344
372
  return {
345
- path: url,
346
- filePath: getOutputFilePath(url),
373
+ path,
374
+ filePath: getOutputFilePath(path),
347
375
  html,
348
376
  fileSize: Buffer.byteLength(html, "utf8"),
349
377
  renderDuration: Math.round(duration),
@@ -355,8 +383,8 @@ async function batchRenderRoutes(routes, options = {}) {
355
383
  } catch (error) {
356
384
  const duration = performance.now() - startTime;
357
385
  return {
358
- path: url,
359
- filePath: getOutputFilePath(url),
386
+ path,
387
+ filePath: getOutputFilePath(path),
360
388
  html: "",
361
389
  fileSize: 0,
362
390
  renderDuration: Math.round(duration),
@@ -927,6 +955,7 @@ function createStaticGen(options) {
927
955
  for (let index = 0; index < eligibleDescriptors.length; index += 1) {
928
956
  const descriptor = eligibleDescriptors[index];
929
957
  const entry = selectRouteForGeneration(descriptor, previousEntries.get(descriptor.routeId) ?? null, effectiveMode, changedKeys, changedRoutes);
958
+ if (entry.reason === "unchanged" && !outputFileExists(options.outputDir, descriptor.filePath)) entry.reason = "new-route";
930
959
  selected.push(entry);
931
960
  if (entry.reason !== "unchanged") routesToRender.push(entry);
932
961
  }
package/dist/ssr/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import { T as SSRDataMissingError } from "../render-context-DGHnEveC.js";
2
- import { a as SSRAccessDecisionError, i as renderRouteRequestToString, n as renderToString, r as renderRouteRequest, t as renderToStream } from "../ssr-BJ8ug7zH.js";
3
- import { c as getRenderContext, d as escapeHtml, l as withRenderContext, n as renderToStringSync, s as createRenderContext, u as withRenderContextAsync } from "../render-sync-IC5lMFpq.js";
2
+ import { a as SSRAccessDecisionError, i as renderRouteRequestToString, n as renderToString, r as renderRouteRequest, t as renderToStream } from "../ssr-DueDLmhp.js";
3
+ import { c as getRenderContext, d as escapeHtml, l as withRenderContext, n as renderToStringSync, s as createRenderContext, u as withRenderContextAsync } from "../render-sync-Qz-9Hcqw.js";
4
4
  export { SSRAccessDecisionError, SSRDataMissingError, createRenderContext, escapeHtml, getRenderContext, renderRouteRequest, renderRouteRequestToString, renderToStream, renderToString, renderToStringSync, withRenderContext, withRenderContextAsync };
@@ -1,5 +1,5 @@
1
1
  import { n as isPromiseLike } from "./promise-Dz8iIHAm.js";
2
- import { d as isCustomElementName } from "./url-CnbfpX0K.js";
2
+ import { d as isCustomElementName } from "./url-C9xMpMMv.js";
3
3
  //#region src/common/prop-classification.ts
4
4
  /**
5
5
  * The prop vocabulary shared by the DOM renderer and the SSR renderer.
@@ -1,11 +1,11 @@
1
- import { r as validateCspNonce } from "./csp-nonce-DwGw1A6Q.js";
1
+ import { r as validateCspNonce } from "./csp-nonce-D-XM_uuJ.js";
2
2
  import { T as SSRDataMissingError, n as getActiveRenderContext, u as setDeferredBoundaryParent } from "./render-context-DGHnEveC.js";
3
3
  import { n as isPromiseLike } from "./promise-Dz8iIHAm.js";
4
- import { c as withTelemetry, i as dehydrateDataRuntime, t as createQueryPrefetchContext } from "./query-registry-WMCN0BJL.js";
5
- import { C as removeRouteBasePath, S as normalizeRouteBasePath, _ as getMatchingRouteRecord, a as resolveRouteRequest, n as getRouteRenderContext } from "./resolution-Cx82-xjW.js";
6
- import { t as createDataRuntime } from "./data-runtime-C1bFAlba.js";
7
- import { n as renderDocument } from "./ssr-DoV-vJ-5.js";
8
- import { a as serializeHydrationRenderData, i as StringSink, n as renderToStringSync, o as withHydratedAuth, r as StreamSink, s as createRenderContext, t as renderSSRRouteAppToSink, u as withRenderContextAsync } from "./render-sync-IC5lMFpq.js";
4
+ import { c as withTelemetry, i as dehydrateDataRuntime, t as createQueryPrefetchContext } from "./query-registry-tzSiVrV_.js";
5
+ import { C as removeRouteBasePath, S as normalizeRouteBasePath, _ as getMatchingRouteRecord, a as resolveRouteRequest, n as getRouteRenderContext } from "./resolution-CF1BqHLm.js";
6
+ import { t as createDataRuntime } from "./data-runtime-i-RD0Ffm.js";
7
+ import { n as renderDocument } from "./ssr-DPfdcq0e.js";
8
+ import { a as serializeHydrationRenderData, i as StringSink, n as renderToStringSync, o as withHydratedAuth, r as StreamSink, s as createRenderContext, t as renderSSRRouteAppToSink, u as withRenderContextAsync } from "./render-sync-Qz-9Hcqw.js";
9
9
  //#region src/ssr/errors.ts
10
10
  /**
11
11
  * Thrown by synchronous route SSR (`renderToString()`/`renderToStream()`) when
@@ -1,4 +1,4 @@
1
- import { D as isTracking, E as getTrackingComputation, F as logger, L as isProductionEnvironment, O as notifySource, S as queueTask, T as Signal, a as getCurrentInstance, b as getFlushVersion, h as isRendering, k as trackSource, r as claimHook, s as requireInstance, v as effectScheduler, w as Computation } from "./instance-BAnfmXOR.js";
1
+ import { D as isTracking, E as getTrackingComputation, I as logger, O as notifySource, R as isProductionEnvironment, S as queueTask, T as Signal, a as getCurrentInstance, b as getFlushVersion, d as recordUndo, h as isRendering, k as trackSource, r as claimHook, s as requireInstance, v as effectScheduler, w as Computation } from "./instance-DL-YKrj6.js";
2
2
  import { t as markReadable } from "./readable-DFWOsTac.js";
3
3
  import { n as isSnapshotSource } from "./snapshot-Cjx4N988.js";
4
4
  //#region src/core/api/state.ts
@@ -114,6 +114,13 @@ function createDerived(owner, compute, label) {
114
114
  })),
115
115
  setCompute(fn) {
116
116
  if (fn === current) return;
117
+ const previous = current;
118
+ const sources = new Set(computation._sources ?? []);
119
+ recordUndo(() => {
120
+ current = previous;
121
+ computation.restoreSources(sources);
122
+ computation.deferRetry();
123
+ });
117
124
  current = fn;
118
125
  computation.invalidate();
119
126
  }
@@ -212,6 +219,17 @@ function createSelector(owner, initialSource, initialEquals) {
212
219
  return {
213
220
  predicate,
214
221
  setSource(nextSource, nextEquals) {
222
+ if (nextSource === source && nextEquals === equals) return;
223
+ const previousSource = source;
224
+ const previousEquals = equals;
225
+ const sources = new Set(watcher._sources ?? []);
226
+ recordUndo(() => {
227
+ source = previousSource;
228
+ equals = previousEquals;
229
+ watcher.restoreSources(sources);
230
+ watcher.invalidate();
231
+ notifySource(allObjects);
232
+ });
215
233
  const comparatorChanged = equals !== nextEquals;
216
234
  equals = nextEquals;
217
235
  if (comparatorChanged) notifySource(allObjects, getTrackingComputation() ?? void 0);
@@ -111,7 +111,7 @@ function createCollection() {
111
111
  };
112
112
  registry.set(node, item);
113
113
  return () => {
114
- registry.delete(node);
114
+ if (registry.get(node) === item) registry.delete(node);
115
115
  };
116
116
  }
117
117
  function items() {
@@ -1,9 +1,9 @@
1
- import { y as flushSync } from "../instance-BAnfmXOR.js";
2
- import { n as createSource, s as notify, u as readSource } from "../hooks-BimKStr4.js";
3
- import { v as matchRoute } from "../resolution-Cx82-xjW.js";
4
- import { a as cleanupApp, n as createSPA, r as createIsland } from "../boot-DaoTYoCw.js";
5
- import { h as addInvalidationListener, t as createDataRuntime, u as resolveDataRuntimeState } from "../data-runtime-C1bFAlba.js";
6
- import { a as loadingQueryState, i as freshQueryState, o as refreshingQueryState, r as errorQueryState, s as staleQueryState } from "../data-BCwClJiF.js";
1
+ import { y as flushSync } from "../instance-DL-YKrj6.js";
2
+ import { n as createSource, s as notify, u as readSource } from "../hooks-kjLigwDJ.js";
3
+ import { v as matchRoute } from "../resolution-CF1BqHLm.js";
4
+ import { a as cleanupApp, n as createSPA, r as createIsland } from "../boot-DUJkrqGs.js";
5
+ import { h as addInvalidationListener, t as createDataRuntime, u as resolveDataRuntimeState } from "../data-runtime-i-RD0Ffm.js";
6
+ import { a as loadingQueryState, i as freshQueryState, o as refreshingQueryState, r as errorQueryState, s as staleQueryState } from "../data-BsnOUpQ6.js";
7
7
  import { i as normalizeAsyncDataError } from "../shared-O2ZnmYAf.js";
8
8
  //#region src/testing/render.ts
9
9
  const renderStates = /* @__PURE__ */ new WeakMap();
@@ -1,4 +1,4 @@
1
- import { F as logger, I as isDevelopmentEnvironment } from "./instance-BAnfmXOR.js";
1
+ import { I as logger, L as isDevelopmentEnvironment } from "./instance-DL-YKrj6.js";
2
2
  //#region src/common/attr-names.ts
3
3
  /**
4
4
  * JSX prop name to rendered attribute name, shared by the DOM renderer and SSR.
@@ -15,7 +15,7 @@ import { F as logger, I as isDevelopmentEnvironment } from "./instance-BAnfmXOR.
15
15
  * Custom elements (a tag name containing `-`) define their own attributes, so
16
16
  * they only get this base table and never the SVG table below.
17
17
  */
18
- const PUBLIC_ATTRIBUTE_NAME_MAP = {
18
+ const PUBLIC_ATTRIBUTE_NAME_MAP = Object.assign(Object.create(null), {
19
19
  className: "class",
20
20
  htmlFor: "for",
21
21
  autoComplete: "autocomplete",
@@ -36,8 +36,8 @@ const PUBLIC_ATTRIBUTE_NAME_MAP = {
36
36
  strokeLinejoin: "stroke-linejoin",
37
37
  fillRule: "fill-rule",
38
38
  clipRule: "clip-rule"
39
- };
40
- const SVG_ATTRIBUTE_NAME_MAP = {};
39
+ });
40
+ const SVG_ATTRIBUTE_NAME_MAP = Object.create(null);
41
41
  /**
42
42
  * SVG presentation attributes are hyphenated, and the XML-namespaced ones use
43
43
  * a prefix; JSX spells both in camelCase (`strokeDasharray`, `xlinkHref`).
@@ -52,11 +52,11 @@ function getPublicAttributeName(propName, customElement = false) {
52
52
  if (propName.startsWith("attr:")) return propName.slice(5);
53
53
  return PUBLIC_ATTRIBUTE_NAME_MAP[propName] ?? (customElement ? void 0 : SVG_ATTRIBUTE_NAME_MAP[propName]) ?? propName;
54
54
  }
55
- const ATTRIBUTE_PREFIX_NAMESPACES = {
55
+ const ATTRIBUTE_PREFIX_NAMESPACES = Object.assign(Object.create(null), {
56
56
  xlink: "http://www.w3.org/1999/xlink",
57
57
  xml: "http://www.w3.org/XML/1998/namespace",
58
58
  xmlns: "http://www.w3.org/2000/xmlns/"
59
- };
59
+ });
60
60
  const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
61
61
  const MATHML_NAMESPACE = "http://www.w3.org/1998/Math/MathML";
62
62
  /**
@@ -1,8 +1,8 @@
1
- import { r as validateCspNonce } from "./csp-nonce-DwGw1A6Q.js";
1
+ import { r as validateCspNonce } from "./csp-nonce-D-XM_uuJ.js";
2
2
  import { g as withHydrationVerificationRender, v as getHydrationRenderUrl } from "./render-context-DGHnEveC.js";
3
- import { C as removeRouteBasePath, S as normalizeRouteBasePath, f as currentAuth, n as getRouteRenderContext, y as resolveRouteFromRoutes } from "./resolution-Cx82-xjW.js";
4
- import { t as SSR_RENDER_DATA_ATTR } from "./ssr-DoV-vJ-5.js";
5
- import { i as StringSink, s as createRenderContext, t as renderSSRRouteAppToSink } from "./render-sync-IC5lMFpq.js";
3
+ import { C as removeRouteBasePath, S as normalizeRouteBasePath, f as currentAuth, n as getRouteRenderContext, y as resolveRouteFromRoutes } from "./resolution-CF1BqHLm.js";
4
+ import { t as SSR_RENDER_DATA_ATTR } from "./ssr-DPfdcq0e.js";
5
+ import { i as StringSink, s as createRenderContext, t as renderSSRRouteAppToSink } from "./render-sync-Qz-9Hcqw.js";
6
6
  //#region src/ssr/render-resolved.ts
7
7
  function sameRouteParams(left, right) {
8
8
  if (!left || !right) return !left && !right;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askrjs/askr",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "A TypeScript UI runtime with getter-based state, fine-grained bindings, transactional commits with rollback, and one route graph for SPA, SSR, and SSG.",
5
5
  "keywords": [
6
6
  "askr",