@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.
- package/CHANGELOG.md +55 -1
- package/dist/actions/index.js +4 -4
- package/dist/benchmark.js +6 -6
- package/dist/boot/index.js +1 -1
- package/dist/{boot-DaoTYoCw.js → boot-DUJkrqGs.js} +79 -36
- package/dist/{browser-activity-CB8e-V4f.js → browser-activity-2r5gA1Cb.js} +6 -4
- package/dist/components/index.js +1 -1
- package/dist/{compose-ref-DWzdbxsD.js → compose-ref-ccRU59BM.js} +7 -1
- package/dist/control/index.js +1 -1
- package/dist/{control-nfpT2fbK.js → control-hr3B0QaD.js} +4 -2
- package/dist/{csp-nonce-DwGw1A6Q.js → csp-nonce-D-XM_uuJ.js} +1 -1
- package/dist/data/index.js +3 -3
- package/dist/{data-BCwClJiF.js → data-BsnOUpQ6.js} +18 -8
- package/dist/{data-runtime-C1bFAlba.js → data-runtime-i-RD0Ffm.js} +1 -1
- package/dist/{deferred-bEEHHvic.js → deferred-nGZglpj6.js} +5 -5
- package/dist/{error-boundary-Bpwofwps.js → error-boundary-ChXoIFVl.js} +2 -2
- package/dist/foundations/index.js +2 -2
- package/dist/foundations/interactions/index.js +1 -1
- package/dist/foundations/state/index.js +1 -1
- package/dist/foundations/structures/index.js +2 -2
- package/dist/foundations/utilities/index.js +1 -1
- package/dist/fx/index.js +2 -2
- package/dist/{hooks-BimKStr4.js → hooks-kjLigwDJ.js} +1 -1
- package/dist/index.js +5 -5
- package/dist/{instance-BAnfmXOR.js → instance-DL-YKrj6.js} +6 -2
- package/dist/{interactions-D2BoREb-.js → interactions-B_wfsDQg.js} +5 -1
- package/dist/{manifest-CW9gyNBY.js → manifest-BNupb86f.js} +1 -1
- package/dist/{navigate-CP_0Zy5U.js → navigate-DsfO12hB.js} +95 -79
- package/dist/{portal-DuOKfnLa.js → portal-LYf4cbHd.js} +3 -3
- package/dist/{query-registry-WMCN0BJL.js → query-registry-tzSiVrV_.js} +7 -2
- package/dist/{render-sync-IC5lMFpq.js → render-sync-Qz-9Hcqw.js} +187 -29
- package/dist/{resolution-Cx82-xjW.js → resolution-CF1BqHLm.js} +22 -8
- package/dist/{resource-CLjB7RBQ.js → resource-BhcaFqdB.js} +2 -2
- package/dist/resources/index.js +25 -27
- package/dist/router/index.js +8 -8
- package/dist/{scope-CwpVSHVf.js → scope-ila_zaId.js} +2 -2
- package/dist/ssg/index.js +43 -14
- package/dist/ssr/index.js +2 -2
- package/dist/{ssr-DoV-vJ-5.js → ssr-DPfdcq0e.js} +1 -1
- package/dist/{ssr-BJ8ug7zH.js → ssr-DueDLmhp.js} +6 -6
- package/dist/{state-DWO1KzkX.js → state-i9D4EtY6.js} +19 -1
- package/dist/{structures-D4dDMqHX.js → structures-CkehlOT3.js} +1 -1
- package/dist/testing/index.js +6 -6
- package/dist/{url-CnbfpX0K.js → url-C9xMpMMv.js} +6 -6
- package/dist/{verify-hydration-DpVaDnqz.js → verify-hydration-Jh5rnm_w.js} +4 -4
- 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-
|
|
2
|
-
import { n as createRouteRegistry } from "../manifest-
|
|
3
|
-
import { c as route, n as resolveDeferredValues } from "../deferred-
|
|
4
|
-
import { n as renderDocument } from "../ssr-
|
|
5
|
-
import { n as renderToString } from "../ssr-
|
|
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) =>
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
346
|
-
filePath: getOutputFilePath(
|
|
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
|
|
359
|
-
filePath: getOutputFilePath(
|
|
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-
|
|
3
|
-
import { c as getRenderContext, d as escapeHtml, l as withRenderContext, n as renderToStringSync, s as createRenderContext, u as withRenderContextAsync } from "../render-sync-
|
|
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-
|
|
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-
|
|
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-
|
|
5
|
-
import { C as removeRouteBasePath, S as normalizeRouteBasePath, _ as getMatchingRouteRecord, a as resolveRouteRequest, n as getRouteRenderContext } from "./resolution-
|
|
6
|
-
import { t as createDataRuntime } from "./data-runtime-
|
|
7
|
-
import { n as renderDocument } from "./ssr-
|
|
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-
|
|
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,
|
|
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);
|
package/dist/testing/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { y as flushSync } from "../instance-
|
|
2
|
-
import { n as createSource, s as notify, u as readSource } from "../hooks-
|
|
3
|
-
import { v as matchRoute } from "../resolution-
|
|
4
|
-
import { a as cleanupApp, n as createSPA, r as createIsland } from "../boot-
|
|
5
|
-
import { h as addInvalidationListener, t as createDataRuntime, u as resolveDataRuntimeState } from "../data-runtime-
|
|
6
|
-
import { a as loadingQueryState, i as freshQueryState, o as refreshingQueryState, r as errorQueryState, s as staleQueryState } from "../data-
|
|
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 {
|
|
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-
|
|
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-
|
|
4
|
-
import { t as SSR_RENDER_DATA_ATTR } from "./ssr-
|
|
5
|
-
import { i as StringSink, s as createRenderContext, t as renderSSRRouteAppToSink } from "./render-sync-
|
|
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.
|
|
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",
|