ts-procedures 5.13.0 → 5.15.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/agents/ts-procedures-architect.md +0 -1
- package/agent_config/claude-code/skills/ts-procedures/anti-patterns.md +0 -25
- package/agent_config/claude-code/skills/ts-procedures/api-reference.md +26 -4
- package/agent_config/claude-code/skills/ts-procedures/patterns.md +2 -1
- package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/client.md +3 -0
- package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono-api.md +1 -1
- package/agent_config/copilot/copilot-instructions.md +2 -2
- package/agent_config/cursor/cursorrules +2 -2
- 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/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/build/implementations/http/hono-api/index.d.ts +15 -3
- package/build/implementations/http/hono-api/index.js +3 -32
- package/build/implementations/http/hono-api/index.js.map +1 -1
- package/build/implementations/http/hono-api/index.test.js +6 -6
- package/build/implementations/http/hono-api/index.test.js.map +1 -1
- package/docs/client-and-codegen.md +2 -0
- package/package.json +2 -3
- package/src/codegen/bin/cli.test.ts +35 -0
- package/src/codegen/bin/cli.ts +11 -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 +2 -0
- package/src/implementations/http/hono-api/index.test.ts +6 -6
- package/src/implementations/http/hono-api/index.ts +17 -36
- 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.d.ts +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/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 |
|
|
@@ -881,7 +881,7 @@ describe('HonoAPIAppBuilder', () => {
|
|
|
881
881
|
)
|
|
882
882
|
|
|
883
883
|
builder.register(API, () => ({}))
|
|
884
|
-
|
|
884
|
+
expect(() => builder.build()).toThrow(/pathParams is not defined/)
|
|
885
885
|
})
|
|
886
886
|
|
|
887
887
|
test('throws when schema.input.pathParams defined but path has no params', async () => {
|
|
@@ -903,7 +903,7 @@ describe('HonoAPIAppBuilder', () => {
|
|
|
903
903
|
)
|
|
904
904
|
|
|
905
905
|
builder.register(API, () => ({}))
|
|
906
|
-
|
|
906
|
+
expect(() => builder.build()).toThrow(/has no path parameters/)
|
|
907
907
|
})
|
|
908
908
|
|
|
909
909
|
test('no error when path has params and pathParams schema matches', async () => {
|
|
@@ -925,7 +925,7 @@ describe('HonoAPIAppBuilder', () => {
|
|
|
925
925
|
)
|
|
926
926
|
|
|
927
927
|
builder.register(API, () => ({}))
|
|
928
|
-
|
|
928
|
+
expect(builder.build()).toBeDefined()
|
|
929
929
|
})
|
|
930
930
|
|
|
931
931
|
test('throws when pathParams schema keys do not match path param names', async () => {
|
|
@@ -948,7 +948,7 @@ describe('HonoAPIAppBuilder', () => {
|
|
|
948
948
|
)
|
|
949
949
|
|
|
950
950
|
builder.register(API, () => ({}))
|
|
951
|
-
|
|
951
|
+
expect(() => builder.build()).toThrow(/Path param mismatch/)
|
|
952
952
|
})
|
|
953
953
|
|
|
954
954
|
test('throws when path has multiple params and schema is missing one', async () => {
|
|
@@ -971,7 +971,7 @@ describe('HonoAPIAppBuilder', () => {
|
|
|
971
971
|
)
|
|
972
972
|
|
|
973
973
|
builder.register(API, () => ({}))
|
|
974
|
-
|
|
974
|
+
expect(() => builder.build()).toThrow(/commentId/)
|
|
975
975
|
})
|
|
976
976
|
|
|
977
977
|
test('no validation when schema.input is not used', async () => {
|
|
@@ -989,7 +989,7 @@ describe('HonoAPIAppBuilder', () => {
|
|
|
989
989
|
)
|
|
990
990
|
|
|
991
991
|
builder.register(API, () => ({}))
|
|
992
|
-
|
|
992
|
+
expect(builder.build()).toBeDefined()
|
|
993
993
|
})
|
|
994
994
|
})
|
|
995
995
|
|
|
@@ -19,22 +19,7 @@ export type { APIConfig, APIHttpRouteDoc, APIInput, HttpMethod }
|
|
|
19
19
|
|
|
20
20
|
export type QueryParser = (queryString: string) => Record<string, unknown>
|
|
21
21
|
|
|
22
|
-
/**
|
|
23
|
-
let _qsModule: { parse: (str: string, opts?: any) => any } | false | undefined
|
|
24
|
-
|
|
25
|
-
async function loadQs(): Promise<{ parse: (str: string, opts?: any) => any } | undefined> {
|
|
26
|
-
if (_qsModule === undefined) {
|
|
27
|
-
try {
|
|
28
|
-
const mod = await import('qs')
|
|
29
|
-
_qsModule = mod.default ?? mod
|
|
30
|
-
} catch {
|
|
31
|
-
_qsModule = false
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return _qsModule || undefined
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/** Fallback query parser using native URLSearchParams */
|
|
22
|
+
/** Default query parser using native URLSearchParams. */
|
|
38
23
|
function parseQueryNative(queryString: string): Record<string, unknown> {
|
|
39
24
|
const searchParams = new URLSearchParams(queryString)
|
|
40
25
|
const result: Record<string, unknown> = {}
|
|
@@ -45,21 +30,6 @@ function parseQueryNative(queryString: string): Record<string, unknown> {
|
|
|
45
30
|
return result
|
|
46
31
|
}
|
|
47
32
|
|
|
48
|
-
/**
|
|
49
|
-
* Resolves the query parser once. Called during build() so handlers use a sync parser.
|
|
50
|
-
* Priority: custom queryParser > qs (optional peer dep) > native URLSearchParams
|
|
51
|
-
*/
|
|
52
|
-
async function resolveQueryParser(custom?: QueryParser): Promise<QueryParser> {
|
|
53
|
-
if (custom) return custom
|
|
54
|
-
|
|
55
|
-
const qs = await loadQs()
|
|
56
|
-
if (qs) {
|
|
57
|
-
return (raw: string) => qs.parse(raw) as Record<string, unknown>
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return parseQueryNative
|
|
61
|
-
}
|
|
62
|
-
|
|
63
33
|
/** Extract path parameter names from a route pattern (e.g., '/users/:id' → ['id']) */
|
|
64
34
|
function extractPathParamNames(path: string): string[] {
|
|
65
35
|
const matches = path.match(/:([a-zA-Z_][a-zA-Z0-9_]*)/g)
|
|
@@ -104,7 +74,20 @@ export type HonoAPIAppBuilderConfig = {
|
|
|
104
74
|
pathPrefix?: string
|
|
105
75
|
/**
|
|
106
76
|
* Custom query string parser. Receives the raw query string (without '?').
|
|
107
|
-
*
|
|
77
|
+
*
|
|
78
|
+
* Default: native `URLSearchParams`. The default handles:
|
|
79
|
+
* - flat keys: `?page=2&limit=10` → `{ page: '2', limit: '10' }`
|
|
80
|
+
* - repeated keys: `?tag=a&tag=b` → `{ tag: ['a', 'b'] }`
|
|
81
|
+
*
|
|
82
|
+
* The default does NOT parse any of these — the bracket/dot syntax is kept
|
|
83
|
+
* as part of the literal key name, not interpreted:
|
|
84
|
+
* - bracket objects: `?user[name]=John` → `{ 'user[name]': 'John' }`
|
|
85
|
+
* - bracket arrays: `?tags[]=a&tags[]=b` → `{ 'tags[]': ['a', 'b'] }`
|
|
86
|
+
* - dot paths: `?user.name=John` → `{ 'user.name': 'John' }`
|
|
87
|
+
* - comma-split arrays: `?tags=a,b,c` → `{ tags: 'a,b,c' }`
|
|
88
|
+
*
|
|
89
|
+
* For any of the above, install `qs` and opt in explicitly:
|
|
90
|
+
* `queryParser: (raw) => qs.parse(raw) as Record<string, unknown>`
|
|
108
91
|
*/
|
|
109
92
|
queryParser?: QueryParser
|
|
110
93
|
onRequestStart?: (c: Context) => void
|
|
@@ -216,11 +199,9 @@ export class HonoAPIAppBuilder {
|
|
|
216
199
|
|
|
217
200
|
/**
|
|
218
201
|
* Builds and returns the Hono application with registered API routes.
|
|
219
|
-
* Async because it resolves the query parser (qs optional peer dep) once at build time.
|
|
220
202
|
*/
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
const queryParser = await resolveQueryParser(this.config?.queryParser)
|
|
203
|
+
build(): Hono {
|
|
204
|
+
const queryParser = this.config?.queryParser ?? parseQueryNative
|
|
224
205
|
|
|
225
206
|
this.factories.forEach(({ factory, factoryContext, extendProcedureDoc }) => {
|
|
226
207
|
factory.getProcedures().map((procedure: TProcedureRegistration<any, APIConfig>) => {
|
|
@@ -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 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -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 {};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { ClientRequestError, ClientPathParamError, ClientStreamError } from './errors.js';
|
|
3
|
-
describe('ClientRequestError', () => {
|
|
4
|
-
it('includes status, headers, and body', () => {
|
|
5
|
-
const err = new ClientRequestError({
|
|
6
|
-
status: 401,
|
|
7
|
-
headers: { 'x-request-id': 'abc' },
|
|
8
|
-
body: { message: 'Unauthorized' },
|
|
9
|
-
procedureName: 'GetUser',
|
|
10
|
-
scope: 'users',
|
|
11
|
-
});
|
|
12
|
-
expect(err).toBeInstanceOf(Error);
|
|
13
|
-
expect(err.name).toBe('ClientRequestError');
|
|
14
|
-
expect(err.status).toBe(401);
|
|
15
|
-
expect(err.headers['x-request-id']).toBe('abc');
|
|
16
|
-
expect(err.body).toEqual({ message: 'Unauthorized' });
|
|
17
|
-
expect(err.procedureName).toBe('GetUser');
|
|
18
|
-
expect(err.scope).toBe('users');
|
|
19
|
-
expect(err.message).toBe('GetUser (users) failed with status 401');
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
describe('ClientPathParamError', () => {
|
|
23
|
-
it('reports missing param', () => {
|
|
24
|
-
const err = new ClientPathParamError('id', '/users/:id', 'GetUser');
|
|
25
|
-
expect(err).toBeInstanceOf(Error);
|
|
26
|
-
expect(err.name).toBe('ClientPathParamError');
|
|
27
|
-
expect(err.message).toContain('id');
|
|
28
|
-
expect(err.message).toContain('/users/:id');
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
describe('ClientStreamError', () => {
|
|
32
|
-
it('includes procedure context', () => {
|
|
33
|
-
const err = new ClientStreamError('stream interrupted', 'Watch', 'events');
|
|
34
|
-
expect(err).toBeInstanceOf(Error);
|
|
35
|
-
expect(err.name).toBe('ClientStreamError');
|
|
36
|
-
expect(err.procedureName).toBe('Watch');
|
|
37
|
-
expect(err.scope).toBe('events');
|
|
38
|
-
expect(err.message).toBe('stream interrupted');
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
//# sourceMappingURL=errors.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors.test.js","sourceRoot":"","sources":["../../../src/client/errors.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEzF,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,GAAG,GAAG,IAAI,kBAAkB,CAAC;YACjC,MAAM,EAAE,GAAG;YACX,OAAO,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE;YAClC,IAAI,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE;YACjC,aAAa,EAAE,SAAS;YACxB,KAAK,EAAE,OAAO;SACf,CAAC,CAAA;QACF,MAAM,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;QACjC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAA;QAC3C,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC5B,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC/C,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAA;QACrD,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QACzC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC/B,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAA;IACpE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,IAAI,EAAE,YAAY,EAAE,SAAS,CAAC,CAAA;QACnE,MAAM,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;QACjC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;QAC7C,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;QACnC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAA;IAC7C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAAC,oBAAoB,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAA;QAC1E,MAAM,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;QACjC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;QAC1C,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACvC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAChC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { ClientAdapter } from './types.js';
|
|
2
|
-
export interface FetchAdapterConfig {
|
|
3
|
-
headers?: Record<string, string>;
|
|
4
|
-
}
|
|
5
|
-
/**
|
|
6
|
-
* Creates a fetch-based ClientAdapter.
|
|
7
|
-
*
|
|
8
|
-
* - `config.headers` are default headers applied to every request.
|
|
9
|
-
* - Per-request headers override config headers (spread order).
|
|
10
|
-
* - Works in Node.js 18+ and browsers (uses standard fetch + ReadableStream).
|
|
11
|
-
*/
|
|
12
|
-
export declare function createFetchAdapter(config?: FetchAdapterConfig): ClientAdapter;
|