@mandujs/core 0.54.32 → 0.55.0-beta.1
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 +654 -654
- package/package.json +106 -210
- package/scripts/postinstall-lock.ts +153 -153
- package/src/a11y/__tests__/run-audit.test.ts +333 -333
- package/src/a11y/fix-hints.ts +76 -76
- package/src/a11y/index.ts +18 -18
- package/src/a11y/run-audit.ts +15 -15
- package/src/a11y/types.ts +125 -125
- package/src/agent/__tests__/apply.test.ts +224 -0
- package/src/agent/__tests__/context.test.ts +97 -98
- package/src/agent/apply.ts +1031 -0
- package/src/agent/context.ts +552 -552
- package/src/agent/index.ts +4 -3
- package/src/agent/plan.ts +161 -243
- package/src/agent/repair.ts +239 -162
- package/src/agent/sync.ts +197 -198
- package/src/agent/types.ts +242 -94
- package/src/agent/verify.ts +55 -55
- package/src/auth/__tests__/login.test.ts +1 -1
- package/src/auth/__tests__/password.test.ts +15 -5
- package/src/auth/__tests__/reset.test.ts +2 -2
- package/src/auth/__tests__/tokens.test.ts +274 -274
- package/src/auth/__tests__/verification.test.ts +274 -274
- package/src/auth/index.ts +76 -76
- package/src/auth/login.ts +225 -225
- package/src/auth/password.ts +14 -2
- package/src/auth/reset.ts +243 -243
- package/src/auth/tokens.ts +612 -612
- package/src/auth/verification.ts +253 -253
- package/src/brain/__tests__/redactor.test.ts +94 -94
- package/src/brain/adapters/__tests__/_helpers.ts +83 -83
- package/src/brain/adapters/__tests__/anthropic-oauth.test.ts +196 -196
- package/src/brain/adapters/__tests__/chatgpt-auth.test.ts +193 -193
- package/src/brain/adapters/__tests__/openai-oauth.test.ts +209 -209
- package/src/brain/adapters/__tests__/resolver.test.ts +143 -143
- package/src/brain/adapters/anthropic-oauth.ts +1 -1
- package/src/brain/adapters/chatgpt-auth.ts +300 -300
- package/src/brain/adapters/index.ts +319 -319
- package/src/brain/adapters/oauth-flow.ts +439 -439
- package/src/brain/consent.ts +240 -240
- package/src/brain/credentials.ts +396 -396
- package/src/brain/doctor/analyzer.ts +7 -7
- package/src/bundler/__snapshots__/build.test.ts.snap +5 -5
- package/src/bundler/__tests__/build-runner.ts +166 -166
- package/src/bundler/__tests__/client-boundary-transform.test.ts +524 -524
- package/src/bundler/__tests__/cold-start.test.ts +60 -60
- package/src/bundler/__tests__/css.test.ts +49 -20
- package/src/bundler/__tests__/dev-reliability.test.ts +619 -619
- package/src/bundler/__tests__/extended-watch.test.ts +711 -711
- package/src/bundler/__tests__/fast-refresh.test.ts +24 -24
- package/src/bundler/__tests__/generation.test.ts +447 -0
- package/src/bundler/__tests__/hdr.test.ts +24 -18
- package/src/bundler/__tests__/hmr-client.test.ts +62 -24
- package/src/bundler/__tests__/jsx-runtime-shim.test.ts +179 -140
- package/src/bundler/__tests__/manifest-schema.test.ts +305 -266
- package/src/bundler/__tests__/prod-smoke.test.ts +138 -138
- package/src/bundler/__tests__/reverse-import-graph.test.ts +42 -42
- package/src/bundler/__tests__/slot-dispatch.test.ts +573 -573
- package/src/bundler/__tests__/url-cap-and-slot-regex.test.ts +286 -286
- package/src/bundler/__tests__/vendor-cache.test.ts +455 -455
- package/src/bundler/analyzer.ts +15 -15
- package/src/bundler/budget.ts +404 -404
- package/src/bundler/build.test.ts +898 -915
- package/src/bundler/build.ts +113 -24
- package/src/bundler/client-boundary-transform.ts +977 -977
- package/src/bundler/css.ts +65 -44
- package/src/bundler/dev.ts +105 -73
- package/src/bundler/fast-refresh-preamble.ts +47 -47
- package/src/bundler/generation.ts +602 -0
- package/src/bundler/index.ts +3 -3
- package/src/bundler/manifest-schema.ts +55 -40
- package/src/bundler/plugins/__tests__/block-generated-imports.test.ts +13 -13
- package/src/bundler/plugins/__tests__/react-compiler-config.test.ts +83 -83
- package/src/bundler/plugins/__tests__/react-compiler-lint.test.ts +110 -110
- package/src/bundler/plugins/block-generated-imports.ts +16 -15
- package/src/bundler/plugins/index.ts +83 -83
- package/src/bundler/plugins/react-compiler-config.ts +108 -108
- package/src/bundler/plugins/react-compiler-lint.ts +253 -253
- package/src/bundler/plugins/react-compiler.ts +162 -162
- package/src/bundler/prerender.ts +29 -9
- package/src/bundler/reverse-import-graph.ts +339 -339
- package/src/bundler/safe-build.test.ts +1 -1
- package/src/bundler/safe-build.ts +103 -103
- package/src/bundler/scenario-matrix.ts +229 -229
- package/src/bundler/types.ts +58 -56
- package/src/bundler/vendor-cache-types.ts +130 -130
- package/src/bundler/vendor-cache.ts +526 -526
- package/src/change/snapshot.ts +18 -18
- package/src/client/Form.tsx +105 -105
- package/src/client/Link.tsx +9 -9
- package/src/client/__tests__/props-serialization.test.ts +37 -37
- package/src/client/__tests__/use-sse.test.ts +153 -153
- package/src/client/globals.ts +1 -1
- package/src/client/hooks.ts +362 -362
- package/src/client/hydrate.ts +2 -2
- package/src/client/index.ts +1 -1
- package/src/client/island.ts +79 -79
- package/src/client/prefetch-helper.ts +55 -55
- package/src/client/props-serialization.ts +233 -233
- package/src/client/runtime-entry.ts +598 -598
- package/src/client/runtime.ts +1 -1
- package/src/client/serialize.ts +50 -50
- package/src/client/use-fetch.ts +6 -6
- package/src/client/use-head.ts +197 -197
- package/src/client/use-sse.ts +378 -378
- package/src/client/window-state.ts +101 -101
- package/src/components/Image-compat.ts +3 -0
- package/src/components/Image.tsx +162 -162
- package/src/config/validate.ts +1 -1
- package/src/config/watcher.ts +311 -311
- package/src/constants.ts +40 -40
- package/src/content/collection.ts +9 -9
- package/src/content/content-layer.ts +7 -7
- package/src/content/data-store.ts +245 -245
- package/src/content/frontmatter.ts +189 -189
- package/src/content/generate-types.ts +1 -1
- package/src/content/index.ts +2 -2
- package/src/content/loader-context.ts +171 -171
- package/src/content/loaders/api.ts +216 -216
- package/src/content/loaders/file.ts +172 -172
- package/src/content/loaders/glob.ts +253 -253
- package/src/content/loaders/index.ts +34 -34
- package/src/content/loaders/types.ts +137 -137
- package/src/content/meta-store.ts +209 -209
- package/src/content/prebuild.test.ts +571 -571
- package/src/content/prebuild.ts +636 -636
- package/src/content/schema.ts +20 -20
- package/src/content/sidebar.ts +630 -630
- package/src/content/slug.ts +110 -110
- package/src/content/types.ts +282 -282
- package/src/content/watcher.ts +135 -135
- package/src/contract/client-safe.test.ts +42 -42
- package/src/contract/client-safe.ts +114 -114
- package/src/contract/define.ts +11 -11
- package/src/contract/index.ts +1 -1
- package/src/contract/normalize.test.ts +276 -276
- package/src/contract/normalize.ts +410 -410
- package/src/contract/registry.test.ts +206 -206
- package/src/contract/route-helpers.ts +1 -1
- package/src/contract/rpc.ts +443 -443
- package/src/contract/types.ts +58 -58
- package/src/db/__tests__/db.test.ts +9 -9
- package/src/db/index.ts +2 -2
- package/src/db/migrations/history-table.ts +345 -345
- package/src/db/migrations/index.ts +3 -3
- package/src/db/migrations/lock.ts +324 -324
- package/src/db/migrations/runner.ts +650 -650
- package/src/deploy/cache.ts +140 -140
- package/src/deploy/compile/vercel.ts +344 -344
- package/src/deploy/index.ts +87 -87
- package/src/deploy/inference/brain.ts +268 -268
- package/src/deploy/inference/context.ts +82 -82
- package/src/deploy/inference/filling-extract.ts +245 -245
- package/src/deploy/inference/heuristic.ts +182 -182
- package/src/deploy/intent.ts +173 -173
- package/src/deploy/plan.ts +178 -178
- package/src/design/__tests__/agents-link.test.ts +109 -109
- package/src/design/__tests__/extract-patch-diff.test.ts +265 -265
- package/src/design/__tests__/lint.test.ts +110 -110
- package/src/design/__tests__/parser.test.ts +195 -195
- package/src/design/__tests__/tailwind-theme.test.ts +229 -229
- package/src/design/agents-link.ts +165 -165
- package/src/design/diff.ts +138 -138
- package/src/design/extract.ts +285 -285
- package/src/design/index.ts +102 -102
- package/src/design/lint.ts +209 -209
- package/src/design/parser.ts +555 -555
- package/src/design/patch.ts +241 -241
- package/src/design/scaffold.ts +147 -147
- package/src/design/tailwind-theme.ts +441 -441
- package/src/design/types.ts +210 -210
- package/src/desktop/__tests__/smoke.test.ts +2 -2
- package/src/desktop/__tests__/webview-fallback.test.ts +12 -32
- package/src/desktop/__tests__/window.test.ts +20 -99
- package/src/desktop/__tests__/worker.test.ts +266 -266
- package/src/desktop/index.ts +43 -43
- package/src/desktop/types.ts +158 -158
- package/src/desktop/webview-fallback.ts +17 -4
- package/src/desktop/window.ts +17 -8
- package/src/desktop/worker.ts +180 -180
- package/src/dev-error-overlay/__tests__/overlay-injector.test.ts +241 -241
- package/src/dev-error-overlay/index.ts +30 -30
- package/src/dev-error-overlay/overlay-injector.ts +243 -243
- package/src/dev-error-overlay/overlay-styles.ts +52 -52
- package/src/dev-error-overlay/types.ts +66 -66
- package/src/devtools/ai/context-builder.ts +375 -375
- package/src/devtools/ai/index.ts +25 -25
- package/src/devtools/ai/mcp-connector.ts +25 -25
- package/src/devtools/client/catchers/error-catcher.ts +344 -344
- package/src/devtools/client/catchers/index.ts +18 -18
- package/src/devtools/client/components/index.ts +39 -39
- package/src/devtools/client/components/mandu-character.tsx +331 -331
- package/src/devtools/client/components/panel/errors-panel.tsx +259 -259
- package/src/devtools/client/components/panel/guard-panel.tsx +30 -30
- package/src/devtools/client/components/panel/islands-panel.tsx +16 -16
- package/src/devtools/client/components/panel/network-panel.tsx +291 -291
- package/src/devtools/client/components/panel/panel-container.tsx +1 -1
- package/src/devtools/client/components/panel/preview-panel.tsx +46 -46
- package/src/devtools/client/filters/context-filters.ts +282 -282
- package/src/devtools/client/filters/index.ts +16 -16
- package/src/devtools/client/index.ts +63 -63
- package/src/devtools/hook/create-hook.ts +207 -207
- package/src/devtools/hook/index.ts +13 -13
- package/src/devtools/index.ts +439 -439
- package/src/devtools/init.ts +265 -265
- package/src/devtools/protocol.ts +237 -237
- package/src/devtools/server/index.ts +17 -17
- package/src/devtools/types.ts +35 -35
- package/src/devtools/worker/index.ts +25 -25
- package/src/devtools/worker/redaction-worker.ts +233 -233
- package/src/diagnose/__tests__/checks.test.ts +136 -136
- package/src/diagnose/checks.ts +185 -185
- package/src/diagnose/index.ts +17 -17
- package/src/diagnose/run.ts +10 -10
- package/src/diagnose/types.ts +53 -53
- package/src/email/__tests__/email.test.ts +355 -355
- package/src/email/index.ts +282 -282
- package/src/email/smtp.ts +64 -64
- package/src/error/domains.ts +265 -265
- package/src/error/types.ts +6 -6
- package/src/errors/extractor.ts +409 -409
- package/src/errors/index.ts +19 -19
- package/src/filling/__tests__/session-sqlite.test.ts +5 -1
- package/src/filling/auth.ts +308 -308
- package/src/filling/body-parse.test.ts +60 -60
- package/src/filling/cookie-codec.ts +5 -3
- package/src/filling/deps.ts +265 -265
- package/src/filling/head-method.test.ts +154 -154
- package/src/filling/session-sqlite.ts +617 -617
- package/src/filling/sse.ts +5 -5
- package/src/filling/ws.ts +78 -78
- package/src/generator/generate.ts +30 -30
- package/src/generator/index.ts +3 -3
- package/src/generator/templates.test.ts +48 -48
- package/src/generator/templates.ts +219 -219
- package/src/guard/__tests__/design-inline-class.test.ts +219 -219
- package/src/guard/__tests__/tsgolint-bridge.test.ts +347 -347
- package/src/guard/analyzer.ts +360 -360
- package/src/guard/auto-correct.ts +1 -1
- package/src/guard/check.ts +39 -24
- package/src/guard/config-guard.ts +13 -13
- package/src/guard/contract-guard.ts +9 -9
- package/src/guard/define-rule.ts +243 -243
- package/src/guard/design-inline-class.ts +393 -393
- package/src/guard/file-type.test.ts +24 -24
- package/src/guard/fs-routes-policy.ts +51 -51
- package/src/guard/graph.ts +1 -1
- package/src/guard/healing.ts +36 -36
- package/src/guard/index.ts +11 -11
- package/src/guard/presets/atomic.ts +70 -70
- package/src/guard/presets/clean.ts +77 -77
- package/src/guard/presets/fsd.ts +79 -79
- package/src/guard/presets/hexagonal.ts +68 -68
- package/src/guard/reporter.ts +442 -442
- package/src/guard/rule-presets.ts +379 -379
- package/src/guard/semantic-slots.ts +1 -1
- package/src/guard/suggestions.ts +358 -358
- package/src/guard/tsgolint-bridge.ts +512 -512
- package/src/guard/types.ts +348 -348
- package/src/guard/watcher.ts +405 -405
- package/src/i18n/define.ts +126 -126
- package/src/i18n/index.ts +52 -52
- package/src/i18n/message-registry.ts +173 -173
- package/src/i18n/types.ts +112 -112
- package/src/id/__tests__/id.test.ts +3 -3
- package/src/id/index.ts +105 -105
- package/src/index.ts +9 -48
- package/src/internal/client-boundary.ts +266 -266
- package/src/internal/index.ts +2 -2
- package/src/kitchen/api/agent-devtools-api.ts +779 -779
- package/src/kitchen/api/bundle-inspector.ts +179 -0
- package/src/kitchen/api/errors-grouping.ts +126 -126
- package/src/kitchen/api/file-api.ts +11 -11
- package/src/kitchen/kitchen-handler.ts +36 -0
- package/src/kitchen/kitchen-ui.ts +456 -0
- package/src/logging/index.ts +22 -22
- package/src/logging/transports.ts +365 -365
- package/src/middleware/bridge.ts +147 -147
- package/src/middleware/compose.ts +134 -134
- package/src/middleware/compress.ts +62 -62
- package/src/middleware/cors.ts +47 -47
- package/src/middleware/csrf.ts +328 -328
- package/src/middleware/define.ts +132 -132
- package/src/middleware/jwt.ts +134 -134
- package/src/middleware/logger.ts +58 -58
- package/src/middleware/oauth/__tests__/oauth.test.ts +1 -1
- package/src/middleware/oauth/index.ts +505 -505
- package/src/middleware/oauth/providers.ts +115 -115
- package/src/middleware/rate-limit/index.ts +522 -522
- package/src/middleware/rate-limit/sqlite-store.ts +382 -382
- package/src/middleware/scheduler-cron.ts +96 -96
- package/src/middleware/secure/__tests__/secure.test.ts +360 -360
- package/src/middleware/secure/csp.ts +193 -193
- package/src/middleware/session.ts +174 -174
- package/src/middleware/timeout.ts +55 -55
- package/src/observability/logger-adapter.ts +36 -36
- package/src/observability/sqlite-store.ts +254 -254
- package/src/openapi/generator.ts +1 -1
- package/src/openapi/openapi.test.ts +43 -43
- package/src/perf/__tests__/user-marks.test.ts +354 -354
- package/src/perf/index.ts +133 -133
- package/src/perf/user-marks.ts +1 -1
- package/src/plugins/__tests__/lifecycle-integration.test.ts +272 -272
- package/src/plugins/__tests__/runner.test.ts +409 -409
- package/src/plugins/define.ts +124 -124
- package/src/plugins/examples/dep-check-plugin.ts +80 -80
- package/src/plugins/examples/prerender-cache-plugin.ts +111 -111
- package/src/plugins/examples/sitemap-plugin.ts +65 -65
- package/src/plugins/runner.ts +361 -361
- package/src/plugins/types.ts +368 -368
- package/src/report/index.ts +1 -1
- package/src/resource/__tests__/generator.test.ts +7 -7
- package/src/resource/__tests__/schema.test.ts +14 -14
- package/src/resource/ddl/__tests__/diff.test.ts +639 -639
- package/src/resource/ddl/__tests__/emit.test.ts +165 -165
- package/src/resource/ddl/__tests__/snapshot.test.ts +499 -499
- package/src/resource/ddl/emit.ts +146 -146
- package/src/resource/ddl/persistence-types.ts +218 -218
- package/src/resource/ddl/type-map.ts +223 -223
- package/src/resource/ddl/types.ts +232 -232
- package/src/resource/generator-repo.ts +630 -630
- package/src/resource/generator-schema.ts +11 -11
- package/src/resource/generators/slot.ts +72 -72
- package/src/resource/schema.ts +21 -21
- package/src/router/client-entry.test.ts +227 -227
- package/src/router/client-entry.ts +218 -218
- package/src/router/fs-patterns.test.ts +96 -96
- package/src/router/fs-routes.test.ts +532 -532
- package/src/router/fs-routes.ts +53 -53
- package/src/router/fs-scanner.ts +216 -216
- package/src/router/fs-types.ts +19 -19
- package/src/router/route-source-analyzer.ts +521 -521
- package/src/routes/index.ts +74 -74
- package/src/routes/metadata-routes.ts +427 -427
- package/src/routes/types.ts +341 -341
- package/src/runtime/__tests__/devtools-adapter.test.ts +68 -68
- package/src/runtime/__tests__/error-boundary-redaction.test.ts +141 -141
- package/src/runtime/__tests__/hdr-client.test.ts +223 -223
- package/src/runtime/__tests__/http-errors.test.ts +117 -117
- package/src/runtime/__tests__/inline-client-hydration.test.ts +237 -237
- package/src/runtime/__tests__/not-found.test.ts +152 -152
- package/src/runtime/__tests__/observability-lifecycle.test.ts +103 -103
- package/src/runtime/__tests__/page-render-response.test.ts +517 -517
- package/src/runtime/__tests__/request-middleware.test.ts +70 -70
- package/src/runtime/__tests__/searchparams-page-props.test.ts +81 -81
- package/src/runtime/adapter.ts +47 -47
- package/src/runtime/boundary.tsx +252 -252
- package/src/runtime/cache.ts +494 -494
- package/src/runtime/compose.ts +222 -222
- package/src/runtime/devtools-adapter.ts +68 -68
- package/src/runtime/escape.ts +34 -34
- package/src/runtime/fast-refresh-runtime.ts +322 -322
- package/src/runtime/fast-refresh-types.ts +1 -1
- package/src/runtime/handler.ts +65 -65
- package/src/runtime/handlers.ts +30 -11
- package/src/runtime/http-errors.ts +113 -113
- package/src/runtime/image-handler.ts +1 -1
- package/src/runtime/lifecycle.ts +381 -381
- package/src/runtime/logger.test.ts +345 -345
- package/src/runtime/middleware.ts +264 -264
- package/src/runtime/not-found.ts +93 -93
- package/src/runtime/observability-lifecycle.ts +290 -290
- package/src/runtime/openapi-endpoint.ts +236 -236
- package/src/runtime/page-render-response.ts +287 -274
- package/src/runtime/ppr.ts +74 -74
- package/src/runtime/rate-limit.ts +1 -1
- package/src/runtime/redirect.ts +1 -1
- package/src/runtime/registry.ts +171 -171
- package/src/runtime/request-middleware.ts +31 -31
- package/src/runtime/router.test.ts +4 -4
- package/src/runtime/router.ts +10 -10
- package/src/runtime/server.ts +127 -211
- package/src/runtime/shims.ts +48 -48
- package/src/runtime/ssr.ts +43 -17
- package/src/runtime/static-files.ts +369 -289
- package/src/runtime/streaming-ssr.ts +219 -180
- package/src/runtime/trace.ts +144 -144
- package/src/scheduler/__tests__/scheduler.test.ts +12 -11
- package/src/scheduler/index.ts +11 -5
- package/src/scheduler/validate.ts +169 -169
- package/src/seo/index.ts +219 -219
- package/src/seo/integration/ssr.ts +306 -306
- package/src/seo/render/basic.ts +435 -435
- package/src/seo/render/index.ts +143 -143
- package/src/seo/render/jsonld.ts +539 -539
- package/src/seo/render/opengraph.ts +197 -197
- package/src/seo/render/robots.ts +116 -116
- package/src/seo/render/sitemap.ts +137 -137
- package/src/seo/render/twitter.ts +127 -127
- package/src/seo/resolve/opengraph.ts +143 -143
- package/src/seo/resolve/robots.ts +73 -73
- package/src/seo/resolve/title.ts +94 -94
- package/src/seo/resolve/twitter.ts +73 -73
- package/src/seo/resolve/url.ts +104 -104
- package/src/seo/routes/index.ts +290 -290
- package/src/seo/types.ts +588 -588
- package/src/slot/validator.ts +39 -39
- package/src/spec/schema.ts +35 -35
- package/src/storage/s3/__tests__/s3.test.ts +479 -479
- package/src/storage/s3/index.ts +412 -412
- package/src/testing/__tests__/assertions.test.ts +632 -632
- package/src/testing/__tests__/reporter.test.ts +454 -454
- package/src/testing/assertions.ts +986 -986
- package/src/testing/db.ts +157 -157
- package/src/testing/index.ts +9 -3
- package/src/testing/lcov.ts +192 -0
- package/src/testing/mocks.ts +203 -203
- package/src/testing/session.ts +190 -190
- package/src/types/branded.ts +56 -56
- package/src/types/index.ts +1 -1
- package/src/utils/safe-io.ts +188 -188
- package/src/utils/string-safe.ts +298 -298
- package/src/watcher/__tests__/watcher.test.ts +59 -59
- package/src/watcher/watcher.ts +61 -61
|
@@ -1,266 +1,266 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
|
-
|
|
4
|
-
import type { BundleManifest } from "../bundler/types";
|
|
5
|
-
import { serializeProps } from "../client/serialize";
|
|
6
|
-
import { escapeJsonForInlineScript } from "../runtime/escape";
|
|
7
|
-
|
|
8
|
-
export interface ManduClientBoundaryProps {
|
|
9
|
-
routeId: string;
|
|
10
|
-
boundaryId: string;
|
|
11
|
-
module: string;
|
|
12
|
-
exportName: string;
|
|
13
|
-
props?: Record<string, unknown>;
|
|
14
|
-
hydrate?: string;
|
|
15
|
-
src?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface BoundaryRenderContext {
|
|
19
|
-
routeId?: string;
|
|
20
|
-
bundleManifest?: BundleManifest;
|
|
21
|
-
instanceCounts: Map<string, number>;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface ManduClientBoundaryRenderScope {
|
|
25
|
-
<T>(render: () => T): T;
|
|
26
|
-
wrapElement(element: React.ReactElement): React.ReactElement;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const boundaryContextStack: BoundaryRenderContext[] = [];
|
|
30
|
-
const boundaryAsyncStorage = new AsyncLocalStorage<BoundaryRenderContext>();
|
|
31
|
-
const BoundaryReactContext = React.createContext<BoundaryRenderContext | undefined>(undefined);
|
|
32
|
-
|
|
33
|
-
export function createManduClientBoundaryRenderScope(
|
|
34
|
-
routeId: string | undefined,
|
|
35
|
-
bundleManifest: BundleManifest | undefined,
|
|
36
|
-
): ManduClientBoundaryRenderScope {
|
|
37
|
-
const context: BoundaryRenderContext = { routeId, bundleManifest, instanceCounts: new Map() };
|
|
38
|
-
const scope = (<T>(render: () => T): T => runWithBoundaryContext(context, render)) as ManduClientBoundaryRenderScope;
|
|
39
|
-
scope.wrapElement = (element: React.ReactElement): React.ReactElement =>
|
|
40
|
-
React.createElement(BoundaryReactContext.Provider, { value: context }, element);
|
|
41
|
-
return scope;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function renderWithManduClientBoundaryManifest<T>(
|
|
45
|
-
routeId: string | undefined,
|
|
46
|
-
bundleManifest: BundleManifest | undefined,
|
|
47
|
-
render: () => T,
|
|
48
|
-
): T {
|
|
49
|
-
return createManduClientBoundaryRenderScope(routeId, bundleManifest)(render);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function runWithBoundaryContext<T>(
|
|
53
|
-
context: BoundaryRenderContext,
|
|
54
|
-
render: () => T,
|
|
55
|
-
): T {
|
|
56
|
-
boundaryContextStack.push(context);
|
|
57
|
-
try {
|
|
58
|
-
return boundaryAsyncStorage.run(context, render);
|
|
59
|
-
} catch (error) {
|
|
60
|
-
throw error;
|
|
61
|
-
} finally {
|
|
62
|
-
boundaryContextStack.pop();
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function __ManduClientBoundary({
|
|
67
|
-
routeId,
|
|
68
|
-
boundaryId,
|
|
69
|
-
module,
|
|
70
|
-
exportName,
|
|
71
|
-
props = {},
|
|
72
|
-
hydrate = "visible",
|
|
73
|
-
src,
|
|
74
|
-
}: ManduClientBoundaryProps): React.ReactElement {
|
|
75
|
-
const fallbackContext = getCurrentBoundaryContext();
|
|
76
|
-
return React.createElement(
|
|
77
|
-
BoundaryReactContext.Consumer,
|
|
78
|
-
{
|
|
79
|
-
children: (reactContext: BoundaryRenderContext | undefined) =>
|
|
80
|
-
renderClientBoundaryElement({
|
|
81
|
-
routeId,
|
|
82
|
-
boundaryId,
|
|
83
|
-
module,
|
|
84
|
-
exportName,
|
|
85
|
-
props,
|
|
86
|
-
hydrate,
|
|
87
|
-
src,
|
|
88
|
-
}, reactContext ?? fallbackContext),
|
|
89
|
-
},
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function renderClientBoundaryElement(
|
|
94
|
-
{
|
|
95
|
-
routeId,
|
|
96
|
-
boundaryId,
|
|
97
|
-
module,
|
|
98
|
-
exportName,
|
|
99
|
-
props = {},
|
|
100
|
-
hydrate = "visible",
|
|
101
|
-
src,
|
|
102
|
-
}: ManduClientBoundaryProps,
|
|
103
|
-
context: BoundaryRenderContext | undefined,
|
|
104
|
-
): React.ReactElement {
|
|
105
|
-
assertSerializableBoundaryProps({ routeId, boundaryId, module, exportName, props });
|
|
106
|
-
const serializedProps = serializeProps(props);
|
|
107
|
-
const priority = hydrate === "load" ? "immediate" : hydrate;
|
|
108
|
-
const resolvedSrc = src ?? resolveBoundarySrc(context, routeId, boundaryId);
|
|
109
|
-
const instanceId = nextBoundaryInstanceId(context, boundaryId);
|
|
110
|
-
|
|
111
|
-
return React.createElement(
|
|
112
|
-
React.Fragment,
|
|
113
|
-
null,
|
|
114
|
-
React.createElement("div", {
|
|
115
|
-
"data-mandu-island": instanceId,
|
|
116
|
-
"data-mandu-boundary-id": boundaryId,
|
|
117
|
-
"data-mandu-route-id": routeId,
|
|
118
|
-
"data-mandu-src": resolvedSrc,
|
|
119
|
-
"data-mandu-priority": priority,
|
|
120
|
-
"data-hydrate": hydrate,
|
|
121
|
-
"data-mandu-client-module": module,
|
|
122
|
-
"data-mandu-client-export": exportName,
|
|
123
|
-
style: { display: "contents" },
|
|
124
|
-
}),
|
|
125
|
-
React.createElement("script", {
|
|
126
|
-
type: "application/json",
|
|
127
|
-
"data-mandu-props": instanceId,
|
|
128
|
-
dangerouslySetInnerHTML: {
|
|
129
|
-
__html: escapeJsonForInlineScript(serializedProps),
|
|
130
|
-
},
|
|
131
|
-
}),
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function assertSerializableBoundaryProps({
|
|
136
|
-
routeId,
|
|
137
|
-
boundaryId,
|
|
138
|
-
module,
|
|
139
|
-
exportName,
|
|
140
|
-
props,
|
|
141
|
-
}: Required<Pick<ManduClientBoundaryProps, "routeId" | "boundaryId" | "module" | "exportName" | "props">>): void {
|
|
142
|
-
const reason = findNonSerializableBoundaryValue(props, "$", new WeakSet<object>());
|
|
143
|
-
if (!reason) return;
|
|
144
|
-
|
|
145
|
-
throw new Error(
|
|
146
|
-
`[MANDU_BOUNDARY_UNSERIALIZABLE_PROP] Client boundary props are not serializable for route "${routeId}", boundary "${boundaryId}" (${module}#${exportName}): ${reason}. ` +
|
|
147
|
-
"Pass plain serializable data, or construct functions, React elements, symbols, promises, and class instances inside the client component.",
|
|
148
|
-
);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function findNonSerializableBoundaryValue(
|
|
152
|
-
value: unknown,
|
|
153
|
-
path: string,
|
|
154
|
-
seen: WeakSet<object>,
|
|
155
|
-
): string | null {
|
|
156
|
-
if (value === null || value === undefined) return null;
|
|
157
|
-
|
|
158
|
-
const valueType = typeof value;
|
|
159
|
-
if (valueType === "string" || valueType === "number" || valueType === "boolean" || valueType === "bigint") {
|
|
160
|
-
return null;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if (valueType === "function") {
|
|
164
|
-
return `${path} is a function`;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
if (valueType === "symbol") {
|
|
168
|
-
return `${path} is a symbol`;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if (valueType !== "object") {
|
|
172
|
-
return `${path} has unsupported type "${valueType}"`;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (React.isValidElement(value)) {
|
|
176
|
-
return `${path} is a React element`;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (value instanceof Date || value instanceof URL || value instanceof RegExp || value instanceof Error) {
|
|
180
|
-
return null;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (seen.has(value)) {
|
|
184
|
-
return null;
|
|
185
|
-
}
|
|
186
|
-
seen.add(value);
|
|
187
|
-
|
|
188
|
-
if (value instanceof Promise) {
|
|
189
|
-
return `${path} is a Promise`;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (value instanceof Map) {
|
|
193
|
-
let index = 0;
|
|
194
|
-
for (const [key, entryValue] of value.entries()) {
|
|
195
|
-
const keyReason = findNonSerializableBoundaryValue(key, `${path}.<map-key:${index}>`, seen);
|
|
196
|
-
if (keyReason) return keyReason;
|
|
197
|
-
const valueReason = findNonSerializableBoundaryValue(entryValue, `${path}.<map-value:${index}>`, seen);
|
|
198
|
-
if (valueReason) return valueReason;
|
|
199
|
-
index++;
|
|
200
|
-
}
|
|
201
|
-
return null;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (value instanceof Set) {
|
|
205
|
-
let index = 0;
|
|
206
|
-
for (const entryValue of value.values()) {
|
|
207
|
-
const reason = findNonSerializableBoundaryValue(entryValue, `${path}.<set:${index}>`, seen);
|
|
208
|
-
if (reason) return reason;
|
|
209
|
-
index++;
|
|
210
|
-
}
|
|
211
|
-
return null;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
if (Array.isArray(value)) {
|
|
215
|
-
for (let index = 0; index < value.length; index++) {
|
|
216
|
-
const reason = findNonSerializableBoundaryValue(value[index], `${path}[${index}]`, seen);
|
|
217
|
-
if (reason) return reason;
|
|
218
|
-
}
|
|
219
|
-
return null;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const prototype = Object.getPrototypeOf(value);
|
|
223
|
-
if (prototype !== Object.prototype && prototype !== null) {
|
|
224
|
-
const name = prototype?.constructor?.name ?? "unknown";
|
|
225
|
-
return `${path} is a ${name} instance`;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
for (const [key, entryValue] of Object.entries(value as Record<string, unknown>)) {
|
|
229
|
-
const reason = findNonSerializableBoundaryValue(entryValue, `${path}.${key}`, seen);
|
|
230
|
-
if (reason) return reason;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
return null;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
function nextBoundaryInstanceId(context: BoundaryRenderContext | undefined, boundaryId: string): string {
|
|
237
|
-
if (!context) return boundaryId;
|
|
238
|
-
|
|
239
|
-
const count = context.instanceCounts.get(boundaryId) ?? 0;
|
|
240
|
-
context.instanceCounts.set(boundaryId, count + 1);
|
|
241
|
-
return count === 0 ? boundaryId : `${boundaryId}--${count}`;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
function resolveBoundarySrc(
|
|
245
|
-
context: BoundaryRenderContext | undefined,
|
|
246
|
-
routeId: string,
|
|
247
|
-
boundaryId: string,
|
|
248
|
-
): string | undefined {
|
|
249
|
-
const manifest = context?.bundleManifest;
|
|
250
|
-
if (!manifest) return undefined;
|
|
251
|
-
|
|
252
|
-
const boundary = manifest.boundaries?.[boundaryId];
|
|
253
|
-
if (boundary?.js) return cacheBust(boundary.js);
|
|
254
|
-
|
|
255
|
-
const effectiveRouteId = routeId || context?.routeId;
|
|
256
|
-
const routeBundle = effectiveRouteId ? manifest.bundles[effectiveRouteId] : undefined;
|
|
257
|
-
return routeBundle?.js ? cacheBust(routeBundle.js) : undefined;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
function cacheBust(src: string): string {
|
|
261
|
-
return `${src}${src.includes("?") ? "&" : "?"}t=${Date.now()}`;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
function getCurrentBoundaryContext(): BoundaryRenderContext | undefined {
|
|
265
|
-
return boundaryAsyncStorage.getStore() ?? boundaryContextStack[boundaryContextStack.length - 1];
|
|
266
|
-
}
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
|
+
|
|
4
|
+
import type { BundleManifest } from "../bundler/types";
|
|
5
|
+
import { serializeProps } from "../client/serialize";
|
|
6
|
+
import { escapeJsonForInlineScript } from "../runtime/escape";
|
|
7
|
+
|
|
8
|
+
export interface ManduClientBoundaryProps {
|
|
9
|
+
routeId: string;
|
|
10
|
+
boundaryId: string;
|
|
11
|
+
module: string;
|
|
12
|
+
exportName: string;
|
|
13
|
+
props?: Record<string, unknown>;
|
|
14
|
+
hydrate?: string;
|
|
15
|
+
src?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface BoundaryRenderContext {
|
|
19
|
+
routeId?: string;
|
|
20
|
+
bundleManifest?: BundleManifest;
|
|
21
|
+
instanceCounts: Map<string, number>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ManduClientBoundaryRenderScope {
|
|
25
|
+
<T>(render: () => T): T;
|
|
26
|
+
wrapElement(element: React.ReactElement): React.ReactElement;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const boundaryContextStack: BoundaryRenderContext[] = [];
|
|
30
|
+
const boundaryAsyncStorage = new AsyncLocalStorage<BoundaryRenderContext>();
|
|
31
|
+
const BoundaryReactContext = React.createContext<BoundaryRenderContext | undefined>(undefined);
|
|
32
|
+
|
|
33
|
+
export function createManduClientBoundaryRenderScope(
|
|
34
|
+
routeId: string | undefined,
|
|
35
|
+
bundleManifest: BundleManifest | undefined,
|
|
36
|
+
): ManduClientBoundaryRenderScope {
|
|
37
|
+
const context: BoundaryRenderContext = { routeId, bundleManifest, instanceCounts: new Map() };
|
|
38
|
+
const scope = (<T>(render: () => T): T => runWithBoundaryContext(context, render)) as ManduClientBoundaryRenderScope;
|
|
39
|
+
scope.wrapElement = (element: React.ReactElement): React.ReactElement =>
|
|
40
|
+
React.createElement(BoundaryReactContext.Provider, { value: context }, element);
|
|
41
|
+
return scope;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function renderWithManduClientBoundaryManifest<T>(
|
|
45
|
+
routeId: string | undefined,
|
|
46
|
+
bundleManifest: BundleManifest | undefined,
|
|
47
|
+
render: () => T,
|
|
48
|
+
): T {
|
|
49
|
+
return createManduClientBoundaryRenderScope(routeId, bundleManifest)(render);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function runWithBoundaryContext<T>(
|
|
53
|
+
context: BoundaryRenderContext,
|
|
54
|
+
render: () => T,
|
|
55
|
+
): T {
|
|
56
|
+
boundaryContextStack.push(context);
|
|
57
|
+
try {
|
|
58
|
+
return boundaryAsyncStorage.run(context, render);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
throw error;
|
|
61
|
+
} finally {
|
|
62
|
+
boundaryContextStack.pop();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function __ManduClientBoundary({
|
|
67
|
+
routeId,
|
|
68
|
+
boundaryId,
|
|
69
|
+
module,
|
|
70
|
+
exportName,
|
|
71
|
+
props = {},
|
|
72
|
+
hydrate = "visible",
|
|
73
|
+
src,
|
|
74
|
+
}: ManduClientBoundaryProps): React.ReactElement {
|
|
75
|
+
const fallbackContext = getCurrentBoundaryContext();
|
|
76
|
+
return React.createElement(
|
|
77
|
+
BoundaryReactContext.Consumer,
|
|
78
|
+
{
|
|
79
|
+
children: (reactContext: BoundaryRenderContext | undefined) =>
|
|
80
|
+
renderClientBoundaryElement({
|
|
81
|
+
routeId,
|
|
82
|
+
boundaryId,
|
|
83
|
+
module,
|
|
84
|
+
exportName,
|
|
85
|
+
props,
|
|
86
|
+
hydrate,
|
|
87
|
+
src,
|
|
88
|
+
}, reactContext ?? fallbackContext),
|
|
89
|
+
},
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function renderClientBoundaryElement(
|
|
94
|
+
{
|
|
95
|
+
routeId,
|
|
96
|
+
boundaryId,
|
|
97
|
+
module,
|
|
98
|
+
exportName,
|
|
99
|
+
props = {},
|
|
100
|
+
hydrate = "visible",
|
|
101
|
+
src,
|
|
102
|
+
}: ManduClientBoundaryProps,
|
|
103
|
+
context: BoundaryRenderContext | undefined,
|
|
104
|
+
): React.ReactElement {
|
|
105
|
+
assertSerializableBoundaryProps({ routeId, boundaryId, module, exportName, props });
|
|
106
|
+
const serializedProps = serializeProps(props);
|
|
107
|
+
const priority = hydrate === "load" ? "immediate" : hydrate;
|
|
108
|
+
const resolvedSrc = src ?? resolveBoundarySrc(context, routeId, boundaryId);
|
|
109
|
+
const instanceId = nextBoundaryInstanceId(context, boundaryId);
|
|
110
|
+
|
|
111
|
+
return React.createElement(
|
|
112
|
+
React.Fragment,
|
|
113
|
+
null,
|
|
114
|
+
React.createElement("div", {
|
|
115
|
+
"data-mandu-island": instanceId,
|
|
116
|
+
"data-mandu-boundary-id": boundaryId,
|
|
117
|
+
"data-mandu-route-id": routeId,
|
|
118
|
+
"data-mandu-src": resolvedSrc,
|
|
119
|
+
"data-mandu-priority": priority,
|
|
120
|
+
"data-hydrate": hydrate,
|
|
121
|
+
"data-mandu-client-module": module,
|
|
122
|
+
"data-mandu-client-export": exportName,
|
|
123
|
+
style: { display: "contents" },
|
|
124
|
+
}),
|
|
125
|
+
React.createElement("script", {
|
|
126
|
+
type: "application/json",
|
|
127
|
+
"data-mandu-props": instanceId,
|
|
128
|
+
dangerouslySetInnerHTML: {
|
|
129
|
+
__html: escapeJsonForInlineScript(serializedProps),
|
|
130
|
+
},
|
|
131
|
+
}),
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function assertSerializableBoundaryProps({
|
|
136
|
+
routeId,
|
|
137
|
+
boundaryId,
|
|
138
|
+
module,
|
|
139
|
+
exportName,
|
|
140
|
+
props,
|
|
141
|
+
}: Required<Pick<ManduClientBoundaryProps, "routeId" | "boundaryId" | "module" | "exportName" | "props">>): void {
|
|
142
|
+
const reason = findNonSerializableBoundaryValue(props, "$", new WeakSet<object>());
|
|
143
|
+
if (!reason) return;
|
|
144
|
+
|
|
145
|
+
throw new Error(
|
|
146
|
+
`[MANDU_BOUNDARY_UNSERIALIZABLE_PROP] Client boundary props are not serializable for route "${routeId}", boundary "${boundaryId}" (${module}#${exportName}): ${reason}. ` +
|
|
147
|
+
"Pass plain serializable data, or construct functions, React elements, symbols, promises, and class instances inside the client component.",
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function findNonSerializableBoundaryValue(
|
|
152
|
+
value: unknown,
|
|
153
|
+
path: string,
|
|
154
|
+
seen: WeakSet<object>,
|
|
155
|
+
): string | null {
|
|
156
|
+
if (value === null || value === undefined) return null;
|
|
157
|
+
|
|
158
|
+
const valueType = typeof value;
|
|
159
|
+
if (valueType === "string" || valueType === "number" || valueType === "boolean" || valueType === "bigint") {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (valueType === "function") {
|
|
164
|
+
return `${path} is a function`;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (valueType === "symbol") {
|
|
168
|
+
return `${path} is a symbol`;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (valueType !== "object") {
|
|
172
|
+
return `${path} has unsupported type "${valueType}"`;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (React.isValidElement(value)) {
|
|
176
|
+
return `${path} is a React element`;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (value instanceof Date || value instanceof URL || value instanceof RegExp || value instanceof Error) {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (seen.has(value)) {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
seen.add(value);
|
|
187
|
+
|
|
188
|
+
if (value instanceof Promise) {
|
|
189
|
+
return `${path} is a Promise`;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (value instanceof Map) {
|
|
193
|
+
let index = 0;
|
|
194
|
+
for (const [key, entryValue] of value.entries()) {
|
|
195
|
+
const keyReason = findNonSerializableBoundaryValue(key, `${path}.<map-key:${index}>`, seen);
|
|
196
|
+
if (keyReason) return keyReason;
|
|
197
|
+
const valueReason = findNonSerializableBoundaryValue(entryValue, `${path}.<map-value:${index}>`, seen);
|
|
198
|
+
if (valueReason) return valueReason;
|
|
199
|
+
index++;
|
|
200
|
+
}
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (value instanceof Set) {
|
|
205
|
+
let index = 0;
|
|
206
|
+
for (const entryValue of value.values()) {
|
|
207
|
+
const reason = findNonSerializableBoundaryValue(entryValue, `${path}.<set:${index}>`, seen);
|
|
208
|
+
if (reason) return reason;
|
|
209
|
+
index++;
|
|
210
|
+
}
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (Array.isArray(value)) {
|
|
215
|
+
for (let index = 0; index < value.length; index++) {
|
|
216
|
+
const reason = findNonSerializableBoundaryValue(value[index], `${path}[${index}]`, seen);
|
|
217
|
+
if (reason) return reason;
|
|
218
|
+
}
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const prototype = Object.getPrototypeOf(value);
|
|
223
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
224
|
+
const name = prototype?.constructor?.name ?? "unknown";
|
|
225
|
+
return `${path} is a ${name} instance`;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
for (const [key, entryValue] of Object.entries(value as Record<string, unknown>)) {
|
|
229
|
+
const reason = findNonSerializableBoundaryValue(entryValue, `${path}.${key}`, seen);
|
|
230
|
+
if (reason) return reason;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function nextBoundaryInstanceId(context: BoundaryRenderContext | undefined, boundaryId: string): string {
|
|
237
|
+
if (!context) return boundaryId;
|
|
238
|
+
|
|
239
|
+
const count = context.instanceCounts.get(boundaryId) ?? 0;
|
|
240
|
+
context.instanceCounts.set(boundaryId, count + 1);
|
|
241
|
+
return count === 0 ? boundaryId : `${boundaryId}--${count}`;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function resolveBoundarySrc(
|
|
245
|
+
context: BoundaryRenderContext | undefined,
|
|
246
|
+
routeId: string,
|
|
247
|
+
boundaryId: string,
|
|
248
|
+
): string | undefined {
|
|
249
|
+
const manifest = context?.bundleManifest;
|
|
250
|
+
if (!manifest) return undefined;
|
|
251
|
+
|
|
252
|
+
const boundary = manifest.boundaries?.[boundaryId];
|
|
253
|
+
if (boundary?.js) return cacheBust(boundary.js);
|
|
254
|
+
|
|
255
|
+
const effectiveRouteId = routeId || context?.routeId;
|
|
256
|
+
const routeBundle = effectiveRouteId ? manifest.bundles[effectiveRouteId] : undefined;
|
|
257
|
+
return routeBundle?.js ? cacheBust(routeBundle.js) : undefined;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function cacheBust(src: string): string {
|
|
261
|
+
return `${src}${src.includes("?") ? "&" : "?"}t=${Date.now()}`;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function getCurrentBoundaryContext(): BoundaryRenderContext | undefined {
|
|
265
|
+
return boundaryAsyncStorage.getStore() ?? boundaryContextStack[boundaryContextStack.length - 1];
|
|
266
|
+
}
|
package/src/internal/index.ts
CHANGED
|
@@ -11,8 +11,8 @@ export * as watcher from "../watcher";
|
|
|
11
11
|
export * as runtimeCache from "../runtime/cache";
|
|
12
12
|
export * as runtimeRouter from "../runtime/router";
|
|
13
13
|
export * as runtimeServer from "../runtime/server";
|
|
14
|
-
export * as runtimeFastRefreshTypes from "../runtime/fast-refresh-types";
|
|
15
|
-
export * as clientBoundary from "./client-boundary";
|
|
14
|
+
export * as runtimeFastRefreshTypes from "../runtime/fast-refresh-types";
|
|
15
|
+
export * as clientBoundary from "./client-boundary";
|
|
16
16
|
|
|
17
17
|
export * as resourceDdlDiff from "../resource/ddl/diff";
|
|
18
18
|
export * as resourceDdlEmit from "../resource/ddl/emit";
|