@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
package/src/runtime/handler.ts
CHANGED
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mandu Fetch Handler Factory
|
|
3
|
-
* 런타임 중립적 fetch handler 생성
|
|
4
|
-
* Bun.serve, Node.js http, Cloudflare Workers 등에서 공통 사용
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { Router } from "./router";
|
|
8
|
-
import type { ServerRegistry } from "./server";
|
|
9
|
-
import type {
|
|
10
|
-
MiddlewareFn,
|
|
11
|
-
MiddlewareConfig,
|
|
12
|
-
InternalMiddlewareContext,
|
|
13
|
-
} from "./middleware";
|
|
14
|
-
import { createMiddlewareContext, getMiddlewareMatch } from "./middleware";
|
|
15
|
-
import { type CorsOptions, isCorsRequest, applyCorsToResponse } from "./cors";
|
|
16
|
-
|
|
17
|
-
export interface FetchHandlerOptions {
|
|
18
|
-
router: Router;
|
|
19
|
-
registry: ServerRegistry;
|
|
20
|
-
corsOptions: CorsOptions | false;
|
|
21
|
-
middlewareFn: MiddlewareFn | null;
|
|
22
|
-
middlewareConfig: MiddlewareConfig | null;
|
|
23
|
-
handleRequest: (req: Request, router: Router, registry: ServerRegistry) => Promise<Response>;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* 런타임 중립적 fetch handler 생성
|
|
28
|
-
* 미들웨어, CORS, 라우트 디스패치를 모두 포함
|
|
29
|
-
*/
|
|
30
|
-
export function createFetchHandler(options: FetchHandlerOptions): (req: Request) => Promise<Response> {
|
|
31
|
-
const { router, registry, corsOptions, handleRequest, middlewareFn, middlewareConfig } = options;
|
|
32
|
-
|
|
33
|
-
return async function fetchHandler(req: Request): Promise<Response> {
|
|
34
|
-
// 글로벌 미들웨어 실행 (라우트 매칭 전)
|
|
35
|
-
if (middlewareFn) {
|
|
36
|
-
const url = new URL(req.url);
|
|
37
|
-
const middlewareMatch = getMiddlewareMatch(url.pathname, middlewareConfig);
|
|
38
|
-
if (middlewareMatch.matched) {
|
|
39
|
-
const mwCtx = createMiddlewareContext(req, middlewareMatch.params);
|
|
40
|
-
try {
|
|
41
|
-
const response = await middlewareFn(mwCtx, async () => {
|
|
42
|
-
const rewrittenReq = (mwCtx as InternalMiddlewareContext).getRewrittenRequest();
|
|
43
|
-
return handleRequest(rewrittenReq ?? req, router, registry);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
if (corsOptions && isCorsRequest(req)) {
|
|
47
|
-
return applyCorsToResponse(response, req, corsOptions);
|
|
48
|
-
}
|
|
49
|
-
return response;
|
|
50
|
-
} catch (error) {
|
|
51
|
-
console.error("[Mandu Middleware] Error:", error);
|
|
52
|
-
return new Response("Internal Server Error", { status: 500 });
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const response = await handleRequest(req, router, registry);
|
|
58
|
-
|
|
59
|
-
if (corsOptions && isCorsRequest(req)) {
|
|
60
|
-
return applyCorsToResponse(response, req, corsOptions);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return response;
|
|
64
|
-
};
|
|
65
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Mandu Fetch Handler Factory
|
|
3
|
+
* 런타임 중립적 fetch handler 생성
|
|
4
|
+
* Bun.serve, Node.js http, Cloudflare Workers 등에서 공통 사용
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { Router } from "./router";
|
|
8
|
+
import type { ServerRegistry } from "./server";
|
|
9
|
+
import type {
|
|
10
|
+
MiddlewareFn,
|
|
11
|
+
MiddlewareConfig,
|
|
12
|
+
InternalMiddlewareContext,
|
|
13
|
+
} from "./middleware";
|
|
14
|
+
import { createMiddlewareContext, getMiddlewareMatch } from "./middleware";
|
|
15
|
+
import { type CorsOptions, isCorsRequest, applyCorsToResponse } from "./cors";
|
|
16
|
+
|
|
17
|
+
export interface FetchHandlerOptions {
|
|
18
|
+
router: Router;
|
|
19
|
+
registry: ServerRegistry;
|
|
20
|
+
corsOptions: CorsOptions | false;
|
|
21
|
+
middlewareFn: MiddlewareFn | null;
|
|
22
|
+
middlewareConfig: MiddlewareConfig | null;
|
|
23
|
+
handleRequest: (req: Request, router: Router, registry: ServerRegistry) => Promise<Response>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 런타임 중립적 fetch handler 생성
|
|
28
|
+
* 미들웨어, CORS, 라우트 디스패치를 모두 포함
|
|
29
|
+
*/
|
|
30
|
+
export function createFetchHandler(options: FetchHandlerOptions): (req: Request) => Promise<Response> {
|
|
31
|
+
const { router, registry, corsOptions, handleRequest, middlewareFn, middlewareConfig } = options;
|
|
32
|
+
|
|
33
|
+
return async function fetchHandler(req: Request): Promise<Response> {
|
|
34
|
+
// 글로벌 미들웨어 실행 (라우트 매칭 전)
|
|
35
|
+
if (middlewareFn) {
|
|
36
|
+
const url = new URL(req.url);
|
|
37
|
+
const middlewareMatch = getMiddlewareMatch(url.pathname, middlewareConfig);
|
|
38
|
+
if (middlewareMatch.matched) {
|
|
39
|
+
const mwCtx = createMiddlewareContext(req, middlewareMatch.params);
|
|
40
|
+
try {
|
|
41
|
+
const response = await middlewareFn(mwCtx, async () => {
|
|
42
|
+
const rewrittenReq = (mwCtx as InternalMiddlewareContext).getRewrittenRequest();
|
|
43
|
+
return handleRequest(rewrittenReq ?? req, router, registry);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (corsOptions && isCorsRequest(req)) {
|
|
47
|
+
return applyCorsToResponse(response, req, corsOptions);
|
|
48
|
+
}
|
|
49
|
+
return response;
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error("[Mandu Middleware] Error:", error);
|
|
52
|
+
return new Response("Internal Server Error", { status: 500 });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const response = await handleRequest(req, router, registry);
|
|
58
|
+
|
|
59
|
+
if (corsOptions && isCorsRequest(req)) {
|
|
60
|
+
return applyCorsToResponse(response, req, corsOptions);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return response;
|
|
64
|
+
};
|
|
65
|
+
}
|
package/src/runtime/handlers.ts
CHANGED
|
@@ -111,7 +111,7 @@ function createMethodDispatcher(module: RouteModule, routeId: string) {
|
|
|
111
111
|
};
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
export interface RegisterHandlersOptions {
|
|
114
|
+
export interface RegisterHandlersOptions {
|
|
115
115
|
/**
|
|
116
116
|
* Module import function (dev: importFresh, start: standard import).
|
|
117
117
|
* The optional `opts.changedFile` is forwarded into Phase 7.0 B5's
|
|
@@ -140,8 +140,14 @@ export interface RegisterHandlersOptions {
|
|
|
140
140
|
* invalidation). Forwarded to `importFn` so the incremental
|
|
141
141
|
* `bundledImport` can skip rebuilds for modules the file isn't part of.
|
|
142
142
|
*/
|
|
143
|
-
changedFile?: string;
|
|
144
|
-
|
|
143
|
+
changedFile?: string;
|
|
144
|
+
/**
|
|
145
|
+
* Fail registration when an API module cannot be imported or does not
|
|
146
|
+
* expose a callable handler. Production build/start paths enable this;
|
|
147
|
+
* dev keeps tolerant registration so the overlay can recover on edit.
|
|
148
|
+
*/
|
|
149
|
+
strict?: boolean;
|
|
150
|
+
}
|
|
145
151
|
|
|
146
152
|
/**
|
|
147
153
|
* Register manifest routes as server handlers.
|
|
@@ -152,7 +158,13 @@ export async function registerManifestHandlers(
|
|
|
152
158
|
rootDir: string,
|
|
153
159
|
options: RegisterHandlersOptions
|
|
154
160
|
): Promise<void> {
|
|
155
|
-
const {
|
|
161
|
+
const {
|
|
162
|
+
importFn,
|
|
163
|
+
registeredLayouts,
|
|
164
|
+
isReload = false,
|
|
165
|
+
changedFile,
|
|
166
|
+
strict = false,
|
|
167
|
+
} = options;
|
|
156
168
|
const baseImportOpts: { changedFile?: string } | undefined =
|
|
157
169
|
changedFile !== undefined ? { changedFile } : undefined;
|
|
158
170
|
const importOptsForRoute = (route?: RoutesManifest["routes"][number]) => {
|
|
@@ -220,16 +232,23 @@ export async function registerManifestHandlers(
|
|
|
220
232
|
handler = createMethodDispatcher(handler as RouteModule, route.id);
|
|
221
233
|
}
|
|
222
234
|
|
|
223
|
-
if (typeof handler !== "function") {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
235
|
+
if (typeof handler !== "function") {
|
|
236
|
+
const message = `API handler conversion failed: ${route.id} (type: ${typeof handler})`;
|
|
237
|
+
if (strict) throw new Error(message);
|
|
238
|
+
console.warn(` ⚠️ ${message}`);
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
227
241
|
|
|
228
242
|
registerApiHandler(route.id, handler as (req: Request, params?: Record<string, string>) => Response | Promise<Response>);
|
|
229
243
|
console.log(` 📡 API: ${route.pattern} -> ${route.id}`);
|
|
230
|
-
} catch (error) {
|
|
231
|
-
|
|
232
|
-
|
|
244
|
+
} catch (error) {
|
|
245
|
+
if (strict) {
|
|
246
|
+
throw new Error(`[Mandu] Failed to load API handler: ${route.id}`, {
|
|
247
|
+
cause: error,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
console.error(` ❌ Failed to load API handler: ${route.id}`, error);
|
|
251
|
+
}
|
|
233
252
|
} else if (route.kind === "page" && route.componentModule) {
|
|
234
253
|
const componentPath = path.resolve(rootDir, route.componentModule);
|
|
235
254
|
const isIsland = needsHydration(route);
|
|
@@ -1,113 +1,113 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Module-level HTTP error helpers.
|
|
3
|
-
*
|
|
4
|
-
* These are the standalone counterparts to `ctx.unauthorized()`,
|
|
5
|
-
* `ctx.forbidden()`, and `ctx.error()` on {@link ManduContext}. When a
|
|
6
|
-
* caller is inside a filling handler the ctx methods are ergonomic —
|
|
7
|
-
* they thread pending cookies through automatically. Outside the ctx
|
|
8
|
-
* (e.g. plain utilities, middleware composition, SSR loaders that
|
|
9
|
-
* prefer `return` over `ctx.json`), these module-level functions mint
|
|
10
|
-
* the same shape directly.
|
|
11
|
-
*
|
|
12
|
-
* ## Design notes
|
|
13
|
-
*
|
|
14
|
-
* - `unauthorized()` sets `WWW-Authenticate: Bearer` per RFC 7235 so
|
|
15
|
-
* browsers/proxies know a scheme. Opt out by passing a custom
|
|
16
|
-
* `WWW-Authenticate` header (or `null` via `{ headers }`).
|
|
17
|
-
* - `forbidden()` is JSON by default (same shape as `ctx.forbidden()`).
|
|
18
|
-
* - `badRequest()` accepts either a string (→ simple error body) or a
|
|
19
|
-
* `{ message, errors }` object for structured validation failures.
|
|
20
|
-
* - All three merge caller-provided headers via `new Headers(init)`
|
|
21
|
-
* semantics — later keys win, which matches Response constructor.
|
|
22
|
-
*
|
|
23
|
-
* The returned Response is plain — no brand symbol. Unlike `redirect()`
|
|
24
|
-
* / `notFound()`, these do not short-circuit the SSR pipeline; they are
|
|
25
|
-
* terminal API responses and the caller is expected to return them up.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
/** Shape of the JSON body for `badRequest()` when given an object. */
|
|
29
|
-
export interface BadRequestBody {
|
|
30
|
-
/** Human-readable message. Required. */
|
|
31
|
-
message: string;
|
|
32
|
-
/** Optional structured validation detail (e.g. per-field errors). */
|
|
33
|
-
errors?: unknown;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* 401 Unauthorized. Sets `WWW-Authenticate: Bearer` by default so clients
|
|
38
|
-
* know the expected auth scheme. To override, pass a custom header via
|
|
39
|
-
* `options.headers`:
|
|
40
|
-
*
|
|
41
|
-
* ```ts
|
|
42
|
-
* unauthorized("Token expired", { headers: { "WWW-Authenticate": 'Basic realm="app"' } });
|
|
43
|
-
* ```
|
|
44
|
-
*
|
|
45
|
-
* Body is JSON: `{ error: "Unauthorized" }` (or the provided `message`).
|
|
46
|
-
*/
|
|
47
|
-
export function unauthorized(message?: string, options: ResponseInit = {}): Response {
|
|
48
|
-
const body = JSON.stringify({ error: message ?? "Unauthorized" });
|
|
49
|
-
const headers = new Headers(options.headers);
|
|
50
|
-
if (!headers.has("WWW-Authenticate")) {
|
|
51
|
-
headers.set("WWW-Authenticate", "Bearer");
|
|
52
|
-
}
|
|
53
|
-
if (!headers.has("Content-Type")) {
|
|
54
|
-
headers.set("Content-Type", "application/json; charset=utf-8");
|
|
55
|
-
}
|
|
56
|
-
return new Response(body, {
|
|
57
|
-
status: 401,
|
|
58
|
-
statusText: options.statusText,
|
|
59
|
-
headers,
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* 403 Forbidden. JSON body: `{ error: string }`.
|
|
65
|
-
*
|
|
66
|
-
* Use this when the client is authenticated but not authorised for the
|
|
67
|
-
* resource (contrast with {@link unauthorized}, which signals a missing
|
|
68
|
-
* or invalid credential).
|
|
69
|
-
*/
|
|
70
|
-
export function forbidden(message?: string, options: ResponseInit = {}): Response {
|
|
71
|
-
const body = JSON.stringify({ error: message ?? "Forbidden" });
|
|
72
|
-
const headers = new Headers(options.headers);
|
|
73
|
-
if (!headers.has("Content-Type")) {
|
|
74
|
-
headers.set("Content-Type", "application/json; charset=utf-8");
|
|
75
|
-
}
|
|
76
|
-
return new Response(body, {
|
|
77
|
-
status: 403,
|
|
78
|
-
statusText: options.statusText,
|
|
79
|
-
headers,
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* 400 Bad Request. Accepts either a plain string or a `{ message, errors }`
|
|
85
|
-
* object. In both cases the response body is JSON.
|
|
86
|
-
*
|
|
87
|
-
* - `badRequest("invalid id")` → `{ "error": "invalid id" }`
|
|
88
|
-
* - `badRequest({ message: "validation failed", errors: { email: ["required"] } })`
|
|
89
|
-
* → `{ "error": "validation failed", "errors": { "email": ["required"] } }`
|
|
90
|
-
*
|
|
91
|
-
* The top-level key is always `error` (string), matching `ctx.error()` in
|
|
92
|
-
* `filling/context.ts`. Structured `errors` is passed through untouched —
|
|
93
|
-
* callers decide the shape (Zod flatten, per-field map, etc.).
|
|
94
|
-
*/
|
|
95
|
-
export function badRequest(
|
|
96
|
-
input: string | BadRequestBody = "Bad Request",
|
|
97
|
-
options: ResponseInit = {}
|
|
98
|
-
): Response {
|
|
99
|
-
const body =
|
|
100
|
-
typeof input === "string"
|
|
101
|
-
? { error: input }
|
|
102
|
-
: { error: input.message, ...(input.errors !== undefined ? { errors: input.errors } : {}) };
|
|
103
|
-
|
|
104
|
-
const headers = new Headers(options.headers);
|
|
105
|
-
if (!headers.has("Content-Type")) {
|
|
106
|
-
headers.set("Content-Type", "application/json; charset=utf-8");
|
|
107
|
-
}
|
|
108
|
-
return new Response(JSON.stringify(body), {
|
|
109
|
-
status: 400,
|
|
110
|
-
statusText: options.statusText,
|
|
111
|
-
headers,
|
|
112
|
-
});
|
|
113
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Module-level HTTP error helpers.
|
|
3
|
+
*
|
|
4
|
+
* These are the standalone counterparts to `ctx.unauthorized()`,
|
|
5
|
+
* `ctx.forbidden()`, and `ctx.error()` on {@link ManduContext}. When a
|
|
6
|
+
* caller is inside a filling handler the ctx methods are ergonomic —
|
|
7
|
+
* they thread pending cookies through automatically. Outside the ctx
|
|
8
|
+
* (e.g. plain utilities, middleware composition, SSR loaders that
|
|
9
|
+
* prefer `return` over `ctx.json`), these module-level functions mint
|
|
10
|
+
* the same shape directly.
|
|
11
|
+
*
|
|
12
|
+
* ## Design notes
|
|
13
|
+
*
|
|
14
|
+
* - `unauthorized()` sets `WWW-Authenticate: Bearer` per RFC 7235 so
|
|
15
|
+
* browsers/proxies know a scheme. Opt out by passing a custom
|
|
16
|
+
* `WWW-Authenticate` header (or `null` via `{ headers }`).
|
|
17
|
+
* - `forbidden()` is JSON by default (same shape as `ctx.forbidden()`).
|
|
18
|
+
* - `badRequest()` accepts either a string (→ simple error body) or a
|
|
19
|
+
* `{ message, errors }` object for structured validation failures.
|
|
20
|
+
* - All three merge caller-provided headers via `new Headers(init)`
|
|
21
|
+
* semantics — later keys win, which matches Response constructor.
|
|
22
|
+
*
|
|
23
|
+
* The returned Response is plain — no brand symbol. Unlike `redirect()`
|
|
24
|
+
* / `notFound()`, these do not short-circuit the SSR pipeline; they are
|
|
25
|
+
* terminal API responses and the caller is expected to return them up.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/** Shape of the JSON body for `badRequest()` when given an object. */
|
|
29
|
+
export interface BadRequestBody {
|
|
30
|
+
/** Human-readable message. Required. */
|
|
31
|
+
message: string;
|
|
32
|
+
/** Optional structured validation detail (e.g. per-field errors). */
|
|
33
|
+
errors?: unknown;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 401 Unauthorized. Sets `WWW-Authenticate: Bearer` by default so clients
|
|
38
|
+
* know the expected auth scheme. To override, pass a custom header via
|
|
39
|
+
* `options.headers`:
|
|
40
|
+
*
|
|
41
|
+
* ```ts
|
|
42
|
+
* unauthorized("Token expired", { headers: { "WWW-Authenticate": 'Basic realm="app"' } });
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* Body is JSON: `{ error: "Unauthorized" }` (or the provided `message`).
|
|
46
|
+
*/
|
|
47
|
+
export function unauthorized(message?: string, options: ResponseInit = {}): Response {
|
|
48
|
+
const body = JSON.stringify({ error: message ?? "Unauthorized" });
|
|
49
|
+
const headers = new Headers(options.headers);
|
|
50
|
+
if (!headers.has("WWW-Authenticate")) {
|
|
51
|
+
headers.set("WWW-Authenticate", "Bearer");
|
|
52
|
+
}
|
|
53
|
+
if (!headers.has("Content-Type")) {
|
|
54
|
+
headers.set("Content-Type", "application/json; charset=utf-8");
|
|
55
|
+
}
|
|
56
|
+
return new Response(body, {
|
|
57
|
+
status: 401,
|
|
58
|
+
statusText: options.statusText,
|
|
59
|
+
headers,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 403 Forbidden. JSON body: `{ error: string }`.
|
|
65
|
+
*
|
|
66
|
+
* Use this when the client is authenticated but not authorised for the
|
|
67
|
+
* resource (contrast with {@link unauthorized}, which signals a missing
|
|
68
|
+
* or invalid credential).
|
|
69
|
+
*/
|
|
70
|
+
export function forbidden(message?: string, options: ResponseInit = {}): Response {
|
|
71
|
+
const body = JSON.stringify({ error: message ?? "Forbidden" });
|
|
72
|
+
const headers = new Headers(options.headers);
|
|
73
|
+
if (!headers.has("Content-Type")) {
|
|
74
|
+
headers.set("Content-Type", "application/json; charset=utf-8");
|
|
75
|
+
}
|
|
76
|
+
return new Response(body, {
|
|
77
|
+
status: 403,
|
|
78
|
+
statusText: options.statusText,
|
|
79
|
+
headers,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 400 Bad Request. Accepts either a plain string or a `{ message, errors }`
|
|
85
|
+
* object. In both cases the response body is JSON.
|
|
86
|
+
*
|
|
87
|
+
* - `badRequest("invalid id")` → `{ "error": "invalid id" }`
|
|
88
|
+
* - `badRequest({ message: "validation failed", errors: { email: ["required"] } })`
|
|
89
|
+
* → `{ "error": "validation failed", "errors": { "email": ["required"] } }`
|
|
90
|
+
*
|
|
91
|
+
* The top-level key is always `error` (string), matching `ctx.error()` in
|
|
92
|
+
* `filling/context.ts`. Structured `errors` is passed through untouched —
|
|
93
|
+
* callers decide the shape (Zod flatten, per-field map, etc.).
|
|
94
|
+
*/
|
|
95
|
+
export function badRequest(
|
|
96
|
+
input: string | BadRequestBody = "Bad Request",
|
|
97
|
+
options: ResponseInit = {}
|
|
98
|
+
): Response {
|
|
99
|
+
const body =
|
|
100
|
+
typeof input === "string"
|
|
101
|
+
? { error: input }
|
|
102
|
+
: { error: input.message, ...(input.errors !== undefined ? { errors: input.errors } : {}) };
|
|
103
|
+
|
|
104
|
+
const headers = new Headers(options.headers);
|
|
105
|
+
if (!headers.has("Content-Type")) {
|
|
106
|
+
headers.set("Content-Type", "application/json; charset=utf-8");
|
|
107
|
+
}
|
|
108
|
+
return new Response(JSON.stringify(body), {
|
|
109
|
+
status: 400,
|
|
110
|
+
statusText: options.statusText,
|
|
111
|
+
headers,
|
|
112
|
+
});
|
|
113
|
+
}
|