ts-procedures 8.6.0 → 9.1.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/CHANGELOG.md +540 -0
- 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 +37 -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-scope.d.ts +13 -30
- package/build/codegen/emit-scope.js +15 -844
- package/build/codegen/emit-scope.js.map +1 -1
- package/build/codegen/emit-scope.test.js +67 -0
- 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} +27 -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 +183 -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 +10 -4
- package/docs/client-error-handling.md +5 -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 +58 -6
- package/docs/migration-v8-to-v9.md +200 -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 +25 -48
- 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/__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 +104 -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-scope.test.ts +75 -2
- package/src/codegen/emit-scope.ts +15 -1048
- 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/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/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} +31 -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 +196 -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/2026-06-08-dx-round2-declines.md +0 -45
- 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/plans/2026-06-08-codegen-dx-surfacing.md +0 -428
- 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/docs/superpowers/specs/2026-06-08-dx-feedback-round-2-design.md +0 -376
- 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,200 @@
|
|
|
1
|
+
# Migrating from v8 to v9
|
|
2
|
+
|
|
3
|
+
v9 is a ground-up restructuring of the library with one iron-clad guarantee:
|
|
4
|
+
**generated codegen output is byte-identical to v8.6.0** (TypeScript, Kotlin,
|
|
5
|
+
and Swift targets, every mode). If you consume a generated client, regenerating
|
|
6
|
+
with v9 produces the same files — nothing to migrate on the consumer side.
|
|
7
|
+
|
|
8
|
+
The flip side of that guarantee: known v8 codegen issues carried over into
|
|
9
|
+
9.0.0 unchanged — output couldn't change, so neither could the bugs. Fixes
|
|
10
|
+
resume in 9.x releases when they can land without breaking parity for output
|
|
11
|
+
that compiles today. First such fix: routes that declare `errors` but no
|
|
12
|
+
req/res schema now emit a namespace housing their `Errors` union instead of a
|
|
13
|
+
dangling type reference (the old output never typechecked, so no working
|
|
14
|
+
consumer's bytes change).
|
|
15
|
+
|
|
16
|
+
Server-side and tooling APIs have breaking changes, listed exhaustively below.
|
|
17
|
+
|
|
18
|
+
## TL;DR checklist
|
|
19
|
+
|
|
20
|
+
| v8 | v9 |
|
|
21
|
+
|---|---|
|
|
22
|
+
| `Procedures({ config: { noRuntimeValidation: true } })` | `Procedures({ validation: false })` |
|
|
23
|
+
| Suretype schemas | Removed — use TypeBox (or a custom `SchemaAdapter`) |
|
|
24
|
+
| `import { HonoAppBuilder } from 'ts-procedures/hono'` | unchanged |
|
|
25
|
+
| `TStreamProcedureRegistration.isStream` | Removed — branch on `kind: 'rpc-stream'` |
|
|
26
|
+
| Duplicate-name registration threw `Error` | Throws `ProcedureRegistrationError` (same message) |
|
|
27
|
+
| `TSchemaLib<T>` | Still exported; `Infer<T>` is the new primary name |
|
|
28
|
+
| `extractJsonSchema(schema)` | `extractJsonSchema(schema, adapters)` — or just use the factory |
|
|
29
|
+
| `schemaParser(...)` | Removed — `computeSchema(name, schema, { adapters, compile })` |
|
|
30
|
+
| `isSuretypeSchema` | Removed |
|
|
31
|
+
| `ts-procedures/http` types (`RPCConfig`, `APIConfig`, doc shapes) | unchanged (moved internally to `server/types`, same subpath) |
|
|
32
|
+
| `dispatchPreStreamError` returned a Hono `Response` | Returns `{ type: 'body', statusCode, body }` \| `{ type: 'response', response }` — adapters translate |
|
|
33
|
+
| — | New: `ts-procedures/server` subpath (transport-agnostic adapter toolkit) |
|
|
34
|
+
|
|
35
|
+
## Core factory
|
|
36
|
+
|
|
37
|
+
### `Procedures()` options
|
|
38
|
+
|
|
39
|
+
The v8 `builder` argument (`{ config, onCreate }`) is replaced by a flat
|
|
40
|
+
options bag:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
// v8
|
|
44
|
+
const { Create } = Procedures<Ctx>({ config: { noRuntimeValidation: true }, onCreate })
|
|
45
|
+
|
|
46
|
+
// v9
|
|
47
|
+
const { Create } = Procedures<Ctx>({
|
|
48
|
+
validation: false, // replaces noRuntimeValidation: true
|
|
49
|
+
onCreate, // unchanged signature
|
|
50
|
+
})
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
New options (no v8 equivalent):
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
Procedures<Ctx>({
|
|
57
|
+
// Customize AJV (options merged over the defaults, or pass an Ajv instance)
|
|
58
|
+
validation: { ajv: { coerceTypes: false } },
|
|
59
|
+
|
|
60
|
+
// Plug in another schema library (TypeBox remains built-in)
|
|
61
|
+
schema: { adapters: [myZodAdapter] },
|
|
62
|
+
|
|
63
|
+
// Factory-level defaults for CreateHttp / CreateHttpStream
|
|
64
|
+
http: { pathPrefix: '/v1', scope: 'billing' },
|
|
65
|
+
})
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`validation: false` keeps v8's `noRuntimeValidation` semantics exactly:
|
|
69
|
+
schemas and validators are still computed at registration (bad schemas fail
|
|
70
|
+
fast); only the per-call validation runs are skipped. The per-call
|
|
71
|
+
`ctx.isPrevalidated` escape hatch is unchanged.
|
|
72
|
+
|
|
73
|
+
### Suretype removed
|
|
74
|
+
|
|
75
|
+
Suretype support (deprecated through v8) is gone: no `isSuretypeSchema`, no
|
|
76
|
+
Suretype branch in type inference. Migrate schemas to TypeBox
|
|
77
|
+
(`import { Type } from 'typebox'`). If you must keep another schema library,
|
|
78
|
+
implement the new `SchemaAdapter` interface:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import type { SchemaAdapter } from 'ts-procedures'
|
|
82
|
+
|
|
83
|
+
const zodAdapter: SchemaAdapter = {
|
|
84
|
+
name: 'zod',
|
|
85
|
+
detect: (s) => s instanceof z.ZodType,
|
|
86
|
+
toJsonSchema: (s) => z.toJSONSchema(s as z.ZodType),
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Note: compile-time inference (`Infer<T>`) is built in only for TypeBox; custom
|
|
91
|
+
adapters get runtime validation + docs.
|
|
92
|
+
|
|
93
|
+
### Stream registrations
|
|
94
|
+
|
|
95
|
+
`isStream: true` is removed from `TStreamProcedureRegistration` and from
|
|
96
|
+
`CreateStream(...).info`. Branch on the `kind` discriminant
|
|
97
|
+
(`'rpc' | 'rpc-stream' | 'http' | 'http-stream'`), which exists since v8 —
|
|
98
|
+
and which every creator's `info` now also carries (v8 only put it on
|
|
99
|
+
`CreateHttpStream`'s info).
|
|
100
|
+
|
|
101
|
+
### Duplicate names
|
|
102
|
+
|
|
103
|
+
Registering the same name twice now throws `ProcedureRegistrationError`
|
|
104
|
+
instead of a bare `Error`. The message is unchanged
|
|
105
|
+
(`Procedure with name <name> is already registered`), so message-based
|
|
106
|
+
assertions keep passing; `instanceof Error` also still holds.
|
|
107
|
+
|
|
108
|
+
### Error classes
|
|
109
|
+
|
|
110
|
+
Same four classes, same constructor signatures, same `instanceof` hierarchy.
|
|
111
|
+
New: every framework error carries a `kind` field
|
|
112
|
+
(`'procedure' | 'validation' | 'yield-validation' | 'registration'`) as an
|
|
113
|
+
alternative to `instanceof`.
|
|
114
|
+
|
|
115
|
+
## Schema utilities (low-level)
|
|
116
|
+
|
|
117
|
+
Most users never call these directly; the factory does.
|
|
118
|
+
|
|
119
|
+
- `schemaParser` is gone. Its behavior lives in
|
|
120
|
+
`computeSchema(name, schema, { adapters, compile, definitionInfo? })`, which
|
|
121
|
+
throws `ProcedureRegistrationError` instead of taking an `onParseError`
|
|
122
|
+
callback.
|
|
123
|
+
- `extractJsonSchema(schema, adapters)` now takes the adapter list explicitly
|
|
124
|
+
(e.g. `[typeboxAdapter]`).
|
|
125
|
+
- AJV is no longer a module-level singleton. `createValidatorCompiler()`
|
|
126
|
+
builds a per-factory compiler; defaults (`allErrors`, `coerceTypes`,
|
|
127
|
+
`removeAdditional`, ajv-formats) are unchanged.
|
|
128
|
+
|
|
129
|
+
## HTTP server layer
|
|
130
|
+
|
|
131
|
+
### Same surface, new home
|
|
132
|
+
|
|
133
|
+
`HonoAppBuilder` keeps its v8 public surface verbatim: constructor config
|
|
134
|
+
stratification (`rpc.*`, `api.*`, `stream.*`, `errors`, `unknownError`,
|
|
135
|
+
`onError`, `onRequestError`, `onRequestStart/End`, `pathPrefix`, `app`),
|
|
136
|
+
`register()`, lazy `docs`, `build()`, `toDocEnvelope()`, `skippedProcedures`,
|
|
137
|
+
static `makeRoutePath`, and the `sse()` helper re-export. Wire behavior
|
|
138
|
+
(routes, status codes, SSE events, error bodies) is unchanged — verified by an
|
|
139
|
+
envelope-parity test against a captured v8 envelope and by the ported v8 test
|
|
140
|
+
suite.
|
|
141
|
+
|
|
142
|
+
The machinery behind it moved into the new transport-agnostic
|
|
143
|
+
`ts-procedures/server` subpath: route-doc builders, error taxonomy + dispatch,
|
|
144
|
+
request channel extraction, SSE metadata, path resolution, `DocRegistry`,
|
|
145
|
+
`writeDocEnvelope`. The `ts-procedures/http-docs`, `ts-procedures/http-errors`,
|
|
146
|
+
and `ts-procedures/http` subpaths re-export the same names as v8.
|
|
147
|
+
|
|
148
|
+
### Writing your own adapter (new capability)
|
|
149
|
+
|
|
150
|
+
v8's dispatch produced Hono `Response` objects; v9's is data-in/data-out:
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
import {
|
|
154
|
+
dispatchPreStreamError, // → { type: 'body', statusCode, body } | { type: 'response', response }
|
|
155
|
+
dispatchMidStreamError, // → { data, sseEvent?, runOnCatch? }
|
|
156
|
+
extractReqChannels, // RequestSource → declared schema.req channels
|
|
157
|
+
resolveFactoryContext,
|
|
158
|
+
buildRpcRouteDoc, // + buildHttpRouteDoc / buildStreamRouteDoc / buildHttpStreamRouteDoc
|
|
159
|
+
} from 'ts-procedures/server'
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
A Fastify/Express adapter is now ~4 thin handlers translating between the
|
|
163
|
+
framework's request/response/streaming primitives and these helpers — use
|
|
164
|
+
`src/adapters/hono/` as the blueprint. Only the taxonomy callbacks' `raw`
|
|
165
|
+
parameter is typed `unknown` at the server layer (it is your framework's
|
|
166
|
+
request context; cast in your adapter).
|
|
167
|
+
|
|
168
|
+
### SSE wire normalization (behavior fix)
|
|
169
|
+
|
|
170
|
+
`rpc-stream` and `http-stream` routes now share one SSE sequencer, which
|
|
171
|
+
removed two v8 inconsistencies: `sse(data, { event, id, retry })` metadata is
|
|
172
|
+
now honored on `http-stream` yields and error events (v8 silently ignored it
|
|
173
|
+
there), and a `null` yield serializes as empty SSE data on both route kinds
|
|
174
|
+
(v8's `http-stream` sent the string `null`). Yield/return/error event names,
|
|
175
|
+
id sequencing, and the `event: 'return'` envelope are unchanged.
|
|
176
|
+
|
|
177
|
+
### Astro adapter
|
|
178
|
+
|
|
179
|
+
Unchanged (`createAstroHandler`, `getAstroContext` from `ts-procedures/astro`).
|
|
180
|
+
|
|
181
|
+
## Client runtime and codegen
|
|
182
|
+
|
|
183
|
+
- `ts-procedures/client`: identical to v8.6.0 — the runtime files are
|
|
184
|
+
content-frozen because self-contained codegen bundles them verbatim.
|
|
185
|
+
- `ts-procedures/codegen` + `npx ts-procedures-codegen`: same options, flags,
|
|
186
|
+
config file, watch mode, orphan pruning. Output is byte-identical to v8.6.0
|
|
187
|
+
except the version stamp in the generated header comment.
|
|
188
|
+
|
|
189
|
+
## New in v9 (non-breaking)
|
|
190
|
+
|
|
191
|
+
- `Procedures({ http: { pathPrefix, scope } })` — factory-level defaults that
|
|
192
|
+
remove per-route boilerplate on `CreateHttp` / `CreateHttpStream`. The
|
|
193
|
+
prefix becomes part of the route's identity (it shows up in `config.path`
|
|
194
|
+
and route docs), unlike the builder-level `pathPrefix`, which is a
|
|
195
|
+
deployment mount point.
|
|
196
|
+
- `Procedures({ validation: { ajv } })` — per-factory AJV configuration.
|
|
197
|
+
- `Procedures({ schema: { adapters } })` — pluggable schema libraries.
|
|
198
|
+
- `ts-procedures/server` — the adapter toolkit described above.
|
|
199
|
+
- `Infer<T>` as the primary inference type (alias `TSchemaLib` retained).
|
|
200
|
+
- `ProcedureError.kind` discriminant.
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# ts-procedures v9 Rewrite — Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
+
|
|
5
|
+
**Goal:** Build `v9/` — a self-contained next-major `ts-procedures` package with redesigned core/schema/server layers and byte-identical codegen output, verified by goldens captured from the v8 build.
|
|
6
|
+
|
|
7
|
+
**Architecture:** Golden-anchored rewrite (spec: `v9/docs/specs/2026-06-09-v9-rewrite-design.md`). Output-producing layers (codegen emitters, bundled client runtime, DocEnvelope shape) are ported content-faithfully; core/schema/server are redesigned for DX and pluggability.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** TypeScript (ES2024, NodeNext, tsc build), vitest, AJV + ajv-formats, TypeBox, Hono (peer), ajsc ^7.3.0 (optional).
|
|
10
|
+
|
|
11
|
+
**Port convention:** Tasks marked **PORT** copy the named v8 file(s) under `src/…` into the v9 path, adjusting only import paths and (where stated) renames. Tasks marked **PORT-VERBATIM** must be byte-identical copies. Tasks marked **NEW** are TDD'd from the signatures given. Every task ends with `npx vitest run <file>` green and a commit.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Phase 0 — Scaffold, baseline capture, client freeze
|
|
16
|
+
|
|
17
|
+
### Task 0.1: Package scaffold
|
|
18
|
+
**Files:** Create `v9/package.json`, `v9/tsconfig.json`, `v9/vitest.config.ts`, `v9/eslint.config.js`, `v9/.gitignore` (`build/`, `node_modules/`).
|
|
19
|
+
- [ ] `package.json`: name `ts-procedures`, version `9.0.0`, `type: module`, same exports-map subpaths as v8 root `package.json:21-53` but pointing at v9 layout (`./hono` → `build/adapters/hono/index.js`, `./astro` → `build/adapters/astro/index.js`, `./http` → types-only `build/server/types.d.ts`, `./http-docs` → `build/server/doc-registry.js`, `./http-errors` → `build/server/errors/taxonomy.js`, `./client` → `build/client/index.js`, `./codegen` → `build/codegen/index.js`, plus new `./server` → `build/server/index.js`); bin `ts-procedures-codegen` → `build/codegen/bin/cli.js`; deps copied from root (ajv, ajv-formats, typebox; peer hono; optional ajsc ^7.3.0).
|
|
20
|
+
- [ ] `tsconfig.json` / `vitest.config.ts` / `eslint.config.js`: mirror root configs (rootDir `src`, outDir `build`).
|
|
21
|
+
- [ ] Verify root test runner does NOT pick up `v9/` (`cat vitest.config.ts` at root; if its include would match `v9/**`, add `v9/**` to root exclude — the only permitted root touch, justified by isolation).
|
|
22
|
+
- [ ] `cd v9 && npm install` succeeds. Commit: `chore(v9): package scaffold`.
|
|
23
|
+
|
|
24
|
+
### Task 0.2: Client runtime freeze (PORT-VERBATIM)
|
|
25
|
+
**Files:** Copy all of root `src/client/*.ts` (10 runtime files + tests) → `v9/src/client/`.
|
|
26
|
+
- [ ] Copy files byte-identically (runtime files MUST not change — they are bundled into generated `_client.ts`/`_types.ts`).
|
|
27
|
+
- [ ] Create `v9/src/client/freeze.test.ts`: hashes the 10 runtime files (`errors.ts, classify-error.ts, error-dispatch.ts, request-builder.ts, resolve-options.ts, hooks.ts, call.ts, stream.ts, fetch-adapter.ts, index.ts, types.ts`) and compares to recorded v8 sha256 values, with a message explaining the bundling contract.
|
|
28
|
+
- [ ] `npx vitest run src/client` green (ported client tests + freeze test). Commit.
|
|
29
|
+
|
|
30
|
+
### Task 0.3: Fixture envelopes
|
|
31
|
+
**Files:** Copy root `src/codegen/__fixtures__/users-envelope.json` → `v9/src/codegen/__fixtures__/`; Create `v9/src/codegen/__fixtures__/models-envelope.json`.
|
|
32
|
+
- [ ] `models-envelope.json`: hand-authored DocEnvelope (same shape) with ≥2 scopes, `$id`-bearing shared models used across scopes (to exercise `_models.ts`, `x-named-type` referencing, collision-free naming), route-level `errors`, an `http-stream` route, and ErrorDocs with schemas.
|
|
33
|
+
- [ ] Validate it loads through the **v8** pipeline: `node` one-liner calling root `build/codegen` `generateClient({ envelope, outDir, dryRun: true })` without error. Commit.
|
|
34
|
+
|
|
35
|
+
### Task 0.4: Golden baseline capture from v8
|
|
36
|
+
**Files:** Create `v9/tools/capture-goldens.mjs`; output `v9/src/codegen/__goldens__/<case>/…`.
|
|
37
|
+
- [ ] Run `npm run build` at root (produces `build/codegen`).
|
|
38
|
+
- [ ] Script imports root `../build/codegen/index.js` and runs the 7-case matrix from the spec §2 (ts-default / ts-flat / ts-external-runtime / ts-no-share-models / ts-shared-models-module / kotlin-default / swift-default) over BOTH fixture envelopes (kotlin/swift only need users-envelope), writing every generated file under `__goldens__/<case>-<envelope>/`.
|
|
39
|
+
- [ ] Commit captured goldens: `test(v9): capture v8.6.0 codegen golden baselines`.
|
|
40
|
+
|
|
41
|
+
### Task 0.5: Golden test harness
|
|
42
|
+
**Files:** Create `v9/src/codegen/goldens.test.ts`, `v9/src/codegen/test-helpers/golden.ts` (PORT root `src/codegen/test-helpers/golden.ts`, extended).
|
|
43
|
+
- [ ] Harness normalizes two placeholders before byte-compare: envelope-hash comment line and the version inside `CODEGEN_HEADER`.
|
|
44
|
+
- [ ] `goldens.test.ts` iterates the matrix, calls v9 `generateClient` (not yet existing) and compares each file. Mark the whole suite `describe.todo`/skipped until Phase 5 starts, then it becomes the acceptance gate. Commit.
|
|
45
|
+
|
|
46
|
+
## Phase 1 — Core (NEW, TDD)
|
|
47
|
+
|
|
48
|
+
### Task 1.1: Errors + definition site
|
|
49
|
+
**Files:** Create `v9/src/core/errors.ts`, `v9/src/core/definition-site.ts` (PORT root `src/stack-utils.ts` logic), tests alongside.
|
|
50
|
+
- [ ] Keep four classes (`ProcedureError`, `ProcedureValidationError`, `ProcedureYieldValidationError`, `ProcedureRegistrationError`) with a shared base carrying `kind`, `procedureName`, `meta`, `definedAt`; definition-stack enrichment preserved. Port/adapt root `src/errors.test.ts` + `src/stack-utils.test.ts`.
|
|
51
|
+
|
|
52
|
+
### Task 1.2: Schema layer
|
|
53
|
+
**Files:** Create `v9/src/schema/adapter.ts`, `typebox.ts`, `compile.ts`, `compute-schema.ts`, `types.ts`, tests.
|
|
54
|
+
- [ ] `adapter.ts`:
|
|
55
|
+
```ts
|
|
56
|
+
export interface SchemaAdapter {
|
|
57
|
+
name: string
|
|
58
|
+
detect(schema: unknown): boolean
|
|
59
|
+
toJsonSchema(schema: unknown): TJSONSchema
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
- [ ] `typebox.ts`: detection via `~kind` / `Symbol.for('TypeBox.Kind')` (port from root `src/schema/resolve-schema-lib.ts`); Suretype removed.
|
|
63
|
+
- [ ] `compile.ts`: `createValidatorCompiler(options?: { ajv?: Ajv | AjvOptions })` returning `compile(jsonSchema): (value) => { errors?: TSchemaValidationError[] }`; default AJV opts `allErrors+coerceTypes+removeAdditional` + ajv-formats (parity with root `src/schema/parser.ts:25-31`).
|
|
64
|
+
- [ ] `compute-schema.ts`: PORT semantics of root `src/schema/compute-schema.ts` + `parser.ts` channel handling (params XOR req, req channels pathParams/query/body/headers, res doc-only, yieldType) on top of the adapter + compiler. Port/adapt the four root schema test files (drop Suretype cases).
|
|
65
|
+
|
|
66
|
+
### Task 1.3: Procedures factory + four creators
|
|
67
|
+
**Files:** Create `v9/src/core/procedures.ts`, `create.ts`, `create-stream.ts`, `create-http.ts`, `create-http-stream.ts`, `context.ts`, `types.ts`, tests.
|
|
68
|
+
- [ ] Factory options per spec §5: `{ onCreate?, validation?: false | { ajv? }, schema?: { adapter? }, http?: { pathPrefix?, scope? } }`.
|
|
69
|
+
- [ ] Behavior parity targets: dual return `{ [name], procedure, info }`; registration objects with `kind` discriminants identical to root `src/types.ts:30-133` (the hono layer + envelope depend on these); `ctx.error()`/`ctx.signal`/`isPrevalidated`; stream `validateYields`; CreateHttp path-param cross-check; duplicate-name `ProcedureRegistrationError`; `getProcedures()/getProcedure/removeProcedure/clear`.
|
|
70
|
+
- [ ] `http` factory defaults merge UNDER per-route config (route wins); `scope` default applies only when route omits it.
|
|
71
|
+
- [ ] Port/adapt root tests: `create.test.ts`, `create-stream.test.ts`, `create-http.test.ts`, `create-http-stream.test.ts`, `index.test.ts`, `migration.test.ts` (update for renamed options); NEW tests for `validation: false`, custom `SchemaAdapter`, `http` defaults.
|
|
72
|
+
|
|
73
|
+
## Phase 2 — Server layer (NEW seam, PORTed semantics)
|
|
74
|
+
|
|
75
|
+
### Task 2.1: Frozen doc types + route-doc builders
|
|
76
|
+
**Files:** Create `v9/src/server/types.ts` (PORT root `src/implementations/types.ts`), `v9/src/server/docs/{rpc,http,stream,http-stream}-doc.ts` (PORT root `src/implementations/http/hono/docs/*`), tests.
|
|
77
|
+
- [ ] Shapes unchanged (spec §2 corollary). SSE yieldType envelope wrapping preserved exactly (root `stream-doc.ts:20-30`).
|
|
78
|
+
|
|
79
|
+
### Task 2.2: Error taxonomy + dispatch
|
|
80
|
+
**Files:** Create `v9/src/server/errors/taxonomy.ts` (PORT root `src/implementations/http/error-taxonomy.ts`), `v9/src/server/errors/dispatch.ts` (PORT root `error-dispatch.ts`), tests (PORT `error-taxonomy.test.ts`, `on-request-error.test.ts` relevant parts).
|
|
81
|
+
|
|
82
|
+
### Task 2.3: Request helpers, SSE, paths, DocRegistry
|
|
83
|
+
**Files:** Create `v9/src/server/request/params.ts` + `query.ts` (de-duplicate root `hono/handlers/http.ts:18-66` / `http-stream.ts:11-59` copies into one), `v9/src/server/sse.ts` (`sse()`/`getSSEMeta` + a shared `writeSseSequence` iteration helper extracted from root `stream.ts:117-141` / `http-stream.ts:105-114`), `v9/src/server/paths.ts` (PORT root `hono/path.ts`), `v9/src/server/doc-registry.ts` (PORT root `doc-registry.ts`), `v9/src/server/doc-envelope.ts` (PORT root `src/doc-envelope.ts`), `v9/src/server/index.ts` barrel, tests (PORT `doc-registry.test.ts`, `doc-envelope.test.ts`; NEW for params/query/sse helpers).
|
|
84
|
+
- [ ] No Hono imports anywhere under `server/` (enforced by a lint-style test grepping imports).
|
|
85
|
+
|
|
86
|
+
## Phase 3 — Adapters
|
|
87
|
+
|
|
88
|
+
### Task 3.1: Hono builder
|
|
89
|
+
**Files:** Create `v9/src/adapters/hono/index.ts`, `types.ts`, `handlers/{rpc,http,stream,http-stream}.ts` — thin glue over `server/*`; tests PORTed from root `src/implementations/http/hono/**/*.test.ts` + `route-errors.test.ts`.
|
|
90
|
+
- [ ] Public surface parity: constructor config stratification, `register()`, lazy `docs`, `build()`, `toDocEnvelope()`, `makeRoutePath`, `sse` re-export.
|
|
91
|
+
- [ ] **Envelope parity test:** same factory set built via v9 builder produces `toDocEnvelope()` deep-equal to a captured v8 envelope (generate the v8 envelope with a small script against root build, commit as fixture).
|
|
92
|
+
|
|
93
|
+
### Task 3.2: Astro adapter (PORT)
|
|
94
|
+
**Files:** `v9/src/adapters/astro/*` from root `src/implementations/http/astro/*` + its test.
|
|
95
|
+
|
|
96
|
+
## Phase 4 — Codegen (PORT with internal split; goldens are the gate)
|
|
97
|
+
|
|
98
|
+
### Task 4.1: Foundation modules (PORT)
|
|
99
|
+
**Files:** `v9/src/codegen/`: `constants.ts`, `naming.ts`, `schema-walk.ts`, `resolve-envelope.ts`, `group-routes.ts`, `collect-models.ts`, `model-refs.ts`, `emit-types.ts`, `targets/_shared/*` — each with its root test file.
|
|
100
|
+
|
|
101
|
+
### Task 4.2: emit split (PORT emit-scope.ts → `emit/`)
|
|
102
|
+
**Files:** `v9/src/codegen/emit/scope-file.ts`, `rpc-route.ts`, `api-route.ts`, `stream-route.ts`, `http-stream-route.ts`, `format-types.ts`, `declarations.ts`.
|
|
103
|
+
- [ ] Move code verbatim by responsibility; every emitted string literal unchanged. Port `emit-scope.test.ts` against the new module boundaries.
|
|
104
|
+
|
|
105
|
+
### Task 4.3: Remaining emitters + targets (PORT)
|
|
106
|
+
**Files:** `emit-models.ts`, `emit-errors.ts`, `emit-index.ts`, `emit-client-types.ts`, `emit-client-runtime.ts` (reads `v9/src/client/*.ts` — frozen in Task 0.2), `targets/ts/run.ts`, `targets/kotlin/*`, `targets/swift/*`, `pipeline.ts`, `index.ts` — each with root tests (incl. kotlin/swift integration goldens + `e2e.test.ts`).
|
|
107
|
+
|
|
108
|
+
### Task 4.4: Goldens green (acceptance gate)
|
|
109
|
+
- [ ] Unskip Task 0.5 suite; `npx vitest run src/codegen/goldens.test.ts` → every file in every case byte-identical. Fix v9 until green. Commit: `test(v9): golden parity with v8.6.0 codegen output`.
|
|
110
|
+
|
|
111
|
+
### Task 4.5: CLI (PORT + FLAG_SPECS unification)
|
|
112
|
+
**Files:** `v9/src/codegen/bin/flag-specs.ts` (PORT, extended with per-flag `takesValue`/`configKey`), `v9/src/codegen/bin/cli.ts` (parseArgs driven by FLAG_SPECS; behavior identical — strict unknown-flag error, did-you-mean, `--help`, config file, watch mode), tests PORT `cli.test.ts` + `flag-specs.test.ts`.
|
|
113
|
+
|
|
114
|
+
## Phase 5 — Finishing
|
|
115
|
+
|
|
116
|
+
### Task 5.1: Root barrel + build
|
|
117
|
+
**Files:** `v9/src/exports.ts` (mirror root `src/exports.ts` minus Suretype, plus new server exports). `cd v9 && npm run build` clean; `npm run lint` clean.
|
|
118
|
+
|
|
119
|
+
### Task 5.2: Docs
|
|
120
|
+
**Files:** `v9/README.md` (full library README: quickstart, four kinds, hono builder, error taxonomy, client, codegen), `v9/docs/migration-v8-to-v9.md` (every breaking change with before/after).
|
|
121
|
+
|
|
122
|
+
### Task 5.3: Full verification
|
|
123
|
+
- [ ] `cd v9 && npx vitest run` — all green; `npm run build`; goldens re-verified; final commit.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Self-review notes
|
|
128
|
+
- Spec coverage: §2→Tasks 0.3-0.5/4.4; §5→1.1-1.3; §6→2.1-2.3/3.1; §7→4.1-4.5; §8 woven through; §9 exclusions respected (no client changes beyond verbatim port, no agent_config).
|
|
129
|
+
- Port tasks intentionally reference v8 source files as the code source of truth instead of inlining thousands of lines.
|
|
130
|
+
- Type consistency: registration/doc/descriptor shapes pinned to root `src/types.ts` / `src/implementations/types.ts` / client `types.ts` by the freeze decisions.
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# ts-procedures v9 — Ground-Up Rewrite Design
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-06-09
|
|
4
|
+
**Status:** Approved for implementation (autonomous /goal directive; final review with user at the end)
|
|
5
|
+
**Location:** `v9/` — a self-contained package directory inside the repo, fully separate from the root v8 project.
|
|
6
|
+
|
|
7
|
+
## 1. Goal
|
|
8
|
+
|
|
9
|
+
Build the next major version (9.0.0) of `ts-procedures` as a brand-new package in `v9/`, with its own
|
|
10
|
+
`package.json`, free to break any API — **except generated codegen output, which must remain exactly what
|
|
11
|
+
v8.6.0 emits today** (TS, Kotlin, Swift; all mode combinations). Downstream apps depend on that polished output.
|
|
12
|
+
|
|
13
|
+
Quality bar: most readable, well-structured, best-DX, extendable, configurable, pluggable version of the
|
|
14
|
+
library possible.
|
|
15
|
+
|
|
16
|
+
## 2. The one hard constraint, made executable
|
|
17
|
+
|
|
18
|
+
"Codegen output that currently exists" becomes a byte-level golden contract:
|
|
19
|
+
|
|
20
|
+
1. **Capture baselines from v8 first.** A capture script runs the *current root build's* codegen
|
|
21
|
+
(`../build/codegen`) against fixture envelopes and writes every generated file to
|
|
22
|
+
`v9/src/codegen/__goldens__/<case>/`.
|
|
23
|
+
2. **Golden matrix** (each case = full output dir):
|
|
24
|
+
- `ts-default` — namespace mode, selfContained, shareModels, jsdoc (all defaults)
|
|
25
|
+
- `ts-flat` — `namespaceTypes: false`
|
|
26
|
+
- `ts-external-runtime` — `selfContained: false`
|
|
27
|
+
- `ts-no-share-models` — `shareModels: false`
|
|
28
|
+
- `ts-shared-models-module` — `sharedModelsModule` convention path
|
|
29
|
+
- `kotlin-default` — kotlinx serializer
|
|
30
|
+
- `swift-default` — codable serializer
|
|
31
|
+
3. **Fixture envelopes:** the existing `users-envelope.json` plus a richer `models-envelope.json`
|
|
32
|
+
(adds `$id`-bearing shared models across scopes, route-level `errors`, http-stream routes) so the
|
|
33
|
+
shareModels/`_models.ts` paths are pinned too.
|
|
34
|
+
4. **Golden test harness** in v9 compares v9 output byte-for-byte against the captured baselines, splicing
|
|
35
|
+
two placeholders: the envelope hash comment (already supported by v8's golden helper) and the package
|
|
36
|
+
version in `CODEGEN_HEADER` (v9 emits `9.x`; everything else must match exactly).
|
|
37
|
+
5. These tests are written **before** any v9 codegen code and stay red until the port is faithful.
|
|
38
|
+
|
|
39
|
+
Two corollaries that fall out of the constraint:
|
|
40
|
+
|
|
41
|
+
- **Bundled client runtime is content-frozen.** Self-contained mode concatenates `src/client/*.ts`
|
|
42
|
+
verbatim (imports stripped) into `_client.ts`/`_types.ts`. Therefore v9's `src/client/` keeps the same
|
|
43
|
+
ten files with byte-identical content. Client improvements are out of scope for 9.0 and gated on a
|
|
44
|
+
future bundler change.
|
|
45
|
+
- **DocEnvelope JSON shape is frozen.** It is codegen's input. Server-side APIs may change freely as long
|
|
46
|
+
as `toDocEnvelope()` emits the same shapes (`kind` discriminants, `jsonSchema` channel layout, SSE
|
|
47
|
+
envelope wrapping, `fullPath`, `errors: string[]`, ErrorDoc/HeaderDoc).
|
|
48
|
+
|
|
49
|
+
## 3. What changes vs. what is preserved
|
|
50
|
+
|
|
51
|
+
| Area | v9 disposition |
|
|
52
|
+
|---|---|
|
|
53
|
+
| Codegen emitted output | **Frozen** (golden-verified) |
|
|
54
|
+
| Codegen internals | Restructured: `emit-scope.ts` (1049 LOC) split into per-kind emitters + shared formatting modules; CLI parsing derived from `FLAG_SPECS` instead of a parallel hand-written switch |
|
|
55
|
+
| Client runtime (`src/client/`) | **Frozen content** (bundling), ported verbatim |
|
|
56
|
+
| DocEnvelope shape | **Frozen** |
|
|
57
|
+
| Core factory / Create* API | Redesigned for DX (see §5) |
|
|
58
|
+
| Schema layer | Pluggable adapters; **Suretype dropped**; AJV configurable |
|
|
59
|
+
| HTTP server layer | Split into transport-agnostic `server/` + thin framework adapters (`hono/`, `astro/`) |
|
|
60
|
+
| Error taxonomy | Kept (it's good); relocated to `server/errors/`; same semantics |
|
|
61
|
+
| Subpath exports | Same names kept (`.`/`./hono`/`./astro`/`./http`/`./http-docs`/`./http-errors`/`./client`/`./codegen`), plus new `./server` |
|
|
62
|
+
| agent_config | Out of scope for the v9 directory (release-time copy; root owns it today) |
|
|
63
|
+
|
|
64
|
+
## 4. Package layout
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
v9/
|
|
68
|
+
├── package.json # name: ts-procedures, version: 9.0.0, type: module
|
|
69
|
+
├── tsconfig.json # ES2024, NodeNext, strict — mirrors root
|
|
70
|
+
├── vitest.config.ts
|
|
71
|
+
├── eslint.config.js
|
|
72
|
+
├── docs/
|
|
73
|
+
│ └── specs/2026-06-09-v9-rewrite-design.md (this file)
|
|
74
|
+
├── tools/
|
|
75
|
+
│ └── capture-goldens.mjs # runs root v8 build's codegen → __goldens__
|
|
76
|
+
└── src/
|
|
77
|
+
├── exports.ts # root barrel
|
|
78
|
+
├── core/ # framework-agnostic procedure definitions
|
|
79
|
+
│ ├── procedures.ts # Procedures() factory + registry
|
|
80
|
+
│ ├── create.ts / create-stream.ts / create-http.ts / create-http-stream.ts
|
|
81
|
+
│ ├── context.ts # ctx.error(), signal contracts
|
|
82
|
+
│ ├── errors.ts # ProcedureError family (4 classes, shared base)
|
|
83
|
+
│ ├── definition-site.ts # stack-capture (was stack-utils.ts)
|
|
84
|
+
│ └── types.ts
|
|
85
|
+
├── schema/
|
|
86
|
+
│ ├── adapter.ts # SchemaAdapter interface (extract + infer hooks)
|
|
87
|
+
│ ├── typebox.ts # built-in TypeBox adapter (auto-detected default)
|
|
88
|
+
│ ├── compile.ts # AJV compilation, factory-configurable instance
|
|
89
|
+
│ └── compute-schema.ts
|
|
90
|
+
├── server/ # transport-agnostic HTTP machinery (NEW seam)
|
|
91
|
+
│ ├── types.ts # DocEnvelope, route docs (frozen shapes)
|
|
92
|
+
│ ├── docs/ # buildRpc/Api/Stream/HttpStream route docs
|
|
93
|
+
│ ├── doc-registry.ts
|
|
94
|
+
│ ├── doc-envelope.ts # writeDocEnvelope
|
|
95
|
+
│ ├── errors/
|
|
96
|
+
│ │ ├── taxonomy.ts # defineErrorTaxonomy, defaults, topo sort
|
|
97
|
+
│ │ └── dispatch.ts # pre-stream / mid-stream dispatch
|
|
98
|
+
│ ├── request/
|
|
99
|
+
│ │ ├── params.ts # extractParams (pathParams/query/body/headers)
|
|
100
|
+
│ │ └── query.ts # parseQueryNative + QueryParser type
|
|
101
|
+
│ ├── sse.ts # sse() metadata, SSE event sequencing helper
|
|
102
|
+
│ └── paths.ts # makeRoutePath, resolveFullPath
|
|
103
|
+
├── adapters/
|
|
104
|
+
│ ├── hono/ # thin HonoAppBuilder over server/*
|
|
105
|
+
│ └── astro/ # port of the astro handler
|
|
106
|
+
├── client/ # FROZEN content (ten files, verbatim from v8)
|
|
107
|
+
└── codegen/
|
|
108
|
+
├── pipeline.ts, resolve-envelope.ts, group-routes.ts, ...
|
|
109
|
+
├── emit/ # was emit-scope.ts — split:
|
|
110
|
+
│ ├── scope-file.ts # orchestration (namespace/flat assembly)
|
|
111
|
+
│ ├── rpc-route.ts / api-route.ts / stream-route.ts / http-stream-route.ts
|
|
112
|
+
│ ├── format-types.ts # formatTypes/formatSubNamespace/rename
|
|
113
|
+
│ └── declarations.ts # DeclarationCollector
|
|
114
|
+
├── targets/{_shared,ts,kotlin,swift}/
|
|
115
|
+
├── bin/{cli.ts,flag-specs.ts}
|
|
116
|
+
├── __fixtures__/ # users-envelope.json + models-envelope.json
|
|
117
|
+
└── __goldens__/ # captured v8 output (the contract)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Build = plain `tsc` to `build/`, ESM-only — same as v8 (it works and keeps publishing simple).
|
|
121
|
+
Root `vitest.config.ts` excludes `v9/`; v9 has its own config (complete separation).
|
|
122
|
+
|
|
123
|
+
## 5. Core API design
|
|
124
|
+
|
|
125
|
+
The four kinds stay (`rpc`, `rpc-stream`, `http`, `http-stream`) and the dual-return shape stays — both
|
|
126
|
+
are proven DX:
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
const { GetUser, procedure, info } = Create('GetUser', { schema: { params, returnType } }, handler)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Changes:
|
|
133
|
+
|
|
134
|
+
1. **Single options bag for the factory** with named sub-configs replacing scattered flags:
|
|
135
|
+
```ts
|
|
136
|
+
const { Create, CreateStream, CreateHttp, CreateHttpStream, getProcedures } =
|
|
137
|
+
Procedures<Ctx, Ext>({
|
|
138
|
+
onCreate?: (registration) => void,
|
|
139
|
+
validation?: false | { ajv?: AjvLike | AjvOptions }, // replaces noRuntimeValidation: true
|
|
140
|
+
schema?: { adapter?: SchemaAdapter }, // pluggable; TypeBox auto-detected default
|
|
141
|
+
http?: { pathPrefix?: string, scope?: string }, // factory-level defaults for CreateHttp*
|
|
142
|
+
})
|
|
143
|
+
```
|
|
144
|
+
`validation: false` reads better than `noRuntimeValidation: true`; AJV options/instance become
|
|
145
|
+
injectable instead of a hardcoded module singleton (default stays `allErrors + coerceTypes +
|
|
146
|
+
removeAdditional` for behavioral parity).
|
|
147
|
+
2. **Factory-level HTTP defaults** (`http.pathPrefix`, `http.scope`) merge under each `CreateHttp` config —
|
|
148
|
+
addresses the documented per-route boilerplate pain without changing envelope output shape.
|
|
149
|
+
3. **Error classes:** keep the four (`ProcedureError`, `ProcedureValidationError`,
|
|
150
|
+
`ProcedureYieldValidationError`, `ProcedureRegistrationError`) because taxonomy dispatch and docs key
|
|
151
|
+
off `instanceof` and class names; unify internals on one base with a `kind` field, keep definition-site
|
|
152
|
+
stack enrichment (genuinely good v8 feature).
|
|
153
|
+
4. **Schema layer:** `SchemaAdapter = { detect(schema): boolean; toJsonSchema(schema): TJSONSchema }`.
|
|
154
|
+
TypeBox adapter ships built-in and is the default; Suretype is removed (deprecated since v8). The AJV
|
|
155
|
+
compile step lives in `schema/compile.ts` behind a small `Validator` type so a future non-AJV engine is
|
|
156
|
+
a config swap, not a rewrite.
|
|
157
|
+
5. **Context contract unchanged** (`ctx.error()`, `ctx.signal?` on rpc/http, guaranteed `ctx.signal` on
|
|
158
|
+
streams, `isPrevalidated` escape hatch kept for builders).
|
|
159
|
+
|
|
160
|
+
## 6. Server layer design
|
|
161
|
+
|
|
162
|
+
The v8 hono directory mixes three concerns: framework binding, HTTP semantics, and doc generation. v9
|
|
163
|
+
separates them:
|
|
164
|
+
|
|
165
|
+
- **`server/`** is pure: no Hono imports. It owns param extraction, query parsing, success-status
|
|
166
|
+
defaults, SSE event sequencing (auto-incrementing ids, `event: 'return'` envelope, `sse()` metadata via
|
|
167
|
+
WeakMap), error taxonomy + pre/mid-stream dispatch, route-doc builders, DocRegistry, and path resolution.
|
|
168
|
+
This kills the v8 duplication (query/param extraction copy-pasted between http.ts and http-stream.ts;
|
|
169
|
+
near-identical SSE loops in stream.ts and http-stream.ts) once, in one place.
|
|
170
|
+
- **`adapters/hono/`** keeps the v8 `HonoAppBuilder` surface users like — chainable `register()`,
|
|
171
|
+
stratified config (`rpc.*`, `api.*`, `stream.*`, cross-cutting `errors`/`unknownError`/`onError`/
|
|
172
|
+
`onRequestError`/`onRequestStart/End`), lazy `docs`, `build()`, `toDocEnvelope()` — but each handler is
|
|
173
|
+
~20 lines of Hono-specific glue (read request, call server/* helpers, write response). Writing a
|
|
174
|
+
Fastify/Express adapter becomes a contained exercise against documented seams rather than a fork.
|
|
175
|
+
- **Envelope parity test:** build the same factories through the v9 hono builder and assert deep-equality
|
|
176
|
+
of `toDocEnvelope()` against a captured v8 envelope for the same procedure set.
|
|
177
|
+
|
|
178
|
+
## 7. Codegen design
|
|
179
|
+
|
|
180
|
+
Port with internal restructuring, never output restructuring:
|
|
181
|
+
|
|
182
|
+
1. Goldens first (see §2) — red until faithful.
|
|
183
|
+
2. Modules port nearly as-is where already clean (`pipeline.ts`, `group-routes.ts`, `collect-models.ts`,
|
|
184
|
+
`model-refs.ts`, `emit-models.ts`, `emit-errors.ts`, `emit-index.ts`, `targets/*`).
|
|
185
|
+
3. `emit-scope.ts` is split into `emit/` per-kind modules (§4 layout). Every emitted string literal moves
|
|
186
|
+
verbatim; only file boundaries and shared helpers change.
|
|
187
|
+
4. `emit-client-runtime.ts` / `emit-client-types.ts` read v9's `src/client/*.ts` — identical content by
|
|
188
|
+
the freeze in §2 — so `_client.ts`/`_types.ts` match.
|
|
189
|
+
5. CLI: `parseArgs` is generated from `FLAG_SPECS` (single source of truth; v8 had a hand-written switch
|
|
190
|
+
plus a parallel spec table that could drift). Flags, defaults, help text, error messages, and
|
|
191
|
+
did-you-mean behavior remain identical and are covered by ported CLI tests.
|
|
192
|
+
6. `generateClient` options, config-file loading, watch mode, orphan pruning (`CODEGEN_SIGNATURE`
|
|
193
|
+
version-agnostic) all keep v8 semantics.
|
|
194
|
+
|
|
195
|
+
## 8. Testing strategy
|
|
196
|
+
|
|
197
|
+
- **Goldens** (§2) are the spine — they encode the only hard requirement.
|
|
198
|
+
- **Envelope parity** test for the hono builder (§6).
|
|
199
|
+
- **Ported unit tests:** v8's co-located tests move with each module (adapted imports/APIs). Target: the
|
|
200
|
+
full behavioral surface of core/schema/server/client/codegen covered; client tests port verbatim since
|
|
201
|
+
the runtime is verbatim.
|
|
202
|
+
- **New tests** for new seams: SchemaAdapter plug-in, factory `validation`/`http` defaults, server/*
|
|
203
|
+
helpers in isolation.
|
|
204
|
+
- TDD discipline for all newly designed code (core/schema/server); port-then-verify for frozen code.
|
|
205
|
+
|
|
206
|
+
## 9. Out of scope for 9.0.0
|
|
207
|
+
|
|
208
|
+
- Client runtime improvements (frozen by the bundling contract; revisit with an AST-based bundler in 9.x).
|
|
209
|
+
- New codegen targets, new emit options.
|
|
210
|
+
- agent_config refresh, README/marketing docs rewrite (a migration guide `docs/migration-v8-to-v9.md` IS
|
|
211
|
+
in scope).
|
|
212
|
+
- Suretype support (removed), Express builder (the v9 seam makes it easy later, not built now).
|
|
213
|
+
|
|
214
|
+
## 10. Risks
|
|
215
|
+
|
|
216
|
+
| Risk | Mitigation |
|
|
217
|
+
|---|---|
|
|
218
|
+
| Hidden output drift in untested codegen paths | Two fixture envelopes × 7-case matrix; richer than v8's own coverage; e2e content tests also ported |
|
|
219
|
+
| Client verbatim port silently diverges | A test hashes each of the ten client files against recorded v8 hashes |
|
|
220
|
+
| Envelope drift from redesigned server layer | Deep-equality envelope parity test |
|
|
221
|
+
| ajsc version behavior | Same dependency pin (`^7.3.0`), same dynamic-import pattern |
|
package/docs/streaming.md
CHANGED
|
@@ -109,6 +109,18 @@ for await (const item of CancellableStream({}, {})) {
|
|
|
109
109
|
|
|
110
110
|
For the built-in Hono streaming integration, see [HTTP Integrations](./http-integrations.md). `HonoAppBuilder` dispatches `CreateStream` and `CreateHttpStream` procedures as SSE or text streams from the same `register()` call as your RPC and REST routes.
|
|
111
111
|
|
|
112
|
+
Wrap a yield with the `sse()` helper to attach SSE metadata (`event:`, `id:`, `retry:` fields). The value is returned unchanged — metadata rides in a WeakMap, never on the payload:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import { sse } from 'ts-procedures/hono'
|
|
116
|
+
|
|
117
|
+
async function* (ctx, params) {
|
|
118
|
+
yield sse({ progress: 0.5 }, { event: 'progress', id: 'p-1' })
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
SSE wire behavior is identical for `rpc-stream` (`CreateStream`) and `http-stream` (`CreateHttpStream`) routes — both are served by the same event sequencer. `sse()` metadata is honored on both kinds, and a `null` yield serializes as empty SSE data on both. (Through v8, `http-stream` routes ignored `sse()` metadata and wrote the string `null` for null yields; v9 normalized this.)
|
|
123
|
+
|
|
112
124
|
## Stream Errors
|
|
113
125
|
|
|
114
126
|
Streaming procedures support the same error handling as regular procedures (see [Error Handling](./core.md#error-handling)).
|