@askrjs/askr 0.0.28 → 0.0.29
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 +44 -172
- package/dist/_virtual/_rolldown/runtime.js +7 -0
- package/dist/bench/components/benchmark-row.d.ts +20 -0
- package/dist/bench/components/benchmark-row.d.ts.map +1 -0
- package/dist/bench/components/benchmark-row.js +42 -0
- package/dist/bench/components/benchmark-row.js.map +1 -0
- package/dist/bench/components/benchmark-table.js +25 -0
- package/dist/bench/components/benchmark-table.js.map +1 -0
- package/dist/benchmark.d.ts +22 -0
- package/dist/benchmark.d.ts.map +1 -0
- package/dist/benchmark.js +64 -1
- package/dist/benchmark.js.map +1 -0
- package/dist/bin/askr-ssg.d.ts +22 -26
- package/dist/bin/askr-ssg.d.ts.map +1 -1
- package/dist/bin/askr-ssg.js +149 -2
- package/dist/bin/askr-ssg.js.map +1 -0
- package/dist/boot/index.d.ts +64 -42
- package/dist/boot/index.d.ts.map +1 -1
- package/dist/boot/index.js +416 -2
- package/dist/boot/index.js.map +1 -0
- package/dist/common/component.d.ts +14 -13
- package/dist/common/component.d.ts.map +1 -1
- package/dist/common/control.d.ts +13 -0
- package/dist/common/control.d.ts.map +1 -0
- package/dist/common/control.js +14 -0
- package/dist/common/control.js.map +1 -0
- package/dist/common/env.js +47 -0
- package/dist/common/env.js.map +1 -0
- package/dist/common/jsx.d.ts +17 -15
- package/dist/common/jsx.d.ts.map +1 -1
- package/dist/common/jsx.js +8 -1
- package/dist/common/jsx.js.map +1 -0
- package/dist/common/props.d.ts +14 -11
- package/dist/common/props.d.ts.map +1 -1
- package/dist/common/router.d.ts +190 -32
- package/dist/common/router.d.ts.map +1 -1
- package/dist/common/ssr-errors.d.ts +6 -3
- package/dist/common/ssr-errors.d.ts.map +1 -1
- package/dist/common/ssr-errors.js +16 -1
- package/dist/common/ssr-errors.js.map +1 -0
- package/dist/common/ssr.d.ts +12 -9
- package/dist/common/ssr.d.ts.map +1 -1
- package/dist/common/vnode.d.ts +17 -15
- package/dist/common/vnode.d.ts.map +1 -1
- package/dist/common/vnode.js +10 -1
- package/dist/common/vnode.js.map +1 -0
- package/dist/components/link.d.ts +37 -25
- package/dist/components/link.d.ts.map +1 -1
- package/dist/components/link.js +64 -1
- package/dist/components/link.js.map +1 -0
- package/dist/control/case.d.ts +17 -0
- package/dist/control/case.d.ts.map +1 -0
- package/dist/control/case.js +69 -0
- package/dist/control/case.js.map +1 -0
- package/dist/control/for.d.ts +23 -0
- package/dist/control/for.d.ts.map +1 -0
- package/dist/control/for.js +62 -0
- package/dist/control/for.js.map +1 -0
- package/dist/control/index.d.ts +4 -0
- package/dist/control/index.js +4 -0
- package/dist/control/shared.js +20 -0
- package/dist/control/shared.js.map +1 -0
- package/dist/control/show.d.ts +14 -0
- package/dist/control/show.d.ts.map +1 -0
- package/dist/control/show.js +33 -0
- package/dist/control/show.js.map +1 -0
- package/dist/dev/invariant.js +29 -2
- package/dist/dev/invariant.js.map +1 -0
- package/dist/dev/logger.js +37 -1
- package/dist/dev/logger.js.map +1 -0
- package/dist/foundations/icon/icon.d.ts +53 -0
- package/dist/foundations/icon/icon.d.ts.map +1 -0
- package/dist/foundations/icon/icon.js +88 -0
- package/dist/foundations/icon/icon.js.map +1 -0
- package/dist/foundations/icon/icon.types.d.ts +21 -0
- package/dist/foundations/icon/icon.types.d.ts.map +1 -0
- package/dist/foundations/index.d.ts +10 -3
- package/dist/foundations/index.js +9 -1
- package/dist/foundations/interactions/interaction-policy.js +93 -1
- package/dist/foundations/interactions/interaction-policy.js.map +1 -0
- package/dist/foundations/interactions/pressable.js +51 -1
- package/dist/foundations/interactions/pressable.js.map +1 -0
- package/dist/foundations/structures/collection.d.ts +25 -40
- package/dist/foundations/structures/collection.d.ts.map +1 -1
- package/dist/foundations/structures/collection.js +51 -1
- package/dist/foundations/structures/collection.js.map +1 -0
- package/dist/foundations/structures/layer.d.ts +47 -68
- package/dist/foundations/structures/layer.d.ts.map +1 -1
- package/dist/foundations/structures/layer.js +81 -1
- package/dist/foundations/structures/layer.js.map +1 -0
- package/dist/foundations/structures/layout.d.ts +6 -3
- package/dist/foundations/structures/layout.d.ts.map +1 -1
- package/dist/foundations/structures/layout.js +13 -1
- package/dist/foundations/structures/layout.js.map +1 -0
- package/dist/foundations/structures/portal.d.ts +17 -10
- package/dist/foundations/structures/portal.d.ts.map +1 -1
- package/dist/foundations/structures/portal.js +105 -1
- package/dist/foundations/structures/portal.js.map +1 -0
- package/dist/foundations/structures/presence.d.ts +11 -5
- package/dist/foundations/structures/presence.d.ts.map +1 -1
- package/dist/foundations/structures/presence.js +39 -1
- package/dist/foundations/structures/presence.js.map +1 -0
- package/dist/foundations/structures/slot.d.ts +11 -8
- package/dist/foundations/structures/slot.d.ts.map +1 -1
- package/dist/foundations/structures/slot.js +41 -1
- package/dist/foundations/structures/slot.js.map +1 -0
- package/dist/foundations/structures.d.ts +7 -14
- package/dist/foundations/structures.js +6 -1
- package/dist/foundations/utilities/aria.js +11 -1
- package/dist/foundations/utilities/aria.js.map +1 -0
- package/dist/foundations/utilities/compose-handlers.js +20 -1
- package/dist/foundations/utilities/compose-handlers.js.map +1 -0
- package/dist/foundations/utilities/compose-ref.d.ts +7 -4
- package/dist/foundations/utilities/compose-ref.d.ts.map +1 -1
- package/dist/foundations/utilities/compose-ref.js +18 -1
- package/dist/foundations/utilities/compose-ref.js.map +1 -0
- package/dist/foundations/utilities/merge-props.js +49 -1
- package/dist/foundations/utilities/merge-props.js.map +1 -0
- package/dist/fx/fx.d.ts +24 -21
- package/dist/fx/fx.d.ts.map +1 -1
- package/dist/fx/fx.js +212 -1
- package/dist/fx/fx.js.map +1 -0
- package/dist/fx/index.d.ts +4 -7
- package/dist/fx/index.js +4 -1
- package/dist/fx/noop.js +9 -1
- package/dist/fx/noop.js.map +1 -0
- package/dist/fx/timing.d.ts +24 -21
- package/dist/fx/timing.d.ts.map +1 -1
- package/dist/fx/timing.js +236 -1
- package/dist/fx/timing.js.map +1 -0
- package/dist/index.d.ts +21 -23
- package/dist/index.js +34 -1
- package/dist/index.js.map +1 -0
- package/dist/jsx/index.d.ts +1 -4
- package/dist/jsx/index.js +3 -1
- package/dist/jsx/types.d.ts +18 -25
- package/dist/jsx/types.d.ts.map +1 -1
- package/dist/jsx/types.js +1 -1
- package/dist/jsx/utils.d.ts +4 -3
- package/dist/jsx/utils.d.ts.map +1 -1
- package/dist/jsx/utils.js +19 -1
- package/dist/jsx/utils.js.map +1 -0
- package/dist/jsx-dev-runtime.d.ts +8 -0
- package/dist/jsx-dev-runtime.d.ts.map +1 -0
- package/dist/jsx-dev-runtime.js +32 -1
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime.d.ts +12 -0
- package/dist/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx-runtime.js +45 -1
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/jsx-runtime2.d.ts +2 -0
- package/dist/jsx-runtime2.js +3 -0
- package/dist/renderer/children.js +293 -0
- package/dist/renderer/children.js.map +1 -0
- package/dist/renderer/cleanup.js +150 -1
- package/dist/renderer/cleanup.js.map +1 -0
- package/dist/renderer/dom.js +2439 -1
- package/dist/renderer/dom.js.map +1 -0
- package/dist/renderer/env.js +1 -0
- package/dist/renderer/evaluate.js +450 -1
- package/dist/renderer/evaluate.js.map +1 -0
- package/dist/renderer/fastpath.js +145 -1
- package/dist/renderer/fastpath.js.map +1 -0
- package/dist/renderer/index.js +24 -1
- package/dist/renderer/index.js.map +1 -0
- package/dist/renderer/keyed.js +119 -1
- package/dist/renderer/keyed.js.map +1 -0
- package/dist/renderer/reconcile.js +359 -1
- package/dist/renderer/reconcile.js.map +1 -0
- package/dist/renderer/types.js +1 -1
- package/dist/renderer/utils.js +220 -1
- package/dist/renderer/utils.js.map +1 -0
- package/dist/resources/index.d.ts +3 -9
- package/dist/resources/index.js +3 -1
- package/dist/router/index.d.ts +6 -10
- package/dist/router/index.js +5 -1
- package/dist/router/match.js +83 -1
- package/dist/router/match.js.map +1 -0
- package/dist/router/navigate.d.ts +20 -8
- package/dist/router/navigate.d.ts.map +1 -1
- package/dist/router/navigate.js +288 -1
- package/dist/router/navigate.js.map +1 -0
- package/dist/router/policy.d.ts +22 -0
- package/dist/router/policy.d.ts.map +1 -0
- package/dist/router/policy.js +116 -0
- package/dist/router/policy.js.map +1 -0
- package/dist/router/route-context.js +79 -0
- package/dist/router/route-context.js.map +1 -0
- package/dist/router/route.d.ts +101 -34
- package/dist/router/route.d.ts.map +1 -1
- package/dist/router/route.js +599 -1
- package/dist/router/route.js.map +1 -0
- package/dist/runtime/child-scope.d.ts +21 -0
- package/dist/runtime/child-scope.d.ts.map +1 -0
- package/dist/runtime/child-scope.js +77 -0
- package/dist/runtime/child-scope.js.map +1 -0
- package/dist/runtime/component.d.ts +67 -56
- package/dist/runtime/component.d.ts.map +1 -1
- package/dist/runtime/component.js +462 -1
- package/dist/runtime/component.js.map +1 -0
- package/dist/runtime/context.d.ts +28 -42
- package/dist/runtime/context.d.ts.map +1 -1
- package/dist/runtime/context.js +205 -1
- package/dist/runtime/context.js.map +1 -0
- package/dist/runtime/control.d.ts +43 -0
- package/dist/runtime/control.d.ts.map +1 -0
- package/dist/runtime/control.js +125 -0
- package/dist/runtime/control.js.map +1 -0
- package/dist/runtime/derive.d.ts +12 -9
- package/dist/runtime/derive.d.ts.map +1 -1
- package/dist/runtime/derive.js +134 -1
- package/dist/runtime/derive.js.map +1 -0
- package/dist/runtime/dev-namespace.js +57 -1
- package/dist/runtime/dev-namespace.js.map +1 -0
- package/dist/runtime/effect.d.ts +32 -0
- package/dist/runtime/effect.d.ts.map +1 -0
- package/dist/runtime/effect.js +146 -0
- package/dist/runtime/effect.js.map +1 -0
- package/dist/runtime/events.js +162 -1
- package/dist/runtime/events.js.map +1 -0
- package/dist/runtime/execution-model.js +15 -1
- package/dist/runtime/execution-model.js.map +1 -0
- package/dist/runtime/fastlane.js +204 -1
- package/dist/runtime/fastlane.js.map +1 -0
- package/dist/runtime/for-bench.d.ts +41 -0
- package/dist/runtime/for-bench.d.ts.map +1 -0
- package/dist/runtime/for-bench.js +173 -0
- package/dist/runtime/for-bench.js.map +1 -0
- package/dist/runtime/for.d.ts +62 -49
- package/dist/runtime/for.d.ts.map +1 -1
- package/dist/runtime/for.js +668 -1
- package/dist/runtime/for.js.map +1 -0
- package/dist/runtime/operations.d.ts +18 -15
- package/dist/runtime/operations.d.ts.map +1 -1
- package/dist/runtime/operations.js +209 -1
- package/dist/runtime/operations.js.map +1 -0
- package/dist/runtime/perf-metrics.js +64 -1
- package/dist/runtime/perf-metrics.js.map +1 -0
- package/dist/runtime/readable.d.ts +24 -18
- package/dist/runtime/readable.d.ts.map +1 -1
- package/dist/runtime/readable.js +118 -1
- package/dist/runtime/readable.js.map +1 -0
- package/dist/runtime/resource-cell.js +102 -1
- package/dist/runtime/resource-cell.js.map +1 -0
- package/dist/runtime/scheduler.d.ts +51 -50
- package/dist/runtime/scheduler.d.ts.map +1 -1
- package/dist/runtime/scheduler.js +328 -1
- package/dist/runtime/scheduler.js.map +1 -0
- package/dist/runtime/selector.d.ts +7 -5
- package/dist/runtime/selector.d.ts.map +1 -1
- package/dist/runtime/selector.js +188 -1
- package/dist/runtime/selector.js.map +1 -0
- package/dist/runtime/ssr-bridge.js +24 -1
- package/dist/runtime/ssr-bridge.js.map +1 -0
- package/dist/runtime/state.d.ts +11 -19
- package/dist/runtime/state.d.ts.map +1 -1
- package/dist/runtime/state.js +99 -1
- package/dist/runtime/state.js.map +1 -0
- package/dist/ssg/batch-render.d.ts +10 -10
- package/dist/ssg/batch-render.d.ts.map +1 -1
- package/dist/ssg/batch-render.js +84 -1
- package/dist/ssg/batch-render.js.map +1 -0
- package/dist/ssg/create-static-gen.d.ts +28 -29
- package/dist/ssg/create-static-gen.d.ts.map +1 -1
- package/dist/ssg/create-static-gen.js +282 -1
- package/dist/ssg/create-static-gen.js.map +1 -0
- package/dist/ssg/generate-metadata.d.ts +12 -15
- package/dist/ssg/generate-metadata.d.ts.map +1 -1
- package/dist/ssg/generate-metadata.js +94 -1
- package/dist/ssg/generate-metadata.js.map +1 -0
- package/dist/ssg/incremental-manifest.js +56 -1
- package/dist/ssg/incremental-manifest.js.map +1 -0
- package/dist/ssg/index.d.ts +8 -28
- package/dist/ssg/index.js +7 -1
- package/dist/ssg/resolve-ssg-data.d.ts +10 -13
- package/dist/ssg/resolve-ssg-data.d.ts.map +1 -1
- package/dist/ssg/resolve-ssg-data.js +46 -1
- package/dist/ssg/resolve-ssg-data.js.map +1 -0
- package/dist/ssg/route-utils.d.ts +14 -10
- package/dist/ssg/route-utils.d.ts.map +1 -1
- package/dist/ssg/route-utils.js +24 -1
- package/dist/ssg/route-utils.js.map +1 -0
- package/dist/ssg/types.d.ts +157 -144
- package/dist/ssg/types.d.ts.map +1 -1
- package/dist/ssg/write-static-files.d.ts +8 -14
- package/dist/ssg/write-static-files.d.ts.map +1 -1
- package/dist/ssg/write-static-files.js +73 -1
- package/dist/ssg/write-static-files.js.map +1 -0
- package/dist/ssr/attrs.js +93 -1
- package/dist/ssr/attrs.js.map +1 -0
- package/dist/ssr/context.d.ts +31 -35
- package/dist/ssr/context.d.ts.map +1 -1
- package/dist/ssr/context.js +63 -1
- package/dist/ssr/context.js.map +1 -0
- package/dist/ssr/errors.d.ts +6 -4
- package/dist/ssr/errors.d.ts.map +1 -1
- package/dist/ssr/errors.js +4 -1
- package/dist/ssr/errors.js.map +1 -0
- package/dist/ssr/escape.js +153 -1
- package/dist/ssr/escape.js.map +1 -0
- package/dist/ssr/index.d.ts +74 -72
- package/dist/ssr/index.d.ts.map +1 -1
- package/dist/ssr/index.js +543 -1
- package/dist/ssr/index.js.map +1 -0
- package/dist/ssr/render-keys.d.ts +27 -29
- package/dist/ssr/render-keys.d.ts.map +1 -1
- package/dist/ssr/render-keys.js +39 -1
- package/dist/ssr/render-keys.js.map +1 -0
- package/dist/ssr/sink.js +86 -1
- package/dist/ssr/sink.js.map +1 -0
- package/dist/ssr/stream-render.js +76 -1
- package/dist/ssr/stream-render.js.map +1 -0
- package/dist/ssr/types.d.ts +14 -13
- package/dist/ssr/types.d.ts.map +1 -1
- package/package.json +49 -69
- package/dist/_virtual/___vite-browser-external.js +0 -1
- package/dist/_virtual/__vite-browser-external.js +0 -1
- package/dist/_virtual/_commonjsHelpers.js +0 -1
- package/dist/_virtual/_fs.js +0 -1
- package/dist/_virtual/_path.js +0 -1
- package/dist/_virtual/main.js +0 -1
- package/dist/_virtual/preload-helper.js +0 -1
- package/dist/bench/benchmark-entry.d.ts +0 -14
- package/dist/bench/benchmark-entry.d.ts.map +0 -1
- package/dist/common/errors.d.ts +0 -53
- package/dist/common/errors.d.ts.map +0 -1
- package/dist/common/index.d.ts +0 -14
- package/dist/common/index.d.ts.map +0 -1
- package/dist/dev/invariant.d.ts +0 -83
- package/dist/dev/invariant.d.ts.map +0 -1
- package/dist/dev/logger.d.ts +0 -13
- package/dist/dev/logger.d.ts.map +0 -1
- package/dist/dev/vite-plugin-askr.d.ts +0 -25
- package/dist/dev/vite-plugin-askr.d.ts.map +0 -1
- package/dist/dev/warnings.d.ts +0 -5
- package/dist/dev/warnings.d.ts.map +0 -1
- package/dist/for/for.d.ts +0 -16
- package/dist/for/for.d.ts.map +0 -1
- package/dist/for/for.js +0 -1
- package/dist/for/index.d.ts +0 -2
- package/dist/for/index.d.ts.map +0 -1
- package/dist/for/index.js +0 -1
- package/dist/foundations/core.d.ts +0 -23
- package/dist/foundations/core.d.ts.map +0 -1
- package/dist/foundations/core.js +0 -1
- package/dist/foundations/index.d.ts.map +0 -1
- package/dist/foundations/interactions/dismissable.d.ts +0 -58
- package/dist/foundations/interactions/dismissable.d.ts.map +0 -1
- package/dist/foundations/interactions/dismissable.js +0 -1
- package/dist/foundations/interactions/focusable.d.ts +0 -16
- package/dist/foundations/interactions/focusable.d.ts.map +0 -1
- package/dist/foundations/interactions/focusable.js +0 -1
- package/dist/foundations/interactions/hoverable.d.ts +0 -19
- package/dist/foundations/interactions/hoverable.d.ts.map +0 -1
- package/dist/foundations/interactions/hoverable.js +0 -1
- package/dist/foundations/interactions/index.d.ts +0 -5
- package/dist/foundations/interactions/index.d.ts.map +0 -1
- package/dist/foundations/interactions/interaction-policy.d.ts +0 -96
- package/dist/foundations/interactions/interaction-policy.d.ts.map +0 -1
- package/dist/foundations/interactions/pressable.d.ts +0 -54
- package/dist/foundations/interactions/pressable.d.ts.map +0 -1
- package/dist/foundations/interactions/roving-focus.d.ts +0 -117
- package/dist/foundations/interactions/roving-focus.d.ts.map +0 -1
- package/dist/foundations/interactions/roving-focus.js +0 -1
- package/dist/foundations/state/controllable.d.ts +0 -53
- package/dist/foundations/state/controllable.d.ts.map +0 -1
- package/dist/foundations/state/controllable.js +0 -1
- package/dist/foundations/state/index.d.ts +0 -2
- package/dist/foundations/state/index.d.ts.map +0 -1
- package/dist/foundations/structures/index.d.ts +0 -5
- package/dist/foundations/structures/index.d.ts.map +0 -1
- package/dist/foundations/structures.d.ts.map +0 -1
- package/dist/foundations/utilities/aria.d.ts +0 -13
- package/dist/foundations/utilities/aria.d.ts.map +0 -1
- package/dist/foundations/utilities/compose-handlers.d.ts +0 -34
- package/dist/foundations/utilities/compose-handlers.d.ts.map +0 -1
- package/dist/foundations/utilities/event-types.d.ts +0 -17
- package/dist/foundations/utilities/event-types.d.ts.map +0 -1
- package/dist/foundations/utilities/index.d.ts +0 -7
- package/dist/foundations/utilities/index.d.ts.map +0 -1
- package/dist/foundations/utilities/merge-props.d.ts +0 -2
- package/dist/foundations/utilities/merge-props.d.ts.map +0 -1
- package/dist/foundations/utilities/use-id.d.ts +0 -29
- package/dist/foundations/utilities/use-id.d.ts.map +0 -1
- package/dist/foundations/utilities/use-id.js +0 -1
- package/dist/fx/index.d.ts.map +0 -1
- package/dist/fx/noop.d.ts +0 -12
- package/dist/fx/noop.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/jsx/index.d.ts.map +0 -1
- package/dist/jsx/jsx-dev-runtime.d.ts +0 -4
- package/dist/jsx/jsx-dev-runtime.d.ts.map +0 -1
- package/dist/jsx/jsx-runtime.d.ts +0 -10
- package/dist/jsx/jsx-runtime.d.ts.map +0 -1
- package/dist/node_modules/esbuild/lib/main.js +0 -65
- package/dist/renderer/cleanup.d.ts +0 -28
- package/dist/renderer/cleanup.d.ts.map +0 -1
- package/dist/renderer/dom.d.ts +0 -64
- package/dist/renderer/dom.d.ts.map +0 -1
- package/dist/renderer/evaluate.d.ts +0 -4
- package/dist/renderer/evaluate.d.ts.map +0 -1
- package/dist/renderer/fastpath.d.ts +0 -7
- package/dist/renderer/fastpath.d.ts.map +0 -1
- package/dist/renderer/index.d.ts +0 -6
- package/dist/renderer/index.d.ts.map +0 -1
- package/dist/renderer/keyed.d.ts +0 -23
- package/dist/renderer/keyed.d.ts.map +0 -1
- package/dist/renderer/reconcile.d.ts +0 -88
- package/dist/renderer/reconcile.d.ts.map +0 -1
- package/dist/renderer/types.d.ts +0 -3
- package/dist/renderer/types.d.ts.map +0 -1
- package/dist/renderer/utils.d.ts +0 -63
- package/dist/renderer/utils.d.ts.map +0 -1
- package/dist/resources/index.d.ts.map +0 -1
- package/dist/router/index.d.ts.map +0 -1
- package/dist/router/match.d.ts +0 -22
- package/dist/router/match.d.ts.map +0 -1
- package/dist/runtime/dev-namespace.d.ts +0 -31
- package/dist/runtime/dev-namespace.d.ts.map +0 -1
- package/dist/runtime/events.d.ts +0 -53
- package/dist/runtime/events.d.ts.map +0 -1
- package/dist/runtime/execution-model.d.ts +0 -4
- package/dist/runtime/execution-model.d.ts.map +0 -1
- package/dist/runtime/fastlane.d.ts +0 -27
- package/dist/runtime/fastlane.d.ts.map +0 -1
- package/dist/runtime/hydration.d.ts +0 -25
- package/dist/runtime/hydration.d.ts.map +0 -1
- package/dist/runtime/perf-metrics.d.ts +0 -25
- package/dist/runtime/perf-metrics.d.ts.map +0 -1
- package/dist/runtime/resource-cell.d.ts +0 -35
- package/dist/runtime/resource-cell.d.ts.map +0 -1
- package/dist/runtime/snapshot.d.ts +0 -25
- package/dist/runtime/snapshot.d.ts.map +0 -1
- package/dist/runtime/ssr-bridge.d.ts +0 -10
- package/dist/runtime/ssr-bridge.d.ts.map +0 -1
- package/dist/ssg/discover-resources.d.ts +0 -15
- package/dist/ssg/discover-resources.d.ts.map +0 -1
- package/dist/ssg/incremental-manifest.d.ts +0 -23
- package/dist/ssg/incremental-manifest.d.ts.map +0 -1
- package/dist/ssg/index.d.ts.map +0 -1
- package/dist/ssr/attrs.d.ts +0 -26
- package/dist/ssr/attrs.d.ts.map +0 -1
- package/dist/ssr/create-ssr.d.ts +0 -19
- package/dist/ssr/create-ssr.d.ts.map +0 -1
- package/dist/ssr/escape.d.ts +0 -38
- package/dist/ssr/escape.d.ts.map +0 -1
- package/dist/ssr/sink.d.ts +0 -23
- package/dist/ssr/sink.d.ts.map +0 -1
- package/dist/ssr/stream-render.d.ts +0 -7
- package/dist/ssr/stream-render.d.ts.map +0 -1
- package/dist/vite/index.js +0 -4
|
@@ -1 +1,282 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { addPerfDuration, incrementPerfMetric } from "../runtime/perf-metrics.js";
|
|
2
|
+
import { resolveSsgData, validateRoutes } from "./resolve-ssg-data.js";
|
|
3
|
+
import { resolveRouteDescriptor } from "./route-utils.js";
|
|
4
|
+
import { batchRenderRoutes } from "./batch-render.js";
|
|
5
|
+
import { writeStaticFiles } from "./write-static-files.js";
|
|
6
|
+
import { generateSSGResult, resultToMetadata, writeMetadata } from "./generate-metadata.js";
|
|
7
|
+
import { getExistingOutputFileSize, hashHtml, outputFileExists, readIncrementalManifest, writeIncrementalManifest } from "./incremental-manifest.js";
|
|
8
|
+
//#region src/ssg/create-static-gen.ts
|
|
9
|
+
function getRuntimeOnlyDiagnostic(descriptor) {
|
|
10
|
+
const { route } = descriptor;
|
|
11
|
+
if (route.auth === true) return `Skipped prerender for "${descriptor.path}": authenticated routes are runtime-only by default.`;
|
|
12
|
+
if (route.role) return `Skipped prerender for "${descriptor.path}": role-gated routes are runtime-only by default.`;
|
|
13
|
+
if (route.permission) return `Skipped prerender for "${descriptor.path}": permission-gated routes are runtime-only by default.`;
|
|
14
|
+
if (route.policies && route.policies.length > 0) return `Skipped prerender for "${descriptor.path}": routes with custom policies are runtime-only by default.`;
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
function resolveParallelism(requested) {
|
|
18
|
+
if (requested !== "auto") return Math.max(1, requested ?? 1);
|
|
19
|
+
const maybeNavigator = globalThis;
|
|
20
|
+
const envWorkers = Number(maybeNavigator.process?.env?.ASKR_SSG_WORKERS ?? maybeNavigator.process?.env?.NUMBER_OF_PROCESSORS ?? maybeNavigator.process?.env?.UV_THREADPOOL_SIZE);
|
|
21
|
+
if (Number.isFinite(envWorkers) && envWorkers > 0) return Math.max(1, Math.trunc(envWorkers));
|
|
22
|
+
if (typeof maybeNavigator.navigator?.hardwareConcurrency === "number") return Math.max(1, maybeNavigator.navigator.hardwareConcurrency);
|
|
23
|
+
return 1;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Create a Static Site Generator
|
|
27
|
+
*
|
|
28
|
+
* Usage:
|
|
29
|
+
* ```ts
|
|
30
|
+
* const ssg = createStaticGen({
|
|
31
|
+
* routes: [
|
|
32
|
+
* { path: '/', component: HomePage },
|
|
33
|
+
* { path: '/about', component: AboutPage },
|
|
34
|
+
* ],
|
|
35
|
+
* outputDir: './dist',
|
|
36
|
+
* dataOverrides: {
|
|
37
|
+
* '/api/posts': { posts: [...] }
|
|
38
|
+
* }
|
|
39
|
+
* });
|
|
40
|
+
*
|
|
41
|
+
* const result = await ssg.generate();
|
|
42
|
+
* console.log(`Generated ${result.successful}/${result.totalRoutes} routes`);
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
function createStaticGen(options) {
|
|
46
|
+
let result = null;
|
|
47
|
+
const seed = options.seed ?? 12345;
|
|
48
|
+
const resolvedParallelism = resolveParallelism(options.parallelism);
|
|
49
|
+
const resolvedConcurrency = Math.max(1, options.concurrency ?? resolvedParallelism);
|
|
50
|
+
if (!Array.isArray(options.routes) || options.routes.length === 0) throw new Error("routes array is required");
|
|
51
|
+
if (!options.outputDir || options.outputDir.trim().length === 0) throw new Error("outputDir is required");
|
|
52
|
+
return {
|
|
53
|
+
/**
|
|
54
|
+
* Generate static HTML for all routes
|
|
55
|
+
* Writes to outputDir with metadata.json
|
|
56
|
+
* Returns detailed results
|
|
57
|
+
*/
|
|
58
|
+
async generate(generateOptions = {}) {
|
|
59
|
+
validateRoutes(options.routes);
|
|
60
|
+
const changedKeys = dedupeStrings(generateOptions.changedKeys);
|
|
61
|
+
const changedRoutes = dedupeStrings(generateOptions.changedRoutes);
|
|
62
|
+
const requestedMode = generateOptions.mode ?? "full";
|
|
63
|
+
const previousManifest = !generateOptions.forceFull && requestedMode === "incremental" ? readIncrementalManifest(options.outputDir, seed) : null;
|
|
64
|
+
const effectiveMode = generateOptions.forceFull || requestedMode !== "incremental" || previousManifest === null ? "full" : "incremental";
|
|
65
|
+
const dataMap = resolveSsgData(options.routes, { dataOverrides: options.dataOverrides });
|
|
66
|
+
const descriptors = options.routes.map(resolveRouteDescriptor);
|
|
67
|
+
const routeResultsById = /* @__PURE__ */ new Map();
|
|
68
|
+
const eligibleDescriptors = [];
|
|
69
|
+
for (const descriptor of descriptors) {
|
|
70
|
+
const diagnostic = getRuntimeOnlyDiagnostic(descriptor);
|
|
71
|
+
if (diagnostic) {
|
|
72
|
+
routeResultsById.set(descriptor.routeId, {
|
|
73
|
+
path: descriptor.path,
|
|
74
|
+
filePath: descriptor.filePath,
|
|
75
|
+
html: "",
|
|
76
|
+
fileSize: 0,
|
|
77
|
+
renderDuration: 0,
|
|
78
|
+
resourceCount: 0,
|
|
79
|
+
status: "skipped",
|
|
80
|
+
reason: "runtime-only",
|
|
81
|
+
written: false,
|
|
82
|
+
error: diagnostic
|
|
83
|
+
});
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
eligibleDescriptors.push(descriptor);
|
|
87
|
+
}
|
|
88
|
+
const previousEntries = new Map((previousManifest?.routes ?? []).map((entry) => [entry.routeId, entry]));
|
|
89
|
+
const currentRouteIds = new Set(eligibleDescriptors.map((descriptor) => descriptor.routeId));
|
|
90
|
+
const selected = [];
|
|
91
|
+
const routesToRender = [];
|
|
92
|
+
for (let index = 0; index < eligibleDescriptors.length; index += 1) {
|
|
93
|
+
const descriptor = eligibleDescriptors[index];
|
|
94
|
+
const entry = selectRouteForGeneration(descriptor, previousEntries.get(descriptor.routeId) ?? null, effectiveMode, changedKeys, changedRoutes);
|
|
95
|
+
selected.push(entry);
|
|
96
|
+
if (entry.reason !== "unchanged") routesToRender.push(entry);
|
|
97
|
+
}
|
|
98
|
+
const renderStartTime = performance.now();
|
|
99
|
+
incrementPerfMetric("ssgWorkerCount", resolvedParallelism);
|
|
100
|
+
const renderedResults = routesToRender.length > 0 ? await batchRenderRoutes(getRoutesToRender(routesToRender), {
|
|
101
|
+
seed,
|
|
102
|
+
dataMap,
|
|
103
|
+
concurrency: resolvedConcurrency
|
|
104
|
+
}) : [];
|
|
105
|
+
addPerfDuration("ssgRenderTimeMs", performance.now() - renderStartTime);
|
|
106
|
+
const renderedByRouteId = /* @__PURE__ */ new Map();
|
|
107
|
+
for (let index = 0; index < renderedResults.length; index += 1) renderedByRouteId.set(routesToRender[index].descriptor.routeId, renderedResults[index]);
|
|
108
|
+
let cacheHits = 0;
|
|
109
|
+
const nextManifestRoutes = [];
|
|
110
|
+
for (const entry of selected) {
|
|
111
|
+
const { descriptor, previous, reason } = entry;
|
|
112
|
+
const baseData = dataMap[descriptor.route.path] ?? dataMap[descriptor.path] ?? {};
|
|
113
|
+
const resourceCount = Object.keys(baseData).length;
|
|
114
|
+
if (reason === "unchanged") {
|
|
115
|
+
routeResultsById.set(descriptor.routeId, {
|
|
116
|
+
path: descriptor.path,
|
|
117
|
+
filePath: descriptor.filePath,
|
|
118
|
+
html: "",
|
|
119
|
+
fileSize: previous?.htmlHash !== null && previous !== null ? getExistingOutputFileSize(options.outputDir, descriptor.filePath) : 0,
|
|
120
|
+
renderDuration: 0,
|
|
121
|
+
resourceCount,
|
|
122
|
+
status: "skipped",
|
|
123
|
+
reason: "unchanged",
|
|
124
|
+
written: false
|
|
125
|
+
});
|
|
126
|
+
if (previous) nextManifestRoutes.push({
|
|
127
|
+
...previous,
|
|
128
|
+
path: descriptor.path,
|
|
129
|
+
filePath: descriptor.filePath,
|
|
130
|
+
invalidationKeys: descriptor.invalidationKeys.slice()
|
|
131
|
+
});
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
const rendered = renderedByRouteId.get(descriptor.routeId);
|
|
135
|
+
if (!rendered) throw new Error(`Missing rendered result for route "${descriptor.path}"`);
|
|
136
|
+
const nextResult = {
|
|
137
|
+
...rendered,
|
|
138
|
+
path: descriptor.path,
|
|
139
|
+
filePath: descriptor.filePath,
|
|
140
|
+
resourceCount,
|
|
141
|
+
reason,
|
|
142
|
+
written: false
|
|
143
|
+
};
|
|
144
|
+
if (nextResult.status === "success") {
|
|
145
|
+
const htmlDigest = hashHtml(nextResult.html);
|
|
146
|
+
const shouldWrite = effectiveMode === "full" || !previous || previous.htmlHash !== htmlDigest || !outputFileExists(options.outputDir, descriptor.filePath);
|
|
147
|
+
nextResult.written = shouldWrite;
|
|
148
|
+
if (!shouldWrite) cacheHits += 1;
|
|
149
|
+
nextManifestRoutes.push({
|
|
150
|
+
routeId: descriptor.routeId,
|
|
151
|
+
path: descriptor.path,
|
|
152
|
+
filePath: descriptor.filePath,
|
|
153
|
+
invalidationKeys: descriptor.invalidationKeys.slice(),
|
|
154
|
+
htmlHash: htmlDigest,
|
|
155
|
+
lastStatus: "success"
|
|
156
|
+
});
|
|
157
|
+
} else nextManifestRoutes.push({
|
|
158
|
+
routeId: descriptor.routeId,
|
|
159
|
+
path: descriptor.path,
|
|
160
|
+
filePath: descriptor.filePath,
|
|
161
|
+
invalidationKeys: descriptor.invalidationKeys.slice(),
|
|
162
|
+
htmlHash: previous?.htmlHash ?? null,
|
|
163
|
+
lastStatus: "error"
|
|
164
|
+
});
|
|
165
|
+
routeResultsById.set(descriptor.routeId, nextResult);
|
|
166
|
+
}
|
|
167
|
+
const removedResults = collectRemovedRouteResults(previousManifest, currentRouteIds);
|
|
168
|
+
const routeResults = [];
|
|
169
|
+
for (let index = 0; index < descriptors.length; index += 1) {
|
|
170
|
+
const routeResult = routeResultsById.get(descriptors[index].routeId);
|
|
171
|
+
if (routeResult) routeResults.push(routeResult);
|
|
172
|
+
}
|
|
173
|
+
routeResults.push(...removedResults);
|
|
174
|
+
const writeStartTime = performance.now();
|
|
175
|
+
await writeStaticFiles(routeResults, options.outputDir, { concurrency: resolvedConcurrency });
|
|
176
|
+
addPerfDuration("ssgWriteTimeMs", performance.now() - writeStartTime);
|
|
177
|
+
result = generateSSGResult(routeResults, {
|
|
178
|
+
mode: effectiveMode,
|
|
179
|
+
cacheHits,
|
|
180
|
+
invalidatedKeys: changedKeys,
|
|
181
|
+
invalidatedRoutes: changedRoutes
|
|
182
|
+
});
|
|
183
|
+
await writeMetadata(resultToMetadata(result), options.outputDir);
|
|
184
|
+
await writeIncrementalManifest({
|
|
185
|
+
schemaVersion: 1,
|
|
186
|
+
seed,
|
|
187
|
+
mode: effectiveMode,
|
|
188
|
+
routes: nextManifestRoutes
|
|
189
|
+
}, options.outputDir);
|
|
190
|
+
return result;
|
|
191
|
+
},
|
|
192
|
+
/**
|
|
193
|
+
* Get effective config in a serializable form for diagnostics.
|
|
194
|
+
*/
|
|
195
|
+
getConfig() {
|
|
196
|
+
return {
|
|
197
|
+
routeCount: options.routes.length,
|
|
198
|
+
outputDir: options.outputDir,
|
|
199
|
+
seed,
|
|
200
|
+
concurrency: resolvedConcurrency,
|
|
201
|
+
parallelism: resolvedParallelism,
|
|
202
|
+
hasDataOverrides: !!options.dataOverrides
|
|
203
|
+
};
|
|
204
|
+
},
|
|
205
|
+
/**
|
|
206
|
+
* Get the last generation result
|
|
207
|
+
* Returns null if generate() hasn't been called
|
|
208
|
+
*/
|
|
209
|
+
getResult() {
|
|
210
|
+
return result;
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
function dedupeStrings(values) {
|
|
215
|
+
return values ? Array.from(new Set(values)) : [];
|
|
216
|
+
}
|
|
217
|
+
function getRoutesToRender(selected) {
|
|
218
|
+
const routes = [];
|
|
219
|
+
for (let index = 0; index < selected.length; index += 1) routes.push(selected[index].descriptor.route);
|
|
220
|
+
return routes;
|
|
221
|
+
}
|
|
222
|
+
function selectRouteForGeneration(descriptor, previous, mode, changedKeys, changedRoutes) {
|
|
223
|
+
if (mode === "full") return {
|
|
224
|
+
descriptor,
|
|
225
|
+
reason: "full",
|
|
226
|
+
previous
|
|
227
|
+
};
|
|
228
|
+
if (!previous) return {
|
|
229
|
+
descriptor,
|
|
230
|
+
reason: "new-route",
|
|
231
|
+
previous
|
|
232
|
+
};
|
|
233
|
+
if (previous.lastStatus === "error" || previous.htmlHash === null) return {
|
|
234
|
+
descriptor,
|
|
235
|
+
reason: "new-route",
|
|
236
|
+
previous
|
|
237
|
+
};
|
|
238
|
+
if (descriptor.invalidationKeys.length === 0) return {
|
|
239
|
+
descriptor,
|
|
240
|
+
reason: "no-keys",
|
|
241
|
+
previous
|
|
242
|
+
};
|
|
243
|
+
if (changedRoutes.includes(descriptor.path)) return {
|
|
244
|
+
descriptor,
|
|
245
|
+
reason: "changed-route",
|
|
246
|
+
previous
|
|
247
|
+
};
|
|
248
|
+
if (descriptor.invalidationKeys.some((key) => changedKeys.includes(key))) return {
|
|
249
|
+
descriptor,
|
|
250
|
+
reason: "changed-key",
|
|
251
|
+
previous
|
|
252
|
+
};
|
|
253
|
+
return {
|
|
254
|
+
descriptor,
|
|
255
|
+
reason: "unchanged",
|
|
256
|
+
previous
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
function collectRemovedRouteResults(manifest, currentRouteIds) {
|
|
260
|
+
if (!manifest) return [];
|
|
261
|
+
const results = [];
|
|
262
|
+
for (let index = 0; index < manifest.routes.length; index += 1) {
|
|
263
|
+
const entry = manifest.routes[index];
|
|
264
|
+
if (currentRouteIds.has(entry.routeId)) continue;
|
|
265
|
+
results.push({
|
|
266
|
+
path: entry.path,
|
|
267
|
+
filePath: entry.filePath,
|
|
268
|
+
html: "",
|
|
269
|
+
fileSize: 0,
|
|
270
|
+
renderDuration: 0,
|
|
271
|
+
resourceCount: 0,
|
|
272
|
+
status: "removed",
|
|
273
|
+
reason: "deleted",
|
|
274
|
+
written: false
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
return results;
|
|
278
|
+
}
|
|
279
|
+
//#endregion
|
|
280
|
+
export { createStaticGen };
|
|
281
|
+
|
|
282
|
+
//# sourceMappingURL=create-static-gen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-static-gen.js","names":[],"sources":["../../src/ssg/create-static-gen.ts"],"sourcesContent":["/**\n * Static Site Generation API\n *\n * Main orchestrator for batch rendering, file I/O, and metadata generation\n */\n\nimport type {\n RouteRenderReason,\n RouteRenderResult,\n SSGGenerateOptions,\n SSGMode,\n SSGOptions,\n SSGResult,\n} from './types';\nimport { resolveSsgData, validateRoutes } from './resolve-ssg-data';\nimport { batchRenderRoutes } from './batch-render';\nimport { writeStaticFiles } from './write-static-files';\nimport {\n generateSSGResult,\n resultToMetadata,\n writeMetadata,\n} from './generate-metadata';\nimport {\n getExistingOutputFileSize,\n outputFileExists,\n readIncrementalManifest,\n type IncrementalManifest,\n type IncrementalManifestRouteEntry,\n writeIncrementalManifest,\n hashHtml,\n SSG_MANIFEST_SCHEMA_VERSION,\n} from './incremental-manifest';\nimport {\n resolveRouteDescriptor,\n type ResolvedRouteDescriptor,\n} from './route-utils';\nimport { addPerfDuration, incrementPerfMetric } from '../runtime/perf-metrics';\n\ninterface SelectedRoute {\n descriptor: ResolvedRouteDescriptor;\n reason: RouteRenderReason;\n previous: IncrementalManifestRouteEntry | null;\n}\n\nfunction getRuntimeOnlyDiagnostic(\n descriptor: ResolvedRouteDescriptor\n): string | null {\n const { route } = descriptor;\n\n if (route.auth === true) {\n return `Skipped prerender for \"${descriptor.path}\": authenticated routes are runtime-only by default.`;\n }\n\n if (route.role) {\n return `Skipped prerender for \"${descriptor.path}\": role-gated routes are runtime-only by default.`;\n }\n\n if (route.permission) {\n return `Skipped prerender for \"${descriptor.path}\": permission-gated routes are runtime-only by default.`;\n }\n\n if (route.policies && route.policies.length > 0) {\n return `Skipped prerender for \"${descriptor.path}\": routes with custom policies are runtime-only by default.`;\n }\n\n return null;\n}\n\nfunction resolveParallelism(requested: number | 'auto' | undefined): number {\n if (requested !== 'auto') {\n return Math.max(1, requested ?? 1);\n }\n\n const maybeNavigator = globalThis as typeof globalThis & {\n navigator?: { hardwareConcurrency?: number };\n process?: { env?: Record<string, string | undefined> };\n };\n\n const envWorkers = Number(\n maybeNavigator.process?.env?.ASKR_SSG_WORKERS ??\n maybeNavigator.process?.env?.NUMBER_OF_PROCESSORS ??\n maybeNavigator.process?.env?.UV_THREADPOOL_SIZE\n );\n if (Number.isFinite(envWorkers) && envWorkers > 0) {\n return Math.max(1, Math.trunc(envWorkers));\n }\n\n if (typeof maybeNavigator.navigator?.hardwareConcurrency === 'number') {\n return Math.max(1, maybeNavigator.navigator.hardwareConcurrency);\n }\n\n return 1;\n}\n\n/**\n * Create a Static Site Generator\n *\n * Usage:\n * ```ts\n * const ssg = createStaticGen({\n * routes: [\n * { path: '/', component: HomePage },\n * { path: '/about', component: AboutPage },\n * ],\n * outputDir: './dist',\n * dataOverrides: {\n * '/api/posts': { posts: [...] }\n * }\n * });\n *\n * const result = await ssg.generate();\n * console.log(`Generated ${result.successful}/${result.totalRoutes} routes`);\n * ```\n */\nexport function createStaticGen(options: SSGOptions) {\n let result: SSGResult | null = null;\n const seed = options.seed ?? 12345;\n const resolvedParallelism = resolveParallelism(options.parallelism);\n const resolvedConcurrency = Math.max(\n 1,\n options.concurrency ?? resolvedParallelism\n );\n\n if (!Array.isArray(options.routes) || options.routes.length === 0) {\n throw new Error('routes array is required');\n }\n\n if (!options.outputDir || options.outputDir.trim().length === 0) {\n throw new Error('outputDir is required');\n }\n\n return {\n /**\n * Generate static HTML for all routes\n * Writes to outputDir with metadata.json\n * Returns detailed results\n */\n async generate(\n generateOptions: SSGGenerateOptions = {}\n ): Promise<SSGResult> {\n // Validate input\n validateRoutes(options.routes);\n\n const changedKeys = dedupeStrings(generateOptions.changedKeys);\n const changedRoutes = dedupeStrings(generateOptions.changedRoutes);\n const requestedMode = generateOptions.mode ?? 'full';\n const previousManifest =\n !generateOptions.forceFull && requestedMode === 'incremental'\n ? readIncrementalManifest(options.outputDir, seed)\n : null;\n const effectiveMode: SSGMode =\n generateOptions.forceFull ||\n requestedMode !== 'incremental' ||\n previousManifest === null\n ? 'full'\n : 'incremental';\n\n // Resolve data\n const dataMap = resolveSsgData(options.routes, {\n dataOverrides: options.dataOverrides,\n });\n\n const descriptors = options.routes.map(resolveRouteDescriptor);\n const routeResultsById = new Map<string, RouteRenderResult>();\n const eligibleDescriptors: ResolvedRouteDescriptor[] = [];\n\n for (const descriptor of descriptors) {\n const diagnostic = getRuntimeOnlyDiagnostic(descriptor);\n if (diagnostic) {\n routeResultsById.set(descriptor.routeId, {\n path: descriptor.path,\n filePath: descriptor.filePath,\n html: '',\n fileSize: 0,\n renderDuration: 0,\n resourceCount: 0,\n status: 'skipped',\n reason: 'runtime-only',\n written: false,\n error: diagnostic,\n });\n continue;\n }\n\n eligibleDescriptors.push(descriptor);\n }\n\n const previousEntries = new Map(\n (previousManifest?.routes ?? []).map((entry) => [entry.routeId, entry])\n );\n const currentRouteIds = new Set(\n eligibleDescriptors.map((descriptor) => descriptor.routeId)\n );\n\n const selected: SelectedRoute[] = [];\n const routesToRender: SelectedRoute[] = [];\n for (let index = 0; index < eligibleDescriptors.length; index += 1) {\n const descriptor = eligibleDescriptors[index];\n const entry = selectRouteForGeneration(\n descriptor,\n previousEntries.get(descriptor.routeId) ?? null,\n effectiveMode,\n changedKeys,\n changedRoutes\n );\n selected.push(entry);\n if (entry.reason !== 'unchanged') {\n routesToRender.push(entry);\n }\n }\n const renderStartTime = performance.now();\n incrementPerfMetric('ssgWorkerCount', resolvedParallelism);\n const renderedResults =\n routesToRender.length > 0\n ? await batchRenderRoutes(getRoutesToRender(routesToRender), {\n seed,\n dataMap,\n concurrency: resolvedConcurrency,\n })\n : [];\n addPerfDuration('ssgRenderTimeMs', performance.now() - renderStartTime);\n const renderedByRouteId = new Map<string, RouteRenderResult>();\n for (let index = 0; index < renderedResults.length; index += 1) {\n renderedByRouteId.set(\n routesToRender[index].descriptor.routeId,\n renderedResults[index]\n );\n }\n\n let cacheHits = 0;\n const nextManifestRoutes: IncrementalManifestRouteEntry[] = [];\n\n for (const entry of selected) {\n const { descriptor, previous, reason } = entry;\n const baseData =\n dataMap[descriptor.route.path] ?? dataMap[descriptor.path] ?? {};\n const resourceCount = Object.keys(baseData).length;\n\n if (reason === 'unchanged') {\n routeResultsById.set(descriptor.routeId, {\n path: descriptor.path,\n filePath: descriptor.filePath,\n html: '',\n fileSize:\n previous?.htmlHash !== null && previous !== null\n ? getExistingOutputFileSize(\n options.outputDir,\n descriptor.filePath\n )\n : 0,\n renderDuration: 0,\n resourceCount,\n status: 'skipped',\n reason: 'unchanged',\n written: false,\n });\n\n if (previous) {\n nextManifestRoutes.push({\n ...previous,\n path: descriptor.path,\n filePath: descriptor.filePath,\n invalidationKeys: descriptor.invalidationKeys.slice(),\n });\n }\n continue;\n }\n\n const rendered = renderedByRouteId.get(descriptor.routeId);\n if (!rendered) {\n throw new Error(\n `Missing rendered result for route \"${descriptor.path}\"`\n );\n }\n\n const nextResult: RouteRenderResult = {\n ...rendered,\n path: descriptor.path,\n filePath: descriptor.filePath,\n resourceCount,\n reason,\n written: false,\n };\n\n if (nextResult.status === 'success') {\n const htmlDigest = hashHtml(nextResult.html);\n const shouldWrite =\n effectiveMode === 'full' ||\n !previous ||\n previous.htmlHash !== htmlDigest ||\n !outputFileExists(options.outputDir, descriptor.filePath);\n\n nextResult.written = shouldWrite;\n if (!shouldWrite) {\n cacheHits += 1;\n }\n\n nextManifestRoutes.push({\n routeId: descriptor.routeId,\n path: descriptor.path,\n filePath: descriptor.filePath,\n invalidationKeys: descriptor.invalidationKeys.slice(),\n htmlHash: htmlDigest,\n lastStatus: 'success',\n });\n } else {\n nextManifestRoutes.push({\n routeId: descriptor.routeId,\n path: descriptor.path,\n filePath: descriptor.filePath,\n invalidationKeys: descriptor.invalidationKeys.slice(),\n htmlHash: previous?.htmlHash ?? null,\n lastStatus: 'error',\n });\n }\n\n routeResultsById.set(descriptor.routeId, nextResult);\n }\n\n const removedResults = collectRemovedRouteResults(\n previousManifest,\n currentRouteIds\n );\n const routeResults: RouteRenderResult[] = [];\n for (let index = 0; index < descriptors.length; index += 1) {\n const routeResult = routeResultsById.get(descriptors[index].routeId);\n if (routeResult) {\n routeResults.push(routeResult);\n }\n }\n routeResults.push(...removedResults);\n\n // Write HTML files to disk and remove stale output\n const writeStartTime = performance.now();\n await writeStaticFiles(routeResults, options.outputDir, {\n concurrency: resolvedConcurrency,\n });\n addPerfDuration('ssgWriteTimeMs', performance.now() - writeStartTime);\n\n // Generate result object\n result = generateSSGResult(routeResults, {\n mode: effectiveMode,\n cacheHits,\n invalidatedKeys: changedKeys,\n invalidatedRoutes: changedRoutes,\n });\n\n // Write metadata\n const metadata = resultToMetadata(result);\n await writeMetadata(metadata, options.outputDir);\n\n await writeIncrementalManifest(\n {\n schemaVersion: SSG_MANIFEST_SCHEMA_VERSION,\n seed,\n mode: effectiveMode,\n routes: nextManifestRoutes,\n },\n options.outputDir\n );\n\n return result;\n },\n\n /**\n * Get effective config in a serializable form for diagnostics.\n */\n getConfig() {\n return {\n routeCount: options.routes.length,\n outputDir: options.outputDir,\n seed,\n concurrency: resolvedConcurrency,\n parallelism: resolvedParallelism,\n hasDataOverrides: !!options.dataOverrides,\n };\n },\n\n /**\n * Get the last generation result\n * Returns null if generate() hasn't been called\n */\n getResult(): SSGResult | null {\n return result;\n },\n };\n}\n\nfunction dedupeStrings(values?: string[]): string[] {\n return values ? Array.from(new Set(values)) : [];\n}\n\nfunction getRoutesToRender(selected: SelectedRoute[]): SSGOptions['routes'] {\n const routes: SSGOptions['routes'] = [];\n for (let index = 0; index < selected.length; index += 1) {\n routes.push(selected[index].descriptor.route);\n }\n return routes;\n}\n\nfunction selectRouteForGeneration(\n descriptor: ResolvedRouteDescriptor,\n previous: IncrementalManifestRouteEntry | null,\n mode: SSGMode,\n changedKeys: string[],\n changedRoutes: string[]\n): SelectedRoute {\n if (mode === 'full') {\n return { descriptor, reason: 'full', previous };\n }\n\n if (!previous) {\n return { descriptor, reason: 'new-route', previous };\n }\n\n if (previous.lastStatus === 'error' || previous.htmlHash === null) {\n return { descriptor, reason: 'new-route', previous };\n }\n\n if (descriptor.invalidationKeys.length === 0) {\n return { descriptor, reason: 'no-keys', previous };\n }\n\n if (changedRoutes.includes(descriptor.path)) {\n return { descriptor, reason: 'changed-route', previous };\n }\n\n if (descriptor.invalidationKeys.some((key) => changedKeys.includes(key))) {\n return { descriptor, reason: 'changed-key', previous };\n }\n\n return { descriptor, reason: 'unchanged', previous };\n}\n\nfunction collectRemovedRouteResults(\n manifest: IncrementalManifest | null,\n currentRouteIds: Set<string>\n): RouteRenderResult[] {\n if (!manifest) {\n return [];\n }\n\n const results: RouteRenderResult[] = [];\n for (let index = 0; index < manifest.routes.length; index += 1) {\n const entry = manifest.routes[index];\n if (currentRouteIds.has(entry.routeId)) {\n continue;\n }\n results.push({\n path: entry.path,\n filePath: entry.filePath,\n html: '',\n fileSize: 0,\n renderDuration: 0,\n resourceCount: 0,\n status: 'removed' as const,\n reason: 'deleted' as const,\n written: false,\n });\n }\n\n return results;\n}\n"],"mappings":";;;;;;;;AA4CA,SAAS,yBACP,YACe;CACf,MAAM,EAAE,UAAU;AAElB,KAAI,MAAM,SAAS,KACjB,QAAO,0BAA0B,WAAW,KAAK;AAGnD,KAAI,MAAM,KACR,QAAO,0BAA0B,WAAW,KAAK;AAGnD,KAAI,MAAM,WACR,QAAO,0BAA0B,WAAW,KAAK;AAGnD,KAAI,MAAM,YAAY,MAAM,SAAS,SAAS,EAC5C,QAAO,0BAA0B,WAAW,KAAK;AAGnD,QAAO;;AAGT,SAAS,mBAAmB,WAAgD;AAC1E,KAAI,cAAc,OAChB,QAAO,KAAK,IAAI,GAAG,aAAa,EAAE;CAGpC,MAAM,iBAAiB;CAKvB,MAAM,aAAa,OACjB,eAAe,SAAS,KAAK,oBAC3B,eAAe,SAAS,KAAK,wBAC7B,eAAe,SAAS,KAAK,mBAChC;AACD,KAAI,OAAO,SAAS,WAAW,IAAI,aAAa,EAC9C,QAAO,KAAK,IAAI,GAAG,KAAK,MAAM,WAAW,CAAC;AAG5C,KAAI,OAAO,eAAe,WAAW,wBAAwB,SAC3D,QAAO,KAAK,IAAI,GAAG,eAAe,UAAU,oBAAoB;AAGlE,QAAO;;;;;;;;;;;;;;;;;;;;;;AAuBT,SAAgB,gBAAgB,SAAqB;CACnD,IAAI,SAA2B;CAC/B,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,sBAAsB,mBAAmB,QAAQ,YAAY;CACnE,MAAM,sBAAsB,KAAK,IAC/B,GACA,QAAQ,eAAe,oBACxB;AAED,KAAI,CAAC,MAAM,QAAQ,QAAQ,OAAO,IAAI,QAAQ,OAAO,WAAW,EAC9D,OAAM,IAAI,MAAM,2BAA2B;AAG7C,KAAI,CAAC,QAAQ,aAAa,QAAQ,UAAU,MAAM,CAAC,WAAW,EAC5D,OAAM,IAAI,MAAM,wBAAwB;AAG1C,QAAO;;;;;;EAML,MAAM,SACJ,kBAAsC,EAAE,EACpB;AAEpB,kBAAe,QAAQ,OAAO;GAE9B,MAAM,cAAc,cAAc,gBAAgB,YAAY;GAC9D,MAAM,gBAAgB,cAAc,gBAAgB,cAAc;GAClE,MAAM,gBAAgB,gBAAgB,QAAQ;GAC9C,MAAM,mBACJ,CAAC,gBAAgB,aAAa,kBAAkB,gBAC5C,wBAAwB,QAAQ,WAAW,KAAK,GAChD;GACN,MAAM,gBACJ,gBAAgB,aAChB,kBAAkB,iBAClB,qBAAqB,OACjB,SACA;GAGN,MAAM,UAAU,eAAe,QAAQ,QAAQ,EAC7C,eAAe,QAAQ,eACxB,CAAC;GAEF,MAAM,cAAc,QAAQ,OAAO,IAAI,uBAAuB;GAC9D,MAAM,mCAAmB,IAAI,KAAgC;GAC7D,MAAM,sBAAiD,EAAE;AAEzD,QAAK,MAAM,cAAc,aAAa;IACpC,MAAM,aAAa,yBAAyB,WAAW;AACvD,QAAI,YAAY;AACd,sBAAiB,IAAI,WAAW,SAAS;MACvC,MAAM,WAAW;MACjB,UAAU,WAAW;MACrB,MAAM;MACN,UAAU;MACV,gBAAgB;MAChB,eAAe;MACf,QAAQ;MACR,QAAQ;MACR,SAAS;MACT,OAAO;MACR,CAAC;AACF;;AAGF,wBAAoB,KAAK,WAAW;;GAGtC,MAAM,kBAAkB,IAAI,KACzB,kBAAkB,UAAU,EAAE,EAAE,KAAK,UAAU,CAAC,MAAM,SAAS,MAAM,CAAC,CACxE;GACD,MAAM,kBAAkB,IAAI,IAC1B,oBAAoB,KAAK,eAAe,WAAW,QAAQ,CAC5D;GAED,MAAM,WAA4B,EAAE;GACpC,MAAM,iBAAkC,EAAE;AAC1C,QAAK,IAAI,QAAQ,GAAG,QAAQ,oBAAoB,QAAQ,SAAS,GAAG;IAClE,MAAM,aAAa,oBAAoB;IACvC,MAAM,QAAQ,yBACZ,YACA,gBAAgB,IAAI,WAAW,QAAQ,IAAI,MAC3C,eACA,aACA,cACD;AACD,aAAS,KAAK,MAAM;AACpB,QAAI,MAAM,WAAW,YACnB,gBAAe,KAAK,MAAM;;GAG9B,MAAM,kBAAkB,YAAY,KAAK;AACzC,uBAAoB,kBAAkB,oBAAoB;GAC1D,MAAM,kBACJ,eAAe,SAAS,IACpB,MAAM,kBAAkB,kBAAkB,eAAe,EAAE;IACzD;IACA;IACA,aAAa;IACd,CAAC,GACF,EAAE;AACR,mBAAgB,mBAAmB,YAAY,KAAK,GAAG,gBAAgB;GACvE,MAAM,oCAAoB,IAAI,KAAgC;AAC9D,QAAK,IAAI,QAAQ,GAAG,QAAQ,gBAAgB,QAAQ,SAAS,EAC3D,mBAAkB,IAChB,eAAe,OAAO,WAAW,SACjC,gBAAgB,OACjB;GAGH,IAAI,YAAY;GAChB,MAAM,qBAAsD,EAAE;AAE9D,QAAK,MAAM,SAAS,UAAU;IAC5B,MAAM,EAAE,YAAY,UAAU,WAAW;IACzC,MAAM,WACJ,QAAQ,WAAW,MAAM,SAAS,QAAQ,WAAW,SAAS,EAAE;IAClE,MAAM,gBAAgB,OAAO,KAAK,SAAS,CAAC;AAE5C,QAAI,WAAW,aAAa;AAC1B,sBAAiB,IAAI,WAAW,SAAS;MACvC,MAAM,WAAW;MACjB,UAAU,WAAW;MACrB,MAAM;MACN,UACE,UAAU,aAAa,QAAQ,aAAa,OACxC,0BACE,QAAQ,WACR,WAAW,SACZ,GACD;MACN,gBAAgB;MAChB;MACA,QAAQ;MACR,QAAQ;MACR,SAAS;MACV,CAAC;AAEF,SAAI,SACF,oBAAmB,KAAK;MACtB,GAAG;MACH,MAAM,WAAW;MACjB,UAAU,WAAW;MACrB,kBAAkB,WAAW,iBAAiB,OAAO;MACtD,CAAC;AAEJ;;IAGF,MAAM,WAAW,kBAAkB,IAAI,WAAW,QAAQ;AAC1D,QAAI,CAAC,SACH,OAAM,IAAI,MACR,sCAAsC,WAAW,KAAK,GACvD;IAGH,MAAM,aAAgC;KACpC,GAAG;KACH,MAAM,WAAW;KACjB,UAAU,WAAW;KACrB;KACA;KACA,SAAS;KACV;AAED,QAAI,WAAW,WAAW,WAAW;KACnC,MAAM,aAAa,SAAS,WAAW,KAAK;KAC5C,MAAM,cACJ,kBAAkB,UAClB,CAAC,YACD,SAAS,aAAa,cACtB,CAAC,iBAAiB,QAAQ,WAAW,WAAW,SAAS;AAE3D,gBAAW,UAAU;AACrB,SAAI,CAAC,YACH,cAAa;AAGf,wBAAmB,KAAK;MACtB,SAAS,WAAW;MACpB,MAAM,WAAW;MACjB,UAAU,WAAW;MACrB,kBAAkB,WAAW,iBAAiB,OAAO;MACrD,UAAU;MACV,YAAY;MACb,CAAC;UAEF,oBAAmB,KAAK;KACtB,SAAS,WAAW;KACpB,MAAM,WAAW;KACjB,UAAU,WAAW;KACrB,kBAAkB,WAAW,iBAAiB,OAAO;KACrD,UAAU,UAAU,YAAY;KAChC,YAAY;KACb,CAAC;AAGJ,qBAAiB,IAAI,WAAW,SAAS,WAAW;;GAGtD,MAAM,iBAAiB,2BACrB,kBACA,gBACD;GACD,MAAM,eAAoC,EAAE;AAC5C,QAAK,IAAI,QAAQ,GAAG,QAAQ,YAAY,QAAQ,SAAS,GAAG;IAC1D,MAAM,cAAc,iBAAiB,IAAI,YAAY,OAAO,QAAQ;AACpE,QAAI,YACF,cAAa,KAAK,YAAY;;AAGlC,gBAAa,KAAK,GAAG,eAAe;GAGpC,MAAM,iBAAiB,YAAY,KAAK;AACxC,SAAM,iBAAiB,cAAc,QAAQ,WAAW,EACtD,aAAa,qBACd,CAAC;AACF,mBAAgB,kBAAkB,YAAY,KAAK,GAAG,eAAe;AAGrE,YAAS,kBAAkB,cAAc;IACvC,MAAM;IACN;IACA,iBAAiB;IACjB,mBAAmB;IACpB,CAAC;AAIF,SAAM,cADW,iBAAiB,OACd,EAAU,QAAQ,UAAU;AAEhD,SAAM,yBACJ;IACE,eAAA;IACA;IACA,MAAM;IACN,QAAQ;IACT,EACD,QAAQ,UACT;AAED,UAAO;;;;;EAMT,YAAY;AACV,UAAO;IACL,YAAY,QAAQ,OAAO;IAC3B,WAAW,QAAQ;IACnB;IACA,aAAa;IACb,aAAa;IACb,kBAAkB,CAAC,CAAC,QAAQ;IAC7B;;;;;;EAOH,YAA8B;AAC5B,UAAO;;EAEV;;AAGH,SAAS,cAAc,QAA6B;AAClD,QAAO,SAAS,MAAM,KAAK,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE;;AAGlD,SAAS,kBAAkB,UAAiD;CAC1E,MAAM,SAA+B,EAAE;AACvC,MAAK,IAAI,QAAQ,GAAG,QAAQ,SAAS,QAAQ,SAAS,EACpD,QAAO,KAAK,SAAS,OAAO,WAAW,MAAM;AAE/C,QAAO;;AAGT,SAAS,yBACP,YACA,UACA,MACA,aACA,eACe;AACf,KAAI,SAAS,OACX,QAAO;EAAE;EAAY,QAAQ;EAAQ;EAAU;AAGjD,KAAI,CAAC,SACH,QAAO;EAAE;EAAY,QAAQ;EAAa;EAAU;AAGtD,KAAI,SAAS,eAAe,WAAW,SAAS,aAAa,KAC3D,QAAO;EAAE;EAAY,QAAQ;EAAa;EAAU;AAGtD,KAAI,WAAW,iBAAiB,WAAW,EACzC,QAAO;EAAE;EAAY,QAAQ;EAAW;EAAU;AAGpD,KAAI,cAAc,SAAS,WAAW,KAAK,CACzC,QAAO;EAAE;EAAY,QAAQ;EAAiB;EAAU;AAG1D,KAAI,WAAW,iBAAiB,MAAM,QAAQ,YAAY,SAAS,IAAI,CAAC,CACtE,QAAO;EAAE;EAAY,QAAQ;EAAe;EAAU;AAGxD,QAAO;EAAE;EAAY,QAAQ;EAAa;EAAU;;AAGtD,SAAS,2BACP,UACA,iBACqB;AACrB,KAAI,CAAC,SACH,QAAO,EAAE;CAGX,MAAM,UAA+B,EAAE;AACvC,MAAK,IAAI,QAAQ,GAAG,QAAQ,SAAS,OAAO,QAAQ,SAAS,GAAG;EAC9D,MAAM,QAAQ,SAAS,OAAO;AAC9B,MAAI,gBAAgB,IAAI,MAAM,QAAQ,CACpC;AAEF,UAAQ,KAAK;GACX,MAAM,MAAM;GACZ,UAAU,MAAM;GAChB,MAAM;GACN,UAAU;GACV,gBAAgB;GAChB,eAAe;GACf,QAAQ;GACR,QAAQ;GACR,SAAS;GACV,CAAC;;AAGJ,QAAO"}
|
|
@@ -1,27 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* Generates and serializes metadata about generated static files.
|
|
5
|
-
* This module is Node-only and not intended for browser builds.
|
|
6
|
-
*/
|
|
7
|
-
import type { RouteRenderResult, SSGMetadata, SSGMode, SSGResult } from './types';
|
|
1
|
+
import { RouteRenderResult, SSGMetadata, SSGMode, SSGResult } from "./types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/ssg/generate-metadata.d.ts
|
|
8
4
|
interface GenerateResultOptions {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
mode?: SSGMode;
|
|
6
|
+
cacheHits?: number;
|
|
7
|
+
invalidatedKeys?: string[];
|
|
8
|
+
invalidatedRoutes?: string[];
|
|
13
9
|
}
|
|
14
10
|
/**
|
|
15
11
|
* Generate SSGResult from render results
|
|
16
12
|
*/
|
|
17
|
-
|
|
13
|
+
declare function generateSSGResult(results: RouteRenderResult[], options?: GenerateResultOptions): SSGResult;
|
|
18
14
|
/**
|
|
19
15
|
* Convert SSGResult to metadata for JSON serialization
|
|
20
16
|
*/
|
|
21
|
-
|
|
17
|
+
declare function resultToMetadata(result: SSGResult): SSGMetadata;
|
|
22
18
|
/**
|
|
23
19
|
* Write metadata.json to output directory
|
|
24
20
|
*/
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
declare function writeMetadata(metadata: Record<string, unknown>, outputDir: string): Promise<void>;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { generateSSGResult, resultToMetadata, writeMetadata };
|
|
27
24
|
//# sourceMappingURL=generate-metadata.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-metadata.d.ts","
|
|
1
|
+
{"version":3,"file":"generate-metadata.d.ts","names":[],"sources":["../../src/ssg/generate-metadata.ts"],"mappings":";;;UAgBU,qBAAA;EACR,IAAA,GAAO,OAAA;EACP,SAAA;EACA,eAAA;EACA,iBAAA;AAAA;;AAMF;;iBAAgB,iBAAA,CACd,OAAA,EAAS,iBAAA,IACT,OAAA,GAAS,qBAAA,GACR,SAAA;;;;iBA6Ca,gBAAA,CAAiB,MAAA,EAAQ,SAAA,GAAY,WAAA;;;;iBAsC/B,aAAA,CACpB,QAAA,EAAU,MAAA,mBACV,SAAA,WACC,OAAA"}
|
|
@@ -1 +1,94 @@
|
|
|
1
|
-
import
|
|
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 };
|
|
93
|
+
|
|
94
|
+
//# sourceMappingURL=generate-metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-metadata.js","names":[],"sources":["../../src/ssg/generate-metadata.ts"],"sourcesContent":["/**\n * Metadata generation for SSG\n *\n * Generates and serializes metadata about generated static files.\n * This module is Node-only and not intended for browser builds.\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as pathModule from 'node:path';\nimport type {\n RouteRenderResult,\n SSGMetadata,\n SSGMode,\n SSGResult,\n} from './types';\n\ninterface GenerateResultOptions {\n mode?: SSGMode;\n cacheHits?: number;\n invalidatedKeys?: string[];\n invalidatedRoutes?: string[];\n}\n\n/**\n * Generate SSGResult from render results\n */\nexport function generateSSGResult(\n results: RouteRenderResult[],\n options: GenerateResultOptions = {}\n): SSGResult {\n let successful = 0;\n let failed = 0;\n let totalDuration = 0;\n let rebuilt = 0;\n let skipped = 0;\n let removed = 0;\n\n for (let index = 0; index < results.length; index += 1) {\n const result = results[index];\n totalDuration += result.renderDuration;\n\n if (result.status === 'success') {\n successful += 1;\n rebuilt += 1;\n } else if (result.status === 'error') {\n failed += 1;\n rebuilt += 1;\n } else if (result.status === 'skipped') {\n skipped += 1;\n } else if (result.status === 'removed') {\n removed += 1;\n }\n }\n\n return {\n generatedAt: new Date().toISOString(),\n totalRoutes: results.length,\n successful,\n failed,\n totalDuration: Math.round(totalDuration),\n mode: options.mode ?? 'full',\n rebuilt,\n skipped,\n removed,\n cacheHits: options.cacheHits ?? 0,\n invalidatedKeys: options.invalidatedKeys?.slice() ?? [],\n invalidatedRoutes: options.invalidatedRoutes?.slice() ?? [],\n routes: results,\n };\n}\n\n/**\n * Convert SSGResult to metadata for JSON serialization\n */\nexport function resultToMetadata(result: SSGResult): SSGMetadata {\n const routes: SSGMetadata['routes'] = [];\n\n for (let index = 0; index < result.routes.length; index += 1) {\n const route = result.routes[index];\n routes.push({\n path: route.path,\n filePath: route.filePath,\n fileSize: route.fileSize,\n renderDuration: route.renderDuration,\n resourceCount: route.resourceCount,\n status: route.status,\n reason: route.reason,\n written: route.written,\n error: route.error,\n });\n }\n\n return {\n generatedAt: result.generatedAt,\n totalRoutes: result.totalRoutes,\n successful: result.successful,\n failed: result.failed,\n totalDuration: result.totalDuration,\n mode: result.mode,\n rebuilt: result.rebuilt,\n skipped: result.skipped,\n removed: result.removed,\n cacheHits: result.cacheHits,\n invalidatedKeys: result.invalidatedKeys.slice(),\n invalidatedRoutes: result.invalidatedRoutes.slice(),\n routes,\n };\n}\n\n/**\n * Write metadata.json to output directory\n */\nexport async function writeMetadata(\n metadata: Record<string, unknown>,\n outputDir: string\n): Promise<void> {\n const filePath = pathModule.join(outputDir, 'metadata.json');\n\n // Ensure directory exists\n await fs.mkdir(outputDir, { recursive: true });\n\n // Write metadata file with formatting\n await fs.writeFile(filePath, JSON.stringify(metadata, null, 2), 'utf8');\n}\n"],"mappings":";;;;;;;;;;;;AA0BA,SAAgB,kBACd,SACA,UAAiC,EAAE,EACxB;CACX,IAAI,aAAa;CACjB,IAAI,SAAS;CACb,IAAI,gBAAgB;CACpB,IAAI,UAAU;CACd,IAAI,UAAU;CACd,IAAI,UAAU;AAEd,MAAK,IAAI,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,SAAS,GAAG;EACtD,MAAM,SAAS,QAAQ;AACvB,mBAAiB,OAAO;AAExB,MAAI,OAAO,WAAW,WAAW;AAC/B,iBAAc;AACd,cAAW;aACF,OAAO,WAAW,SAAS;AACpC,aAAU;AACV,cAAW;aACF,OAAO,WAAW,UAC3B,YAAW;WACF,OAAO,WAAW,UAC3B,YAAW;;AAIf,QAAO;EACL,8BAAa,IAAI,MAAM,EAAC,aAAa;EACrC,aAAa,QAAQ;EACrB;EACA;EACA,eAAe,KAAK,MAAM,cAAc;EACxC,MAAM,QAAQ,QAAQ;EACtB;EACA;EACA;EACA,WAAW,QAAQ,aAAa;EAChC,iBAAiB,QAAQ,iBAAiB,OAAO,IAAI,EAAE;EACvD,mBAAmB,QAAQ,mBAAmB,OAAO,IAAI,EAAE;EAC3D,QAAQ;EACT;;;;;AAMH,SAAgB,iBAAiB,QAAgC;CAC/D,MAAM,SAAgC,EAAE;AAExC,MAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,OAAO,QAAQ,SAAS,GAAG;EAC5D,MAAM,QAAQ,OAAO,OAAO;AAC5B,SAAO,KAAK;GACV,MAAM,MAAM;GACZ,UAAU,MAAM;GAChB,UAAU,MAAM;GAChB,gBAAgB,MAAM;GACtB,eAAe,MAAM;GACrB,QAAQ,MAAM;GACd,QAAQ,MAAM;GACd,SAAS,MAAM;GACf,OAAO,MAAM;GACd,CAAC;;AAGJ,QAAO;EACL,aAAa,OAAO;EACpB,aAAa,OAAO;EACpB,YAAY,OAAO;EACnB,QAAQ,OAAO;EACf,eAAe,OAAO;EACtB,MAAM,OAAO;EACb,SAAS,OAAO;EAChB,SAAS,OAAO;EAChB,SAAS,OAAO;EAChB,WAAW,OAAO;EAClB,iBAAiB,OAAO,gBAAgB,OAAO;EAC/C,mBAAmB,OAAO,kBAAkB,OAAO;EACnD;EACD;;;;;AAMH,eAAsB,cACpB,UACA,WACe;CACf,MAAM,WAAW,WAAW,KAAK,WAAW,gBAAgB;AAG5D,OAAM,GAAG,MAAM,WAAW,EAAE,WAAW,MAAM,CAAC;AAG9C,OAAM,GAAG,UAAU,UAAU,KAAK,UAAU,UAAU,MAAM,EAAE,EAAE,OAAO"}
|
|
@@ -1 +1,56 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import * as fsPromises from "node:fs/promises";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as pathModule from "node:path";
|
|
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, hashHtml, outputFileExists, readIncrementalManifest, writeIncrementalManifest };
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=incremental-manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"incremental-manifest.js","names":[],"sources":["../../src/ssg/incremental-manifest.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport * as fsPromises from 'node:fs/promises';\nimport * as pathModule from 'node:path';\nimport type { RouteRenderStatus, SSGMode } from './types';\n\nexport const SSG_MANIFEST_SCHEMA_VERSION = 1;\nconst MANIFEST_DIR = '.askr';\nconst MANIFEST_FILE = 'ssg-manifest.json';\n\nexport interface IncrementalManifestRouteEntry {\n routeId: string;\n path: string;\n filePath: string;\n invalidationKeys: string[];\n htmlHash: string | null;\n lastStatus: Extract<RouteRenderStatus, 'success' | 'error'>;\n}\n\nexport interface IncrementalManifest {\n schemaVersion: number;\n seed: number;\n mode: SSGMode;\n routes: IncrementalManifestRouteEntry[];\n}\n\nexport function hashHtml(html: string): string {\n // Deterministic 32-bit FNV-1a hash is sufficient for incremental change checks.\n let hash = 0x811c9dc5;\n for (let index = 0; index < html.length; index += 1) {\n hash ^= html.charCodeAt(index);\n hash = Math.imul(hash, 0x01000193);\n }\n return (hash >>> 0).toString(16).padStart(8, '0');\n}\n\nexport function getIncrementalManifestPath(outputDir: string): string {\n return pathModule.join(outputDir, MANIFEST_DIR, MANIFEST_FILE);\n}\n\nexport function readIncrementalManifest(\n outputDir: string,\n seed: number\n): IncrementalManifest | null {\n const manifestPath = getIncrementalManifestPath(outputDir);\n if (!fs.existsSync(manifestPath)) {\n return null;\n }\n\n try {\n const raw = fs.readFileSync(manifestPath, 'utf8');\n const parsed = JSON.parse(raw) as Partial<IncrementalManifest>;\n\n if (\n parsed.schemaVersion !== SSG_MANIFEST_SCHEMA_VERSION ||\n parsed.seed !== seed ||\n !Array.isArray(parsed.routes)\n ) {\n return null;\n }\n\n const routes = parsed.routes.filter(\n (entry): entry is IncrementalManifestRouteEntry =>\n !!entry &&\n typeof entry.routeId === 'string' &&\n typeof entry.path === 'string' &&\n typeof entry.filePath === 'string' &&\n Array.isArray(entry.invalidationKeys) &&\n (entry.htmlHash === null || typeof entry.htmlHash === 'string') &&\n (entry.lastStatus === 'success' || entry.lastStatus === 'error')\n );\n\n if (routes.length !== parsed.routes.length) {\n return null;\n }\n\n return {\n schemaVersion: SSG_MANIFEST_SCHEMA_VERSION,\n seed,\n mode: parsed.mode === 'incremental' ? 'incremental' : 'full',\n routes,\n };\n } catch {\n return null;\n }\n}\n\nexport async function writeIncrementalManifest(\n manifest: IncrementalManifest,\n outputDir: string\n): Promise<void> {\n const manifestPath = getIncrementalManifestPath(outputDir);\n await fsPromises.mkdir(pathModule.dirname(manifestPath), { recursive: true });\n await fsPromises.writeFile(\n manifestPath,\n JSON.stringify(manifest, null, 2),\n 'utf8'\n );\n}\n\nexport function getExistingOutputFileSize(\n outputDir: string,\n filePath: string\n): number {\n const fullPath = pathModule.join(outputDir, filePath);\n if (!fs.existsSync(fullPath)) {\n return 0;\n }\n\n try {\n return fs.statSync(fullPath).size;\n } catch {\n return 0;\n }\n}\n\nexport function outputFileExists(outputDir: string, filePath: string): boolean {\n return fs.existsSync(pathModule.join(outputDir, filePath));\n}\n"],"mappings":";;;AAMA,MAAM,eAAe;AACrB,MAAM,gBAAgB;AAkBtB,SAAgB,SAAS,MAAsB;CAE7C,IAAI,OAAO;AACX,MAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS,GAAG;AACnD,UAAQ,KAAK,WAAW,MAAM;AAC9B,SAAO,KAAK,KAAK,MAAM,SAAW;;AAEpC,SAAQ,SAAS,GAAG,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI;;AAGnD,SAAgB,2BAA2B,WAA2B;AACpE,QAAO,WAAW,KAAK,WAAW,cAAc,cAAc;;AAGhE,SAAgB,wBACd,WACA,MAC4B;CAC5B,MAAM,eAAe,2BAA2B,UAAU;AAC1D,KAAI,CAAC,GAAG,WAAW,aAAa,CAC9B,QAAO;AAGT,KAAI;EACF,MAAM,MAAM,GAAG,aAAa,cAAc,OAAO;EACjD,MAAM,SAAS,KAAK,MAAM,IAAI;AAE9B,MACE,OAAO,kBAAA,KACP,OAAO,SAAS,QAChB,CAAC,MAAM,QAAQ,OAAO,OAAO,CAE7B,QAAO;EAGT,MAAM,SAAS,OAAO,OAAO,QAC1B,UACC,CAAC,CAAC,SACF,OAAO,MAAM,YAAY,YACzB,OAAO,MAAM,SAAS,YACtB,OAAO,MAAM,aAAa,YAC1B,MAAM,QAAQ,MAAM,iBAAiB,KACpC,MAAM,aAAa,QAAQ,OAAO,MAAM,aAAa,cACrD,MAAM,eAAe,aAAa,MAAM,eAAe,SAC3D;AAED,MAAI,OAAO,WAAW,OAAO,OAAO,OAClC,QAAO;AAGT,SAAO;GACL,eAAA;GACA;GACA,MAAM,OAAO,SAAS,gBAAgB,gBAAgB;GACtD;GACD;SACK;AACN,SAAO;;;AAIX,eAAsB,yBACpB,UACA,WACe;CACf,MAAM,eAAe,2BAA2B,UAAU;AAC1D,OAAM,WAAW,MAAM,WAAW,QAAQ,aAAa,EAAE,EAAE,WAAW,MAAM,CAAC;AAC7E,OAAM,WAAW,UACf,cACA,KAAK,UAAU,UAAU,MAAM,EAAE,EACjC,OACD;;AAGH,SAAgB,0BACd,WACA,UACQ;CACR,MAAM,WAAW,WAAW,KAAK,WAAW,SAAS;AACrD,KAAI,CAAC,GAAG,WAAW,SAAS,CAC1B,QAAO;AAGT,KAAI;AACF,SAAO,GAAG,SAAS,SAAS,CAAC;SACvB;AACN,SAAO;;;AAIX,SAAgB,iBAAiB,WAAmB,UAA2B;AAC7E,QAAO,GAAG,WAAW,WAAW,KAAK,WAAW,SAAS,CAAC"}
|
package/dist/ssg/index.d.ts
CHANGED
|
@@ -1,28 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*
|
|
10
|
-
* const ssg = createStaticGen({
|
|
11
|
-
* routes: [
|
|
12
|
-
* { path: '/', component: HomePage },
|
|
13
|
-
* { path: '/about', component: AboutPage },
|
|
14
|
-
* ],
|
|
15
|
-
* outputDir: './dist',
|
|
16
|
-
* });
|
|
17
|
-
*
|
|
18
|
-
* const result = await ssg.generate();
|
|
19
|
-
* console.log(`Generated ${result.successful} routes`);
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
export { createStaticGen } from './create-static-gen';
|
|
23
|
-
export type { RouteConfig, RouteRenderReason, SSGOptions, SSGGenerateOptions, SSGMode, SSGResult, SSGMetadata, RouteRenderResult, RouteRenderStatus, DiscoveredResources, } from './types';
|
|
24
|
-
export { batchRenderRoutes } from './batch-render';
|
|
25
|
-
export { writeStaticFiles, getOutputFilePath } from './write-static-files';
|
|
26
|
-
export { generateSSGResult, resultToMetadata, writeMetadata, } from './generate-metadata';
|
|
27
|
-
export { resolveSsgData, validateRoutes } from './resolve-ssg-data';
|
|
28
|
-
//# sourceMappingURL=index.d.ts.map
|
|
1
|
+
import { DiscoveredResources, RouteConfig, RouteRenderReason, RouteRenderResult, RouteRenderStatus, SSGGenerateOptions, SSGMetadata, SSGMode, SSGOptions, SSGResult } from "./types.js";
|
|
2
|
+
import { createStaticGen } from "./create-static-gen.js";
|
|
3
|
+
import { batchRenderRoutes } from "./batch-render.js";
|
|
4
|
+
import { getOutputFilePath } from "./route-utils.js";
|
|
5
|
+
import { writeStaticFiles } from "./write-static-files.js";
|
|
6
|
+
import { generateSSGResult, resultToMetadata, writeMetadata } from "./generate-metadata.js";
|
|
7
|
+
import { resolveSsgData, validateRoutes } from "./resolve-ssg-data.js";
|
|
8
|
+
export { type DiscoveredResources, type RouteConfig, type RouteRenderReason, type RouteRenderResult, type RouteRenderStatus, type SSGGenerateOptions, type SSGMetadata, type SSGMode, type SSGOptions, type SSGResult, batchRenderRoutes, createStaticGen, generateSSGResult, getOutputFilePath, resolveSsgData, resultToMetadata, validateRoutes, writeMetadata, writeStaticFiles };
|
package/dist/ssg/index.js
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { resolveSsgData, validateRoutes } from "./resolve-ssg-data.js";
|
|
2
|
+
import { getOutputFilePath } from "./route-utils.js";
|
|
3
|
+
import { batchRenderRoutes } from "./batch-render.js";
|
|
4
|
+
import { writeStaticFiles } from "./write-static-files.js";
|
|
5
|
+
import { generateSSGResult, resultToMetadata, writeMetadata } from "./generate-metadata.js";
|
|
6
|
+
import { createStaticGen } from "./create-static-gen.js";
|
|
7
|
+
export { batchRenderRoutes, createStaticGen, generateSSGResult, getOutputFilePath, resolveSsgData, resultToMetadata, validateRoutes, writeMetadata, writeStaticFiles };
|