ts-procedures 5.14.0 → 5.16.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/agent_config/claude-code/skills/ts-procedures/SKILL.md +1 -1
- package/agent_config/claude-code/skills/ts-procedures/api-reference.md +59 -4
- package/agent_config/claude-code/skills/ts-procedures/patterns.md +103 -3
- package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/client.md +36 -5
- package/agent_config/copilot/copilot-instructions.md +56 -7
- package/agent_config/cursor/cursorrules +56 -7
- package/build/client/call.d.ts +18 -9
- package/build/client/call.js +25 -19
- package/build/client/call.js.map +1 -1
- package/build/client/call.test.js +167 -17
- package/build/client/call.test.js.map +1 -1
- package/build/client/index.d.ts +1 -1
- package/build/client/index.js +18 -3
- package/build/client/index.js.map +1 -1
- package/build/client/index.test.js +104 -0
- package/build/client/index.test.js.map +1 -1
- package/build/client/resolve-options.d.ts +45 -0
- package/build/client/resolve-options.js +82 -0
- package/build/client/resolve-options.js.map +1 -0
- package/build/client/resolve-options.test.js +158 -0
- package/build/client/resolve-options.test.js.map +1 -0
- package/build/client/stream.d.ts +18 -9
- package/build/client/stream.js +24 -19
- package/build/client/stream.js.map +1 -1
- package/build/client/stream.test.js +102 -46
- package/build/client/stream.test.js.map +1 -1
- package/build/client/types.d.ts +68 -1
- package/build/client/types.js +1 -1
- package/build/codegen/bin/cli.d.ts +2 -0
- package/build/codegen/bin/cli.js +11 -0
- package/build/codegen/bin/cli.js.map +1 -1
- package/build/codegen/bin/cli.test.js +30 -0
- package/build/codegen/bin/cli.test.js.map +1 -1
- package/build/codegen/e2e.test.js +141 -0
- package/build/codegen/e2e.test.js.map +1 -1
- package/build/codegen/emit-client-runtime.js +3 -0
- package/build/codegen/emit-client-runtime.js.map +1 -1
- package/build/codegen/index.d.ts +1 -0
- package/build/codegen/index.js +1 -0
- package/build/codegen/index.js.map +1 -1
- package/build/codegen/pipeline.d.ts +1 -0
- package/build/codegen/pipeline.js +8 -2
- package/build/codegen/pipeline.js.map +1 -1
- package/build/codegen/pipeline.test.js +34 -1
- package/build/codegen/pipeline.test.js.map +1 -1
- package/docs/client-and-codegen.md +125 -2
- package/package.json +1 -1
- package/src/client/call.test.ts +202 -29
- package/src/client/call.ts +41 -28
- package/src/client/index.test.ts +117 -0
- package/src/client/index.ts +25 -8
- package/src/client/resolve-options.test.ts +205 -0
- package/src/client/resolve-options.ts +113 -0
- package/src/client/stream.test.ts +132 -107
- package/src/client/stream.ts +40 -25
- package/src/client/types.ts +74 -2
- package/src/codegen/bin/cli.test.ts +35 -0
- package/src/codegen/bin/cli.ts +11 -0
- package/src/codegen/e2e.test.ts +151 -0
- package/src/codegen/emit-client-runtime.ts +3 -0
- package/src/codegen/index.ts +2 -0
- package/src/codegen/pipeline.test.ts +46 -1
- package/src/codegen/pipeline.ts +9 -2
- package/src/implementations/http/README.md +11 -1
- package/build/src/client/call.d.ts +0 -14
- package/build/src/client/call.js +0 -47
- package/build/src/client/call.js.map +0 -1
- package/build/src/client/call.test.js +0 -124
- package/build/src/client/call.test.js.map +0 -1
- package/build/src/client/errors.d.ts +0 -25
- package/build/src/client/errors.js +0 -33
- package/build/src/client/errors.js.map +0 -1
- package/build/src/client/errors.test.d.ts +0 -1
- package/build/src/client/errors.test.js +0 -41
- package/build/src/client/errors.test.js.map +0 -1
- package/build/src/client/fetch-adapter.d.ts +0 -12
- package/build/src/client/fetch-adapter.js +0 -156
- package/build/src/client/fetch-adapter.js.map +0 -1
- package/build/src/client/fetch-adapter.test.d.ts +0 -1
- package/build/src/client/fetch-adapter.test.js +0 -271
- package/build/src/client/fetch-adapter.test.js.map +0 -1
- package/build/src/client/hooks.d.ts +0 -17
- package/build/src/client/hooks.js +0 -40
- package/build/src/client/hooks.js.map +0 -1
- package/build/src/client/hooks.test.d.ts +0 -1
- package/build/src/client/hooks.test.js +0 -163
- package/build/src/client/hooks.test.js.map +0 -1
- package/build/src/client/index.d.ts +0 -22
- package/build/src/client/index.js +0 -67
- package/build/src/client/index.js.map +0 -1
- package/build/src/client/index.test.d.ts +0 -1
- package/build/src/client/index.test.js +0 -231
- package/build/src/client/index.test.js.map +0 -1
- package/build/src/client/request-builder.d.ts +0 -13
- package/build/src/client/request-builder.js +0 -53
- package/build/src/client/request-builder.js.map +0 -1
- package/build/src/client/request-builder.test.d.ts +0 -1
- package/build/src/client/request-builder.test.js +0 -160
- package/build/src/client/request-builder.test.js.map +0 -1
- package/build/src/client/stream.d.ts +0 -27
- package/build/src/client/stream.js +0 -118
- package/build/src/client/stream.js.map +0 -1
- package/build/src/client/stream.test.d.ts +0 -1
- package/build/src/client/stream.test.js +0 -228
- package/build/src/client/stream.test.js.map +0 -1
- package/build/src/client/types.d.ts +0 -78
- package/build/src/client/types.js +0 -3
- package/build/src/client/types.js.map +0 -1
- package/build/src/codegen/bin/cli.d.ts +0 -45
- package/build/src/codegen/bin/cli.js +0 -246
- package/build/src/codegen/bin/cli.js.map +0 -1
- package/build/src/codegen/bin/cli.test.d.ts +0 -1
- package/build/src/codegen/bin/cli.test.js +0 -220
- package/build/src/codegen/bin/cli.test.js.map +0 -1
- package/build/src/codegen/constants.d.ts +0 -1
- package/build/src/codegen/constants.js +0 -2
- package/build/src/codegen/constants.js.map +0 -1
- package/build/src/codegen/e2e.test.d.ts +0 -1
- package/build/src/codegen/e2e.test.js +0 -464
- package/build/src/codegen/e2e.test.js.map +0 -1
- package/build/src/codegen/emit-client-runtime.d.ts +0 -9
- package/build/src/codegen/emit-client-runtime.js +0 -99
- package/build/src/codegen/emit-client-runtime.js.map +0 -1
- package/build/src/codegen/emit-client-runtime.test.d.ts +0 -1
- package/build/src/codegen/emit-client-runtime.test.js +0 -78
- package/build/src/codegen/emit-client-runtime.test.js.map +0 -1
- package/build/src/codegen/emit-client-types.d.ts +0 -8
- package/build/src/codegen/emit-client-types.js +0 -25
- package/build/src/codegen/emit-client-types.js.map +0 -1
- package/build/src/codegen/emit-client-types.test.d.ts +0 -1
- package/build/src/codegen/emit-client-types.test.js +0 -33
- package/build/src/codegen/emit-client-types.test.js.map +0 -1
- package/build/src/codegen/emit-errors.d.ts +0 -19
- package/build/src/codegen/emit-errors.js +0 -59
- package/build/src/codegen/emit-errors.js.map +0 -1
- package/build/src/codegen/emit-errors.test.d.ts +0 -1
- package/build/src/codegen/emit-errors.test.js +0 -175
- package/build/src/codegen/emit-errors.test.js.map +0 -1
- package/build/src/codegen/emit-index.d.ts +0 -12
- package/build/src/codegen/emit-index.js +0 -41
- package/build/src/codegen/emit-index.js.map +0 -1
- package/build/src/codegen/emit-index.test.d.ts +0 -1
- package/build/src/codegen/emit-index.test.js +0 -106
- package/build/src/codegen/emit-index.test.js.map +0 -1
- package/build/src/codegen/emit-scope.d.ts +0 -15
- package/build/src/codegen/emit-scope.js +0 -299
- package/build/src/codegen/emit-scope.js.map +0 -1
- package/build/src/codegen/emit-scope.test.d.ts +0 -1
- package/build/src/codegen/emit-scope.test.js +0 -559
- package/build/src/codegen/emit-scope.test.js.map +0 -1
- package/build/src/codegen/emit-types.d.ts +0 -43
- package/build/src/codegen/emit-types.js +0 -111
- package/build/src/codegen/emit-types.js.map +0 -1
- package/build/src/codegen/emit-types.test.d.ts +0 -1
- package/build/src/codegen/emit-types.test.js +0 -184
- package/build/src/codegen/emit-types.test.js.map +0 -1
- package/build/src/codegen/group-routes.d.ts +0 -23
- package/build/src/codegen/group-routes.js +0 -46
- package/build/src/codegen/group-routes.js.map +0 -1
- package/build/src/codegen/group-routes.test.d.ts +0 -1
- package/build/src/codegen/group-routes.test.js +0 -131
- package/build/src/codegen/group-routes.test.js.map +0 -1
- package/build/src/codegen/index.d.ts +0 -15
- package/build/src/codegen/index.js +0 -16
- package/build/src/codegen/index.js.map +0 -1
- package/build/src/codegen/naming.d.ts +0 -7
- package/build/src/codegen/naming.js +0 -21
- package/build/src/codegen/naming.js.map +0 -1
- package/build/src/codegen/naming.test.d.ts +0 -1
- package/build/src/codegen/naming.test.js +0 -40
- package/build/src/codegen/naming.test.js.map +0 -1
- package/build/src/codegen/pipeline.d.ts +0 -17
- package/build/src/codegen/pipeline.js +0 -78
- package/build/src/codegen/pipeline.js.map +0 -1
- package/build/src/codegen/pipeline.test.d.ts +0 -1
- package/build/src/codegen/pipeline.test.js +0 -269
- package/build/src/codegen/pipeline.test.js.map +0 -1
- package/build/src/codegen/resolve-envelope.d.ts +0 -7
- package/build/src/codegen/resolve-envelope.js +0 -46
- package/build/src/codegen/resolve-envelope.js.map +0 -1
- package/build/src/codegen/resolve-envelope.test.d.ts +0 -1
- package/build/src/codegen/resolve-envelope.test.js +0 -69
- package/build/src/codegen/resolve-envelope.test.js.map +0 -1
- package/build/src/errors.d.ts +0 -33
- package/build/src/errors.js +0 -91
- package/build/src/errors.js.map +0 -1
- package/build/src/errors.test.d.ts +0 -1
- package/build/src/errors.test.js +0 -122
- package/build/src/errors.test.js.map +0 -1
- package/build/src/exports.d.ts +0 -7
- package/build/src/exports.js +0 -8
- package/build/src/exports.js.map +0 -1
- package/build/src/implementations/http/doc-registry.d.ts +0 -12
- package/build/src/implementations/http/doc-registry.js +0 -114
- package/build/src/implementations/http/doc-registry.js.map +0 -1
- package/build/src/implementations/http/doc-registry.test.d.ts +0 -1
- package/build/src/implementations/http/doc-registry.test.js +0 -347
- package/build/src/implementations/http/doc-registry.test.js.map +0 -1
- package/build/src/implementations/http/express-rpc/index.d.ts +0 -94
- package/build/src/implementations/http/express-rpc/index.js +0 -185
- package/build/src/implementations/http/express-rpc/index.js.map +0 -1
- package/build/src/implementations/http/express-rpc/index.test.d.ts +0 -1
- package/build/src/implementations/http/express-rpc/index.test.js +0 -684
- package/build/src/implementations/http/express-rpc/index.test.js.map +0 -1
- package/build/src/implementations/http/express-rpc/types.d.ts +0 -11
- package/build/src/implementations/http/express-rpc/types.js +0 -2
- package/build/src/implementations/http/express-rpc/types.js.map +0 -1
- package/build/src/implementations/http/hono-api/index.d.ts +0 -102
- package/build/src/implementations/http/hono-api/index.js +0 -341
- package/build/src/implementations/http/hono-api/index.js.map +0 -1
- package/build/src/implementations/http/hono-api/index.test.d.ts +0 -1
- package/build/src/implementations/http/hono-api/index.test.js +0 -992
- package/build/src/implementations/http/hono-api/index.test.js.map +0 -1
- package/build/src/implementations/http/hono-api/types.d.ts +0 -13
- package/build/src/implementations/http/hono-api/types.js +0 -2
- package/build/src/implementations/http/hono-api/types.js.map +0 -1
- package/build/src/implementations/http/hono-rpc/index.d.ts +0 -92
- package/build/src/implementations/http/hono-rpc/index.js +0 -161
- package/build/src/implementations/http/hono-rpc/index.js.map +0 -1
- package/build/src/implementations/http/hono-rpc/index.test.d.ts +0 -1
- package/build/src/implementations/http/hono-rpc/index.test.js +0 -803
- package/build/src/implementations/http/hono-rpc/index.test.js.map +0 -1
- package/build/src/implementations/http/hono-rpc/types.d.ts +0 -11
- package/build/src/implementations/http/hono-rpc/types.js +0 -2
- package/build/src/implementations/http/hono-rpc/types.js.map +0 -1
- package/build/src/implementations/http/hono-stream/index.d.ts +0 -120
- package/build/src/implementations/http/hono-stream/index.js +0 -309
- package/build/src/implementations/http/hono-stream/index.js.map +0 -1
- package/build/src/implementations/http/hono-stream/index.test.d.ts +0 -1
- package/build/src/implementations/http/hono-stream/index.test.js +0 -1356
- package/build/src/implementations/http/hono-stream/index.test.js.map +0 -1
- package/build/src/implementations/http/hono-stream/types.d.ts +0 -15
- package/build/src/implementations/http/hono-stream/types.js +0 -2
- package/build/src/implementations/http/hono-stream/types.js.map +0 -1
- package/build/src/implementations/types.d.ts +0 -142
- package/build/src/implementations/types.js +0 -2
- package/build/src/implementations/types.js.map +0 -1
- package/build/src/index.d.ts +0 -165
- package/build/src/index.js +0 -253
- package/build/src/index.js.map +0 -1
- package/build/src/index.test.d.ts +0 -1
- package/build/src/index.test.js +0 -890
- package/build/src/index.test.js.map +0 -1
- package/build/src/schema/compute-schema.d.ts +0 -35
- package/build/src/schema/compute-schema.js +0 -41
- package/build/src/schema/compute-schema.js.map +0 -1
- package/build/src/schema/compute-schema.test.d.ts +0 -1
- package/build/src/schema/compute-schema.test.js +0 -107
- package/build/src/schema/compute-schema.test.js.map +0 -1
- package/build/src/schema/extract-json-schema.d.ts +0 -2
- package/build/src/schema/extract-json-schema.js +0 -12
- package/build/src/schema/extract-json-schema.js.map +0 -1
- package/build/src/schema/extract-json-schema.test.d.ts +0 -1
- package/build/src/schema/extract-json-schema.test.js +0 -23
- package/build/src/schema/extract-json-schema.test.js.map +0 -1
- package/build/src/schema/parser.d.ts +0 -28
- package/build/src/schema/parser.js +0 -170
- package/build/src/schema/parser.js.map +0 -1
- package/build/src/schema/parser.test.d.ts +0 -1
- package/build/src/schema/parser.test.js +0 -120
- package/build/src/schema/parser.test.js.map +0 -1
- package/build/src/schema/resolve-schema-lib.d.ts +0 -12
- package/build/src/schema/resolve-schema-lib.js +0 -11
- package/build/src/schema/resolve-schema-lib.js.map +0 -1
- package/build/src/schema/resolve-schema-lib.test.d.ts +0 -1
- package/build/src/schema/resolve-schema-lib.test.js +0 -17
- package/build/src/schema/resolve-schema-lib.test.js.map +0 -1
- package/build/src/schema/types.d.ts +0 -8
- package/build/src/schema/types.js +0 -2
- package/build/src/schema/types.js.map +0 -1
- package/build/src/stack-utils.d.ts +0 -25
- package/build/src/stack-utils.js +0 -95
- package/build/src/stack-utils.js.map +0 -1
- package/build/src/stack-utils.test.d.ts +0 -1
- package/build/src/stack-utils.test.js +0 -80
- package/build/src/stack-utils.test.js.map +0 -1
- /package/build/{src/client/call.test.d.ts → client/resolve-options.test.d.ts} +0 -0
package/src/codegen/bin/cli.ts
CHANGED
|
@@ -21,6 +21,7 @@ export interface CodegenConfig {
|
|
|
21
21
|
namespaceTypes?: boolean
|
|
22
22
|
selfContained?: boolean
|
|
23
23
|
serviceName?: string
|
|
24
|
+
cleanOutDir?: boolean
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export interface ParsedArgs {
|
|
@@ -35,6 +36,7 @@ export interface ParsedArgs {
|
|
|
35
36
|
namespaceTypes: boolean
|
|
36
37
|
selfContained: boolean
|
|
37
38
|
serviceName?: string
|
|
39
|
+
cleanOutDir: boolean
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
// ---------------------------------------------------------------------------
|
|
@@ -85,6 +87,7 @@ export function parseArgs(argv: string[], config?: CodegenConfig): ParsedArgs {
|
|
|
85
87
|
let namespaceTypes = config?.namespaceTypes ?? true
|
|
86
88
|
let selfContained = config?.selfContained ?? true
|
|
87
89
|
let serviceName: string | undefined = config?.serviceName
|
|
90
|
+
let cleanOutDir = config?.cleanOutDir ?? false
|
|
88
91
|
let configPath: string | undefined
|
|
89
92
|
|
|
90
93
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -130,6 +133,10 @@ export function parseArgs(argv: string[], config?: CodegenConfig): ParsedArgs {
|
|
|
130
133
|
selfContained = false
|
|
131
134
|
} else if (arg === '--service-name') {
|
|
132
135
|
serviceName = argv[++i]
|
|
136
|
+
} else if (arg === '--clean-out-dir') {
|
|
137
|
+
cleanOutDir = true
|
|
138
|
+
} else if (arg === '--no-clean-out-dir') {
|
|
139
|
+
cleanOutDir = false
|
|
133
140
|
} else if (arg === '--config') {
|
|
134
141
|
configPath = argv[++i]
|
|
135
142
|
}
|
|
@@ -158,6 +165,7 @@ export function parseArgs(argv: string[], config?: CodegenConfig): ParsedArgs {
|
|
|
158
165
|
namespaceTypes,
|
|
159
166
|
selfContained,
|
|
160
167
|
...(serviceName !== undefined ? { serviceName } : {}),
|
|
168
|
+
cleanOutDir,
|
|
161
169
|
}
|
|
162
170
|
}
|
|
163
171
|
|
|
@@ -190,6 +198,7 @@ async function runWithWatch(parsed: ParsedArgs): Promise<void> {
|
|
|
190
198
|
namespaceTypes: parsed.namespaceTypes,
|
|
191
199
|
selfContained: parsed.selfContained,
|
|
192
200
|
serviceName: parsed.serviceName,
|
|
201
|
+
cleanOutDir: parsed.cleanOutDir,
|
|
193
202
|
}
|
|
194
203
|
|
|
195
204
|
let lastHash: string | undefined
|
|
@@ -216,6 +225,7 @@ async function runWithWatch(parsed: ParsedArgs): Promise<void> {
|
|
|
216
225
|
namespaceTypes: parsed.namespaceTypes,
|
|
217
226
|
selfContained: parsed.selfContained,
|
|
218
227
|
serviceName: parsed.serviceName,
|
|
228
|
+
cleanOutDir: parsed.cleanOutDir,
|
|
219
229
|
})
|
|
220
230
|
console.log(`[ts-procedures-codegen] Generated client files → ${parsed.outDir}`)
|
|
221
231
|
} catch (err) {
|
|
@@ -258,6 +268,7 @@ async function main(): Promise<void> {
|
|
|
258
268
|
namespaceTypes: parsed.namespaceTypes,
|
|
259
269
|
selfContained: parsed.selfContained,
|
|
260
270
|
serviceName: parsed.serviceName,
|
|
271
|
+
cleanOutDir: parsed.cleanOutDir,
|
|
261
272
|
})
|
|
262
273
|
if (parsed.dryRun) {
|
|
263
274
|
console.log(`[ts-procedures-codegen] Dry run complete — ${result.length} files would be generated`)
|
package/src/codegen/e2e.test.ts
CHANGED
|
@@ -481,6 +481,157 @@ describe('E2E: generateClient full pipeline', () => {
|
|
|
481
481
|
execSync(`${tscPath} --noEmit --project ${join(tmpDir, 'tsconfig.json')}`, { stdio: 'pipe' })
|
|
482
482
|
}).not.toThrow()
|
|
483
483
|
})
|
|
484
|
+
|
|
485
|
+
it('_types.ts exports RequestMeta (empty interface ready for augmentation)', async () => {
|
|
486
|
+
tmpDir = makeTmpDir()
|
|
487
|
+
await generateClient({ envelope, outDir: tmpDir, selfContained: true })
|
|
488
|
+
|
|
489
|
+
const content = readFileSync(join(tmpDir, '_types.ts'), 'utf-8')
|
|
490
|
+
expect(content).toContain('export interface RequestMeta')
|
|
491
|
+
// meta on AdapterRequest and ProcedureCallDefaults should be typed as RequestMeta
|
|
492
|
+
expect(content).toContain('meta?: RequestMeta')
|
|
493
|
+
})
|
|
494
|
+
|
|
495
|
+
it('developers can augment RequestMeta for typed per-call meta + typed hook/adapter access', async () => {
|
|
496
|
+
tmpDir = makeTmpDir()
|
|
497
|
+
await generateClient({ envelope, outDir: tmpDir, selfContained: true })
|
|
498
|
+
|
|
499
|
+
// Write a consumer file that augments RequestMeta, then uses typed meta
|
|
500
|
+
// end-to-end: per-call options, createClient defaults, onBeforeRequest, and adapter.
|
|
501
|
+
const consumer = `
|
|
502
|
+
import { createClient } from './_client'
|
|
503
|
+
import type { ClientAdapter } from './_types'
|
|
504
|
+
import { createApiBindings } from './index'
|
|
505
|
+
|
|
506
|
+
declare module './_types' {
|
|
507
|
+
interface RequestMeta {
|
|
508
|
+
traceId: string
|
|
509
|
+
priority?: 'high' | 'low'
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
const typedAdapter: ClientAdapter = {
|
|
514
|
+
async request(req) {
|
|
515
|
+
// req.meta is now typed
|
|
516
|
+
const trace: string | undefined = req.meta?.traceId
|
|
517
|
+
const pri: 'high' | 'low' | undefined = req.meta?.priority
|
|
518
|
+
void trace; void pri
|
|
519
|
+
return { status: 200, headers: {}, body: {} }
|
|
520
|
+
},
|
|
521
|
+
async stream(req) {
|
|
522
|
+
const trace: string | undefined = req.meta?.traceId
|
|
523
|
+
void trace
|
|
524
|
+
return { status: 200, headers: {}, body: (async function*() {})() }
|
|
525
|
+
},
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
const client = createClient({
|
|
529
|
+
adapter: typedAdapter,
|
|
530
|
+
basePath: 'https://api.example.com',
|
|
531
|
+
scopes: createApiBindings,
|
|
532
|
+
defaults: {
|
|
533
|
+
meta: { traceId: 'default-trace' }, // typed
|
|
534
|
+
},
|
|
535
|
+
hooks: {
|
|
536
|
+
onBeforeRequest(ctx) {
|
|
537
|
+
// ctx.request.meta is typed via declaration merging
|
|
538
|
+
const trace: string | undefined = ctx.request.meta?.traceId
|
|
539
|
+
void trace
|
|
540
|
+
return ctx
|
|
541
|
+
},
|
|
542
|
+
},
|
|
543
|
+
})
|
|
544
|
+
|
|
545
|
+
async function run(): Promise<void> {
|
|
546
|
+
// Per-call meta is typed — traceId is required, priority is optional
|
|
547
|
+
await client.users.GetUser(
|
|
548
|
+
{ id: '1' },
|
|
549
|
+
{ meta: { traceId: 'per-call-trace', priority: 'high' } },
|
|
550
|
+
)
|
|
551
|
+
// Timeout + signal + headers typecheck
|
|
552
|
+
await client.users.GetUser(
|
|
553
|
+
{ id: '2' },
|
|
554
|
+
{ timeout: 5000, headers: { 'X-Request-Id': 'abc' }, basePath: 'https://other' },
|
|
555
|
+
)
|
|
556
|
+
}
|
|
557
|
+
void run
|
|
558
|
+
`
|
|
559
|
+
const { writeFileSync } = await import('node:fs')
|
|
560
|
+
writeFileSync(join(tmpDir, 'consumer.ts'), consumer)
|
|
561
|
+
|
|
562
|
+
const tsconfig = {
|
|
563
|
+
compilerOptions: {
|
|
564
|
+
strict: true,
|
|
565
|
+
target: 'ES2022',
|
|
566
|
+
module: 'ES2022',
|
|
567
|
+
moduleResolution: 'bundler',
|
|
568
|
+
noEmit: true,
|
|
569
|
+
skipLibCheck: true,
|
|
570
|
+
},
|
|
571
|
+
include: ['_types.ts', '_client.ts', 'index.ts', 'users.ts', 'events.ts', '_errors.ts', 'consumer.ts'],
|
|
572
|
+
}
|
|
573
|
+
writeFileSync(join(tmpDir, 'tsconfig.json'), JSON.stringify(tsconfig))
|
|
574
|
+
|
|
575
|
+
const { execSync } = await import('node:child_process')
|
|
576
|
+
const tscPath = join(process.cwd(), 'node_modules', '.bin', 'tsc')
|
|
577
|
+
expect(() => {
|
|
578
|
+
execSync(`${tscPath} --noEmit --project ${join(tmpDir, 'tsconfig.json')}`, { stdio: 'pipe' })
|
|
579
|
+
}).not.toThrow()
|
|
580
|
+
})
|
|
581
|
+
|
|
582
|
+
it('augmented RequestMeta rejects wrong types (compile error)', async () => {
|
|
583
|
+
tmpDir = makeTmpDir()
|
|
584
|
+
await generateClient({ envelope, outDir: tmpDir, selfContained: true })
|
|
585
|
+
|
|
586
|
+
// Passing a number for `traceId` (declared as string) should fail tsc
|
|
587
|
+
const consumer = `
|
|
588
|
+
import { createClient, createFetchAdapter } from './_client'
|
|
589
|
+
import { createApiBindings } from './index'
|
|
590
|
+
// RequestMeta is imported only for augmentation below
|
|
591
|
+
import type {} from './_types'
|
|
592
|
+
|
|
593
|
+
declare module './_types' {
|
|
594
|
+
interface RequestMeta {
|
|
595
|
+
traceId: string
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
const client = createClient({
|
|
600
|
+
adapter: createFetchAdapter(),
|
|
601
|
+
basePath: 'https://api.example.com',
|
|
602
|
+
scopes: createApiBindings,
|
|
603
|
+
})
|
|
604
|
+
|
|
605
|
+
async function run(): Promise<void> {
|
|
606
|
+
// @ts-expect-error traceId must be string, not number
|
|
607
|
+
await client.users.GetUser({ id: '1' }, { meta: { traceId: 42 } })
|
|
608
|
+
}
|
|
609
|
+
void run
|
|
610
|
+
`
|
|
611
|
+
const { writeFileSync } = await import('node:fs')
|
|
612
|
+
writeFileSync(join(tmpDir, 'consumer.ts'), consumer)
|
|
613
|
+
|
|
614
|
+
const tsconfig = {
|
|
615
|
+
compilerOptions: {
|
|
616
|
+
strict: true,
|
|
617
|
+
target: 'ES2022',
|
|
618
|
+
module: 'ES2022',
|
|
619
|
+
moduleResolution: 'bundler',
|
|
620
|
+
noEmit: true,
|
|
621
|
+
skipLibCheck: true,
|
|
622
|
+
},
|
|
623
|
+
include: ['_types.ts', '_client.ts', 'index.ts', 'users.ts', 'events.ts', '_errors.ts', 'consumer.ts'],
|
|
624
|
+
}
|
|
625
|
+
writeFileSync(join(tmpDir, 'tsconfig.json'), JSON.stringify(tsconfig))
|
|
626
|
+
|
|
627
|
+
const { execSync } = await import('node:child_process')
|
|
628
|
+
const tscPath = join(process.cwd(), 'node_modules', '.bin', 'tsc')
|
|
629
|
+
// With @ts-expect-error in place, tsc should pass; if RequestMeta wasn't
|
|
630
|
+
// enforcing the type, @ts-expect-error would fail because there'd be no error.
|
|
631
|
+
expect(() => {
|
|
632
|
+
execSync(`${tscPath} --noEmit --project ${join(tmpDir, 'tsconfig.json')}`, { stdio: 'pipe' })
|
|
633
|
+
}).not.toThrow()
|
|
634
|
+
})
|
|
484
635
|
})
|
|
485
636
|
|
|
486
637
|
// ── namespaceTypes mode ───────────────────────────────────────────────────
|
|
@@ -16,8 +16,10 @@ const TYPES_IMPORT = `import type {
|
|
|
16
16
|
StreamDescriptor,
|
|
17
17
|
TypedStream,
|
|
18
18
|
ClientInstance,
|
|
19
|
+
ProcedureCallDefaults,
|
|
19
20
|
ProcedureCallOptions,
|
|
20
21
|
CreateClientConfig,
|
|
22
|
+
RequestMeta,
|
|
21
23
|
} from './_types'`
|
|
22
24
|
|
|
23
25
|
/**
|
|
@@ -27,6 +29,7 @@ const TYPES_IMPORT = `import type {
|
|
|
27
29
|
const SOURCE_FILES = [
|
|
28
30
|
'errors.ts',
|
|
29
31
|
'request-builder.ts',
|
|
32
|
+
'resolve-options.ts',
|
|
30
33
|
'hooks.ts',
|
|
31
34
|
'call.ts',
|
|
32
35
|
'stream.ts',
|
package/src/codegen/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ export interface GenerateClientOptions extends ResolveInput {
|
|
|
10
10
|
namespaceTypes?: boolean
|
|
11
11
|
selfContained?: boolean
|
|
12
12
|
serviceName?: string
|
|
13
|
+
cleanOutDir?: boolean
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export async function generateClient(options: GenerateClientOptions): Promise<GeneratedFile[]> {
|
|
@@ -23,6 +24,7 @@ export async function generateClient(options: GenerateClientOptions): Promise<Ge
|
|
|
23
24
|
namespaceTypes: options.namespaceTypes,
|
|
24
25
|
selfContained: options.selfContained,
|
|
25
26
|
serviceName: options.serviceName,
|
|
27
|
+
cleanOutDir: options.cleanOutDir,
|
|
26
28
|
})
|
|
27
29
|
}
|
|
28
30
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect, afterEach, vi } from 'vitest'
|
|
2
2
|
import { generateClient } from './index.js'
|
|
3
3
|
import { runPipeline } from './pipeline.js'
|
|
4
|
-
import { mkdirSync, rmSync, readFileSync, existsSync } from 'node:fs'
|
|
4
|
+
import { mkdirSync, rmSync, readFileSync, existsSync, writeFileSync } from 'node:fs'
|
|
5
5
|
import { join } from 'node:path'
|
|
6
6
|
import { tmpdir } from 'node:os'
|
|
7
7
|
import type { DocEnvelope } from '../implementations/types.js'
|
|
@@ -288,6 +288,51 @@ describe('generateClient pipeline', () => {
|
|
|
288
288
|
expect(content).not.toContain('createScopeBindings')
|
|
289
289
|
})
|
|
290
290
|
|
|
291
|
+
it('cleanOutDir: true removes stale files before writing', async () => {
|
|
292
|
+
tmpDir = makeTmpDir()
|
|
293
|
+
const stale = join(tmpDir, 'stale.ts')
|
|
294
|
+
writeFileSync(stale, '// stale', 'utf-8')
|
|
295
|
+
expect(existsSync(stale)).toBe(true)
|
|
296
|
+
|
|
297
|
+
await generateClient({ envelope, outDir: tmpDir, cleanOutDir: true })
|
|
298
|
+
|
|
299
|
+
expect(existsSync(stale)).toBe(false)
|
|
300
|
+
expect(existsSync(join(tmpDir, 'index.ts'))).toBe(true)
|
|
301
|
+
expect(existsSync(join(tmpDir, 'users.ts'))).toBe(true)
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
it('cleanOutDir: false (default) leaves unrelated files in place', async () => {
|
|
305
|
+
tmpDir = makeTmpDir()
|
|
306
|
+
const keep = join(tmpDir, 'keep.ts')
|
|
307
|
+
writeFileSync(keep, '// keep', 'utf-8')
|
|
308
|
+
|
|
309
|
+
await generateClient({ envelope, outDir: tmpDir })
|
|
310
|
+
|
|
311
|
+
expect(existsSync(keep)).toBe(true)
|
|
312
|
+
expect(existsSync(join(tmpDir, 'index.ts'))).toBe(true)
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
it('cleanOutDir works when outDir does not exist', async () => {
|
|
316
|
+
tmpDir = makeTmpDir()
|
|
317
|
+
const nested = join(tmpDir, 'nested', 'missing')
|
|
318
|
+
expect(existsSync(nested)).toBe(false)
|
|
319
|
+
|
|
320
|
+
await generateClient({ envelope, outDir: nested, cleanOutDir: true })
|
|
321
|
+
|
|
322
|
+
expect(existsSync(join(nested, 'index.ts'))).toBe(true)
|
|
323
|
+
})
|
|
324
|
+
|
|
325
|
+
it('cleanOutDir is a no-op in dryRun mode', async () => {
|
|
326
|
+
tmpDir = makeTmpDir()
|
|
327
|
+
const keep = join(tmpDir, 'keep.ts')
|
|
328
|
+
writeFileSync(keep, '// keep', 'utf-8')
|
|
329
|
+
|
|
330
|
+
await runPipeline({ envelope, outDir: tmpDir, cleanOutDir: true, dryRun: true })
|
|
331
|
+
|
|
332
|
+
expect(existsSync(keep)).toBe(true)
|
|
333
|
+
expect(existsSync(join(tmpDir, 'index.ts'))).toBe(false)
|
|
334
|
+
})
|
|
335
|
+
|
|
291
336
|
it('throws when a scope key collides with _types in selfContained mode', async () => {
|
|
292
337
|
tmpDir = makeTmpDir()
|
|
293
338
|
const collisionEnvelope: DocEnvelope = {
|
package/src/codegen/pipeline.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdir, writeFile } from 'node:fs/promises'
|
|
1
|
+
import { mkdir, rm, writeFile } from 'node:fs/promises'
|
|
2
2
|
import { join } from 'node:path'
|
|
3
3
|
import { createHash } from 'node:crypto'
|
|
4
4
|
import type { DocEnvelope } from '../implementations/types.js'
|
|
@@ -20,6 +20,7 @@ export interface PipelineOptions {
|
|
|
20
20
|
namespaceTypes?: boolean
|
|
21
21
|
selfContained?: boolean
|
|
22
22
|
serviceName?: string
|
|
23
|
+
cleanOutDir?: boolean
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export interface GeneratedFile {
|
|
@@ -28,7 +29,7 @@ export interface GeneratedFile {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
export async function runPipeline(options: PipelineOptions): Promise<GeneratedFile[]> {
|
|
31
|
-
const { envelope, outDir, ajsc: ajscOpts, dryRun = false, namespaceTypes = false, selfContained = false } = options
|
|
32
|
+
const { envelope, outDir, ajsc: ajscOpts, dryRun = false, namespaceTypes = false, selfContained = false, cleanOutDir = false } = options
|
|
32
33
|
const serviceName = options.serviceName ?? 'Api'
|
|
33
34
|
validateServiceName(serviceName)
|
|
34
35
|
const clientImportPath = selfContained ? './_types' : options.clientImportPath
|
|
@@ -92,11 +93,17 @@ export async function runPipeline(options: PipelineOptions): Promise<GeneratedFi
|
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
if (dryRun) {
|
|
96
|
+
if (cleanOutDir) {
|
|
97
|
+
console.log(`[dry-run] Would clean outDir: ${outDir}`)
|
|
98
|
+
}
|
|
95
99
|
for (const file of files) {
|
|
96
100
|
const bytes = Buffer.byteLength(file.code, 'utf-8')
|
|
97
101
|
console.log(`[dry-run] Would write: ${file.path} (${bytes} bytes)`)
|
|
98
102
|
}
|
|
99
103
|
} else {
|
|
104
|
+
if (cleanOutDir) {
|
|
105
|
+
await rm(outDir, { recursive: true, force: true })
|
|
106
|
+
}
|
|
100
107
|
await mkdir(outDir, { recursive: true })
|
|
101
108
|
for (const file of files) {
|
|
102
109
|
await writeFile(file.path, file.code, 'utf-8')
|
|
@@ -298,6 +298,8 @@ apiBuilder.register(factory, (c) => ctx, {
|
|
|
298
298
|
|
|
299
299
|
**Self-contained mode:** Use `--self-contained` to emit `_types.ts` (all client type definitions) and `_client.ts` (runtime: `createClient`, `createFetchAdapter`, hooks, errors) into the output directory. All scope files and `index.ts` will import from `./_types` instead of `ts-procedures/client`, so consumers have no runtime dependency on `ts-procedures`. With this flag, `ts-procedures` can be a devDependency only.
|
|
300
300
|
|
|
301
|
+
**Clean output directory:** Use `--clean-out-dir` (or `cleanOutDir: true` in the programmatic API) to recursively remove the output directory before writing, so scope files left over from deleted or renamed scopes are pruned. Skipped under `--dry-run`.
|
|
302
|
+
|
|
301
303
|
## Framework Comparison
|
|
302
304
|
|
|
303
305
|
| Aspect | Express | Hono |
|
|
@@ -317,7 +319,15 @@ import type { APIConfig, APIHttpRouteDoc, APIInput, HttpMethod } from 'ts-proced
|
|
|
317
319
|
|
|
318
320
|
// Client Runtime
|
|
319
321
|
import { createClient, createFetchAdapter } from 'ts-procedures/client'
|
|
320
|
-
import type {
|
|
322
|
+
import type {
|
|
323
|
+
ClientAdapter,
|
|
324
|
+
ClientHooks,
|
|
325
|
+
TypedStream,
|
|
326
|
+
ClientInstance,
|
|
327
|
+
ProcedureCallDefaults,
|
|
328
|
+
ProcedureCallOptions,
|
|
329
|
+
RequestMeta,
|
|
330
|
+
} from 'ts-procedures/client'
|
|
321
331
|
|
|
322
332
|
// Code Generation (build-time only)
|
|
323
333
|
import { generateClient } from 'ts-procedures/codegen'
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { ClientAdapter, ClientHooks, CallDescriptor } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Executes a single procedure call through the adapter.
|
|
4
|
-
*
|
|
5
|
-
* Flow:
|
|
6
|
-
* 1. Build AdapterRequest from descriptor
|
|
7
|
-
* 2. Run onBeforeRequest hooks (global then local)
|
|
8
|
-
* 3. Call adapter.request()
|
|
9
|
-
* 4. On adapter error: run onError hooks, re-throw
|
|
10
|
-
* 5. Run onAfterResponse hooks (hooks may mutate response.status)
|
|
11
|
-
* 6. If response status is non-2xx: throw ClientRequestError
|
|
12
|
-
* 7. Return response.body as TResponse
|
|
13
|
-
*/
|
|
14
|
-
export declare function executeCall<TResponse>(descriptor: CallDescriptor, basePath: string, adapter: ClientAdapter, globalHooks: ClientHooks, localHooks: ClientHooks | undefined): Promise<TResponse>;
|
package/build/src/client/call.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { buildAdapterRequest } from './request-builder.js';
|
|
2
|
-
import { runBeforeRequest, runAfterResponse, runOnError } from './hooks.js';
|
|
3
|
-
import { ClientRequestError } from './errors.js';
|
|
4
|
-
/**
|
|
5
|
-
* Executes a single procedure call through the adapter.
|
|
6
|
-
*
|
|
7
|
-
* Flow:
|
|
8
|
-
* 1. Build AdapterRequest from descriptor
|
|
9
|
-
* 2. Run onBeforeRequest hooks (global then local)
|
|
10
|
-
* 3. Call adapter.request()
|
|
11
|
-
* 4. On adapter error: run onError hooks, re-throw
|
|
12
|
-
* 5. Run onAfterResponse hooks (hooks may mutate response.status)
|
|
13
|
-
* 6. If response status is non-2xx: throw ClientRequestError
|
|
14
|
-
* 7. Return response.body as TResponse
|
|
15
|
-
*/
|
|
16
|
-
export async function executeCall(descriptor, basePath, adapter, globalHooks, localHooks) {
|
|
17
|
-
// 1. Build the initial request
|
|
18
|
-
let request = buildAdapterRequest(descriptor, basePath);
|
|
19
|
-
// 2. Run before-request hooks — they may mutate the request
|
|
20
|
-
const beforeCtx = await runBeforeRequest({ procedureName: descriptor.name, scope: descriptor.scope, request }, globalHooks, localHooks);
|
|
21
|
-
request = beforeCtx.request;
|
|
22
|
-
// 3. Call the adapter
|
|
23
|
-
let response;
|
|
24
|
-
try {
|
|
25
|
-
response = await adapter.request(request);
|
|
26
|
-
}
|
|
27
|
-
catch (err) {
|
|
28
|
-
// 4. On adapter error: run error hooks, re-throw
|
|
29
|
-
await runOnError({ procedureName: descriptor.name, scope: descriptor.scope, request, error: err }, globalHooks, localHooks);
|
|
30
|
-
throw err;
|
|
31
|
-
}
|
|
32
|
-
// 5. Run after-response hooks — they may mutate response.status to swallow errors
|
|
33
|
-
await runAfterResponse({ procedureName: descriptor.name, scope: descriptor.scope, request, response }, globalHooks, localHooks);
|
|
34
|
-
// 6. Check status AFTER hooks (hooks may have swallowed the error by mutating status)
|
|
35
|
-
if (response.status < 200 || response.status >= 300) {
|
|
36
|
-
throw new ClientRequestError({
|
|
37
|
-
status: response.status,
|
|
38
|
-
headers: response.headers,
|
|
39
|
-
body: response.body,
|
|
40
|
-
procedureName: descriptor.name,
|
|
41
|
-
scope: descriptor.scope,
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
// 7. Return the body
|
|
45
|
-
return response.body;
|
|
46
|
-
}
|
|
47
|
-
//# sourceMappingURL=call.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"call.js","sourceRoot":"","sources":["../../../src/client/call.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAOhD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,UAA0B,EAC1B,QAAgB,EAChB,OAAsB,EACtB,WAAwB,EACxB,UAAmC;IAEnC,+BAA+B;IAC/B,IAAI,OAAO,GAAG,mBAAmB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;IAEvD,4DAA4D;IAC5D,MAAM,SAAS,GAAG,MAAM,gBAAgB,CACtC,EAAE,aAAa,EAAE,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,EACpE,WAAW,EACX,UAAU,CACX,CAAA;IACD,OAAO,GAAG,SAAS,CAAC,OAAO,CAAA;IAE3B,sBAAsB;IACtB,IAAI,QAAQ,CAAA;IACZ,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAC3C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,iDAAiD;QACjD,MAAM,UAAU,CACd,EAAE,aAAa,EAAE,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAChF,WAAW,EACX,UAAU,CACX,CAAA;QACD,MAAM,GAAG,CAAA;IACX,CAAC;IAED,kFAAkF;IAClF,MAAM,gBAAgB,CACpB,EAAE,aAAa,EAAE,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAC9E,WAAW,EACX,UAAU,CACX,CAAA;IAED,sFAAsF;IACtF,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;QACpD,MAAM,IAAI,kBAAkB,CAAC;YAC3B,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,aAAa,EAAE,UAAU,CAAC,IAAI;YAC9B,KAAK,EAAE,UAAU,CAAC,KAAK;SACxB,CAAC,CAAA;IACJ,CAAC;IAED,qBAAqB;IACrB,OAAO,QAAQ,CAAC,IAAiB,CAAA;AACnC,CAAC"}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
-
import { executeCall } from './call.js';
|
|
3
|
-
import { ClientRequestError } from './errors.js';
|
|
4
|
-
// ── helpers ───────────────────────────────────────────────
|
|
5
|
-
function makeDescriptor(overrides) {
|
|
6
|
-
return {
|
|
7
|
-
name: 'GetUser',
|
|
8
|
-
scope: 'users',
|
|
9
|
-
path: '/users',
|
|
10
|
-
method: 'GET',
|
|
11
|
-
kind: 'rpc',
|
|
12
|
-
params: { id: '42' },
|
|
13
|
-
...overrides,
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
function makeAdapter(response) {
|
|
17
|
-
return {
|
|
18
|
-
request: vi.fn(async (_req) => ({
|
|
19
|
-
status: 200,
|
|
20
|
-
headers: {},
|
|
21
|
-
body: { id: '42', name: 'Alice' },
|
|
22
|
-
...response,
|
|
23
|
-
})),
|
|
24
|
-
stream: vi.fn(async () => {
|
|
25
|
-
throw new Error('stream not expected in call tests');
|
|
26
|
-
}),
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
// ── executeCall ───────────────────────────────────────────
|
|
30
|
-
describe('executeCall', () => {
|
|
31
|
-
it('calls adapter.request and returns body', async () => {
|
|
32
|
-
const adapter = makeAdapter({ body: { id: '1', name: 'Bob' } });
|
|
33
|
-
const result = await executeCall(makeDescriptor(), 'https://api.example.com', adapter, {}, undefined);
|
|
34
|
-
expect(adapter.request).toHaveBeenCalledOnce();
|
|
35
|
-
expect(result).toEqual({ id: '1', name: 'Bob' });
|
|
36
|
-
});
|
|
37
|
-
it('throws ClientRequestError on 4xx response', async () => {
|
|
38
|
-
const adapter = makeAdapter({ status: 404, body: { message: 'Not Found' } });
|
|
39
|
-
await expect(executeCall(makeDescriptor(), 'https://api.example.com', adapter, {}, undefined)).rejects.toThrow(ClientRequestError);
|
|
40
|
-
});
|
|
41
|
-
it('throws ClientRequestError on 5xx response', async () => {
|
|
42
|
-
const adapter = makeAdapter({ status: 500, body: { message: 'Server Error' } });
|
|
43
|
-
await expect(executeCall(makeDescriptor(), 'https://api.example.com', adapter, {}, undefined)).rejects.toThrow(ClientRequestError);
|
|
44
|
-
});
|
|
45
|
-
it('throws ClientRequestError on 199 response (below 200)', async () => {
|
|
46
|
-
const adapter = makeAdapter({ status: 199, body: null });
|
|
47
|
-
await expect(executeCall(makeDescriptor(), 'https://api.example.com', adapter, {}, undefined)).rejects.toThrow(ClientRequestError);
|
|
48
|
-
});
|
|
49
|
-
it('does not throw on 2xx boundary responses (200, 201, 299)', async () => {
|
|
50
|
-
for (const status of [200, 201, 204, 299]) {
|
|
51
|
-
const adapter = makeAdapter({ status, body: null });
|
|
52
|
-
await expect(executeCall(makeDescriptor(), 'https://api.example.com', adapter, {}, undefined)).resolves.not.toThrow();
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
it('runs onBeforeRequest before calling adapter (headers are modified)', async () => {
|
|
56
|
-
const capturedHeaders = [];
|
|
57
|
-
const adapter = {
|
|
58
|
-
request: vi.fn(async (req) => {
|
|
59
|
-
capturedHeaders.push(req.headers ?? {});
|
|
60
|
-
return { status: 200, headers: {}, body: {} };
|
|
61
|
-
}),
|
|
62
|
-
stream: vi.fn(async () => { throw new Error('not expected'); }),
|
|
63
|
-
};
|
|
64
|
-
const globalHooks = {
|
|
65
|
-
onBeforeRequest: (ctx) => ({
|
|
66
|
-
...ctx,
|
|
67
|
-
request: {
|
|
68
|
-
...ctx.request,
|
|
69
|
-
headers: { ...ctx.request.headers, 'x-auth': 'token-123' },
|
|
70
|
-
},
|
|
71
|
-
}),
|
|
72
|
-
};
|
|
73
|
-
await executeCall(makeDescriptor(), 'https://api.example.com', adapter, globalHooks, undefined);
|
|
74
|
-
expect(capturedHeaders[0]?.['x-auth']).toBe('token-123');
|
|
75
|
-
});
|
|
76
|
-
it('runs onAfterResponse after adapter returns', async () => {
|
|
77
|
-
const order = [];
|
|
78
|
-
const adapter = {
|
|
79
|
-
request: vi.fn(async () => {
|
|
80
|
-
order.push('adapter');
|
|
81
|
-
return { status: 200, headers: {}, body: {} };
|
|
82
|
-
}),
|
|
83
|
-
stream: vi.fn(async () => { throw new Error('not expected'); }),
|
|
84
|
-
};
|
|
85
|
-
const globalHooks = {
|
|
86
|
-
onAfterResponse: () => { order.push('afterResponse'); },
|
|
87
|
-
};
|
|
88
|
-
await executeCall(makeDescriptor(), 'https://api.example.com', adapter, globalHooks, undefined);
|
|
89
|
-
expect(order).toEqual(['adapter', 'afterResponse']);
|
|
90
|
-
});
|
|
91
|
-
it('does not throw when onAfterResponse swallows non-2xx by mutating status', async () => {
|
|
92
|
-
const adapter = makeAdapter({ status: 401, body: { message: 'Unauthorized' } });
|
|
93
|
-
const globalHooks = {
|
|
94
|
-
onAfterResponse: (ctx) => {
|
|
95
|
-
// Swallow the error by setting status to 200
|
|
96
|
-
ctx.response.status = 200;
|
|
97
|
-
},
|
|
98
|
-
};
|
|
99
|
-
await expect(executeCall(makeDescriptor(), 'https://api.example.com', adapter, globalHooks, undefined)).resolves.not.toThrow();
|
|
100
|
-
});
|
|
101
|
-
it('runs onError on adapter failure and re-throws', async () => {
|
|
102
|
-
const adapterError = new Error('Network failure');
|
|
103
|
-
const adapter = {
|
|
104
|
-
request: vi.fn(async () => { throw adapterError; }),
|
|
105
|
-
stream: vi.fn(async () => { throw new Error('not expected'); }),
|
|
106
|
-
};
|
|
107
|
-
const receivedErrors = [];
|
|
108
|
-
const globalHooks = {
|
|
109
|
-
onError: (ctx) => { receivedErrors.push(ctx.error); },
|
|
110
|
-
};
|
|
111
|
-
await expect(executeCall(makeDescriptor(), 'https://api.example.com', adapter, globalHooks, undefined)).rejects.toThrow('Network failure');
|
|
112
|
-
expect(receivedErrors[0]).toBe(adapterError);
|
|
113
|
-
});
|
|
114
|
-
it('passes per-procedure hooks as local hooks', async () => {
|
|
115
|
-
const adapter = makeAdapter();
|
|
116
|
-
const localOrder = [];
|
|
117
|
-
const localHooks = {
|
|
118
|
-
onBeforeRequest: (ctx) => { localOrder.push('local-before'); return ctx; },
|
|
119
|
-
};
|
|
120
|
-
await executeCall(makeDescriptor(), 'https://api.example.com', adapter, {}, localHooks);
|
|
121
|
-
expect(localOrder).toContain('local-before');
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
//# sourceMappingURL=call.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"call.test.js","sourceRoot":"","sources":["../../../src/client/call.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export declare class ClientRequestError extends Error {
|
|
2
|
-
readonly name = "ClientRequestError";
|
|
3
|
-
readonly status: number;
|
|
4
|
-
readonly headers: Record<string, string>;
|
|
5
|
-
readonly body: unknown;
|
|
6
|
-
readonly procedureName: string;
|
|
7
|
-
readonly scope: string;
|
|
8
|
-
constructor(opts: {
|
|
9
|
-
status: number;
|
|
10
|
-
headers: Record<string, string>;
|
|
11
|
-
body: unknown;
|
|
12
|
-
procedureName: string;
|
|
13
|
-
scope: string;
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
export declare class ClientPathParamError extends Error {
|
|
17
|
-
readonly name = "ClientPathParamError";
|
|
18
|
-
constructor(param: string, path: string, procedureName: string);
|
|
19
|
-
}
|
|
20
|
-
export declare class ClientStreamError extends Error {
|
|
21
|
-
readonly name = "ClientStreamError";
|
|
22
|
-
readonly procedureName: string;
|
|
23
|
-
readonly scope: string;
|
|
24
|
-
constructor(message: string, procedureName: string, scope: string);
|
|
25
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
export class ClientRequestError extends Error {
|
|
2
|
-
name = 'ClientRequestError';
|
|
3
|
-
status;
|
|
4
|
-
headers;
|
|
5
|
-
body;
|
|
6
|
-
procedureName;
|
|
7
|
-
scope;
|
|
8
|
-
constructor(opts) {
|
|
9
|
-
super(`${opts.procedureName} (${opts.scope}) failed with status ${opts.status}`);
|
|
10
|
-
this.status = opts.status;
|
|
11
|
-
this.headers = opts.headers;
|
|
12
|
-
this.body = opts.body;
|
|
13
|
-
this.procedureName = opts.procedureName;
|
|
14
|
-
this.scope = opts.scope;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
export class ClientPathParamError extends Error {
|
|
18
|
-
name = 'ClientPathParamError';
|
|
19
|
-
constructor(param, path, procedureName) {
|
|
20
|
-
super(`Missing path parameter "${param}" in "${path}" for procedure ${procedureName}`);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
export class ClientStreamError extends Error {
|
|
24
|
-
name = 'ClientStreamError';
|
|
25
|
-
procedureName;
|
|
26
|
-
scope;
|
|
27
|
-
constructor(message, procedureName, scope) {
|
|
28
|
-
super(message);
|
|
29
|
-
this.procedureName = procedureName;
|
|
30
|
-
this.scope = scope;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
//# sourceMappingURL=errors.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/client/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAClC,IAAI,GAAG,oBAAoB,CAAA;IAC3B,MAAM,CAAQ;IACd,OAAO,CAAwB;IAC/B,IAAI,CAAS;IACb,aAAa,CAAQ;IACrB,KAAK,CAAQ;IAEtB,YAAY,IAMX;QACC,KAAK,CAAC,GAAG,IAAI,CAAC,aAAa,KAAK,IAAI,CAAC,KAAK,wBAAwB,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;QAChF,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QACzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAA;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;QACrB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAA;QACvC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;IACzB,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,IAAI,GAAG,sBAAsB,CAAA;IAEtC,YAAY,KAAa,EAAE,IAAY,EAAE,aAAqB;QAC5D,KAAK,CAAC,2BAA2B,KAAK,SAAS,IAAI,mBAAmB,aAAa,EAAE,CAAC,CAAA;IACxF,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACjC,IAAI,GAAG,mBAAmB,CAAA;IAC1B,aAAa,CAAQ;IACrB,KAAK,CAAQ;IAEtB,YAAY,OAAe,EAAE,aAAqB,EAAE,KAAa;QAC/D,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA;QAClC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;IACpB,CAAC;CACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|