@askrjs/askr 0.0.52 → 0.0.54
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/README.md +5 -1
- package/dist/{runtime/scheduler.js → access-Bg4RJNC8.js} +182 -9
- package/dist/actions/index.d.ts +2 -0
- package/dist/actions/index.js +103 -0
- package/dist/{common/attr-names.js → attr-names-CjhzmHOn.js} +1 -1
- package/dist/benchmark.d.ts +6 -2
- package/dist/benchmark.js +63 -11
- package/dist/boot/index.d.ts +61 -2
- package/dist/boot/index.js +1 -203
- package/dist/boot-2ZR3MtO0.js +647 -0
- package/dist/cleanup-DScKZG2i.js +487 -0
- package/dist/component-internal-D9PLuFUc.js +614 -0
- package/dist/component-lifecycle-C7lnU9Bt.js +359 -0
- package/dist/{runtime/component-scope.js → component-scope-CC3cojX9.js} +8 -1
- package/dist/component-scope-CvPba6O6.d.ts +12 -0
- package/dist/components/index.d.ts +17 -2
- package/dist/components/index.js +39 -1
- package/dist/compose-ref-Cc_YkUpM.js +92 -0
- package/dist/{foundations/utilities/compose-ref.d.ts → compose-ref-Cizq72-x.d.ts} +1 -1
- package/dist/control/index.d.ts +1 -3
- package/dist/control/index.js +1 -3
- package/dist/control-BI4RMD2z.d.ts +437 -0
- package/dist/control-Bf4Wkdvv.d.ts +9 -0
- package/dist/{common/control.js → control-DhFRTIoE.js} +1 -1
- package/dist/control-mXROCjL3.js +165 -0
- package/dist/data/index.d.ts +2 -6
- package/dist/data/index.js +4 -5
- package/dist/data-B9dauyDn.js +559 -0
- package/dist/{data/data-runtime.js → data-runtime-SJ1BSUvk.js} +32 -31
- package/dist/deferred-DklLG4qM.js +386 -0
- package/dist/{runtime/effect.js → effect-BwnIvLah.js} +4 -4
- package/dist/fastlane-Dw8SOBr9.js +343 -0
- package/dist/for-internal-CSz8Unkq.js +1563 -0
- package/dist/foundations/icon/index.d.ts +68 -2
- package/dist/foundations/icon/index.js +85 -1
- package/dist/foundations/index.d.ts +2 -5
- package/dist/foundations/index.js +2 -5
- package/dist/foundations/interactions/index.d.ts +264 -6
- package/dist/foundations/interactions/index.js +1 -6
- package/dist/foundations/state/index.d.ts +32 -1
- package/dist/foundations/state/index.js +78 -1
- package/dist/foundations/structures/index.d.ts +2 -7
- package/dist/foundations/structures/index.js +2 -7
- package/dist/foundations/utilities/index.d.ts +2 -6
- package/dist/foundations/utilities/index.js +2 -5
- package/dist/fx/index.d.ts +190 -3
- package/dist/fx/index.js +454 -4
- package/dist/index-B1LNotpU.d.ts +239 -0
- package/dist/index-Bki2rqcr.d.ts +233 -0
- package/dist/index-BnU0NPwM.d.ts +101 -0
- package/dist/index-C8iW3xCt.d.ts +44 -0
- package/dist/index-DwxdIA-t.d.ts +48 -0
- package/dist/{runtime/runtime.d.ts → index-Zb31mCiU.d.ts} +31 -8
- package/dist/index.d.ts +8 -13
- package/dist/index.js +150 -15
- package/dist/interactions-w7gQN4ha.js +280 -0
- package/dist/{data/invalidation-listeners.js → invalidation-listeners-Des3AHYs.js} +1 -1
- package/dist/{common/props.d.ts → jsx-CP0gmYwJ.d.ts} +17 -5
- package/dist/{common/jsx.js → jsx-CUpRxrLH.js} +1 -1
- package/dist/jsx-dev-runtime.d.ts +2 -4
- package/dist/jsx-dev-runtime.js +7 -5
- package/dist/jsx-runtime-92bV2hSa.d.ts +34 -0
- package/dist/jsx-runtime-BVVgDSdq.d.ts +1 -0
- package/dist/jsx-runtime.d.ts +2 -35
- package/dist/jsx-runtime.js +11 -5
- package/dist/{runtime/lifecycle-operations.js → lifecycle-operations-CdRjdsHo.js} +4 -5
- package/dist/navigate-BVDCzOuB.d.ts +34 -0
- package/dist/navigate-D17eVQyI.js +1449 -0
- package/dist/{runtime/portal.js → portal-C47xkwXj.js} +71 -41
- package/dist/query-registry-CQIT4mXr.js +73 -0
- package/dist/{common/render-context.js → render-context-Clw3rFiO.js} +14 -6
- package/dist/renderer-DrLRAD5y.js +6266 -0
- package/dist/{runtime/resource-operation.js → resource-operation-BNY29MVH.js} +118 -15
- package/dist/resources/index.d.ts +42 -3
- package/dist/resources/index.js +3 -4
- package/dist/{common/route-activity.js → route-activity-CNJfpwx-.js} +1 -1
- package/dist/route-matching-vJpvLVbX.js +515 -0
- package/dist/router/index.d.ts +166 -14
- package/dist/router/index.js +150 -12
- package/dist/{common/router.d.ts → router-DCfwLBr-.d.ts} +72 -28
- package/dist/{common/router-internal.js → router-internal-BC0w1_xk.js} +1 -1
- package/dist/{runtime/scheduler.d.ts → scheduler-CmLO4Dfm.d.ts} +1 -3
- package/dist/{runtime/selector.js → selector-DafVYzV4.js} +34 -11
- package/dist/{runtime/snapshot-source.js → snapshot-source-BB42xgwb.js} +1 -1
- package/dist/ssg/index.d.ts +252 -4
- package/dist/ssg/index.js +857 -1
- package/dist/ssr/index.d.ts +225 -8
- package/dist/ssr/index.js +3 -6
- package/dist/{common/ssr.js → ssr-CbQO5xd3.js} +1 -1
- package/dist/ssr-DEARZxJ5.js +1413 -0
- package/dist/{runtime/state.js → state-DPl8lffD.js} +3 -5
- package/dist/structures-DUB3HchX.js +221 -0
- package/dist/testing/index.d.ts +3 -2
- package/dist/testing/index.js +2 -5
- package/dist/{jsx/types.d.ts → types-DnQVG4ZY.d.ts} +2 -5
- package/dist/{foundations/utilities/use-id.js → utilities-C_CGX4Dz.js} +1 -1
- package/dist/{ssr/verify-hydration.js → verify-hydration-BWwu-mWu.js} +2 -2
- package/dist/{common/vnode.js → vnode-CGMJYPMB.js} +2 -2
- package/package.json +12 -7
- package/dist/bench/components/benchmark-row.d.ts +0 -20
- package/dist/bench/components/benchmark-row.js +0 -40
- package/dist/bench/components/benchmark-table.js +0 -23
- package/dist/bin/askr-ssg.d.ts +0 -27
- package/dist/bin/askr-ssg.js +0 -186
- package/dist/boot/hydration.js +0 -139
- package/dist/boot/root-lifecycle.d.ts +0 -18
- package/dist/boot/root-lifecycle.js +0 -209
- package/dist/boot/route-startup.js +0 -54
- package/dist/boot/types.d.ts +0 -61
- package/dist/common/component.d.ts +0 -18
- package/dist/common/control.d.ts +0 -12
- package/dist/common/dom-range.d.ts +0 -13
- package/dist/common/env.js +0 -41
- package/dist/common/error-boundary.d.ts +0 -15
- package/dist/common/invariant.js +0 -15
- package/dist/common/jsx.d.ts +0 -22
- package/dist/common/logger.js +0 -34
- package/dist/common/promise.js +0 -6
- package/dist/common/ssr-errors.d.ts +0 -10
- package/dist/common/ssr-errors.js +0 -14
- package/dist/common/ssr.d.ts +0 -41
- package/dist/common/vnode.d.ts +0 -21
- package/dist/components/error-boundary.d.ts +0 -14
- package/dist/components/error-boundary.js +0 -41
- package/dist/components/link.d.ts +0 -68
- package/dist/components/link.js +0 -74
- package/dist/control/case.d.ts +0 -18
- package/dist/control/case.js +0 -68
- package/dist/control/for.d.ts +0 -23
- package/dist/control/for.js +0 -61
- package/dist/control/shared.d.ts +0 -8
- package/dist/control/shared.js +0 -18
- package/dist/control/show.d.ts +0 -14
- package/dist/control/show.js +0 -32
- package/dist/data/data-runtime.d.ts +0 -27
- package/dist/data/invalidation.d.ts +0 -8
- package/dist/data/invalidation.js +0 -25
- package/dist/data/mutation-cell.d.ts +0 -27
- package/dist/data/mutation-cell.js +0 -133
- package/dist/data/query-cell.d.ts +0 -47
- package/dist/data/query-cell.js +0 -324
- package/dist/data/query-key.js +0 -40
- package/dist/data/shared.js +0 -20
- package/dist/data/testing.js +0 -2
- package/dist/data/types.d.ts +0 -160
- package/dist/foundations/icon/icon.d.ts +0 -52
- package/dist/foundations/icon/icon.js +0 -86
- package/dist/foundations/icon/icon.types.d.ts +0 -21
- package/dist/foundations/interactions/dismissable.d.ts +0 -71
- package/dist/foundations/interactions/dismissable.js +0 -24
- package/dist/foundations/interactions/focusable.d.ts +0 -21
- package/dist/foundations/interactions/focusable.js +0 -16
- package/dist/foundations/interactions/hoverable.d.ts +0 -25
- package/dist/foundations/interactions/hoverable.js +0 -13
- package/dist/foundations/interactions/interaction-policy.d.ts +0 -49
- package/dist/foundations/interactions/interaction-policy.js +0 -120
- package/dist/foundations/interactions/pressable.d.ts +0 -60
- package/dist/foundations/interactions/pressable.js +0 -49
- package/dist/foundations/interactions/roving-focus.d.ts +0 -51
- package/dist/foundations/interactions/roving-focus.js +0 -69
- package/dist/foundations/state/controllable.d.ts +0 -32
- package/dist/foundations/state/controllable.js +0 -80
- package/dist/foundations/structures/collection.d.ts +0 -51
- package/dist/foundations/structures/collection.js +0 -49
- package/dist/foundations/structures/layer.d.ts +0 -80
- package/dist/foundations/structures/layer.js +0 -79
- package/dist/foundations/structures/layout.d.ts +0 -32
- package/dist/foundations/structures/layout.js +0 -11
- package/dist/foundations/structures/portal.d.ts +0 -2
- package/dist/foundations/structures/portal.js +0 -3
- package/dist/foundations/structures/presence.d.ts +0 -36
- package/dist/foundations/structures/presence.js +0 -37
- package/dist/foundations/structures/slot.d.ts +0 -34
- package/dist/foundations/structures/slot.js +0 -39
- package/dist/foundations/utilities/aria.d.ts +0 -15
- package/dist/foundations/utilities/aria.js +0 -15
- package/dist/foundations/utilities/compose-handlers.d.ts +0 -36
- package/dist/foundations/utilities/compose-handlers.js +0 -18
- package/dist/foundations/utilities/compose-ref.js +0 -16
- package/dist/foundations/utilities/event-types.d.ts +0 -19
- package/dist/foundations/utilities/merge-props.d.ts +0 -4
- package/dist/foundations/utilities/merge-props.js +0 -47
- package/dist/foundations/utilities/use-id.d.ts +0 -31
- package/dist/fx/fx.d.ts +0 -32
- package/dist/fx/fx.js +0 -211
- package/dist/fx/noop.js +0 -7
- package/dist/fx/timing.d.ts +0 -158
- package/dist/fx/timing.js +0 -241
- package/dist/jsx/index.d.ts +0 -2
- package/dist/jsx/index.js +0 -4
- package/dist/jsx/types.js +0 -2
- package/dist/jsx/utils.d.ts +0 -4
- package/dist/jsx/utils.js +0 -17
- package/dist/jsx-runtime2.d.ts +0 -3
- package/dist/jsx-runtime2.js +0 -4
- package/dist/renderer/attributes.js +0 -254
- package/dist/renderer/boundaries.js +0 -142
- package/dist/renderer/boundary-materialization.js +0 -72
- package/dist/renderer/boundary-range-adoption.js +0 -76
- package/dist/renderer/boundary-range-sync.js +0 -101
- package/dist/renderer/boundary-state.js +0 -50
- package/dist/renderer/child-shape.js +0 -83
- package/dist/renderer/children-fastpath.js +0 -149
- package/dist/renderer/children.js +0 -158
- package/dist/renderer/cleanup.js +0 -267
- package/dist/renderer/component-host-cleanup.js +0 -143
- package/dist/renderer/component-host-instances.js +0 -116
- package/dist/renderer/component-host-replacement.js +0 -105
- package/dist/renderer/component-host-results.js +0 -138
- package/dist/renderer/component-host.js +0 -172
- package/dist/renderer/dom-host.js +0 -11
- package/dist/renderer/dom-internal.js +0 -243
- package/dist/renderer/dom-range.js +0 -161
- package/dist/renderer/dom.js +0 -11
- package/dist/renderer/element-children.js +0 -359
- package/dist/renderer/env.js +0 -2
- package/dist/renderer/error-boundary-dom.js +0 -86
- package/dist/renderer/evaluate-dom-range.js +0 -84
- package/dist/renderer/evaluate-reconcile.js +0 -257
- package/dist/renderer/evaluate.js +0 -95
- package/dist/renderer/fastpath.js +0 -142
- package/dist/renderer/for-commit-dom-map.js +0 -71
- package/dist/renderer/for-commit-removal.js +0 -27
- package/dist/renderer/for-commit-reorder.js +0 -87
- package/dist/renderer/for-commit.js +0 -442
- package/dist/renderer/hydration-boundaries.js +0 -60
- package/dist/renderer/hydration-listener-transaction.js +0 -49
- package/dist/renderer/index.js +0 -39
- package/dist/renderer/intrinsic-blueprint-analysis.js +0 -202
- package/dist/renderer/intrinsic-blueprint-bindings.js +0 -152
- package/dist/renderer/intrinsic-blueprint-materialization.js +0 -100
- package/dist/renderer/intrinsic-blueprint.js +0 -30
- package/dist/renderer/intrinsic-hydration-adoption.js +0 -66
- package/dist/renderer/keyed-children.js +0 -26
- package/dist/renderer/keyed.js +0 -167
- package/dist/renderer/namespaces.js +0 -21
- package/dist/renderer/prop-bindings.js +0 -315
- package/dist/renderer/reactive-child-dom.js +0 -139
- package/dist/renderer/reactive-child-sources.js +0 -182
- package/dist/renderer/reactive-children.js +0 -303
- package/dist/renderer/reconcile-commit.js +0 -36
- package/dist/renderer/reconcile-fastpaths.js +0 -100
- package/dist/renderer/reconcile-resolution.js +0 -163
- package/dist/renderer/reconcile.js +0 -37
- package/dist/renderer/retained-element-rollback.js +0 -288
- package/dist/renderer/stable-patch.js +0 -80
- package/dist/renderer/static-reuse.js +0 -94
- package/dist/renderer/types.js +0 -2
- package/dist/renderer/utils.js +0 -265
- package/dist/router/access.js +0 -34
- package/dist/router/activity.d.ts +0 -9
- package/dist/router/activity.js +0 -85
- package/dist/router/authoring.d.ts +0 -21
- package/dist/router/authoring.js +0 -196
- package/dist/router/internal-types.d.ts +0 -30
- package/dist/router/lazy.d.ts +0 -18
- package/dist/router/lazy.js +0 -50
- package/dist/router/manifest.d.ts +0 -9
- package/dist/router/manifest.js +0 -47
- package/dist/router/match.js +0 -120
- package/dist/router/navigate.d.ts +0 -10
- package/dist/router/navigate.js +0 -73
- package/dist/router/navigation-registry.d.ts +0 -31
- package/dist/router/navigation-registry.js +0 -103
- package/dist/router/navigation-scroll.d.ts +0 -13
- package/dist/router/navigation-scroll.js +0 -91
- package/dist/router/navigation-targets.d.ts +0 -30
- package/dist/router/navigation-targets.js +0 -634
- package/dist/router/policy.d.ts +0 -27
- package/dist/router/policy.js +0 -130
- package/dist/router/rendering.d.ts +0 -9
- package/dist/router/rendering.js +0 -47
- package/dist/router/resolution.d.ts +0 -3
- package/dist/router/resolution.js +0 -84
- package/dist/router/route-context.js +0 -77
- package/dist/router/route-matching.d.ts +0 -19
- package/dist/router/route-matching.js +0 -173
- package/dist/router/route-query.d.ts +0 -16
- package/dist/router/route-query.js +0 -45
- package/dist/router/route.d.ts +0 -8
- package/dist/router/route.js +0 -10
- package/dist/router/store.d.ts +0 -49
- package/dist/router/store.js +0 -169
- package/dist/router/testing.js +0 -4
- package/dist/runtime/access.d.ts +0 -19
- package/dist/runtime/access.js +0 -43
- package/dist/runtime/child-scope.d.ts +0 -41
- package/dist/runtime/child-scope.js +0 -134
- package/dist/runtime/component-cleanup.d.ts +0 -15
- package/dist/runtime/component-cleanup.js +0 -68
- package/dist/runtime/component-commit.js +0 -167
- package/dist/runtime/component-facade.d.ts +0 -5
- package/dist/runtime/component-facade.js +0 -6
- package/dist/runtime/component-internal.d.ts +0 -105
- package/dist/runtime/component-internal.js +0 -237
- package/dist/runtime/component-lifecycle.d.ts +0 -10
- package/dist/runtime/component-lifecycle.js +0 -33
- package/dist/runtime/component-scope.d.ts +0 -54
- package/dist/runtime/component.d.ts +0 -5
- package/dist/runtime/component.js +0 -6
- package/dist/runtime/context.d.ts +0 -72
- package/dist/runtime/context.js +0 -236
- package/dist/runtime/control.d.ts +0 -62
- package/dist/runtime/control.js +0 -239
- package/dist/runtime/derive.d.ts +0 -16
- package/dist/runtime/derive.js +0 -140
- package/dist/runtime/dev-namespace.d.ts +0 -30
- package/dist/runtime/dev-namespace.js +0 -64
- package/dist/runtime/effect.d.ts +0 -35
- package/dist/runtime/error-boundary.d.ts +0 -4
- package/dist/runtime/error-boundary.js +0 -29
- package/dist/runtime/events.d.ts +0 -58
- package/dist/runtime/events.js +0 -201
- package/dist/runtime/execution-model.d.ts +0 -6
- package/dist/runtime/execution-model.js +0 -13
- package/dist/runtime/fastlane.d.ts +0 -33
- package/dist/runtime/fastlane.js +0 -173
- package/dist/runtime/for-bench.d.ts +0 -40
- package/dist/runtime/for-bench.js +0 -13
- package/dist/runtime/for-internal.d.ts +0 -106
- package/dist/runtime/for-internal.js +0 -285
- package/dist/runtime/for-reconcile.d.ts +0 -7
- package/dist/runtime/for-reconcile.js +0 -442
- package/dist/runtime/for-scopes.d.ts +0 -26
- package/dist/runtime/for-scopes.js +0 -280
- package/dist/runtime/for-signals.d.ts +0 -39
- package/dist/runtime/for-signals.js +0 -213
- package/dist/runtime/for-types.d.ts +0 -8
- package/dist/runtime/for.d.ts +0 -4
- package/dist/runtime/for.js +0 -5
- package/dist/runtime/index.d.ts +0 -24
- package/dist/runtime/index.js +0 -33
- package/dist/runtime/lifecycle-batch.d.ts +0 -59
- package/dist/runtime/lifecycle-batch.js +0 -178
- package/dist/runtime/lifecycle-operation-settlement.d.ts +0 -5
- package/dist/runtime/lifecycle-operation-settlement.js +0 -51
- package/dist/runtime/lifecycle-operations.d.ts +0 -30
- package/dist/runtime/operations.d.ts +0 -3
- package/dist/runtime/operations.js +0 -3
- package/dist/runtime/perf-metrics.d.ts +0 -27
- package/dist/runtime/perf-metrics.js +0 -6
- package/dist/runtime/portal.d.ts +0 -21
- package/dist/runtime/readable.d.ts +0 -34
- package/dist/runtime/readable.js +0 -183
- package/dist/runtime/resource-cell.js +0 -112
- package/dist/runtime/resource-operation.d.ts +0 -12
- package/dist/runtime/runtime.js +0 -57
- package/dist/runtime/selector-store.js +0 -22
- package/dist/runtime/selector.d.ts +0 -10
- package/dist/runtime/snapshot-source.d.ts +0 -9
- package/dist/runtime/state.d.ts +0 -54
- package/dist/ssg/batch-render.js +0 -101
- package/dist/ssg/create-static-gen.d.ts +0 -66
- package/dist/ssg/create-static-gen.js +0 -250
- package/dist/ssg/generate-metadata.js +0 -92
- package/dist/ssg/generation-plan.js +0 -68
- package/dist/ssg/incremental-manifest.js +0 -54
- package/dist/ssg/resolve-ssg-data.js +0 -103
- package/dist/ssg/route-utils.js +0 -22
- package/dist/ssg/static-routes.js +0 -100
- package/dist/ssg/types.d.ts +0 -188
- package/dist/ssg/write-static-files.js +0 -77
- package/dist/ssr/attrs.js +0 -92
- package/dist/ssr/boundaries.js +0 -124
- package/dist/ssr/component-runtime.js +0 -85
- package/dist/ssr/context.d.ts +0 -49
- package/dist/ssr/context.js +0 -89
- package/dist/ssr/errors.d.ts +0 -9
- package/dist/ssr/errors.js +0 -12
- package/dist/ssr/escape.js +0 -191
- package/dist/ssr/hydration-data.js +0 -8
- package/dist/ssr/hydration-verify.d.ts +0 -11
- package/dist/ssr/hydration-verify.js +0 -171
- package/dist/ssr/index-internal.d.ts +0 -14
- package/dist/ssr/index-internal.js +0 -17
- package/dist/ssr/render-keys.js +0 -14
- package/dist/ssr/render-resolved.d.ts +0 -19
- package/dist/ssr/render-resolved.js +0 -33
- package/dist/ssr/render-sync.d.ts +0 -20
- package/dist/ssr/render-sync.js +0 -283
- package/dist/ssr/route-policy-resolution.js +0 -76
- package/dist/ssr/route-render.d.ts +0 -76
- package/dist/ssr/route-render.js +0 -118
- package/dist/ssr/sink.d.ts +0 -25
- package/dist/ssr/sink.js +0 -84
- package/dist/ssr/types.d.ts +0 -22
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
import { addPerfDuration, incrementPerfMetric } from "../runtime/perf-metrics.js";
|
|
2
|
-
import "../runtime/index.js";
|
|
3
|
-
import { resolveRouteDescriptor } from "./route-utils.js";
|
|
4
|
-
import { resolveSsgData, resolveSsgRouteData, validateRoutes } from "./resolve-ssg-data.js";
|
|
5
|
-
import { batchRenderRoutes } from "./batch-render.js";
|
|
6
|
-
import { writeStaticFiles } from "./write-static-files.js";
|
|
7
|
-
import { generateSSGResult, resultToMetadata, writeMetadata } from "./generate-metadata.js";
|
|
8
|
-
import { getExistingOutputFileSize, hashHtml, outputFileExists, readIncrementalManifest, writeIncrementalManifest } from "./incremental-manifest.js";
|
|
9
|
-
import { collectRemovedRouteResults, dedupeStrings, getRoutesToRender, selectRouteForGeneration } from "./generation-plan.js";
|
|
10
|
-
import { normalizeStaticRoutes, splitStaticRoutes } from "./static-routes.js";
|
|
11
|
-
import * as fs from "node:fs/promises";
|
|
12
|
-
import * as pathModule from "node:path";
|
|
13
|
-
import * as os from "node:os";
|
|
14
|
-
//#region src/ssg/create-static-gen.ts
|
|
15
|
-
function resolveParallelism(requested) {
|
|
16
|
-
if (requested !== "auto") return Math.max(1, requested ?? 1);
|
|
17
|
-
const maybeNavigator = globalThis;
|
|
18
|
-
const envWorkers = Number(maybeNavigator.process?.env?.ASKR_SSG_WORKERS ?? maybeNavigator.process?.env?.NUMBER_OF_PROCESSORS ?? maybeNavigator.process?.env?.UV_THREADPOOL_SIZE);
|
|
19
|
-
if (Number.isFinite(envWorkers) && envWorkers > 0) return Math.max(1, Math.trunc(envWorkers));
|
|
20
|
-
if (typeof maybeNavigator.navigator?.hardwareConcurrency === "number") return Math.max(1, maybeNavigator.navigator.hardwareConcurrency);
|
|
21
|
-
const availableParallelism = os.availableParallelism;
|
|
22
|
-
return Math.max(1, availableParallelism?.() ?? os.cpus().length ?? 1);
|
|
23
|
-
}
|
|
24
|
-
async function createStagingDirectory(outputDir) {
|
|
25
|
-
const parent = pathModule.dirname(outputDir);
|
|
26
|
-
const base = pathModule.basename(outputDir);
|
|
27
|
-
await fs.mkdir(parent, { recursive: true });
|
|
28
|
-
return fs.mkdtemp(pathModule.join(parent, `.${base}.askr-staging-`));
|
|
29
|
-
}
|
|
30
|
-
async function replaceOutputDirectory(stagingDir, outputDir, fileOperations = fs) {
|
|
31
|
-
const parent = pathModule.dirname(outputDir);
|
|
32
|
-
const backupDir = pathModule.join(parent, `.${pathModule.basename(outputDir)}.askr-backup-${Date.now()}`);
|
|
33
|
-
let backedUp = false;
|
|
34
|
-
try {
|
|
35
|
-
try {
|
|
36
|
-
await fileOperations.rename(outputDir, backupDir);
|
|
37
|
-
backedUp = true;
|
|
38
|
-
} catch (error) {
|
|
39
|
-
if (error.code !== "ENOENT") throw error;
|
|
40
|
-
}
|
|
41
|
-
await fileOperations.rename(stagingDir, outputDir);
|
|
42
|
-
await fileOperations.rm(backupDir, {
|
|
43
|
-
recursive: true,
|
|
44
|
-
force: true
|
|
45
|
-
});
|
|
46
|
-
} catch (error) {
|
|
47
|
-
if (backedUp) {
|
|
48
|
-
await fileOperations.rm(outputDir, {
|
|
49
|
-
recursive: true,
|
|
50
|
-
force: true
|
|
51
|
-
});
|
|
52
|
-
await fileOperations.rename(backupDir, outputDir);
|
|
53
|
-
}
|
|
54
|
-
throw error;
|
|
55
|
-
} finally {
|
|
56
|
-
await fileOperations.rm(stagingDir, {
|
|
57
|
-
recursive: true,
|
|
58
|
-
force: true
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Create a Static Site Generator
|
|
64
|
-
*
|
|
65
|
-
* Usage:
|
|
66
|
-
* ```ts
|
|
67
|
-
* const ssg = createStaticGen({
|
|
68
|
-
* routes: [
|
|
69
|
-
* { path: '/', component: HomePage },
|
|
70
|
-
* { path: '/about', component: AboutPage },
|
|
71
|
-
* ],
|
|
72
|
-
* outputDir: './dist',
|
|
73
|
-
* dataOverrides: {
|
|
74
|
-
* '/api/posts': { posts: [...] }
|
|
75
|
-
* }
|
|
76
|
-
* });
|
|
77
|
-
*
|
|
78
|
-
* const result = await ssg.generate();
|
|
79
|
-
* console.log(`Generated ${result.successful}/${result.totalRoutes} routes`);
|
|
80
|
-
* ```
|
|
81
|
-
*/
|
|
82
|
-
function createStaticGen(options) {
|
|
83
|
-
let result = null;
|
|
84
|
-
const configuredRoutes = normalizeStaticRoutes(options);
|
|
85
|
-
const seed = options.seed ?? 12345;
|
|
86
|
-
const resolvedParallelism = resolveParallelism(options.parallelism);
|
|
87
|
-
const resolvedConcurrency = Math.max(1, options.concurrency ?? resolvedParallelism);
|
|
88
|
-
if (configuredRoutes.length === 0) throw new Error("routes array or route registry is required");
|
|
89
|
-
if (!options.outputDir || options.outputDir.trim().length === 0) throw new Error("outputDir is required");
|
|
90
|
-
return {
|
|
91
|
-
/**
|
|
92
|
-
* Generate static HTML for all routes
|
|
93
|
-
* Writes to outputDir with metadata.json
|
|
94
|
-
* Returns detailed results
|
|
95
|
-
*/
|
|
96
|
-
async generate(generateOptions = {}) {
|
|
97
|
-
const splitRoutes = await splitStaticRoutes(configuredRoutes);
|
|
98
|
-
const routes = splitRoutes.routes;
|
|
99
|
-
validateRoutes(routes);
|
|
100
|
-
const changedKeys = dedupeStrings(generateOptions.changedKeys);
|
|
101
|
-
const changedRoutes = dedupeStrings(generateOptions.changedRoutes);
|
|
102
|
-
const requestedMode = generateOptions.mode ?? "full";
|
|
103
|
-
const previousManifest = !generateOptions.forceFull && requestedMode === "incremental" ? readIncrementalManifest(options.outputDir, seed) : null;
|
|
104
|
-
const effectiveMode = generateOptions.forceFull || requestedMode !== "incremental" || previousManifest === null ? "full" : "incremental";
|
|
105
|
-
const dataMap = resolveSsgData(routes, { dataOverrides: options.dataOverrides });
|
|
106
|
-
const descriptors = routes.map(resolveRouteDescriptor);
|
|
107
|
-
const routeResultsById = /* @__PURE__ */ new Map();
|
|
108
|
-
for (const runtimeRoute of splitRoutes.runtimeOnly) routeResultsById.set(runtimeRoute.routeId, runtimeRoute.result);
|
|
109
|
-
const eligibleDescriptors = descriptors;
|
|
110
|
-
const previousEntries = new Map((previousManifest?.routes ?? []).map((entry) => [entry.routeId, entry]));
|
|
111
|
-
const currentRouteIds = new Set(eligibleDescriptors.map((descriptor) => descriptor.routeId));
|
|
112
|
-
const selected = [];
|
|
113
|
-
const routesToRender = [];
|
|
114
|
-
for (let index = 0; index < eligibleDescriptors.length; index += 1) {
|
|
115
|
-
const descriptor = eligibleDescriptors[index];
|
|
116
|
-
const entry = selectRouteForGeneration(descriptor, previousEntries.get(descriptor.routeId) ?? null, effectiveMode, changedKeys, changedRoutes);
|
|
117
|
-
selected.push(entry);
|
|
118
|
-
if (entry.reason !== "unchanged") routesToRender.push(entry);
|
|
119
|
-
}
|
|
120
|
-
const renderStartTime = performance.now();
|
|
121
|
-
incrementPerfMetric("ssgWorkerCount", resolvedParallelism);
|
|
122
|
-
const renderedResults = routesToRender.length > 0 ? await batchRenderRoutes(getRoutesToRender(routesToRender), {
|
|
123
|
-
seed,
|
|
124
|
-
dataMap,
|
|
125
|
-
concurrency: resolvedConcurrency,
|
|
126
|
-
document: options.document
|
|
127
|
-
}) : [];
|
|
128
|
-
addPerfDuration("ssgRenderTimeMs", performance.now() - renderStartTime);
|
|
129
|
-
const renderedByRouteId = /* @__PURE__ */ new Map();
|
|
130
|
-
for (let index = 0; index < renderedResults.length; index += 1) renderedByRouteId.set(routesToRender[index].descriptor.routeId, renderedResults[index]);
|
|
131
|
-
let cacheHits = 0;
|
|
132
|
-
const nextManifestRoutes = [];
|
|
133
|
-
for (const entry of selected) {
|
|
134
|
-
const { descriptor, previous, reason } = entry;
|
|
135
|
-
const resolvedData = resolveSsgRouteData(dataMap, descriptor.route.path, descriptor.path);
|
|
136
|
-
const baseData = resolvedData.hasData ? resolvedData.data : void 0;
|
|
137
|
-
const resourceCount = resolvedData.hasData && baseData ? Object.keys(baseData).length : 0;
|
|
138
|
-
if (reason === "unchanged") {
|
|
139
|
-
routeResultsById.set(descriptor.routeId, {
|
|
140
|
-
path: descriptor.path,
|
|
141
|
-
filePath: descriptor.filePath,
|
|
142
|
-
html: "",
|
|
143
|
-
fileSize: previous?.htmlHash !== null && previous !== null ? getExistingOutputFileSize(options.outputDir, descriptor.filePath) : 0,
|
|
144
|
-
renderDuration: 0,
|
|
145
|
-
resourceCount,
|
|
146
|
-
status: "skipped",
|
|
147
|
-
reason: "unchanged",
|
|
148
|
-
written: false
|
|
149
|
-
});
|
|
150
|
-
if (previous) nextManifestRoutes.push({
|
|
151
|
-
...previous,
|
|
152
|
-
path: descriptor.path,
|
|
153
|
-
filePath: descriptor.filePath,
|
|
154
|
-
invalidationKeys: descriptor.invalidationKeys.slice()
|
|
155
|
-
});
|
|
156
|
-
continue;
|
|
157
|
-
}
|
|
158
|
-
const rendered = renderedByRouteId.get(descriptor.routeId);
|
|
159
|
-
if (!rendered) throw new Error(`Missing rendered result for route "${descriptor.path}"`);
|
|
160
|
-
const nextResult = {
|
|
161
|
-
...rendered,
|
|
162
|
-
path: descriptor.path,
|
|
163
|
-
filePath: descriptor.filePath,
|
|
164
|
-
resourceCount,
|
|
165
|
-
reason,
|
|
166
|
-
written: false
|
|
167
|
-
};
|
|
168
|
-
if (nextResult.status === "success") {
|
|
169
|
-
const htmlDigest = hashHtml(nextResult.html);
|
|
170
|
-
const shouldWrite = effectiveMode === "full" || !previous || previous.htmlHash !== htmlDigest || !outputFileExists(options.outputDir, descriptor.filePath);
|
|
171
|
-
nextResult.written = shouldWrite;
|
|
172
|
-
if (!shouldWrite) cacheHits += 1;
|
|
173
|
-
nextManifestRoutes.push({
|
|
174
|
-
routeId: descriptor.routeId,
|
|
175
|
-
path: descriptor.path,
|
|
176
|
-
filePath: descriptor.filePath,
|
|
177
|
-
invalidationKeys: descriptor.invalidationKeys.slice(),
|
|
178
|
-
htmlHash: htmlDigest,
|
|
179
|
-
lastStatus: "success"
|
|
180
|
-
});
|
|
181
|
-
} else nextManifestRoutes.push({
|
|
182
|
-
routeId: descriptor.routeId,
|
|
183
|
-
path: descriptor.path,
|
|
184
|
-
filePath: descriptor.filePath,
|
|
185
|
-
invalidationKeys: descriptor.invalidationKeys.slice(),
|
|
186
|
-
htmlHash: previous?.htmlHash ?? null,
|
|
187
|
-
lastStatus: "error"
|
|
188
|
-
});
|
|
189
|
-
routeResultsById.set(descriptor.routeId, nextResult);
|
|
190
|
-
}
|
|
191
|
-
const removedResults = collectRemovedRouteResults(previousManifest, currentRouteIds);
|
|
192
|
-
const routeResults = [];
|
|
193
|
-
for (const routeId of splitRoutes.outputRouteIds) {
|
|
194
|
-
const routeResult = routeResultsById.get(routeId);
|
|
195
|
-
if (routeResult) routeResults.push(routeResult);
|
|
196
|
-
}
|
|
197
|
-
routeResults.push(...removedResults);
|
|
198
|
-
result = generateSSGResult(routeResults, {
|
|
199
|
-
mode: effectiveMode,
|
|
200
|
-
cacheHits,
|
|
201
|
-
invalidatedKeys: changedKeys,
|
|
202
|
-
invalidatedRoutes: changedRoutes
|
|
203
|
-
});
|
|
204
|
-
if (effectiveMode === "full" && result.failed > 0) return result;
|
|
205
|
-
const targetOutputDir = effectiveMode === "full" ? await createStagingDirectory(options.outputDir) : options.outputDir;
|
|
206
|
-
try {
|
|
207
|
-
const writeStartTime = performance.now();
|
|
208
|
-
await writeStaticFiles(routeResults, targetOutputDir, { concurrency: resolvedConcurrency });
|
|
209
|
-
addPerfDuration("ssgWriteTimeMs", performance.now() - writeStartTime);
|
|
210
|
-
await writeMetadata(resultToMetadata(result), targetOutputDir);
|
|
211
|
-
await writeIncrementalManifest({
|
|
212
|
-
schemaVersion: 1,
|
|
213
|
-
seed,
|
|
214
|
-
mode: effectiveMode,
|
|
215
|
-
routes: nextManifestRoutes
|
|
216
|
-
}, targetOutputDir);
|
|
217
|
-
if (effectiveMode === "full") await replaceOutputDirectory(targetOutputDir, options.outputDir);
|
|
218
|
-
} catch (error) {
|
|
219
|
-
if (effectiveMode === "full") await fs.rm(targetOutputDir, {
|
|
220
|
-
recursive: true,
|
|
221
|
-
force: true
|
|
222
|
-
});
|
|
223
|
-
throw error;
|
|
224
|
-
}
|
|
225
|
-
return result;
|
|
226
|
-
},
|
|
227
|
-
/**
|
|
228
|
-
* Get effective config in a serializable form for diagnostics.
|
|
229
|
-
*/
|
|
230
|
-
getConfig() {
|
|
231
|
-
return {
|
|
232
|
-
routeCount: configuredRoutes.length,
|
|
233
|
-
outputDir: options.outputDir,
|
|
234
|
-
seed,
|
|
235
|
-
concurrency: resolvedConcurrency,
|
|
236
|
-
parallelism: resolvedParallelism,
|
|
237
|
-
hasDataOverrides: !!options.dataOverrides
|
|
238
|
-
};
|
|
239
|
-
},
|
|
240
|
-
/**
|
|
241
|
-
* Get the last generation result
|
|
242
|
-
* Returns null if generate() hasn't been called
|
|
243
|
-
*/
|
|
244
|
-
getResult() {
|
|
245
|
-
return result;
|
|
246
|
-
}
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
//#endregion
|
|
250
|
-
export { createStaticGen, replaceOutputDirectory };
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs/promises";
|
|
2
|
-
import * as pathModule from "node:path";
|
|
3
|
-
//#region src/ssg/generate-metadata.ts
|
|
4
|
-
/**
|
|
5
|
-
* Metadata generation for SSG
|
|
6
|
-
*
|
|
7
|
-
* Generates and serializes metadata about generated static files.
|
|
8
|
-
* This module is Node-only and not intended for browser builds.
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* Generate SSGResult from render results
|
|
12
|
-
*/
|
|
13
|
-
function generateSSGResult(results, options = {}) {
|
|
14
|
-
let successful = 0;
|
|
15
|
-
let failed = 0;
|
|
16
|
-
let totalDuration = 0;
|
|
17
|
-
let rebuilt = 0;
|
|
18
|
-
let skipped = 0;
|
|
19
|
-
let removed = 0;
|
|
20
|
-
for (let index = 0; index < results.length; index += 1) {
|
|
21
|
-
const result = results[index];
|
|
22
|
-
totalDuration += result.renderDuration;
|
|
23
|
-
if (result.status === "success") {
|
|
24
|
-
successful += 1;
|
|
25
|
-
rebuilt += 1;
|
|
26
|
-
} else if (result.status === "error") {
|
|
27
|
-
failed += 1;
|
|
28
|
-
rebuilt += 1;
|
|
29
|
-
} else if (result.status === "skipped") skipped += 1;
|
|
30
|
-
else if (result.status === "removed") removed += 1;
|
|
31
|
-
}
|
|
32
|
-
return {
|
|
33
|
-
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
34
|
-
totalRoutes: results.length,
|
|
35
|
-
successful,
|
|
36
|
-
failed,
|
|
37
|
-
totalDuration: Math.round(totalDuration),
|
|
38
|
-
mode: options.mode ?? "full",
|
|
39
|
-
rebuilt,
|
|
40
|
-
skipped,
|
|
41
|
-
removed,
|
|
42
|
-
cacheHits: options.cacheHits ?? 0,
|
|
43
|
-
invalidatedKeys: options.invalidatedKeys?.slice() ?? [],
|
|
44
|
-
invalidatedRoutes: options.invalidatedRoutes?.slice() ?? [],
|
|
45
|
-
routes: results
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Convert SSGResult to metadata for JSON serialization
|
|
50
|
-
*/
|
|
51
|
-
function resultToMetadata(result) {
|
|
52
|
-
const routes = [];
|
|
53
|
-
for (let index = 0; index < result.routes.length; index += 1) {
|
|
54
|
-
const route = result.routes[index];
|
|
55
|
-
routes.push({
|
|
56
|
-
path: route.path,
|
|
57
|
-
filePath: route.filePath,
|
|
58
|
-
fileSize: route.fileSize,
|
|
59
|
-
renderDuration: route.renderDuration,
|
|
60
|
-
resourceCount: route.resourceCount,
|
|
61
|
-
status: route.status,
|
|
62
|
-
reason: route.reason,
|
|
63
|
-
written: route.written,
|
|
64
|
-
error: route.error
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
return {
|
|
68
|
-
generatedAt: result.generatedAt,
|
|
69
|
-
totalRoutes: result.totalRoutes,
|
|
70
|
-
successful: result.successful,
|
|
71
|
-
failed: result.failed,
|
|
72
|
-
totalDuration: result.totalDuration,
|
|
73
|
-
mode: result.mode,
|
|
74
|
-
rebuilt: result.rebuilt,
|
|
75
|
-
skipped: result.skipped,
|
|
76
|
-
removed: result.removed,
|
|
77
|
-
cacheHits: result.cacheHits,
|
|
78
|
-
invalidatedKeys: result.invalidatedKeys.slice(),
|
|
79
|
-
invalidatedRoutes: result.invalidatedRoutes.slice(),
|
|
80
|
-
routes
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Write metadata.json to output directory
|
|
85
|
-
*/
|
|
86
|
-
async function writeMetadata(metadata, outputDir) {
|
|
87
|
-
const filePath = pathModule.join(outputDir, "metadata.json");
|
|
88
|
-
await fs.mkdir(outputDir, { recursive: true });
|
|
89
|
-
await fs.writeFile(filePath, JSON.stringify(metadata, null, 2), "utf8");
|
|
90
|
-
}
|
|
91
|
-
//#endregion
|
|
92
|
-
export { generateSSGResult, resultToMetadata, writeMetadata };
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
//#region src/ssg/generation-plan.ts
|
|
2
|
-
function dedupeStrings(values) {
|
|
3
|
-
return values ? Array.from(new Set(values)) : [];
|
|
4
|
-
}
|
|
5
|
-
function getRoutesToRender(selected) {
|
|
6
|
-
const routes = [];
|
|
7
|
-
for (let index = 0; index < selected.length; index += 1) routes.push(selected[index].descriptor.route);
|
|
8
|
-
return routes;
|
|
9
|
-
}
|
|
10
|
-
function selectRouteForGeneration(descriptor, previous, mode, changedKeys, changedRoutes) {
|
|
11
|
-
if (mode === "full") return {
|
|
12
|
-
descriptor,
|
|
13
|
-
reason: "full",
|
|
14
|
-
previous
|
|
15
|
-
};
|
|
16
|
-
if (!previous) return {
|
|
17
|
-
descriptor,
|
|
18
|
-
reason: "new-route",
|
|
19
|
-
previous
|
|
20
|
-
};
|
|
21
|
-
if (previous.lastStatus === "error" || previous.htmlHash === null) return {
|
|
22
|
-
descriptor,
|
|
23
|
-
reason: "new-route",
|
|
24
|
-
previous
|
|
25
|
-
};
|
|
26
|
-
if (descriptor.invalidationKeys.length === 0) return {
|
|
27
|
-
descriptor,
|
|
28
|
-
reason: "no-keys",
|
|
29
|
-
previous
|
|
30
|
-
};
|
|
31
|
-
if (changedRoutes.includes(descriptor.path)) return {
|
|
32
|
-
descriptor,
|
|
33
|
-
reason: "changed-route",
|
|
34
|
-
previous
|
|
35
|
-
};
|
|
36
|
-
if (descriptor.invalidationKeys.some((key) => changedKeys.includes(key))) return {
|
|
37
|
-
descriptor,
|
|
38
|
-
reason: "changed-key",
|
|
39
|
-
previous
|
|
40
|
-
};
|
|
41
|
-
return {
|
|
42
|
-
descriptor,
|
|
43
|
-
reason: "unchanged",
|
|
44
|
-
previous
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
function collectRemovedRouteResults(manifest, currentRouteIds) {
|
|
48
|
-
if (!manifest) return [];
|
|
49
|
-
const results = [];
|
|
50
|
-
for (let index = 0; index < manifest.routes.length; index += 1) {
|
|
51
|
-
const entry = manifest.routes[index];
|
|
52
|
-
if (currentRouteIds.has(entry.routeId)) continue;
|
|
53
|
-
results.push({
|
|
54
|
-
path: entry.path,
|
|
55
|
-
filePath: entry.filePath,
|
|
56
|
-
html: "",
|
|
57
|
-
fileSize: 0,
|
|
58
|
-
renderDuration: 0,
|
|
59
|
-
resourceCount: 0,
|
|
60
|
-
status: "removed",
|
|
61
|
-
reason: "deleted",
|
|
62
|
-
written: false
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
return results;
|
|
66
|
-
}
|
|
67
|
-
//#endregion
|
|
68
|
-
export { collectRemovedRouteResults, dedupeStrings, getRoutesToRender, selectRouteForGeneration };
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import * as fsPromises from "node:fs/promises";
|
|
2
|
-
import * as pathModule from "node:path";
|
|
3
|
-
import * as fs from "node:fs";
|
|
4
|
-
const MANIFEST_DIR = ".askr";
|
|
5
|
-
const MANIFEST_FILE = "ssg-manifest.json";
|
|
6
|
-
function hashHtml(html) {
|
|
7
|
-
let hash = 2166136261;
|
|
8
|
-
for (let index = 0; index < html.length; index += 1) {
|
|
9
|
-
hash ^= html.charCodeAt(index);
|
|
10
|
-
hash = Math.imul(hash, 16777619);
|
|
11
|
-
}
|
|
12
|
-
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
13
|
-
}
|
|
14
|
-
function getIncrementalManifestPath(outputDir) {
|
|
15
|
-
return pathModule.join(outputDir, MANIFEST_DIR, MANIFEST_FILE);
|
|
16
|
-
}
|
|
17
|
-
function readIncrementalManifest(outputDir, seed) {
|
|
18
|
-
const manifestPath = getIncrementalManifestPath(outputDir);
|
|
19
|
-
if (!fs.existsSync(manifestPath)) return null;
|
|
20
|
-
try {
|
|
21
|
-
const raw = fs.readFileSync(manifestPath, "utf8");
|
|
22
|
-
const parsed = JSON.parse(raw);
|
|
23
|
-
if (parsed.schemaVersion !== 1 || parsed.seed !== seed || !Array.isArray(parsed.routes)) return null;
|
|
24
|
-
const routes = parsed.routes.filter((entry) => !!entry && typeof entry.routeId === "string" && typeof entry.path === "string" && typeof entry.filePath === "string" && Array.isArray(entry.invalidationKeys) && (entry.htmlHash === null || typeof entry.htmlHash === "string") && (entry.lastStatus === "success" || entry.lastStatus === "error"));
|
|
25
|
-
if (routes.length !== parsed.routes.length) return null;
|
|
26
|
-
return {
|
|
27
|
-
schemaVersion: 1,
|
|
28
|
-
seed,
|
|
29
|
-
mode: parsed.mode === "incremental" ? "incremental" : "full",
|
|
30
|
-
routes
|
|
31
|
-
};
|
|
32
|
-
} catch {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
async function writeIncrementalManifest(manifest, outputDir) {
|
|
37
|
-
const manifestPath = getIncrementalManifestPath(outputDir);
|
|
38
|
-
await fsPromises.mkdir(pathModule.dirname(manifestPath), { recursive: true });
|
|
39
|
-
await fsPromises.writeFile(manifestPath, JSON.stringify(manifest, null, 2), "utf8");
|
|
40
|
-
}
|
|
41
|
-
function getExistingOutputFileSize(outputDir, filePath) {
|
|
42
|
-
const fullPath = pathModule.join(outputDir, filePath);
|
|
43
|
-
if (!fs.existsSync(fullPath)) return 0;
|
|
44
|
-
try {
|
|
45
|
-
return fs.statSync(fullPath).size;
|
|
46
|
-
} catch {
|
|
47
|
-
return 0;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
function outputFileExists(outputDir, filePath) {
|
|
51
|
-
return fs.existsSync(pathModule.join(outputDir, filePath));
|
|
52
|
-
}
|
|
53
|
-
//#endregion
|
|
54
|
-
export { getExistingOutputFileSize, getIncrementalManifestPath, hashHtml, outputFileExists, readIncrementalManifest, writeIncrementalManifest };
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { interpolateRoutePath } from "./route-utils.js";
|
|
2
|
-
//#region src/ssg/resolve-ssg-data.ts
|
|
3
|
-
function hasOwnRouteData(dataMap, path) {
|
|
4
|
-
return Object.prototype.hasOwnProperty.call(dataMap, path);
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Resolve and validate data for SSG routes
|
|
8
|
-
* Returns a map of route path -> SSRData
|
|
9
|
-
*
|
|
10
|
-
* In phase 1: accepts user-supplied dataOverrides
|
|
11
|
-
* In phase 2: can be extended to auto-discover resources
|
|
12
|
-
*/
|
|
13
|
-
function resolveSsgData(routes, options = {}) {
|
|
14
|
-
const { dataOverrides = {} } = options;
|
|
15
|
-
const dataMap = {};
|
|
16
|
-
for (const route of routes) {
|
|
17
|
-
const concretePath = interpolateRoutePath(route.path, route.params);
|
|
18
|
-
const overridePath = concretePath in dataOverrides ? concretePath : route.path in dataOverrides ? route.path : null;
|
|
19
|
-
if (overridePath) {
|
|
20
|
-
const data = dataOverrides[overridePath];
|
|
21
|
-
if (typeof data !== "object" || data === null || Array.isArray(data)) throw new Error(`data for route "${overridePath}" must be an object, got ${typeof data}`);
|
|
22
|
-
dataMap[overridePath] = data;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return dataMap;
|
|
26
|
-
}
|
|
27
|
-
function resolveSsgRouteData(dataMap, routePath, concretePath) {
|
|
28
|
-
if (hasOwnRouteData(dataMap, concretePath)) return {
|
|
29
|
-
hasData: true,
|
|
30
|
-
data: dataMap[concretePath]
|
|
31
|
-
};
|
|
32
|
-
if (hasOwnRouteData(dataMap, routePath)) return {
|
|
33
|
-
hasData: true,
|
|
34
|
-
data: dataMap[routePath]
|
|
35
|
-
};
|
|
36
|
-
return {
|
|
37
|
-
hasData: false,
|
|
38
|
-
data: void 0
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
function isStringRecord(value) {
|
|
42
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
43
|
-
for (const recordValue of Object.values(value)) if (typeof recordValue !== "string") return false;
|
|
44
|
-
return true;
|
|
45
|
-
}
|
|
46
|
-
function validateRouteShape(route) {
|
|
47
|
-
if (typeof route.path !== "string" || !route.path.startsWith("/")) throw new Error(`route path must be a string starting with "/", got "${route.path}"`);
|
|
48
|
-
if (typeof (route.handler ?? route.component) !== "function") throw new Error(`route handler must be a function for path "${route.path}"`);
|
|
49
|
-
if (route.params !== void 0 && !isStringRecord(route.params)) throw new Error(`route "${route.path}" params must be an object containing only string values`);
|
|
50
|
-
if (route.invalidationKeys !== void 0) {
|
|
51
|
-
if (!Array.isArray(route.invalidationKeys)) throw new Error(`route "${route.path}" invalidationKeys must be an array of strings`);
|
|
52
|
-
for (const key of route.invalidationKeys) if (typeof key !== "string" || key.length === 0) throw new Error(`route "${route.path}" invalidationKeys must contain only non-empty strings`);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
function validateEntriesResult(route, entries) {
|
|
56
|
-
if (!Array.isArray(entries)) throw new Error(`route "${route.path}" entries must return an array of param maps`);
|
|
57
|
-
return entries.map((entry, index) => {
|
|
58
|
-
if (!isStringRecord(entry)) throw new Error(`route "${route.path}" entries[${index}] must be an object containing only string values`);
|
|
59
|
-
return entry;
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
async function expandRoutes(routes) {
|
|
63
|
-
if (!Array.isArray(routes)) throw new Error("routes must be an array");
|
|
64
|
-
const expanded = [];
|
|
65
|
-
for (const route of routes) {
|
|
66
|
-
validateRouteShape(route);
|
|
67
|
-
if (route.params) expanded.push({
|
|
68
|
-
...route,
|
|
69
|
-
entries: void 0
|
|
70
|
-
});
|
|
71
|
-
if (!route.entries) {
|
|
72
|
-
if (!route.params) expanded.push(route);
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
const entries = validateEntriesResult(route, await route.entries());
|
|
76
|
-
for (const params of entries) expanded.push({
|
|
77
|
-
...route,
|
|
78
|
-
params,
|
|
79
|
-
entries: void 0
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
return expanded;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Validate routes are properly configured
|
|
86
|
-
*/
|
|
87
|
-
function validateRoutes(routes) {
|
|
88
|
-
if (!Array.isArray(routes)) throw new Error("routes must be an array");
|
|
89
|
-
const seen = /* @__PURE__ */ new Set();
|
|
90
|
-
for (const route of routes) {
|
|
91
|
-
validateRouteShape(route);
|
|
92
|
-
const key = `${route.path}::${JSON.stringify(route.params || {})}`;
|
|
93
|
-
if (seen.has(key)) throw new Error(`duplicate route entry detected for path "${route.path}"`);
|
|
94
|
-
seen.add(key);
|
|
95
|
-
if (route.path.includes("{")) {
|
|
96
|
-
const paramNames = Array.from(route.path.matchAll(/\{([^}]+)\}/g)).map((m) => m[1]);
|
|
97
|
-
if (!route.params) throw new Error(`route "${route.path}" uses path parameters and requires params`);
|
|
98
|
-
for (const name of paramNames) if (!(name in route.params)) throw new Error(`route "${route.path}" missing required param "${name}"`);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
//#endregion
|
|
103
|
-
export { expandRoutes, resolveSsgData, resolveSsgRouteData, validateRoutes };
|
package/dist/ssg/route-utils.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
//#region src/ssg/route-utils.ts
|
|
2
|
-
function getOutputFilePath(pathStr) {
|
|
3
|
-
if (pathStr === "/") return "index.html";
|
|
4
|
-
return `${pathStr.replace(/^\/|\/$/g, "")}/index.html`;
|
|
5
|
-
}
|
|
6
|
-
function interpolateRoutePath(routePath, params) {
|
|
7
|
-
if (!params) return routePath;
|
|
8
|
-
return routePath.replace(/\{([^}]+)\}/g, (_, key) => params[key] ?? "");
|
|
9
|
-
}
|
|
10
|
-
function resolveRouteDescriptor(route) {
|
|
11
|
-
const path = interpolateRoutePath(route.path, route.params);
|
|
12
|
-
const filePath = getOutputFilePath(path);
|
|
13
|
-
return {
|
|
14
|
-
route,
|
|
15
|
-
path,
|
|
16
|
-
filePath,
|
|
17
|
-
routeId: `${path}::${filePath}`,
|
|
18
|
-
invalidationKeys: route.invalidationKeys?.slice() ?? []
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
//#endregion
|
|
22
|
-
export { getOutputFilePath, interpolateRoutePath, resolveRouteDescriptor };
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { _getBuiltInRoutePolicy } from "../router/policy.js";
|
|
2
|
-
import "../router/route.js";
|
|
3
|
-
import { getOutputFilePath, interpolateRoutePath, resolveRouteDescriptor } from "./route-utils.js";
|
|
4
|
-
import { expandRoutes } from "./resolve-ssg-data.js";
|
|
5
|
-
//#region src/ssg/static-routes.ts
|
|
6
|
-
function getRuntimeOnlyDiagnostic(route, path) {
|
|
7
|
-
const policies = route.policies ?? [];
|
|
8
|
-
if (route.auth === true) return `Skipped prerender for "${path}": authenticated routes are runtime-only by default.`;
|
|
9
|
-
if (route.role) return `Skipped prerender for "${path}": role-gated routes are runtime-only by default.`;
|
|
10
|
-
if (route.permission) return `Skipped prerender for "${path}": permission-gated routes are runtime-only by default.`;
|
|
11
|
-
if (policies.length > 0) {
|
|
12
|
-
let hasAuthPolicy = false;
|
|
13
|
-
let hasRolePolicy = false;
|
|
14
|
-
let hasPermissionPolicy = false;
|
|
15
|
-
for (const policy of policies) {
|
|
16
|
-
const metadata = _getBuiltInRoutePolicy(policy);
|
|
17
|
-
if (!metadata) return `Skipped prerender for "${path}": routes with custom policies are runtime-only by default.`;
|
|
18
|
-
if (metadata.kind === "auth") hasAuthPolicy = true;
|
|
19
|
-
else if (metadata.kind === "role") hasRolePolicy = true;
|
|
20
|
-
else if (metadata.kind === "permission") hasPermissionPolicy = true;
|
|
21
|
-
}
|
|
22
|
-
if (hasAuthPolicy) return `Skipped prerender for "${path}": authenticated routes are runtime-only by default.`;
|
|
23
|
-
if (hasRolePolicy) return `Skipped prerender for "${path}": role-gated routes are runtime-only by default.`;
|
|
24
|
-
if (hasPermissionPolicy) return `Skipped prerender for "${path}": permission-gated routes are runtime-only by default.`;
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
function getRouteResultPath(route) {
|
|
30
|
-
return route.params ? interpolateRoutePath(route.path, route.params) : route.path;
|
|
31
|
-
}
|
|
32
|
-
function createRuntimeOnlyRoute(route, diagnostic) {
|
|
33
|
-
const path = getRouteResultPath(route);
|
|
34
|
-
const filePath = getOutputFilePath(path);
|
|
35
|
-
return {
|
|
36
|
-
routeId: `${path}::${filePath}`,
|
|
37
|
-
result: {
|
|
38
|
-
path,
|
|
39
|
-
filePath,
|
|
40
|
-
html: "",
|
|
41
|
-
fileSize: 0,
|
|
42
|
-
renderDuration: 0,
|
|
43
|
-
resourceCount: 0,
|
|
44
|
-
status: "skipped",
|
|
45
|
-
reason: "runtime-only",
|
|
46
|
-
written: false,
|
|
47
|
-
error: diagnostic
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
async function splitStaticRoutes(routes) {
|
|
52
|
-
const prerenderableRoutes = [];
|
|
53
|
-
const runtimeOnly = [];
|
|
54
|
-
const outputRouteIds = [];
|
|
55
|
-
for (const route of routes) {
|
|
56
|
-
const diagnostic = getRuntimeOnlyDiagnostic(route, getRouteResultPath(route));
|
|
57
|
-
if (diagnostic) {
|
|
58
|
-
const runtimeRoute = createRuntimeOnlyRoute(route, diagnostic);
|
|
59
|
-
runtimeOnly.push(runtimeRoute);
|
|
60
|
-
outputRouteIds.push(runtimeRoute.routeId);
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
const expanded = await expandRoutes([route]);
|
|
64
|
-
prerenderableRoutes.push(...expanded);
|
|
65
|
-
for (const expandedRoute of expanded) outputRouteIds.push(resolveRouteDescriptor(expandedRoute).routeId);
|
|
66
|
-
}
|
|
67
|
-
return {
|
|
68
|
-
routes: prerenderableRoutes,
|
|
69
|
-
runtimeOnly,
|
|
70
|
-
outputRouteIds
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
function normalizeStaticRoutes(options) {
|
|
74
|
-
if (options.registry) return routeRegistryToRouteConfigs(options.registry);
|
|
75
|
-
return [...options.routes ?? []];
|
|
76
|
-
}
|
|
77
|
-
function routeRegistryToRouteConfigs(registry) {
|
|
78
|
-
const routeConfigs = [];
|
|
79
|
-
for (const record of registry.manifest.records) {
|
|
80
|
-
if (record.isFallback) continue;
|
|
81
|
-
routeConfigs.push({
|
|
82
|
-
path: record.path,
|
|
83
|
-
handler: record.handler,
|
|
84
|
-
namespace: record.options.namespace,
|
|
85
|
-
auth: record.options.auth,
|
|
86
|
-
role: record.options.role,
|
|
87
|
-
permission: record.options.permission,
|
|
88
|
-
policies: stripRegistryGuestPolicies(record.options.policies),
|
|
89
|
-
entries: record.options.entries
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
return routeConfigs;
|
|
93
|
-
}
|
|
94
|
-
function stripRegistryGuestPolicies(policies) {
|
|
95
|
-
if (!policies || policies.length === 0) return;
|
|
96
|
-
const filtered = policies.filter((policy) => _getBuiltInRoutePolicy(policy)?.kind !== "guest");
|
|
97
|
-
return filtered.length > 0 ? filtered : void 0;
|
|
98
|
-
}
|
|
99
|
-
//#endregion
|
|
100
|
-
export { normalizeStaticRoutes, splitStaticRoutes };
|