@mandujs/core 0.54.31 → 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 +39 -20
- 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,138 +1,138 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase 7.2 R1 Agent C (H4) — production bundle smoke tests.
|
|
3
|
-
*
|
|
4
|
-
* Confirms the Phase 7.1 audit finding L-02 regression is closed: a
|
|
5
|
-
* production build (`minify: true`, no Fast Refresh plugin) must NEVER
|
|
6
|
-
* leak the dev-only symbols that would otherwise install Fast Refresh
|
|
7
|
-
* stubs on `window` (`$RefreshReg$` / `$RefreshSig$` / `__MANDU_HMR__`)
|
|
8
|
-
* or pull in the vendor runtime (`_vendor-react-refresh`).
|
|
9
|
-
*
|
|
10
|
-
* We assert at two layers:
|
|
11
|
-
* (A) the generated output JS bundle is free of the dev symbols
|
|
12
|
-
* (B) the returned manifest has `shared.fastRefresh === undefined`
|
|
13
|
-
*
|
|
14
|
-
* Both layers matter because (A) can drift independently of (B) if a
|
|
15
|
-
* future refactor inlines a symbol name into a comment or data literal.
|
|
16
|
-
*
|
|
17
|
-
* References:
|
|
18
|
-
* docs/security/phase-7-1-audit.md §3 L-02
|
|
19
|
-
* docs/bun/phase-7-2-team-plan.md §3 Agent C H4
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
import { describe, expect, test, beforeAll, afterAll } from "bun:test";
|
|
23
|
-
import { mkdtemp, mkdir, rm, writeFile } from "fs/promises";
|
|
24
|
-
import fs from "fs/promises";
|
|
25
|
-
import { tmpdir } from "os";
|
|
26
|
-
import path from "path";
|
|
27
|
-
import { fastRefreshPlugin } from "../fast-refresh-plugin";
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Strings we treat as dev-only Fast Refresh fingerprints. Any of them
|
|
31
|
-
* appearing in a prod bundle is a leak. We keep the list small and
|
|
32
|
-
* precise so we don't false-flag legitimate unrelated code.
|
|
33
|
-
*/
|
|
34
|
-
const DEV_LEAK_FINGERPRINTS = [
|
|
35
|
-
"$RefreshReg$",
|
|
36
|
-
"$RefreshSig$",
|
|
37
|
-
"__MANDU_HMR__",
|
|
38
|
-
"_vendor-react-refresh",
|
|
39
|
-
"_fast-refresh-runtime",
|
|
40
|
-
] as const;
|
|
41
|
-
|
|
42
|
-
// Integration tests that spin up Bun.build are gated on CI flaky-matrix
|
|
43
|
-
// environments. See `fast-refresh.test.ts` for the same pattern.
|
|
44
|
-
describe.skipIf(process.env.MANDU_SKIP_BUNDLER_TESTS === "1")(
|
|
45
|
-
"prod-smoke — no Fast Refresh leak in production bundles",
|
|
46
|
-
() => {
|
|
47
|
-
let rootDir = "";
|
|
48
|
-
|
|
49
|
-
beforeAll(async () => {
|
|
50
|
-
rootDir = await mkdtemp(path.join(tmpdir(), "mandu-prod-smoke-"));
|
|
51
|
-
// Minimal island source — no JSX runtime, no imports, small AST
|
|
52
|
-
await writeFile(
|
|
53
|
-
path.join(rootDir, "counter.client.tsx"),
|
|
54
|
-
`import { useState } from 'react';
|
|
55
|
-
export default function Counter() {
|
|
56
|
-
const [count, setCount] = useState(0);
|
|
57
|
-
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
|
|
58
|
-
}
|
|
59
|
-
`,
|
|
60
|
-
"utf-8",
|
|
61
|
-
);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
afterAll(async () => {
|
|
65
|
-
if (rootDir) await rm(rootDir, { recursive: true, force: true });
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
test("[S1] production build output contains no dev-only Fast Refresh symbols", async () => {
|
|
69
|
-
// Prod path: `reactFastRefresh` off, plugin `disabled: true`,
|
|
70
|
-
// minify on. Matches the config `buildClientBundles` uses when
|
|
71
|
-
// `options.minify === true`.
|
|
72
|
-
const result = await Bun.build({
|
|
73
|
-
entrypoints: [path.join(rootDir, "counter.client.tsx")],
|
|
74
|
-
target: "browser",
|
|
75
|
-
minify: true,
|
|
76
|
-
plugins: [fastRefreshPlugin({ disabled: true })],
|
|
77
|
-
external: ["react", "react-dom", "react/jsx-dev-runtime", "react/jsx-runtime"],
|
|
78
|
-
});
|
|
79
|
-
expect(result.success).toBe(true);
|
|
80
|
-
|
|
81
|
-
const src = await result.outputs[0]!.text();
|
|
82
|
-
for (const fingerprint of DEV_LEAK_FINGERPRINTS) {
|
|
83
|
-
expect(src.includes(fingerprint)).toBe(false);
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
test("[S2] prod build with reactFastRefresh=true explicitly disabled does not emit stubs", async () => {
|
|
88
|
-
// Defense-in-depth: even if a future config accident leaves
|
|
89
|
-
// `reactFastRefresh: false` off-by-default, the disabled plugin
|
|
90
|
-
// MUST still prevent injection. We pass reactFastRefresh: false
|
|
91
|
-
// here to represent the guaranteed-prod config.
|
|
92
|
-
const result = await Bun.build({
|
|
93
|
-
entrypoints: [path.join(rootDir, "counter.client.tsx")],
|
|
94
|
-
target: "browser",
|
|
95
|
-
minify: true,
|
|
96
|
-
reactFastRefresh: false,
|
|
97
|
-
plugins: [fastRefreshPlugin({ disabled: true })],
|
|
98
|
-
external: ["react", "react-dom", "react/jsx-dev-runtime", "react/jsx-runtime"],
|
|
99
|
-
});
|
|
100
|
-
expect(result.success).toBe(true);
|
|
101
|
-
|
|
102
|
-
const src = await result.outputs[0]!.text();
|
|
103
|
-
expect(src).not.toContain("$RefreshReg$");
|
|
104
|
-
expect(src).not.toContain("$RefreshSig$");
|
|
105
|
-
expect(src).not.toContain("__MANDU_HMR__");
|
|
106
|
-
});
|
|
107
|
-
},
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
// Pure manifest-shape tests run regardless of the bundler skip flag —
|
|
111
|
-
// they don't invoke Bun.build and are safe everywhere.
|
|
112
|
-
describe("prod-smoke — manifest shape invariants (no Bun.build)", () => {
|
|
113
|
-
test("[M1] buildClientBundles prod path would omit shared.fastRefresh", async () => {
|
|
114
|
-
// We cannot easily invoke `buildClientBundles` here without a
|
|
115
|
-
// full Mandu project scaffold, so we assert the contract
|
|
116
|
-
// semantically via the static build.ts source: the `fastRefresh`
|
|
117
|
-
// field is populated only when the vendor shim result has both
|
|
118
|
-
// `reactRefreshRuntime` and `fastRefreshRuntime`. In prod mode
|
|
119
|
-
// `buildVendorShims` is called with `isDev: false` which returns
|
|
120
|
-
// empty strings for those — unwinding to `undefined` in the
|
|
121
|
-
// ternary at `build.ts:1548-1554`.
|
|
122
|
-
//
|
|
123
|
-
// This test documents the invariant textually; the bundler-level
|
|
124
|
-
// integration tests (S1/S2 above) prove the output side.
|
|
125
|
-
const buildSource = await fs.readFile(
|
|
126
|
-
path.join(
|
|
127
|
-
import.meta.dir,
|
|
128
|
-
"..",
|
|
129
|
-
"build.ts",
|
|
130
|
-
),
|
|
131
|
-
"utf-8",
|
|
132
|
-
);
|
|
133
|
-
// The precise construction MUST be guarded by runtime presence.
|
|
134
|
-
expect(buildSource).toContain("vendorResult.reactRefreshRuntime && vendorResult.fastRefreshRuntime");
|
|
135
|
-
// And MUST spread-conditionally include the field.
|
|
136
|
-
expect(buildSource).toContain("...(fastRefresh ? { fastRefresh } : {})");
|
|
137
|
-
});
|
|
138
|
-
});
|
|
1
|
+
/**
|
|
2
|
+
* Phase 7.2 R1 Agent C (H4) — production bundle smoke tests.
|
|
3
|
+
*
|
|
4
|
+
* Confirms the Phase 7.1 audit finding L-02 regression is closed: a
|
|
5
|
+
* production build (`minify: true`, no Fast Refresh plugin) must NEVER
|
|
6
|
+
* leak the dev-only symbols that would otherwise install Fast Refresh
|
|
7
|
+
* stubs on `window` (`$RefreshReg$` / `$RefreshSig$` / `__MANDU_HMR__`)
|
|
8
|
+
* or pull in the vendor runtime (`_vendor-react-refresh`).
|
|
9
|
+
*
|
|
10
|
+
* We assert at two layers:
|
|
11
|
+
* (A) the generated output JS bundle is free of the dev symbols
|
|
12
|
+
* (B) the returned manifest has `shared.fastRefresh === undefined`
|
|
13
|
+
*
|
|
14
|
+
* Both layers matter because (A) can drift independently of (B) if a
|
|
15
|
+
* future refactor inlines a symbol name into a comment or data literal.
|
|
16
|
+
*
|
|
17
|
+
* References:
|
|
18
|
+
* docs/security/phase-7-1-audit.md §3 L-02
|
|
19
|
+
* docs/bun/phase-7-2-team-plan.md §3 Agent C H4
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { describe, expect, test, beforeAll, afterAll } from "bun:test";
|
|
23
|
+
import { mkdtemp, mkdir, rm, writeFile } from "fs/promises";
|
|
24
|
+
import fs from "fs/promises";
|
|
25
|
+
import { tmpdir } from "os";
|
|
26
|
+
import path from "path";
|
|
27
|
+
import { fastRefreshPlugin } from "../fast-refresh-plugin";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Strings we treat as dev-only Fast Refresh fingerprints. Any of them
|
|
31
|
+
* appearing in a prod bundle is a leak. We keep the list small and
|
|
32
|
+
* precise so we don't false-flag legitimate unrelated code.
|
|
33
|
+
*/
|
|
34
|
+
const DEV_LEAK_FINGERPRINTS = [
|
|
35
|
+
"$RefreshReg$",
|
|
36
|
+
"$RefreshSig$",
|
|
37
|
+
"__MANDU_HMR__",
|
|
38
|
+
"_vendor-react-refresh",
|
|
39
|
+
"_fast-refresh-runtime",
|
|
40
|
+
] as const;
|
|
41
|
+
|
|
42
|
+
// Integration tests that spin up Bun.build are gated on CI flaky-matrix
|
|
43
|
+
// environments. See `fast-refresh.test.ts` for the same pattern.
|
|
44
|
+
describe.skipIf(process.env.MANDU_SKIP_BUNDLER_TESTS === "1")(
|
|
45
|
+
"prod-smoke — no Fast Refresh leak in production bundles",
|
|
46
|
+
() => {
|
|
47
|
+
let rootDir = "";
|
|
48
|
+
|
|
49
|
+
beforeAll(async () => {
|
|
50
|
+
rootDir = await mkdtemp(path.join(tmpdir(), "mandu-prod-smoke-"));
|
|
51
|
+
// Minimal island source — no JSX runtime, no imports, small AST
|
|
52
|
+
await writeFile(
|
|
53
|
+
path.join(rootDir, "counter.client.tsx"),
|
|
54
|
+
`import { useState } from 'react';
|
|
55
|
+
export default function Counter() {
|
|
56
|
+
const [count, setCount] = useState(0);
|
|
57
|
+
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
|
|
58
|
+
}
|
|
59
|
+
`,
|
|
60
|
+
"utf-8",
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
afterAll(async () => {
|
|
65
|
+
if (rootDir) await rm(rootDir, { recursive: true, force: true });
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("[S1] production build output contains no dev-only Fast Refresh symbols", async () => {
|
|
69
|
+
// Prod path: `reactFastRefresh` off, plugin `disabled: true`,
|
|
70
|
+
// minify on. Matches the config `buildClientBundles` uses when
|
|
71
|
+
// `options.minify === true`.
|
|
72
|
+
const result = await Bun.build({
|
|
73
|
+
entrypoints: [path.join(rootDir, "counter.client.tsx")],
|
|
74
|
+
target: "browser",
|
|
75
|
+
minify: true,
|
|
76
|
+
plugins: [fastRefreshPlugin({ disabled: true })],
|
|
77
|
+
external: ["react", "react-dom", "react/jsx-dev-runtime", "react/jsx-runtime"],
|
|
78
|
+
});
|
|
79
|
+
expect(result.success).toBe(true);
|
|
80
|
+
|
|
81
|
+
const src = await result.outputs[0]!.text();
|
|
82
|
+
for (const fingerprint of DEV_LEAK_FINGERPRINTS) {
|
|
83
|
+
expect(src.includes(fingerprint)).toBe(false);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("[S2] prod build with reactFastRefresh=true explicitly disabled does not emit stubs", async () => {
|
|
88
|
+
// Defense-in-depth: even if a future config accident leaves
|
|
89
|
+
// `reactFastRefresh: false` off-by-default, the disabled plugin
|
|
90
|
+
// MUST still prevent injection. We pass reactFastRefresh: false
|
|
91
|
+
// here to represent the guaranteed-prod config.
|
|
92
|
+
const result = await Bun.build({
|
|
93
|
+
entrypoints: [path.join(rootDir, "counter.client.tsx")],
|
|
94
|
+
target: "browser",
|
|
95
|
+
minify: true,
|
|
96
|
+
reactFastRefresh: false,
|
|
97
|
+
plugins: [fastRefreshPlugin({ disabled: true })],
|
|
98
|
+
external: ["react", "react-dom", "react/jsx-dev-runtime", "react/jsx-runtime"],
|
|
99
|
+
});
|
|
100
|
+
expect(result.success).toBe(true);
|
|
101
|
+
|
|
102
|
+
const src = await result.outputs[0]!.text();
|
|
103
|
+
expect(src).not.toContain("$RefreshReg$");
|
|
104
|
+
expect(src).not.toContain("$RefreshSig$");
|
|
105
|
+
expect(src).not.toContain("__MANDU_HMR__");
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
// Pure manifest-shape tests run regardless of the bundler skip flag —
|
|
111
|
+
// they don't invoke Bun.build and are safe everywhere.
|
|
112
|
+
describe("prod-smoke — manifest shape invariants (no Bun.build)", () => {
|
|
113
|
+
test("[M1] buildClientBundles prod path would omit shared.fastRefresh", async () => {
|
|
114
|
+
// We cannot easily invoke `buildClientBundles` here without a
|
|
115
|
+
// full Mandu project scaffold, so we assert the contract
|
|
116
|
+
// semantically via the static build.ts source: the `fastRefresh`
|
|
117
|
+
// field is populated only when the vendor shim result has both
|
|
118
|
+
// `reactRefreshRuntime` and `fastRefreshRuntime`. In prod mode
|
|
119
|
+
// `buildVendorShims` is called with `isDev: false` which returns
|
|
120
|
+
// empty strings for those — unwinding to `undefined` in the
|
|
121
|
+
// ternary at `build.ts:1548-1554`.
|
|
122
|
+
//
|
|
123
|
+
// This test documents the invariant textually; the bundler-level
|
|
124
|
+
// integration tests (S1/S2 above) prove the output side.
|
|
125
|
+
const buildSource = await fs.readFile(
|
|
126
|
+
path.join(
|
|
127
|
+
import.meta.dir,
|
|
128
|
+
"..",
|
|
129
|
+
"build.ts",
|
|
130
|
+
),
|
|
131
|
+
"utf-8",
|
|
132
|
+
);
|
|
133
|
+
// The precise construction MUST be guarded by runtime presence.
|
|
134
|
+
expect(buildSource).toContain("vendorResult.reactRefreshRuntime && vendorResult.fastRefreshRuntime");
|
|
135
|
+
// And MUST spread-conditionally include the field.
|
|
136
|
+
expect(buildSource).toContain("...(fastRefresh ? { fastRefresh } : {})");
|
|
137
|
+
});
|
|
138
|
+
});
|
|
@@ -343,18 +343,18 @@ describe("scanFileImports — end-to-end", () => {
|
|
|
343
343
|
*/
|
|
344
344
|
const WATCH_SETTLE_MS = 400;
|
|
345
345
|
|
|
346
|
-
function sleep(ms: number): Promise<void> {
|
|
347
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
async function waitFor(predicate: () => boolean, timeoutMs = 5_000): Promise<boolean> {
|
|
351
|
-
const deadline = Date.now() + timeoutMs;
|
|
352
|
-
while (Date.now() < deadline) {
|
|
353
|
-
if (predicate()) return true;
|
|
354
|
-
await sleep(50);
|
|
355
|
-
}
|
|
356
|
-
return predicate();
|
|
357
|
-
}
|
|
346
|
+
function sleep(ms: number): Promise<void> {
|
|
347
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
async function waitFor(predicate: () => boolean, timeoutMs = 5_000): Promise<boolean> {
|
|
351
|
+
const deadline = Date.now() + timeoutMs;
|
|
352
|
+
while (Date.now() < deadline) {
|
|
353
|
+
if (predicate()) return true;
|
|
354
|
+
await sleep(50);
|
|
355
|
+
}
|
|
356
|
+
return predicate();
|
|
357
|
+
}
|
|
358
358
|
|
|
359
359
|
function createTempProject(): string {
|
|
360
360
|
const root = mkdtempSync(path.join(tmpdir(), "mandu-189-"));
|
|
@@ -443,37 +443,37 @@ describe.skipIf(process.env.MANDU_SKIP_BUNDLER_TESTS === "1")(
|
|
|
443
443
|
onSSRChange: (filePath) => {
|
|
444
444
|
ssrCalls.push(filePath);
|
|
445
445
|
},
|
|
446
|
-
});
|
|
447
|
-
close = bundler.close;
|
|
448
|
-
await bundler.reverseGraphReady;
|
|
449
|
-
|
|
450
|
-
// The leaf change should reach onSSRChange via the
|
|
451
|
-
// barrel -> page.tsx transitive chain. The callback is
|
|
452
|
-
// invoked with the normalized absolute path of page.tsx
|
|
446
|
+
});
|
|
447
|
+
close = bundler.close;
|
|
448
|
+
await bundler.reverseGraphReady;
|
|
449
|
+
|
|
450
|
+
// The leaf change should reach onSSRChange via the
|
|
451
|
+
// barrel -> page.tsx transitive chain. The callback is
|
|
452
|
+
// invoked with the normalized absolute path of page.tsx
|
|
453
453
|
// (the SSR root that imports the barrel).
|
|
454
454
|
const normalizedPage =
|
|
455
455
|
process.platform === "win32"
|
|
456
456
|
? path
|
|
457
457
|
.resolve(rootDir, "app/page.tsx")
|
|
458
458
|
.replace(/\\/g, "/")
|
|
459
|
-
.toLowerCase()
|
|
460
|
-
: path.resolve(rootDir, "app/page.tsx").replace(/\\/g, "/");
|
|
461
|
-
|
|
462
|
-
// Deep leaf edit — NOT in any known root set, NOT in a default
|
|
463
|
-
// common dir (`app/` isn't a common dir by default). During the
|
|
464
|
-
// full suite, reverse-graph seeding and Windows watcher arming can
|
|
465
|
-
// race the first write, so retry with distinct contents until the
|
|
466
|
-
// observable SSR root dispatch appears.
|
|
467
|
-
for (let attempt = 0; attempt < 5 && !ssrCalls.includes(normalizedPage); attempt++) {
|
|
468
|
-
writeFileSync(
|
|
469
|
-
path.join(rootDir, "app/_utils/translations/ko.ts"),
|
|
470
|
-
`export const greeting = "안녕하세요-${attempt}";\n`,
|
|
471
|
-
);
|
|
472
|
-
await waitFor(() => ssrCalls.includes(normalizedPage), WATCH_SETTLE_MS);
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
expect(ssrCalls.length).toBeGreaterThanOrEqual(1);
|
|
476
|
-
// Exact path match — defensive so a future refactor that loses
|
|
459
|
+
.toLowerCase()
|
|
460
|
+
: path.resolve(rootDir, "app/page.tsx").replace(/\\/g, "/");
|
|
461
|
+
|
|
462
|
+
// Deep leaf edit — NOT in any known root set, NOT in a default
|
|
463
|
+
// common dir (`app/` isn't a common dir by default). During the
|
|
464
|
+
// full suite, reverse-graph seeding and Windows watcher arming can
|
|
465
|
+
// race the first write, so retry with distinct contents until the
|
|
466
|
+
// observable SSR root dispatch appears.
|
|
467
|
+
for (let attempt = 0; attempt < 5 && !ssrCalls.includes(normalizedPage); attempt++) {
|
|
468
|
+
writeFileSync(
|
|
469
|
+
path.join(rootDir, "app/_utils/translations/ko.ts"),
|
|
470
|
+
`export const greeting = "안녕하세요-${attempt}";\n`,
|
|
471
|
+
);
|
|
472
|
+
await waitFor(() => ssrCalls.includes(normalizedPage), WATCH_SETTLE_MS);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
expect(ssrCalls.length).toBeGreaterThanOrEqual(1);
|
|
476
|
+
// Exact path match — defensive so a future refactor that loses
|
|
477
477
|
// the normalization surfaces here, not in production.
|
|
478
478
|
expect(ssrCalls).toContain(normalizedPage);
|
|
479
479
|
});
|
|
@@ -502,11 +502,11 @@ describe.skipIf(process.env.MANDU_SKIP_BUNDLER_TESTS === "1")(
|
|
|
502
502
|
// specific-path dispatch here.
|
|
503
503
|
if (filePath !== SSR_CHANGE_WILDCARD) ssrCalls.push(filePath);
|
|
504
504
|
},
|
|
505
|
-
});
|
|
506
|
-
close = bundler.close;
|
|
507
|
-
await bundler.reverseGraphReady;
|
|
508
|
-
|
|
509
|
-
// Write a brand-new file that nothing imports. Has to live
|
|
505
|
+
});
|
|
506
|
+
close = bundler.close;
|
|
507
|
+
await bundler.reverseGraphReady;
|
|
508
|
+
|
|
509
|
+
// Write a brand-new file that nothing imports. Has to live
|
|
510
510
|
// UNDER a watched directory for the watcher to see it at all;
|
|
511
511
|
// `app/` is covered because `page.tsx` itself is there.
|
|
512
512
|
const orphan = path.join(rootDir, "app/orphan.ts");
|