ts-procedures 8.5.0 → 9.0.0
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 +166 -101
- package/agent_config/claude-code/.claude-plugin/plugin.json +1 -1
- package/agent_config/claude-code/agents/ts-procedures-architect.md +11 -10
- package/agent_config/claude-code/skills/ts-procedures/SKILL.md +25 -12
- package/agent_config/claude-code/skills/ts-procedures/anti-patterns.md +10 -12
- package/agent_config/claude-code/skills/ts-procedures/api-reference.md +141 -45
- package/agent_config/claude-code/skills/ts-procedures/checklist.md +7 -6
- package/agent_config/claude-code/skills/ts-procedures/patterns.md +45 -6
- package/agent_config/claude-code/skills/ts-procedures/templates/client.md +1 -1
- package/agent_config/claude-code/skills/ts-procedures/templates/hono.md +1 -1
- package/agent_config/copilot/copilot-instructions.md +50 -33
- package/agent_config/cursor/cursorrules +50 -33
- package/build/adapters/astro/astro-context.js.map +1 -0
- package/build/adapters/astro/create-handler.js.map +1 -0
- package/build/adapters/astro/index.js.map +1 -0
- package/build/{implementations/http → adapters}/astro/index.test.js +1 -1
- package/build/adapters/astro/index.test.js.map +1 -0
- package/build/adapters/astro/rewrite-request.js.map +1 -0
- package/build/adapters/hono/envelope-parity.test.js +98 -0
- package/build/adapters/hono/envelope-parity.test.js.map +1 -0
- package/build/{implementations/http → adapters}/hono/handlers/http-stream.d.ts +1 -1
- package/build/adapters/hono/handlers/http-stream.js +55 -0
- package/build/adapters/hono/handlers/http-stream.js.map +1 -0
- package/build/{implementations/http → adapters}/hono/handlers/http-stream.test.js +1 -1
- package/build/adapters/hono/handlers/http-stream.test.js.map +1 -0
- package/build/{implementations/http → adapters}/hono/handlers/http.d.ts +1 -1
- package/build/adapters/hono/handlers/http.js +50 -0
- package/build/adapters/hono/handlers/http.js.map +1 -0
- package/build/{implementations/http → adapters}/hono/handlers/http.test.js +1 -1
- package/build/adapters/hono/handlers/http.test.js.map +1 -0
- package/build/{implementations/http → adapters}/hono/handlers/rpc.d.ts +2 -2
- package/build/adapters/hono/handlers/rpc.js +23 -0
- package/build/adapters/hono/handlers/rpc.js.map +1 -0
- package/build/{implementations/http → adapters}/hono/handlers/rpc.test.js +1 -1
- package/build/adapters/hono/handlers/rpc.test.js.map +1 -0
- package/build/adapters/hono/handlers/stream.d.ts +12 -0
- package/build/adapters/hono/handlers/stream.js +89 -0
- package/build/adapters/hono/handlers/stream.js.map +1 -0
- package/build/{implementations/http → adapters}/hono/handlers/stream.test.js +3 -2
- package/build/adapters/hono/handlers/stream.test.js.map +1 -0
- package/build/{implementations/http → adapters}/hono/index.d.ts +24 -12
- package/build/{implementations/http → adapters}/hono/index.js +19 -8
- package/build/adapters/hono/index.js.map +1 -0
- package/build/{implementations/http → adapters}/hono/index.test.js +2 -4
- package/build/adapters/hono/index.test.js.map +1 -0
- package/build/{implementations/http → adapters/hono}/on-request-error.test.js +2 -2
- package/build/adapters/hono/on-request-error.test.js.map +1 -0
- package/build/adapters/hono/request.d.ts +7 -0
- package/build/adapters/hono/request.js +22 -0
- package/build/adapters/hono/request.js.map +1 -0
- package/build/{implementations/http → adapters/hono}/route-errors.test.js +4 -4
- package/build/adapters/hono/route-errors.test.js.map +1 -0
- package/build/adapters/hono/types.d.ts +55 -0
- package/build/adapters/hono/types.js +19 -0
- package/build/adapters/hono/types.js.map +1 -0
- package/build/client/freeze.test.js +39 -0
- package/build/client/freeze.test.js.map +1 -0
- package/build/client/typed-error-dispatch.test.js +2 -2
- package/build/client/typed-error-dispatch.test.js.map +1 -1
- package/build/codegen/__fixtures__/make-envelope.d.ts +1 -1
- package/build/codegen/bin/cli.d.ts +5 -0
- package/build/codegen/bin/cli.js +139 -182
- package/build/codegen/bin/cli.js.map +1 -1
- package/build/codegen/bin/cli.test.js +12 -2
- package/build/codegen/bin/cli.test.js.map +1 -1
- package/build/codegen/bin/flag-specs.d.ts +9 -0
- package/build/codegen/bin/flag-specs.js +33 -31
- package/build/codegen/bin/flag-specs.js.map +1 -1
- package/build/codegen/bin/flag-specs.test.js +14 -1
- package/build/codegen/bin/flag-specs.test.js.map +1 -1
- package/build/codegen/collect-models.d.ts +1 -1
- package/build/codegen/emit/api-route.d.ts +8 -0
- package/build/codegen/emit/api-route.js +156 -0
- package/build/codegen/emit/api-route.js.map +1 -0
- package/build/codegen/emit/context.d.ts +30 -0
- package/build/codegen/emit/context.js +2 -0
- package/build/codegen/emit/context.js.map +1 -0
- package/build/codegen/emit/declarations.d.ts +24 -0
- package/build/codegen/emit/declarations.js +48 -0
- package/build/codegen/emit/declarations.js.map +1 -0
- package/build/codegen/emit/format-types.d.ts +61 -0
- package/build/codegen/emit/format-types.js +188 -0
- package/build/codegen/emit/format-types.js.map +1 -0
- package/build/codegen/emit/http-stream-route.d.ts +7 -0
- package/build/codegen/emit/http-stream-route.js +138 -0
- package/build/codegen/emit/http-stream-route.js.map +1 -0
- package/build/codegen/emit/route-shared.d.ts +35 -0
- package/build/codegen/emit/route-shared.js +88 -0
- package/build/codegen/emit/route-shared.js.map +1 -0
- package/build/codegen/emit/rpc-route.d.ts +7 -0
- package/build/codegen/emit/rpc-route.js +37 -0
- package/build/codegen/emit/rpc-route.js.map +1 -0
- package/build/codegen/emit/scope-file.d.ts +39 -0
- package/build/codegen/emit/scope-file.js +166 -0
- package/build/codegen/emit/scope-file.js.map +1 -0
- package/build/codegen/emit/stream-route.d.ts +7 -0
- package/build/codegen/emit/stream-route.js +62 -0
- package/build/codegen/emit/stream-route.js.map +1 -0
- package/build/codegen/emit-errors.d.ts +1 -1
- package/build/codegen/emit-errors.integration.test.js +1 -1
- package/build/codegen/emit-errors.integration.test.js.map +1 -1
- package/build/codegen/emit-index.js +13 -0
- package/build/codegen/emit-index.js.map +1 -1
- package/build/codegen/emit-index.test.js +25 -0
- package/build/codegen/emit-index.test.js.map +1 -1
- package/build/codegen/emit-scope.d.ts +13 -30
- package/build/codegen/emit-scope.js +15 -807
- package/build/codegen/emit-scope.js.map +1 -1
- package/build/codegen/emit-scope.test.js +86 -4
- package/build/codegen/emit-scope.test.js.map +1 -1
- package/build/codegen/goldens.test.js +69 -0
- package/build/codegen/goldens.test.js.map +1 -0
- package/build/codegen/group-routes.d.ts +1 -1
- package/build/codegen/pipeline.d.ts +1 -1
- package/build/codegen/resolve-envelope.d.ts +1 -1
- package/build/codegen/targets/_shared/error-schemas.d.ts +1 -1
- package/build/codegen/targets/_shared/route-slots.d.ts +1 -1
- package/build/codegen/targets/_shared/target-run.d.ts +1 -1
- package/build/codegen/targets/kotlin/emit-route-kotlin.d.ts +1 -1
- package/build/codegen/targets/swift/emit-route-swift.d.ts +1 -1
- package/build/core/create-http-stream.d.ts +50 -0
- package/build/core/create-http-stream.js +108 -0
- package/build/core/create-http-stream.js.map +1 -0
- package/build/{create-http-stream.test.js → core/create-http-stream.test.js} +1 -1
- package/build/core/create-http-stream.test.js.map +1 -0
- package/build/core/create-http.d.ts +51 -0
- package/build/core/create-http.js +65 -0
- package/build/core/create-http.js.map +1 -0
- package/build/{create-http.test.js → core/create-http.test.js} +13 -4
- package/build/core/create-http.test.js.map +1 -0
- package/build/core/create-stream.d.ts +26 -0
- package/build/core/create-stream.js +80 -0
- package/build/core/create-stream.js.map +1 -0
- package/build/{create-stream.test.js → core/create-stream.test.js} +23 -28
- package/build/core/create-stream.test.js.map +1 -0
- package/build/core/create.d.ts +22 -0
- package/build/core/create.js +71 -0
- package/build/core/create.js.map +1 -0
- package/build/{create.test.js → core/create.test.js} +25 -46
- package/build/core/create.test.js.map +1 -0
- package/build/core/definition-site.d.ts +24 -0
- package/build/{stack-utils.js → core/definition-site.js} +20 -20
- package/build/core/definition-site.js.map +1 -0
- package/build/{stack-utils.test.js → core/definition-site.test.js} +12 -3
- package/build/core/definition-site.test.js.map +1 -0
- package/build/{errors.d.ts → core/errors.d.ts} +19 -8
- package/build/{errors.js → core/errors.js} +21 -26
- package/build/core/errors.js.map +1 -0
- package/build/core/errors.test.js.map +1 -0
- package/build/core/factory-options.test.js +82 -0
- package/build/core/factory-options.test.js.map +1 -0
- package/build/core/http-route.d.ts +13 -0
- package/build/core/http-route.js +54 -0
- package/build/core/http-route.js.map +1 -0
- package/build/core/internal.d.ts +72 -0
- package/build/core/internal.js +128 -0
- package/build/core/internal.js.map +1 -0
- package/build/{migration.test.js → core/migration.test.js} +17 -1
- package/build/core/migration.test.js.map +1 -0
- package/build/core/procedures.d.ts +143 -0
- package/build/core/procedures.js +64 -0
- package/build/core/procedures.js.map +1 -0
- package/build/{index.test.js → core/procedures.test.js} +14 -11
- package/build/core/procedures.test.js.map +1 -0
- package/build/core/types.d.ts +182 -0
- package/build/{schema → core}/types.js.map +1 -1
- package/build/exports.d.ts +31 -11
- package/build/exports.js +23 -8
- package/build/exports.js.map +1 -1
- package/build/schema/adapter.d.ts +35 -0
- package/build/schema/adapter.js +13 -0
- package/build/schema/adapter.js.map +1 -0
- package/build/schema/adapter.test.js +53 -0
- package/build/schema/adapter.test.js.map +1 -0
- package/build/schema/compile.d.ts +37 -0
- package/build/schema/compile.js +38 -0
- package/build/schema/compile.js.map +1 -0
- package/build/schema/compile.test.js +78 -0
- package/build/schema/compile.test.js.map +1 -0
- package/build/schema/compute-schema.d.ts +47 -37
- package/build/schema/compute-schema.js +86 -29
- package/build/schema/compute-schema.js.map +1 -1
- package/build/schema/compute-schema.test.js +158 -40
- package/build/schema/compute-schema.test.js.map +1 -1
- package/build/schema/json-schema.d.ts +17 -0
- package/build/schema/json-schema.js +2 -0
- package/build/schema/json-schema.js.map +1 -0
- package/build/schema/typebox.d.ts +11 -0
- package/build/schema/typebox.js +24 -0
- package/build/schema/typebox.js.map +1 -0
- package/build/schema/typebox.test.js +34 -0
- package/build/schema/typebox.test.js.map +1 -0
- package/build/server/context.d.ts +8 -0
- package/build/server/context.js +7 -0
- package/build/server/context.js.map +1 -0
- package/build/server/context.test.js +16 -0
- package/build/server/context.test.js.map +1 -0
- package/build/{doc-envelope.d.ts → server/doc-envelope.d.ts} +1 -1
- package/build/server/doc-envelope.js.map +1 -0
- package/build/server/doc-envelope.test.d.ts +1 -0
- package/build/server/doc-envelope.test.js.map +1 -0
- package/build/{implementations/http → server}/doc-registry.d.ts +7 -2
- package/build/{implementations/http → server}/doc-registry.js +9 -5
- package/build/server/doc-registry.js.map +1 -0
- package/build/server/doc-registry.test.d.ts +1 -0
- package/build/{implementations/http → server}/doc-registry.test.js +27 -24
- package/build/server/doc-registry.test.js.map +1 -0
- package/build/server/docs/docs.test.d.ts +1 -0
- package/build/server/docs/docs.test.js +237 -0
- package/build/server/docs/docs.test.js.map +1 -0
- package/build/{implementations/http/hono → server}/docs/http-doc.d.ts +2 -2
- package/build/{implementations/http/hono → server}/docs/http-doc.js +1 -1
- package/build/server/docs/http-doc.js.map +1 -0
- package/build/{implementations/http/hono → server}/docs/http-stream-doc.d.ts +2 -2
- package/build/{implementations/http/hono → server}/docs/http-stream-doc.js +1 -1
- package/build/server/docs/http-stream-doc.js.map +1 -0
- package/build/{implementations/http/hono → server}/docs/rpc-doc.d.ts +2 -2
- package/build/{implementations/http/hono → server}/docs/rpc-doc.js +1 -1
- package/build/server/docs/rpc-doc.js.map +1 -0
- package/build/{implementations/http/hono → server}/docs/stream-doc.d.ts +2 -2
- package/build/{implementations/http/hono → server}/docs/stream-doc.js +1 -1
- package/build/server/docs/stream-doc.js.map +1 -0
- package/build/server/errors/dispatch.d.ts +96 -0
- package/build/{implementations/http/error-dispatch.js → server/errors/dispatch.js} +20 -10
- package/build/server/errors/dispatch.js.map +1 -0
- package/build/server/errors/dispatch.test.d.ts +1 -0
- package/build/server/errors/dispatch.test.js +418 -0
- package/build/server/errors/dispatch.test.js.map +1 -0
- package/build/{implementations/http/error-taxonomy.d.ts → server/errors/taxonomy.d.ts} +8 -17
- package/build/{implementations/http/error-taxonomy.js → server/errors/taxonomy.js} +6 -15
- package/build/server/errors/taxonomy.js.map +1 -0
- package/build/server/errors/taxonomy.test.d.ts +1 -0
- package/build/{implementations/http/error-taxonomy.test.js → server/errors/taxonomy.test.js} +45 -39
- package/build/server/errors/taxonomy.test.js.map +1 -0
- package/build/server/index.d.ts +29 -0
- package/build/server/index.js +27 -0
- package/build/server/index.js.map +1 -0
- package/build/server/no-framework-imports.test.d.ts +1 -0
- package/build/server/no-framework-imports.test.js +40 -0
- package/build/server/no-framework-imports.test.js.map +1 -0
- package/build/{implementations/http/hono/path.d.ts → server/paths.d.ts} +2 -3
- package/build/{implementations/http/hono/path.js → server/paths.js} +1 -1
- package/build/server/paths.js.map +1 -0
- package/build/server/paths.test.d.ts +1 -0
- package/build/server/paths.test.js +111 -0
- package/build/server/paths.test.js.map +1 -0
- package/build/server/request/params.d.ts +29 -0
- package/build/server/request/params.js +43 -0
- package/build/server/request/params.js.map +1 -0
- package/build/server/request/params.test.d.ts +1 -0
- package/build/server/request/params.test.js +91 -0
- package/build/server/request/params.test.js.map +1 -0
- package/build/server/request/query.d.ts +9 -0
- package/build/server/request/query.js +22 -0
- package/build/server/request/query.js.map +1 -0
- package/build/server/request/query.test.d.ts +1 -0
- package/build/server/request/query.test.js +60 -0
- package/build/server/request/query.test.js.map +1 -0
- package/build/server/sse.d.ts +70 -0
- package/build/server/sse.js +94 -0
- package/build/server/sse.js.map +1 -0
- package/build/server/sse.test.d.ts +1 -0
- package/build/server/sse.test.js +98 -0
- package/build/server/sse.test.js.map +1 -0
- package/build/{implementations → server}/types.d.ts +17 -15
- package/build/{implementations → server}/types.js.map +1 -1
- package/docs/astro-adapter.md +8 -9
- package/docs/client-and-codegen.md +4 -4
- package/docs/client-error-handling.md +92 -5
- package/docs/codegen-kotlin.md +2 -3
- package/docs/codegen-swift.md +1 -2
- package/docs/core.md +135 -54
- package/docs/http-integrations.md +83 -6
- package/docs/migration-v8-to-v9.md +192 -0
- package/docs/plans/2026-06-09-v9-rewrite.md +130 -0
- package/docs/specs/2026-06-09-v9-rewrite-design.md +221 -0
- package/docs/streaming.md +12 -0
- package/package.json +23 -47
- package/src/{implementations/http → adapters}/astro/index.test.ts +2 -2
- package/src/adapters/hono/__fixtures__/parity-envelope.json +389 -0
- package/src/adapters/hono/envelope-parity.test.ts +126 -0
- package/src/{implementations/http → adapters}/hono/handlers/http-stream.test.ts +1 -1
- package/src/adapters/hono/handlers/http-stream.ts +73 -0
- package/src/{implementations/http → adapters}/hono/handlers/http.test.ts +1 -1
- package/src/adapters/hono/handlers/http.ts +70 -0
- package/src/{implementations/http → adapters}/hono/handlers/rpc.test.ts +2 -2
- package/src/adapters/hono/handlers/rpc.ts +39 -0
- package/src/{implementations/http → adapters}/hono/handlers/stream.test.ts +4 -3
- package/src/{implementations/http → adapters}/hono/handlers/stream.ts +19 -92
- package/src/{implementations/http → adapters}/hono/index.test.ts +14 -16
- package/src/{implementations/http → adapters}/hono/index.ts +35 -30
- package/src/{implementations/http → adapters/hono}/on-request-error.test.ts +3 -3
- package/src/adapters/hono/request.ts +28 -0
- package/src/{implementations/http → adapters/hono}/route-errors.test.ts +5 -5
- package/src/{implementations/http → adapters}/hono/types.ts +43 -20
- package/src/client/freeze.test.ts +41 -0
- package/src/client/typed-error-dispatch.test.ts +3 -3
- package/src/codegen/__fixtures__/make-envelope.ts +1 -1
- package/src/codegen/__fixtures__/models-envelope.json +310 -0
- package/src/codegen/__fixtures__/users-envelope.json +9 -0
- package/src/codegen/__goldens__/MANIFEST.json +85 -0
- package/src/codegen/__goldens__/kotlin-default--models/Billing.kt +112 -0
- package/src/codegen/__goldens__/kotlin-default--models/BillingReports.kt +26 -0
- package/src/codegen/__goldens__/kotlin-default--models/Orders.kt +88 -0
- package/src/codegen/__goldens__/kotlin-default--users/Users.kt +189 -0
- package/src/codegen/__goldens__/swift-default--models/Billing.swift +97 -0
- package/src/codegen/__goldens__/swift-default--models/BillingReports.swift +20 -0
- package/src/codegen/__goldens__/swift-default--models/Orders.swift +81 -0
- package/src/codegen/__goldens__/swift-default--users/Users.swift +204 -0
- package/src/codegen/__goldens__/ts-default--models/_client.ts +1319 -0
- package/src/codegen/__goldens__/ts-default--models/_errors.ts +90 -0
- package/src/codegen/__goldens__/ts-default--models/_models.ts +10 -0
- package/src/codegen/__goldens__/ts-default--models/_types.ts +502 -0
- package/src/codegen/__goldens__/ts-default--models/billing-reports.ts +29 -0
- package/src/codegen/__goldens__/ts-default--models/billing.ts +67 -0
- package/src/codegen/__goldens__/ts-default--models/index.ts +48 -0
- package/src/codegen/__goldens__/ts-default--models/orders.ts +80 -0
- package/src/codegen/__goldens__/ts-default--users/_client.ts +1319 -0
- package/src/codegen/__goldens__/ts-default--users/_errors.ts +90 -0
- package/src/codegen/__goldens__/ts-default--users/_types.ts +502 -0
- package/src/codegen/__goldens__/ts-default--users/index.ts +38 -0
- package/src/codegen/__goldens__/ts-default--users/users.ts +169 -0
- package/src/codegen/__goldens__/ts-external-runtime--models/_errors.ts +90 -0
- package/src/codegen/__goldens__/ts-external-runtime--models/_models.ts +10 -0
- package/src/codegen/__goldens__/ts-external-runtime--models/billing-reports.ts +29 -0
- package/src/codegen/__goldens__/ts-external-runtime--models/billing.ts +67 -0
- package/src/codegen/__goldens__/ts-external-runtime--models/index.ts +48 -0
- package/src/codegen/__goldens__/ts-external-runtime--models/orders.ts +80 -0
- package/src/codegen/__goldens__/ts-external-runtime--users/_errors.ts +90 -0
- package/src/codegen/__goldens__/ts-external-runtime--users/index.ts +38 -0
- package/src/codegen/__goldens__/ts-external-runtime--users/users.ts +169 -0
- package/src/codegen/__goldens__/ts-flat--models/_client.ts +1319 -0
- package/src/codegen/__goldens__/ts-flat--models/_errors.ts +87 -0
- package/src/codegen/__goldens__/ts-flat--models/_models.ts +10 -0
- package/src/codegen/__goldens__/ts-flat--models/_types.ts +502 -0
- package/src/codegen/__goldens__/ts-flat--models/billing-reports.ts +28 -0
- package/src/codegen/__goldens__/ts-flat--models/billing.ts +51 -0
- package/src/codegen/__goldens__/ts-flat--models/index.ts +42 -0
- package/src/codegen/__goldens__/ts-flat--models/orders.ts +73 -0
- package/src/codegen/__goldens__/ts-flat--users/_client.ts +1319 -0
- package/src/codegen/__goldens__/ts-flat--users/_errors.ts +87 -0
- package/src/codegen/__goldens__/ts-flat--users/_types.ts +502 -0
- package/src/codegen/__goldens__/ts-flat--users/index.ts +34 -0
- package/src/codegen/__goldens__/ts-flat--users/users.ts +126 -0
- package/src/codegen/__goldens__/ts-no-share-models--models/_client.ts +1319 -0
- package/src/codegen/__goldens__/ts-no-share-models--models/_errors.ts +90 -0
- package/src/codegen/__goldens__/ts-no-share-models--models/_types.ts +502 -0
- package/src/codegen/__goldens__/ts-no-share-models--models/billing-reports.ts +29 -0
- package/src/codegen/__goldens__/ts-no-share-models--models/billing.ts +111 -0
- package/src/codegen/__goldens__/ts-no-share-models--models/index.ts +48 -0
- package/src/codegen/__goldens__/ts-no-share-models--models/orders.ts +112 -0
- package/src/codegen/__goldens__/ts-no-share-models--users/_client.ts +1319 -0
- package/src/codegen/__goldens__/ts-no-share-models--users/_errors.ts +90 -0
- package/src/codegen/__goldens__/ts-no-share-models--users/_types.ts +502 -0
- package/src/codegen/__goldens__/ts-no-share-models--users/index.ts +38 -0
- package/src/codegen/__goldens__/ts-no-share-models--users/users.ts +169 -0
- package/src/codegen/__goldens__/ts-shared-models-module--models/_client.ts +1319 -0
- package/src/codegen/__goldens__/ts-shared-models-module--models/_errors.ts +90 -0
- package/src/codegen/__goldens__/ts-shared-models-module--models/_models.ts +7 -0
- package/src/codegen/__goldens__/ts-shared-models-module--models/_types.ts +502 -0
- package/src/codegen/__goldens__/ts-shared-models-module--models/billing-reports.ts +29 -0
- package/src/codegen/__goldens__/ts-shared-models-module--models/billing.ts +67 -0
- package/src/codegen/__goldens__/ts-shared-models-module--models/index.ts +48 -0
- package/src/codegen/__goldens__/ts-shared-models-module--models/orders.ts +80 -0
- package/src/codegen/bin/cli.test.ts +13 -2
- package/src/codegen/bin/cli.ts +181 -144
- package/src/codegen/bin/flag-specs.test.ts +16 -1
- package/src/codegen/bin/flag-specs.ts +43 -31
- package/src/codegen/bundle-size.test.ts +1 -1
- package/src/codegen/collect-models.ts +1 -1
- package/src/codegen/e2e.test.ts +1 -1
- package/src/codegen/emit/api-route.ts +184 -0
- package/src/codegen/emit/context.ts +32 -0
- package/src/codegen/emit/declarations.ts +49 -0
- package/src/codegen/emit/format-types.ts +232 -0
- package/src/codegen/emit/http-stream-route.ts +162 -0
- package/src/codegen/emit/route-shared.ts +102 -0
- package/src/codegen/emit/rpc-route.ts +49 -0
- package/src/codegen/emit/scope-file.ts +226 -0
- package/src/codegen/emit/stream-route.ts +81 -0
- package/src/codegen/emit-errors.integration.test.ts +2 -2
- package/src/codegen/emit-errors.test.ts +1 -1
- package/src/codegen/emit-errors.ts +1 -1
- package/src/codegen/emit-index.test.ts +34 -0
- package/src/codegen/emit-index.ts +19 -0
- package/src/codegen/emit-scope.test.ts +96 -6
- package/src/codegen/emit-scope.ts +15 -1003
- package/src/codegen/goldens.test.ts +89 -0
- package/src/codegen/group-routes.test.ts +1 -1
- package/src/codegen/group-routes.ts +1 -1
- package/src/codegen/pipeline.test.ts +1 -1
- package/src/codegen/pipeline.ts +1 -1
- package/src/codegen/resolve-envelope.test.ts +1 -1
- package/src/codegen/resolve-envelope.ts +1 -1
- package/src/codegen/targets/_shared/error-schemas.test.ts +1 -1
- package/src/codegen/targets/_shared/error-schemas.ts +1 -1
- package/src/codegen/targets/_shared/route-slots.test.ts +1 -1
- package/src/codegen/targets/_shared/route-slots.ts +1 -1
- package/src/codegen/targets/_shared/target-run.ts +1 -1
- package/src/codegen/targets/kotlin/__fixtures__/users-golden.kt +6 -0
- package/src/codegen/targets/kotlin/emit-route-kotlin.test.ts +1 -1
- package/src/codegen/targets/kotlin/emit-route-kotlin.ts +1 -1
- package/src/codegen/targets/kotlin/emit-scope-kotlin.test.ts +1 -1
- package/src/codegen/targets/swift/__fixtures__/users-golden.swift +6 -0
- package/src/codegen/targets/swift/access-level.test.ts +1 -1
- package/src/codegen/targets/swift/emit-route-swift.test.ts +1 -1
- package/src/codegen/targets/swift/emit-route-swift.ts +1 -1
- package/src/codegen/targets/swift/emit-scope-swift.test.ts +1 -1
- package/src/codegen/targets/ts/shared-models.test.ts +1 -1
- package/src/{create-http-stream.test.ts → core/create-http-stream.test.ts} +1 -1
- package/src/core/create-http-stream.ts +207 -0
- package/src/{create-http.test.ts → core/create-http.test.ts} +15 -4
- package/src/core/create-http.ts +126 -0
- package/src/{create-stream.test.ts → core/create-stream.test.ts} +28 -31
- package/src/core/create-stream.ts +142 -0
- package/src/{create.test.ts → core/create.test.ts} +25 -57
- package/src/core/create.ts +121 -0
- package/src/{stack-utils.test.ts → core/definition-site.test.ts} +14 -3
- package/src/{stack-utils.ts → core/definition-site.ts} +20 -23
- package/src/{errors.test.ts → core/errors.test.ts} +1 -1
- package/src/{errors.ts → core/errors.ts} +30 -28
- package/src/core/factory-options.test.ts +112 -0
- package/src/core/http-route.ts +73 -0
- package/src/core/internal.ts +203 -0
- package/src/{migration.test.ts → core/migration.test.ts} +23 -1
- package/src/{index.test.ts → core/procedures.test.ts} +13 -11
- package/src/core/procedures.ts +75 -0
- package/src/core/types.ts +195 -0
- package/src/exports.ts +60 -11
- package/src/schema/adapter.test.ts +58 -0
- package/src/schema/adapter.ts +45 -0
- package/src/schema/compile.test.ts +95 -0
- package/src/schema/compile.ts +64 -0
- package/src/schema/compute-schema.test.ts +222 -41
- package/src/schema/compute-schema.ts +145 -71
- package/src/schema/json-schema.ts +21 -0
- package/src/schema/typebox.test.ts +40 -0
- package/src/schema/typebox.ts +27 -0
- package/src/server/context.test.ts +22 -0
- package/src/server/context.ts +18 -0
- package/src/{doc-envelope.test.ts → server/doc-envelope.test.ts} +2 -2
- package/src/{doc-envelope.ts → server/doc-envelope.ts} +1 -1
- package/src/{implementations/http → server}/doc-registry.test.ts +32 -26
- package/src/{implementations/http → server}/doc-registry.ts +11 -7
- package/src/server/docs/docs.test.ts +287 -0
- package/src/{implementations/http/hono → server}/docs/http-doc.ts +3 -3
- package/src/{implementations/http/hono → server}/docs/http-stream-doc.ts +3 -3
- package/src/{implementations/http/hono → server}/docs/rpc-doc.ts +3 -3
- package/src/{implementations/http/hono → server}/docs/stream-doc.ts +3 -3
- package/src/server/errors/dispatch.test.ts +450 -0
- package/src/server/errors/dispatch.ts +189 -0
- package/src/{implementations/http/error-taxonomy.test.ts → server/errors/taxonomy.test.ts} +45 -39
- package/src/{implementations/http/error-taxonomy.ts → server/errors/taxonomy.ts} +8 -17
- package/src/server/index.ts +29 -0
- package/src/server/no-framework-imports.test.ts +43 -0
- package/src/server/paths.test.ts +141 -0
- package/src/{implementations/http/hono/path.ts → server/paths.ts} +2 -13
- package/src/server/request/params.test.ts +143 -0
- package/src/server/request/params.ts +68 -0
- package/src/server/request/query.test.ts +70 -0
- package/src/server/request/query.ts +24 -0
- package/src/server/sse.test.ts +113 -0
- package/src/server/sse.ts +117 -0
- package/src/{implementations → server}/types.ts +17 -16
- package/build/create-http-stream.d.ts +0 -58
- package/build/create-http-stream.js +0 -122
- package/build/create-http-stream.js.map +0 -1
- package/build/create-http-stream.test.js.map +0 -1
- package/build/create-http.d.ts +0 -49
- package/build/create-http.js +0 -108
- package/build/create-http.js.map +0 -1
- package/build/create-http.test.js.map +0 -1
- package/build/create-stream.d.ts +0 -35
- package/build/create-stream.js +0 -123
- package/build/create-stream.js.map +0 -1
- package/build/create-stream.test.js.map +0 -1
- package/build/create.d.ts +0 -28
- package/build/create.js +0 -82
- package/build/create.js.map +0 -1
- package/build/create.test.js.map +0 -1
- package/build/doc-envelope.js.map +0 -1
- package/build/doc-envelope.test.js.map +0 -1
- package/build/errors.js.map +0 -1
- package/build/errors.test.js.map +0 -1
- package/build/implementations/http/astro/astro-context.js.map +0 -1
- package/build/implementations/http/astro/create-handler.js.map +0 -1
- package/build/implementations/http/astro/index.js.map +0 -1
- package/build/implementations/http/astro/index.test.js.map +0 -1
- package/build/implementations/http/astro/rewrite-request.js.map +0 -1
- package/build/implementations/http/doc-registry.js.map +0 -1
- package/build/implementations/http/doc-registry.test.js.map +0 -1
- package/build/implementations/http/error-dispatch.d.ts +0 -76
- package/build/implementations/http/error-dispatch.js.map +0 -1
- package/build/implementations/http/error-dispatch.test.js +0 -254
- package/build/implementations/http/error-dispatch.test.js.map +0 -1
- package/build/implementations/http/error-taxonomy.js.map +0 -1
- package/build/implementations/http/error-taxonomy.test.js.map +0 -1
- package/build/implementations/http/hono/docs/http-doc.js.map +0 -1
- package/build/implementations/http/hono/docs/http-stream-doc.js.map +0 -1
- package/build/implementations/http/hono/docs/rpc-doc.js.map +0 -1
- package/build/implementations/http/hono/docs/stream-doc.js.map +0 -1
- package/build/implementations/http/hono/handlers/http-stream.js +0 -123
- package/build/implementations/http/hono/handlers/http-stream.js.map +0 -1
- package/build/implementations/http/hono/handlers/http-stream.test.js.map +0 -1
- package/build/implementations/http/hono/handlers/http.js +0 -110
- package/build/implementations/http/hono/handlers/http.js.map +0 -1
- package/build/implementations/http/hono/handlers/http.test.js.map +0 -1
- package/build/implementations/http/hono/handlers/rpc.js +0 -32
- package/build/implementations/http/hono/handlers/rpc.js.map +0 -1
- package/build/implementations/http/hono/handlers/rpc.test.js.map +0 -1
- package/build/implementations/http/hono/handlers/stream.d.ts +0 -23
- package/build/implementations/http/hono/handlers/stream.js +0 -147
- package/build/implementations/http/hono/handlers/stream.js.map +0 -1
- package/build/implementations/http/hono/handlers/stream.test.js.map +0 -1
- package/build/implementations/http/hono/index.js.map +0 -1
- package/build/implementations/http/hono/index.test.js.map +0 -1
- package/build/implementations/http/hono/path.js.map +0 -1
- package/build/implementations/http/hono/path.test.js +0 -83
- package/build/implementations/http/hono/path.test.js.map +0 -1
- package/build/implementations/http/hono/types.d.ts +0 -51
- package/build/implementations/http/hono/types.js.map +0 -1
- package/build/implementations/http/on-request-error.test.js.map +0 -1
- package/build/implementations/http/route-errors.test.js.map +0 -1
- package/build/index.d.ts +0 -175
- package/build/index.js +0 -47
- package/build/index.js.map +0 -1
- package/build/index.test.js.map +0 -1
- package/build/migration.test.js.map +0 -1
- package/build/schema/extract-json-schema.d.ts +0 -2
- package/build/schema/extract-json-schema.js +0 -12
- package/build/schema/extract-json-schema.js.map +0 -1
- package/build/schema/extract-json-schema.test.js +0 -23
- package/build/schema/extract-json-schema.test.js.map +0 -1
- package/build/schema/parser.d.ts +0 -36
- package/build/schema/parser.js +0 -210
- package/build/schema/parser.js.map +0 -1
- package/build/schema/parser.test.js +0 -120
- package/build/schema/parser.test.js.map +0 -1
- package/build/schema/resolve-schema-lib.d.ts +0 -12
- package/build/schema/resolve-schema-lib.js +0 -11
- package/build/schema/resolve-schema-lib.js.map +0 -1
- package/build/schema/resolve-schema-lib.test.js +0 -17
- package/build/schema/resolve-schema-lib.test.js.map +0 -1
- package/build/schema/types.d.ts +0 -8
- package/build/schema/types.js +0 -2
- package/build/stack-utils.d.ts +0 -25
- package/build/stack-utils.js.map +0 -1
- package/build/stack-utils.test.js.map +0 -1
- package/build/types.d.ts +0 -142
- package/build/types.js +0 -2
- package/build/types.js.map +0 -1
- package/docs/decisions/2026-06-02-monorepo-split-evaluation.md +0 -80
- package/docs/handoffs/ajsc-named-type-collision.md +0 -134
- package/docs/handoffs/ajsc-named-type-support.md +0 -181
- package/docs/handoffs/shared-models-auto-resolve-response.md +0 -181
- package/docs/npm-workspaces-migration-plan.md +0 -611
- package/docs/superpowers/plans/2026-04-24-doc-registry-simplification.md +0 -886
- package/docs/superpowers/plans/2026-04-24-kotlin-codegen-target.md +0 -1265
- package/docs/superpowers/plans/2026-04-25-ajsc-v7-kotlin-polish.md +0 -1993
- package/docs/superpowers/plans/2026-04-29-safe-result-api.md +0 -2293
- package/docs/superpowers/plans/2026-05-07-astro-adapter.md +0 -1391
- package/docs/superpowers/plans/2026-05-08-create-http.md +0 -3355
- package/docs/superpowers/plans/2026-05-08-hono-app-builder-convergence.md +0 -3365
- package/docs/superpowers/plans/2026-06-05-dx-feedback-round.md +0 -1292
- package/docs/superpowers/plans/2026-06-06-shared-models-convention-and-diagnostics.md +0 -659
- package/docs/superpowers/specs/2026-04-24-kotlin-swift-codegen-design.md +0 -401
- package/docs/superpowers/specs/2026-04-25-ajsc-v7-kotlin-polish-design.md +0 -314
- package/docs/superpowers/specs/2026-04-25-swift-codegen-design.md +0 -264
- package/docs/superpowers/specs/2026-04-29-safe-result-api-design.md +0 -324
- package/docs/superpowers/specs/2026-05-07-astro-adapter-design.md +0 -252
- package/docs/superpowers/specs/2026-05-08-create-http-design.md +0 -409
- package/docs/superpowers/specs/2026-05-08-hono-app-builder-convergence-design.md +0 -411
- package/docs/superpowers/specs/2026-06-05-dx-feedback-round-design.md +0 -285
- package/src/create-http-stream.ts +0 -191
- package/src/create-http.ts +0 -210
- package/src/create-stream.ts +0 -228
- package/src/create.ts +0 -172
- package/src/implementations/http/README.md +0 -390
- package/src/implementations/http/error-dispatch.test.ts +0 -283
- package/src/implementations/http/error-dispatch.ts +0 -176
- package/src/implementations/http/hono/handlers/http-stream.ts +0 -152
- package/src/implementations/http/hono/handlers/http.ts +0 -145
- package/src/implementations/http/hono/handlers/rpc.ts +0 -54
- package/src/implementations/http/hono/path.test.ts +0 -96
- package/src/index.ts +0 -101
- package/src/schema/extract-json-schema.test.ts +0 -25
- package/src/schema/extract-json-schema.ts +0 -15
- package/src/schema/parser.test.ts +0 -182
- package/src/schema/parser.ts +0 -265
- package/src/schema/resolve-schema-lib.test.ts +0 -19
- package/src/schema/resolve-schema-lib.ts +0 -29
- package/src/schema/types.ts +0 -20
- package/src/types.ts +0 -133
- /package/build/{implementations/http → adapters}/astro/astro-context.d.ts +0 -0
- /package/build/{implementations/http → adapters}/astro/astro-context.js +0 -0
- /package/build/{implementations/http → adapters}/astro/create-handler.d.ts +0 -0
- /package/build/{implementations/http → adapters}/astro/create-handler.js +0 -0
- /package/build/{implementations/http → adapters}/astro/index.d.ts +0 -0
- /package/build/{implementations/http → adapters}/astro/index.js +0 -0
- /package/build/{implementations/http → adapters}/astro/index.test.d.ts +0 -0
- /package/build/{implementations/http → adapters}/astro/rewrite-request.d.ts +0 -0
- /package/build/{implementations/http → adapters}/astro/rewrite-request.js +0 -0
- /package/build/{create-http-stream.test.d.ts → adapters/hono/envelope-parity.test.d.ts} +0 -0
- /package/build/{implementations/http → adapters}/hono/handlers/http-stream.test.d.ts +0 -0
- /package/build/{implementations/http → adapters}/hono/handlers/http.test.d.ts +0 -0
- /package/build/{implementations/http → adapters}/hono/handlers/rpc.test.d.ts +0 -0
- /package/build/{implementations/http → adapters}/hono/handlers/stream.test.d.ts +0 -0
- /package/build/{implementations/http → adapters}/hono/index.test.d.ts +0 -0
- /package/build/{implementations/http → adapters/hono}/on-request-error.test.d.ts +0 -0
- /package/build/{implementations/http → adapters/hono}/route-errors.test.d.ts +0 -0
- /package/build/{create-http.test.d.ts → client/freeze.test.d.ts} +0 -0
- /package/build/{create-stream.test.d.ts → codegen/goldens.test.d.ts} +0 -0
- /package/build/{create.test.d.ts → core/create-http-stream.test.d.ts} +0 -0
- /package/build/{doc-envelope.test.d.ts → core/create-http.test.d.ts} +0 -0
- /package/build/{errors.test.d.ts → core/create-stream.test.d.ts} +0 -0
- /package/build/{implementations/http/doc-registry.test.d.ts → core/create.test.d.ts} +0 -0
- /package/build/{implementations/http/error-dispatch.test.d.ts → core/definition-site.test.d.ts} +0 -0
- /package/build/{implementations/http/error-taxonomy.test.d.ts → core/errors.test.d.ts} +0 -0
- /package/build/{errors.test.js → core/errors.test.js} +0 -0
- /package/build/{implementations/http/hono/path.test.d.ts → core/factory-options.test.d.ts} +0 -0
- /package/build/{migration.test.d.ts → core/migration.test.d.ts} +0 -0
- /package/build/{index.test.d.ts → core/procedures.test.d.ts} +0 -0
- /package/build/{implementations/http/hono → core}/types.js +0 -0
- /package/build/schema/{extract-json-schema.test.d.ts → adapter.test.d.ts} +0 -0
- /package/build/schema/{parser.test.d.ts → compile.test.d.ts} +0 -0
- /package/build/schema/{resolve-schema-lib.test.d.ts → typebox.test.d.ts} +0 -0
- /package/build/{stack-utils.test.d.ts → server/context.test.d.ts} +0 -0
- /package/build/{doc-envelope.js → server/doc-envelope.js} +0 -0
- /package/build/{doc-envelope.test.js → server/doc-envelope.test.js} +0 -0
- /package/build/{implementations → server}/types.js +0 -0
- /package/src/{implementations/http → adapters}/astro/README.md +0 -0
- /package/src/{implementations/http → adapters}/astro/astro-context.ts +0 -0
- /package/src/{implementations/http → adapters}/astro/create-handler.ts +0 -0
- /package/src/{implementations/http → adapters}/astro/index.ts +0 -0
- /package/src/{implementations/http → adapters}/astro/rewrite-request.ts +0 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { BODY_METHODS, defaultSuccessStatus, extractReqChannels } from './params.js';
|
|
3
|
+
import { parseQueryNative } from './query.js';
|
|
4
|
+
function makeSource(overrides) {
|
|
5
|
+
return {
|
|
6
|
+
pathParams: () => ({ id: '42' }),
|
|
7
|
+
url: () => 'http://localhost/users/42?limit=10&tag=a&tag=b',
|
|
8
|
+
json: async () => ({ name: 'Ada' }),
|
|
9
|
+
headers: () => ({ 'x-api-key': 'secret' }),
|
|
10
|
+
...overrides,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
describe('extractReqChannels', () => {
|
|
14
|
+
test('extracts only the declared channels', async () => {
|
|
15
|
+
const params = await extractReqChannels(makeSource(), 'get', { query: {} }, parseQueryNative);
|
|
16
|
+
expect(Object.keys(params)).toEqual(['query']);
|
|
17
|
+
expect(params.query).toEqual({ limit: '10', tag: ['a', 'b'] });
|
|
18
|
+
});
|
|
19
|
+
test('extracts pathParams channel', async () => {
|
|
20
|
+
const params = await extractReqChannels(makeSource(), 'get', { pathParams: {} }, parseQueryNative);
|
|
21
|
+
expect(params).toEqual({ pathParams: { id: '42' } });
|
|
22
|
+
});
|
|
23
|
+
test('extracts headers channel (lowercased keys come from the source)', async () => {
|
|
24
|
+
const params = await extractReqChannels(makeSource(), 'get', { headers: {} }, parseQueryNative);
|
|
25
|
+
expect(params).toEqual({ headers: { 'x-api-key': 'secret' } });
|
|
26
|
+
});
|
|
27
|
+
test('extracts all four channels for a body-carrying method', async () => {
|
|
28
|
+
const params = await extractReqChannels(makeSource(), 'post', { pathParams: {}, query: {}, body: {}, headers: {} }, parseQueryNative);
|
|
29
|
+
expect(params).toEqual({
|
|
30
|
+
pathParams: { id: '42' },
|
|
31
|
+
query: { limit: '10', tag: ['a', 'b'] },
|
|
32
|
+
body: { name: 'Ada' },
|
|
33
|
+
headers: { 'x-api-key': 'secret' },
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
test.each(['post', 'put', 'patch'])('parses the body for %s', async (method) => {
|
|
37
|
+
const params = await extractReqChannels(makeSource(), method, { body: {} }, parseQueryNative);
|
|
38
|
+
expect(params.body).toEqual({ name: 'Ada' });
|
|
39
|
+
});
|
|
40
|
+
test.each(['get', 'head', 'delete'])('skips the body for %s (never calls source.json)', async (method) => {
|
|
41
|
+
let jsonCalled = false;
|
|
42
|
+
const source = makeSource({
|
|
43
|
+
json: async () => {
|
|
44
|
+
jsonCalled = true;
|
|
45
|
+
return {};
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
const params = await extractReqChannels(source, method, { body: {} }, parseQueryNative);
|
|
49
|
+
expect(jsonCalled).toBe(false);
|
|
50
|
+
expect('body' in params).toBe(false);
|
|
51
|
+
});
|
|
52
|
+
test('JSON parse failure yields {} so validation reports the missing fields', async () => {
|
|
53
|
+
const source = makeSource({
|
|
54
|
+
json: async () => {
|
|
55
|
+
throw new SyntaxError('Unexpected token');
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
const params = await extractReqChannels(source, 'post', { body: {} }, parseQueryNative);
|
|
59
|
+
expect(params.body).toEqual({});
|
|
60
|
+
});
|
|
61
|
+
test('unknown channel is set to undefined (key present, no extraction)', async () => {
|
|
62
|
+
const params = await extractReqChannels(makeSource(), 'get', { cookies: {} }, parseQueryNative);
|
|
63
|
+
expect('cookies' in params).toBe(true);
|
|
64
|
+
expect(params.cookies).toBeUndefined();
|
|
65
|
+
});
|
|
66
|
+
test('empty schema extracts nothing', async () => {
|
|
67
|
+
const params = await extractReqChannels(makeSource(), 'post', {}, parseQueryNative);
|
|
68
|
+
expect(params).toEqual({});
|
|
69
|
+
});
|
|
70
|
+
test('custom query parser is used for the query channel', async () => {
|
|
71
|
+
const params = await extractReqChannels(makeSource(), 'get', { query: {} }, (raw) => ({ raw }));
|
|
72
|
+
expect(params.query).toEqual({ raw: 'limit=10&tag=a&tag=b' });
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe('BODY_METHODS', () => {
|
|
76
|
+
test('contains exactly post, put, patch', () => {
|
|
77
|
+
expect(BODY_METHODS).toEqual(['post', 'put', 'patch']);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
describe('defaultSuccessStatus', () => {
|
|
81
|
+
test('post → 201', () => {
|
|
82
|
+
expect(defaultSuccessStatus('post')).toBe(201);
|
|
83
|
+
});
|
|
84
|
+
test('delete → 204', () => {
|
|
85
|
+
expect(defaultSuccessStatus('delete')).toBe(204);
|
|
86
|
+
});
|
|
87
|
+
test.each(['get', 'put', 'patch', 'head'])('%s → 200', (method) => {
|
|
88
|
+
expect(defaultSuccessStatus(method)).toBe(200);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
//# sourceMappingURL=params.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"params.test.js","sourceRoot":"","sources":["../../../src/server/request/params.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Parses a raw query string into a params record. */
|
|
2
|
+
export type QueryParser = (queryString: string) => Record<string, unknown>;
|
|
3
|
+
/**
|
|
4
|
+
* Default query parser using URLSearchParams. Multi-value keys become arrays;
|
|
5
|
+
* single-value keys remain scalars (matches browser-native behavior).
|
|
6
|
+
*/
|
|
7
|
+
export declare function parseQueryNative(queryString: string): Record<string, unknown>;
|
|
8
|
+
/** Extracts and parses the query string portion of a URL (empty object when none). */
|
|
9
|
+
export declare function extractQuery(url: string, parser: QueryParser): Record<string, unknown>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default query parser using URLSearchParams. Multi-value keys become arrays;
|
|
3
|
+
* single-value keys remain scalars (matches browser-native behavior).
|
|
4
|
+
*/
|
|
5
|
+
export function parseQueryNative(queryString) {
|
|
6
|
+
const sp = new URLSearchParams(queryString);
|
|
7
|
+
const result = {};
|
|
8
|
+
for (const key of new Set(sp.keys())) {
|
|
9
|
+
const values = sp.getAll(key);
|
|
10
|
+
result[key] = values.length > 1 ? values : values[0];
|
|
11
|
+
}
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
14
|
+
/** Extracts and parses the query string portion of a URL (empty object when none). */
|
|
15
|
+
export function extractQuery(url, parser) {
|
|
16
|
+
const q = url.indexOf('?');
|
|
17
|
+
if (q === -1)
|
|
18
|
+
return {};
|
|
19
|
+
const raw = url.slice(q + 1);
|
|
20
|
+
return raw ? parser(raw) : {};
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../../src/server/request/query.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,WAAmB;IAClD,MAAM,EAAE,GAAG,IAAI,eAAe,CAAC,WAAW,CAAC,CAAA;IAC3C,MAAM,MAAM,GAA4B,EAAE,CAAA;IAC1C,KAAK,MAAM,GAAG,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC7B,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IACtD,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,MAAmB;IAC3D,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAC1B,IAAI,CAAC,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,CAAA;IACvB,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IAC5B,OAAO,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;AAC/B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { extractQuery, parseQueryNative } from './query.js';
|
|
3
|
+
describe('parseQueryNative', () => {
|
|
4
|
+
test('single-value keys remain scalars', () => {
|
|
5
|
+
expect(parseQueryNative('a=1&b=two')).toEqual({ a: '1', b: 'two' });
|
|
6
|
+
});
|
|
7
|
+
test('multi-value keys become arrays', () => {
|
|
8
|
+
expect(parseQueryNative('tag=a&tag=b&tag=c')).toEqual({ tag: ['a', 'b', 'c'] });
|
|
9
|
+
});
|
|
10
|
+
test('mixes scalars and arrays', () => {
|
|
11
|
+
expect(parseQueryNative('limit=10&tag=a&tag=b')).toEqual({ limit: '10', tag: ['a', 'b'] });
|
|
12
|
+
});
|
|
13
|
+
test('empty string parses to an empty object', () => {
|
|
14
|
+
expect(parseQueryNative('')).toEqual({});
|
|
15
|
+
});
|
|
16
|
+
test('decodes URL-encoded values (URLSearchParams semantics)', () => {
|
|
17
|
+
expect(parseQueryNative('q=hello%20world&plus=a+b')).toEqual({
|
|
18
|
+
q: 'hello world',
|
|
19
|
+
plus: 'a b',
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
test('key without a value yields an empty string', () => {
|
|
23
|
+
expect(parseQueryNative('flag')).toEqual({ flag: '' });
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
describe('extractQuery', () => {
|
|
27
|
+
test('parses the query portion of a URL', () => {
|
|
28
|
+
expect(extractQuery('http://localhost/users?limit=10&tag=a', parseQueryNative)).toEqual({
|
|
29
|
+
limit: '10',
|
|
30
|
+
tag: 'a',
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
test('returns {} when the URL has no "?"', () => {
|
|
34
|
+
expect(extractQuery('http://localhost/users', parseQueryNative)).toEqual({});
|
|
35
|
+
});
|
|
36
|
+
test('returns {} for a trailing "?" with an empty query', () => {
|
|
37
|
+
expect(extractQuery('http://localhost/users?', parseQueryNative)).toEqual({});
|
|
38
|
+
});
|
|
39
|
+
test('custom parser receives the raw query string and its result passes through', () => {
|
|
40
|
+
let receivedRaw;
|
|
41
|
+
const custom = (raw) => {
|
|
42
|
+
receivedRaw = raw;
|
|
43
|
+
return { parsed: true };
|
|
44
|
+
};
|
|
45
|
+
const result = extractQuery('http://localhost/p?a=1&b=2', custom);
|
|
46
|
+
expect(receivedRaw).toBe('a=1&b=2');
|
|
47
|
+
expect(result).toEqual({ parsed: true });
|
|
48
|
+
});
|
|
49
|
+
test('custom parser is NOT invoked when there is no query string', () => {
|
|
50
|
+
let called = false;
|
|
51
|
+
const custom = (raw) => {
|
|
52
|
+
called = true;
|
|
53
|
+
return { raw };
|
|
54
|
+
};
|
|
55
|
+
expect(extractQuery('http://localhost/p', custom)).toEqual({});
|
|
56
|
+
expect(extractQuery('http://localhost/p?', custom)).toEqual({});
|
|
57
|
+
expect(called).toBe(false);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
//# sourceMappingURL=query.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.test.js","sourceRoot":"","sources":["../../../src/server/request/query.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE metadata attachment, shared by every server adapter's stream handlers.
|
|
3
|
+
*/
|
|
4
|
+
export type SSEOptions = {
|
|
5
|
+
event?: string;
|
|
6
|
+
id?: string;
|
|
7
|
+
retry?: number;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Marks an object yield as an SSE event with custom metadata. Stream handlers
|
|
11
|
+
* read this metadata to set the SSE `event:`, `id:`, and `retry:` fields:
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* yield sse({ progress: 0.5 }, { event: 'progress', id: 'p-1' })
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* The value is returned unchanged — metadata rides in a WeakMap, never on
|
|
18
|
+
* the payload.
|
|
19
|
+
*/
|
|
20
|
+
export declare function sse<T extends object>(data: T, options?: SSEOptions): T;
|
|
21
|
+
/** Reads metadata attached via {@link sse}. Undefined for plain values. */
|
|
22
|
+
export declare function getSSEMeta(value: unknown): SSEOptions | undefined;
|
|
23
|
+
/** One wire-ready SSE event, as handed to the adapter's write function. */
|
|
24
|
+
export type SseEvent = {
|
|
25
|
+
data: string;
|
|
26
|
+
event: string;
|
|
27
|
+
id: string;
|
|
28
|
+
retry?: number;
|
|
29
|
+
};
|
|
30
|
+
/** Adapter-provided sink (e.g. Hono's `stream.writeSSE`). */
|
|
31
|
+
export type SseWrite = (event: SseEvent) => void | Promise<void>;
|
|
32
|
+
/** Yield payloads: strings pass through, `null`/`undefined` become empty data. */
|
|
33
|
+
export declare function serializeSseValue(value: unknown): string;
|
|
34
|
+
/**
|
|
35
|
+
* The SSE wire protocol shared by every stream handler: auto-incrementing
|
|
36
|
+
* event ids, `sse()` metadata overrides, the `event: 'return'` envelope for
|
|
37
|
+
* the generator's return value, and the error-event shape after mid-stream
|
|
38
|
+
* dispatch. Adapters supply only the framework write function.
|
|
39
|
+
*/
|
|
40
|
+
export declare class SseEventSequencer {
|
|
41
|
+
private readonly write;
|
|
42
|
+
/** Event name for yields without `sse()` metadata — the procedure name. */
|
|
43
|
+
private readonly defaultEvent;
|
|
44
|
+
private eventId;
|
|
45
|
+
constructor(write: SseWrite,
|
|
46
|
+
/** Event name for yields without `sse()` metadata — the procedure name. */
|
|
47
|
+
defaultEvent: string);
|
|
48
|
+
/** Writes one yielded value; `sse()` metadata overrides event/id/retry. */
|
|
49
|
+
writeYield(value: unknown): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Writes the generator's return value as the `event: 'return'` payload
|
|
52
|
+
* (clients resolve it via `TypedStream.result`). Skipped for `undefined` —
|
|
53
|
+
* a `void` generator produces no return event.
|
|
54
|
+
*/
|
|
55
|
+
writeReturn(value: unknown): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Writes a dispatched mid-stream error. `sse()` metadata on the payload
|
|
58
|
+
* (attachable inside `onMidStreamError`) wins over the dispatcher's event.
|
|
59
|
+
*/
|
|
60
|
+
writeError(dispatched: {
|
|
61
|
+
data: unknown;
|
|
62
|
+
sseEvent?: string;
|
|
63
|
+
}): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Drives a complete stream: every yield, then the return event. Errors from
|
|
66
|
+
* the iterator propagate to the caller, which dispatches them and writes the
|
|
67
|
+
* result via {@link writeError} (the id sequence continues across the two).
|
|
68
|
+
*/
|
|
69
|
+
pump(iterator: AsyncIterator<unknown, unknown>): Promise<void>;
|
|
70
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const sseMetadata = new WeakMap();
|
|
2
|
+
/**
|
|
3
|
+
* Marks an object yield as an SSE event with custom metadata. Stream handlers
|
|
4
|
+
* read this metadata to set the SSE `event:`, `id:`, and `retry:` fields:
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* yield sse({ progress: 0.5 }, { event: 'progress', id: 'p-1' })
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
10
|
+
* The value is returned unchanged — metadata rides in a WeakMap, never on
|
|
11
|
+
* the payload.
|
|
12
|
+
*/
|
|
13
|
+
export function sse(data, options) {
|
|
14
|
+
sseMetadata.set(data, options ?? {});
|
|
15
|
+
return data;
|
|
16
|
+
}
|
|
17
|
+
/** Reads metadata attached via {@link sse}. Undefined for plain values. */
|
|
18
|
+
export function getSSEMeta(value) {
|
|
19
|
+
if (typeof value === 'object' && value !== null) {
|
|
20
|
+
return sseMetadata.get(value);
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
/** Yield payloads: strings pass through, `null`/`undefined` become empty data. */
|
|
25
|
+
export function serializeSseValue(value) {
|
|
26
|
+
if (typeof value === 'string')
|
|
27
|
+
return value;
|
|
28
|
+
return value != null ? JSON.stringify(value) : '';
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The SSE wire protocol shared by every stream handler: auto-incrementing
|
|
32
|
+
* event ids, `sse()` metadata overrides, the `event: 'return'` envelope for
|
|
33
|
+
* the generator's return value, and the error-event shape after mid-stream
|
|
34
|
+
* dispatch. Adapters supply only the framework write function.
|
|
35
|
+
*/
|
|
36
|
+
export class SseEventSequencer {
|
|
37
|
+
write;
|
|
38
|
+
defaultEvent;
|
|
39
|
+
eventId = 0;
|
|
40
|
+
constructor(write,
|
|
41
|
+
/** Event name for yields without `sse()` metadata — the procedure name. */
|
|
42
|
+
defaultEvent) {
|
|
43
|
+
this.write = write;
|
|
44
|
+
this.defaultEvent = defaultEvent;
|
|
45
|
+
}
|
|
46
|
+
/** Writes one yielded value; `sse()` metadata overrides event/id/retry. */
|
|
47
|
+
async writeYield(value) {
|
|
48
|
+
const meta = getSSEMeta(value);
|
|
49
|
+
await this.write({
|
|
50
|
+
data: serializeSseValue(value),
|
|
51
|
+
event: meta?.event ?? this.defaultEvent,
|
|
52
|
+
id: meta?.id ?? String(this.eventId++),
|
|
53
|
+
...(meta?.retry !== undefined && { retry: meta.retry }),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Writes the generator's return value as the `event: 'return'` payload
|
|
58
|
+
* (clients resolve it via `TypedStream.result`). Skipped for `undefined` —
|
|
59
|
+
* a `void` generator produces no return event.
|
|
60
|
+
*/
|
|
61
|
+
async writeReturn(value) {
|
|
62
|
+
if (value === undefined)
|
|
63
|
+
return;
|
|
64
|
+
const data = typeof value === 'string' ? value : JSON.stringify(value);
|
|
65
|
+
await this.write({ data, event: 'return', id: String(this.eventId++) });
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Writes a dispatched mid-stream error. `sse()` metadata on the payload
|
|
69
|
+
* (attachable inside `onMidStreamError`) wins over the dispatcher's event.
|
|
70
|
+
*/
|
|
71
|
+
async writeError(dispatched) {
|
|
72
|
+
const meta = getSSEMeta(dispatched.data);
|
|
73
|
+
await this.write({
|
|
74
|
+
data: serializeSseValue(dispatched.data),
|
|
75
|
+
event: meta?.event ?? dispatched.sseEvent ?? 'error',
|
|
76
|
+
id: meta?.id ?? String(this.eventId++),
|
|
77
|
+
...(meta?.retry !== undefined && { retry: meta.retry }),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Drives a complete stream: every yield, then the return event. Errors from
|
|
82
|
+
* the iterator propagate to the caller, which dispatches them and writes the
|
|
83
|
+
* result via {@link writeError} (the id sequence continues across the two).
|
|
84
|
+
*/
|
|
85
|
+
async pump(iterator) {
|
|
86
|
+
let result = await iterator.next();
|
|
87
|
+
while (!result.done) {
|
|
88
|
+
await this.writeYield(result.value);
|
|
89
|
+
result = await iterator.next();
|
|
90
|
+
}
|
|
91
|
+
await this.writeReturn(result.value);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=sse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/server/sse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { describe, expect, it, test } from 'vitest';
|
|
2
|
+
import { SseEventSequencer, getSSEMeta, serializeSseValue, sse } from './sse.js';
|
|
3
|
+
describe('sse', () => {
|
|
4
|
+
test('returns the value unchanged (same reference)', () => {
|
|
5
|
+
const payload = { progress: 0.5 };
|
|
6
|
+
const result = sse(payload, { event: 'progress' });
|
|
7
|
+
expect(result).toBe(payload);
|
|
8
|
+
// Metadata rides in a WeakMap — never on the payload itself.
|
|
9
|
+
expect(Object.keys(result)).toEqual(['progress']);
|
|
10
|
+
});
|
|
11
|
+
test('getSSEMeta round-trips the attached options', () => {
|
|
12
|
+
const payload = sse({ progress: 0.5 }, { event: 'progress', id: 'p-1', retry: 3000 });
|
|
13
|
+
expect(getSSEMeta(payload)).toEqual({ event: 'progress', id: 'p-1', retry: 3000 });
|
|
14
|
+
});
|
|
15
|
+
test('defaults to {} when no options are given', () => {
|
|
16
|
+
const payload = sse({ done: true });
|
|
17
|
+
expect(getSSEMeta(payload)).toEqual({});
|
|
18
|
+
});
|
|
19
|
+
test('metadata is per-object — two payloads keep separate options', () => {
|
|
20
|
+
const a = sse({ n: 1 }, { event: 'a' });
|
|
21
|
+
const b = sse({ n: 2 }, { event: 'b' });
|
|
22
|
+
expect(getSSEMeta(a)).toEqual({ event: 'a' });
|
|
23
|
+
expect(getSSEMeta(b)).toEqual({ event: 'b' });
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
describe('getSSEMeta', () => {
|
|
27
|
+
test('returns undefined for plain (undecorated) objects', () => {
|
|
28
|
+
expect(getSSEMeta({ progress: 0.5 })).toBeUndefined();
|
|
29
|
+
});
|
|
30
|
+
test('returns undefined for primitives', () => {
|
|
31
|
+
expect(getSSEMeta('text')).toBeUndefined();
|
|
32
|
+
expect(getSSEMeta(42)).toBeUndefined();
|
|
33
|
+
expect(getSSEMeta(true)).toBeUndefined();
|
|
34
|
+
expect(getSSEMeta(undefined)).toBeUndefined();
|
|
35
|
+
});
|
|
36
|
+
test('returns undefined for null', () => {
|
|
37
|
+
expect(getSSEMeta(null)).toBeUndefined();
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
describe('SseEventSequencer', () => {
|
|
41
|
+
function collector() {
|
|
42
|
+
const written = [];
|
|
43
|
+
return { written, write: (e) => void written.push(e) };
|
|
44
|
+
}
|
|
45
|
+
async function* gen(values, ret) {
|
|
46
|
+
for (const v of values)
|
|
47
|
+
yield v;
|
|
48
|
+
return ret;
|
|
49
|
+
}
|
|
50
|
+
it('writes yields with the default event and auto-incrementing ids', async () => {
|
|
51
|
+
const { written, write } = collector();
|
|
52
|
+
await new SseEventSequencer(write, 'Watch').pump(gen([{ a: 1 }, { a: 2 }]));
|
|
53
|
+
expect(written).toEqual([
|
|
54
|
+
{ data: '{"a":1}', event: 'Watch', id: '0' },
|
|
55
|
+
{ data: '{"a":2}', event: 'Watch', id: '1' },
|
|
56
|
+
]);
|
|
57
|
+
});
|
|
58
|
+
it('sse() metadata overrides event/id/retry on yields', async () => {
|
|
59
|
+
const { written, write } = collector();
|
|
60
|
+
const tagged = sse({ p: 1 }, { event: 'progress', id: 'p-1', retry: 5 });
|
|
61
|
+
await new SseEventSequencer(write, 'Watch').pump(gen([tagged, { p: 2 }]));
|
|
62
|
+
expect(written[0]).toEqual({ data: '{"p":1}', event: 'progress', id: 'p-1', retry: 5 });
|
|
63
|
+
// counter not consumed by the custom id — next auto id is still 0
|
|
64
|
+
expect(written[1]).toEqual({ data: '{"p":2}', event: 'Watch', id: '0' });
|
|
65
|
+
});
|
|
66
|
+
it('emits the return value as event: return and skips undefined returns', async () => {
|
|
67
|
+
const { written, write } = collector();
|
|
68
|
+
await new SseEventSequencer(write, 'W').pump(gen([1], { total: 1 }));
|
|
69
|
+
expect(written[1]).toEqual({ data: '{"total":1}', event: 'return', id: '1' });
|
|
70
|
+
const second = collector();
|
|
71
|
+
await new SseEventSequencer(second.write, 'W').pump(gen([1]));
|
|
72
|
+
expect(second.written).toHaveLength(1);
|
|
73
|
+
});
|
|
74
|
+
it('writeError continues the id sequence and honors dispatched/meta events', async () => {
|
|
75
|
+
const { written, write } = collector();
|
|
76
|
+
const seq = new SseEventSequencer(write, 'W');
|
|
77
|
+
await seq.writeYield('x');
|
|
78
|
+
await seq.writeError({ data: { error: 'boom' }, sseEvent: 'error' });
|
|
79
|
+
expect(written[1]).toEqual({ data: '{"error":"boom"}', event: 'error', id: '1' });
|
|
80
|
+
await seq.writeError({ data: sse({ msg: 'm' }, { event: 'custom-fail' }) });
|
|
81
|
+
expect(written[2].event).toBe('custom-fail');
|
|
82
|
+
});
|
|
83
|
+
it('serializeSseValue: strings pass through, null/undefined become empty', () => {
|
|
84
|
+
expect(serializeSseValue('raw')).toBe('raw');
|
|
85
|
+
expect(serializeSseValue(null)).toBe('');
|
|
86
|
+
expect(serializeSseValue(undefined)).toBe('');
|
|
87
|
+
expect(serializeSseValue(7)).toBe('7');
|
|
88
|
+
});
|
|
89
|
+
it('propagates iterator errors to the caller (dispatch happens outside)', async () => {
|
|
90
|
+
const { write } = collector();
|
|
91
|
+
async function* boom() {
|
|
92
|
+
yield 1;
|
|
93
|
+
throw new Error('mid');
|
|
94
|
+
}
|
|
95
|
+
await expect(new SseEventSequencer(write, 'W').pump(boom())).rejects.toThrow('mid');
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
//# sourceMappingURL=sse.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse.test.js","sourceRoot":"","sources":["../../src/server/sse.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Transport-agnostic HTTP server types.
|
|
3
|
+
*
|
|
4
|
+
* The doc shapes here (`*RouteDoc`, `DocEnvelope`, `ErrorDoc`, `HeaderDoc`)
|
|
5
|
+
* are a FROZEN wire contract: they are the input to client codegen, and v9
|
|
6
|
+
* guarantees byte-identical generated output vs v8. Do not change field names,
|
|
7
|
+
* optionality, or nesting without re-validating the codegen goldens.
|
|
8
|
+
*/
|
|
9
|
+
import type { ProcedureKind } from '../core/types.js';
|
|
10
|
+
import type { ErrorTaxonomy } from './errors/taxonomy.js';
|
|
3
11
|
/**
|
|
4
12
|
* @typeParam TErrorKey - Union of valid taxonomy keys. Defaults to `string`
|
|
5
13
|
* (unconstrained). Narrow it by passing `keyof typeof yourTaxonomy & string`
|
|
@@ -15,10 +23,6 @@ export interface RPCConfig<TErrorKey extends string = string> {
|
|
|
15
23
|
*/
|
|
16
24
|
errors?: TErrorKey[];
|
|
17
25
|
}
|
|
18
|
-
export type FactoryItem<C> = {
|
|
19
|
-
factory: ReturnType<typeof Procedures<C, RPCConfig>>;
|
|
20
|
-
factoryContext: (req: Request) => C;
|
|
21
|
-
};
|
|
22
26
|
export interface RPCHttpRouteDoc extends RPCConfig {
|
|
23
27
|
kind: 'rpc';
|
|
24
28
|
name: string;
|
|
@@ -39,7 +43,7 @@ export type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head';
|
|
|
39
43
|
* typo protection on `errors`.
|
|
40
44
|
*/
|
|
41
45
|
export interface APIConfig<TErrorKey extends string = string> {
|
|
42
|
-
/** HTTP route path (supports
|
|
46
|
+
/** HTTP route path (supports path params, e.g., '/users/:id') */
|
|
43
47
|
path: string;
|
|
44
48
|
/** HTTP method for this endpoint */
|
|
45
49
|
method: HttpMethod;
|
|
@@ -78,12 +82,12 @@ export interface APIHttpRouteDoc {
|
|
|
78
82
|
};
|
|
79
83
|
}
|
|
80
84
|
/**
|
|
81
|
-
* Constrains schema.
|
|
82
|
-
* Use with `satisfies`
|
|
85
|
+
* Constrains `schema.req` channel names to valid HTTP input sources.
|
|
86
|
+
* Use with `satisfies` to catch typos at compile time:
|
|
83
87
|
*
|
|
84
88
|
* @example
|
|
85
89
|
* schema: {
|
|
86
|
-
*
|
|
90
|
+
* req: {
|
|
87
91
|
* pathParams: Type.Object({ id: Type.String() }),
|
|
88
92
|
* qurey: Type.Object({ ... }), // TS error: 'qurey' not in APIInput
|
|
89
93
|
* } satisfies APIInput
|
|
@@ -162,8 +166,7 @@ export type ExtractConfig<TFactory> = TFactory extends {
|
|
|
162
166
|
export type ProceduresFactory = {
|
|
163
167
|
getProcedures: () => Array<{
|
|
164
168
|
name: string;
|
|
165
|
-
kind?:
|
|
166
|
-
isStream?: boolean;
|
|
169
|
+
kind?: ProcedureKind;
|
|
167
170
|
config: any;
|
|
168
171
|
handler: (ctx: any, params?: any) => Promise<any> | AsyncGenerator<any, any, unknown>;
|
|
169
172
|
}>;
|
|
@@ -177,9 +180,8 @@ export interface DocSource<T = AnyHttpRouteDoc> {
|
|
|
177
180
|
readonly docs: T[];
|
|
178
181
|
/**
|
|
179
182
|
* Optional list of procedures that were registered with this builder but
|
|
180
|
-
* couldn't be served by it
|
|
181
|
-
*
|
|
182
|
-
* `toJSON()` time so silently-dropped procedures don't slip through.
|
|
183
|
+
* couldn't be served by it. DocRegistry aggregates these across sources and
|
|
184
|
+
* warns at `toJSON()` time so silently-dropped procedures don't slip through.
|
|
183
185
|
*/
|
|
184
186
|
readonly skippedProcedures?: {
|
|
185
187
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":""}
|
package/docs/astro-adapter.md
CHANGED
|
@@ -26,7 +26,6 @@ my-astro-app/
|
|
|
26
26
|
```ts
|
|
27
27
|
// src/server/procedures/users.ts
|
|
28
28
|
import { Procedures } from 'ts-procedures'
|
|
29
|
-
import type { APIConfig } from 'ts-procedures/http'
|
|
30
29
|
import { Type } from 'typebox'
|
|
31
30
|
|
|
32
31
|
type UserContext = {
|
|
@@ -34,17 +33,17 @@ type UserContext = {
|
|
|
34
33
|
currentUser: { id: string } | null
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
export const usersAPI = Procedures<UserContext
|
|
36
|
+
export const usersAPI = Procedures<UserContext>()
|
|
38
37
|
|
|
39
|
-
usersAPI.
|
|
38
|
+
usersAPI.CreateHttp(
|
|
40
39
|
'GetUser',
|
|
41
40
|
{
|
|
42
41
|
path: '/users/:id',
|
|
43
42
|
method: 'get',
|
|
44
43
|
scope: 'users', // drives the generated client namespace: api.users.GetUser(...)
|
|
45
44
|
schema: {
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
req: { pathParams: Type.Object({ id: Type.String() }) },
|
|
46
|
+
res: { body: Type.Object({ id: Type.String(), name: Type.String() }) },
|
|
48
47
|
},
|
|
49
48
|
},
|
|
50
49
|
async (ctx, { pathParams }) => {
|
|
@@ -128,8 +127,7 @@ The adapter does NOT couple to `DocRegistry`. Wire codegen separately, against t
|
|
|
128
127
|
|
|
129
128
|
```ts
|
|
130
129
|
// scripts/build-docs.ts
|
|
131
|
-
import {
|
|
132
|
-
import { DocRegistry } from 'ts-procedures/http-docs'
|
|
130
|
+
import { writeDocEnvelope } from 'ts-procedures'
|
|
133
131
|
import { HonoAppBuilder } from 'ts-procedures/hono'
|
|
134
132
|
import { usersAPI } from '../src/server/procedures/users'
|
|
135
133
|
|
|
@@ -138,10 +136,11 @@ import { usersAPI } from '../src/server/procedures/users'
|
|
|
138
136
|
const builder = new HonoAppBuilder().register(usersAPI, () => ({} as never))
|
|
139
137
|
builder.build()
|
|
140
138
|
|
|
141
|
-
|
|
142
|
-
writeFileSync('envelope.json', JSON.stringify(envelope, null, 2))
|
|
139
|
+
await writeDocEnvelope(builder, 'envelope.json')
|
|
143
140
|
```
|
|
144
141
|
|
|
142
|
+
`writeDocEnvelope` accepts a built `HonoAppBuilder` (it calls `toDocEnvelope()` for you), a `DocRegistry`, or a plain `DocEnvelope` object, and writes pretty JSON to disk.
|
|
143
|
+
|
|
145
144
|
### Wire it as an npm script
|
|
146
145
|
|
|
147
146
|
```jsonc
|