ts-procedures 10.3.1 → 11.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/agent_config/skills/ts-procedures/api-reference.md +4 -4
- package/build/client/call.d.ts +2 -1
- package/build/client/call.js +20 -9
- package/build/client/call.js.map +1 -1
- package/build/client/call.test.js +72 -9
- package/build/client/call.test.js.map +1 -1
- package/build/client/errors.d.ts +0 -4
- package/build/client/errors.js +0 -2
- package/build/client/errors.js.map +1 -1
- package/build/client/errors.test.js +1 -16
- package/build/client/errors.test.js.map +1 -1
- package/build/client/freeze.test.js +22 -10
- package/build/client/freeze.test.js.map +1 -1
- package/build/client/index.d.ts +1 -1
- package/build/client/index.js +1 -1
- package/build/client/index.js.map +1 -1
- package/build/client/index.test.js +6 -6
- package/build/client/index.test.js.map +1 -1
- package/build/client/resolve-options.d.ts +1 -14
- package/build/client/resolve-options.js +0 -15
- package/build/client/resolve-options.js.map +1 -1
- package/build/client/resolve-options.test.js +1 -63
- package/build/client/resolve-options.test.js.map +1 -1
- package/build/client/stream.test.js +3 -3
- package/build/client/stream.test.js.map +1 -1
- package/build/client/typed-error-dispatch.test.js +2 -2
- package/build/client/typed-error-dispatch.test.js.map +1 -1
- package/build/codegen/e2e.test.js +2 -2
- package/build/codegen/e2e.test.js.map +1 -1
- package/build/codegen/emit-client-runtime.test.js +3 -3
- package/build/codegen/emit-client-runtime.test.js.map +1 -1
- package/build/codegen/emit-index.js +17 -0
- package/build/codegen/emit-index.js.map +1 -1
- package/build/codegen/goldens.test.js +18 -0
- package/build/codegen/goldens.test.js.map +1 -1
- package/build/exports.d.ts +1 -1
- package/build/schema/json-schema.d.ts +0 -2
- package/docs/client-and-codegen.md +2 -2
- package/docs/client-error-handling.md +3 -3
- package/docs/core.md +1 -2
- package/docs/migration-v8-to-v9.md +2 -2
- package/package.json +1 -1
- package/src/client/call.test.ts +80 -8
- package/src/client/call.ts +23 -9
- package/src/client/errors.test.ts +0 -18
- package/src/client/errors.ts +0 -7
- package/src/client/freeze.test.ts +22 -10
- package/src/client/index.test.ts +6 -6
- package/src/client/index.ts +0 -1
- package/src/client/resolve-options.test.ts +0 -73
- package/src/client/resolve-options.ts +1 -20
- package/src/client/stream.test.ts +3 -3
- package/src/client/typed-error-dispatch.test.ts +2 -2
- package/src/codegen/__goldens__/ts-default--models/_client.ts +24 -36
- package/src/codegen/__goldens__/ts-default--models/_types.ts +0 -7
- package/src/codegen/__goldens__/ts-default--models/index.ts +10 -0
- package/src/codegen/__goldens__/ts-default--users/_client.ts +24 -36
- package/src/codegen/__goldens__/ts-default--users/_types.ts +0 -7
- package/src/codegen/__goldens__/ts-default--users/index.ts +10 -0
- package/src/codegen/__goldens__/ts-external-runtime--models/index.ts +10 -0
- package/src/codegen/__goldens__/ts-external-runtime--users/index.ts +10 -0
- package/src/codegen/__goldens__/ts-flat--models/_client.ts +24 -36
- package/src/codegen/__goldens__/ts-flat--models/_types.ts +0 -7
- package/src/codegen/__goldens__/ts-flat--models/index.ts +10 -0
- package/src/codegen/__goldens__/ts-flat--users/_client.ts +24 -36
- package/src/codegen/__goldens__/ts-flat--users/_types.ts +0 -7
- package/src/codegen/__goldens__/ts-flat--users/index.ts +10 -0
- package/src/codegen/__goldens__/ts-no-share-models--models/_client.ts +24 -36
- package/src/codegen/__goldens__/ts-no-share-models--models/_types.ts +0 -7
- package/src/codegen/__goldens__/ts-no-share-models--models/index.ts +10 -0
- package/src/codegen/__goldens__/ts-no-share-models--users/_client.ts +24 -36
- package/src/codegen/__goldens__/ts-no-share-models--users/_types.ts +0 -7
- package/src/codegen/__goldens__/ts-no-share-models--users/index.ts +10 -0
- package/src/codegen/__goldens__/ts-shared-models-module--models/_client.ts +24 -36
- package/src/codegen/__goldens__/ts-shared-models-module--models/_types.ts +0 -7
- package/src/codegen/__goldens__/ts-shared-models-module--models/index.ts +10 -0
- package/src/codegen/e2e.test.ts +2 -2
- package/src/codegen/emit-client-runtime.test.ts +3 -3
- package/src/codegen/emit-index.ts +19 -0
- package/src/codegen/goldens.test.ts +18 -0
- package/src/exports.ts +1 -1
- package/src/schema/json-schema.ts +0 -3
|
@@ -59,13 +59,6 @@ export class ClientHttpError extends Error {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
/** @deprecated Renamed to `ClientHttpError`. The alias is retained for one minor release after the 7.0.0 major bump and will be removed in a subsequent minor (e.g. 7.1.0). Migrate to `ClientHttpError` now. */
|
|
63
|
-
|
|
64
|
-
export const ClientRequestError = ClientHttpError
|
|
65
|
-
/** @deprecated Renamed to `ClientHttpError`. The alias is retained for one minor release after the 7.0.0 major bump and will be removed in a subsequent minor (e.g. 7.1.0). Migrate to `ClientHttpError` now. */
|
|
66
|
-
// eslint-disable-next-line no-redeclare
|
|
67
|
-
export type ClientRequestError = ClientHttpError
|
|
68
|
-
|
|
69
62
|
export class ClientPathParamError extends Error {
|
|
70
63
|
readonly name = 'ClientPathParamError'
|
|
71
64
|
|
|
@@ -305,7 +298,7 @@ export function resolveBasePath(
|
|
|
305
298
|
* - `timeoutMs`: the resolved timeout value (may be 0 if per-call explicitly disables)
|
|
306
299
|
* - `combined`: `AbortSignal.any([...])` of all active signals, or undefined if none
|
|
307
300
|
*
|
|
308
|
-
* Per-call `timeout: 0` disables an inherited default timeout
|
|
301
|
+
* Per-call `timeout: 0` disables an inherited default timeout.
|
|
309
302
|
* Both `defaults.signal` and `options.signal` are included in `combined` when present.
|
|
310
303
|
*/
|
|
311
304
|
export interface SignalSources {
|
|
@@ -338,25 +331,6 @@ export function resolveSignalSources(
|
|
|
338
331
|
return { combined, timeoutSignal, userSignal, timeoutMs }
|
|
339
332
|
}
|
|
340
333
|
|
|
341
|
-
/**
|
|
342
|
-
* Resolves the effective AbortSignal by combining (via `AbortSignal.any`):
|
|
343
|
-
* - default signal (if any)
|
|
344
|
-
* - per-call signal (if any)
|
|
345
|
-
* - timeout signal (if resolved timeout > 0)
|
|
346
|
-
*
|
|
347
|
-
* Returns undefined when none apply. Per-call `timeout: 0` disables an
|
|
348
|
-
* inherited default timeout.
|
|
349
|
-
*
|
|
350
|
-
* @deprecated Prefer `resolveSignalSources` when you need access to individual
|
|
351
|
-
* signal references (e.g. for abort-cause classification).
|
|
352
|
-
*/
|
|
353
|
-
export function resolveSignal(
|
|
354
|
-
defaults: ProcedureCallDefaults | undefined,
|
|
355
|
-
options: ProcedureCallOptions | undefined,
|
|
356
|
-
): AbortSignal | undefined {
|
|
357
|
-
return resolveSignalSources(defaults, options).combined
|
|
358
|
-
}
|
|
359
|
-
|
|
360
334
|
/**
|
|
361
335
|
* Resolves a `ClientHeadersInit` value: a static record passes through, a
|
|
362
336
|
* function is invoked and (if async) awaited — re-evaluated on every call so
|
|
@@ -599,19 +573,32 @@ export async function executeCall<TResponse>(config: ExecuteCallConfig): Promise
|
|
|
599
573
|
procedureName: descriptor.name,
|
|
600
574
|
scope: descriptor.scope,
|
|
601
575
|
})
|
|
576
|
+
let httpError: Error
|
|
602
577
|
if (typed) {
|
|
603
578
|
// Tag so executeSafeCall can distinguish typed registry errors from plain
|
|
604
579
|
// ClientHttpError without re-inspecting the registry.
|
|
605
580
|
;(typed as unknown as { __tsProceduresTyped?: boolean }).__tsProceduresTyped = true
|
|
606
|
-
|
|
581
|
+
httpError = typed
|
|
582
|
+
} else {
|
|
583
|
+
httpError = new ClientHttpError({
|
|
584
|
+
status: response.status,
|
|
585
|
+
headers: response.headers,
|
|
586
|
+
body: response.body,
|
|
587
|
+
procedureName: descriptor.name,
|
|
588
|
+
scope: descriptor.scope,
|
|
589
|
+
})
|
|
607
590
|
}
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
591
|
+
// A non-2xx response is not a thrown adapter error (fetch resolves it), so
|
|
592
|
+
// it bypasses the catch block above. Fire onError here too so the hook is a
|
|
593
|
+
// uniform cross-cutting failure signal across adapter throws AND HTTP error
|
|
594
|
+
// statuses (401/403/5xx). Runs after onAfterResponse, which had its chance
|
|
595
|
+
// to swallow the error by mutating status back into the 2xx range.
|
|
596
|
+
await runOnError(
|
|
597
|
+
{ procedureName: descriptor.name, scope: descriptor.scope, request, error: httpError },
|
|
598
|
+
hooks,
|
|
599
|
+
options,
|
|
600
|
+
)
|
|
601
|
+
throw httpError
|
|
615
602
|
}
|
|
616
603
|
|
|
617
604
|
// 8. Return the body (or { body, headers } when the route declares res.headers)
|
|
@@ -629,7 +616,8 @@ export async function executeCall<TResponse>(config: ExecuteCallConfig): Promise
|
|
|
629
616
|
* 2. Adapter throw, classified → `kind: 'network' | 'timeout' | 'aborted' | <custom> | 'unknown'`
|
|
630
617
|
* 3. Adapter returns non-2xx → `kind: 'typed'` (registry match) or `kind: 'http'`
|
|
631
618
|
*
|
|
632
|
-
* `onError` hook fires on path 2 and 3 (cross-cutting telemetry)
|
|
619
|
+
* `onError` hook fires on path 2 and 3 (cross-cutting telemetry) — including
|
|
620
|
+
* plain non-2xx `ClientHttpError` and typed registry errors — but NOT on
|
|
633
621
|
* path 1 (usage errors bypass the classifier and onError entirely).
|
|
634
622
|
*/
|
|
635
623
|
export async function executeSafeCall<TResponse, ETyped = never>(
|
|
@@ -29,13 +29,6 @@ export class ClientHttpError extends Error {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
/** @deprecated Renamed to `ClientHttpError`. The alias is retained for one minor release after the 7.0.0 major bump and will be removed in a subsequent minor (e.g. 7.1.0). Migrate to `ClientHttpError` now. */
|
|
33
|
-
|
|
34
|
-
export const ClientRequestError = ClientHttpError
|
|
35
|
-
/** @deprecated Renamed to `ClientHttpError`. The alias is retained for one minor release after the 7.0.0 major bump and will be removed in a subsequent minor (e.g. 7.1.0). Migrate to `ClientHttpError` now. */
|
|
36
|
-
// eslint-disable-next-line no-redeclare
|
|
37
|
-
export type ClientRequestError = ClientHttpError
|
|
38
|
-
|
|
39
32
|
export class ClientPathParamError extends Error {
|
|
40
33
|
readonly name = 'ClientPathParamError'
|
|
41
34
|
|
|
@@ -7,6 +7,16 @@ import * as _billing from './billing'
|
|
|
7
7
|
import * as _billingReports from './billing-reports'
|
|
8
8
|
import * as _errorsModule from './_errors'
|
|
9
9
|
|
|
10
|
+
export {
|
|
11
|
+
ClientHttpError,
|
|
12
|
+
ClientPathParamError,
|
|
13
|
+
ClientStreamError,
|
|
14
|
+
ClientNetworkError,
|
|
15
|
+
ClientTimeoutError,
|
|
16
|
+
ClientAbortError,
|
|
17
|
+
ClientParseError,
|
|
18
|
+
} from './_client'
|
|
19
|
+
|
|
10
20
|
export namespace Api {
|
|
11
21
|
export import Orders = _orders.Orders
|
|
12
22
|
export import Billing = _billing.Billing
|
|
@@ -59,13 +59,6 @@ export class ClientHttpError extends Error {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
/** @deprecated Renamed to `ClientHttpError`. The alias is retained for one minor release after the 7.0.0 major bump and will be removed in a subsequent minor (e.g. 7.1.0). Migrate to `ClientHttpError` now. */
|
|
63
|
-
|
|
64
|
-
export const ClientRequestError = ClientHttpError
|
|
65
|
-
/** @deprecated Renamed to `ClientHttpError`. The alias is retained for one minor release after the 7.0.0 major bump and will be removed in a subsequent minor (e.g. 7.1.0). Migrate to `ClientHttpError` now. */
|
|
66
|
-
// eslint-disable-next-line no-redeclare
|
|
67
|
-
export type ClientRequestError = ClientHttpError
|
|
68
|
-
|
|
69
62
|
export class ClientPathParamError extends Error {
|
|
70
63
|
readonly name = 'ClientPathParamError'
|
|
71
64
|
|
|
@@ -305,7 +298,7 @@ export function resolveBasePath(
|
|
|
305
298
|
* - `timeoutMs`: the resolved timeout value (may be 0 if per-call explicitly disables)
|
|
306
299
|
* - `combined`: `AbortSignal.any([...])` of all active signals, or undefined if none
|
|
307
300
|
*
|
|
308
|
-
* Per-call `timeout: 0` disables an inherited default timeout
|
|
301
|
+
* Per-call `timeout: 0` disables an inherited default timeout.
|
|
309
302
|
* Both `defaults.signal` and `options.signal` are included in `combined` when present.
|
|
310
303
|
*/
|
|
311
304
|
export interface SignalSources {
|
|
@@ -338,25 +331,6 @@ export function resolveSignalSources(
|
|
|
338
331
|
return { combined, timeoutSignal, userSignal, timeoutMs }
|
|
339
332
|
}
|
|
340
333
|
|
|
341
|
-
/**
|
|
342
|
-
* Resolves the effective AbortSignal by combining (via `AbortSignal.any`):
|
|
343
|
-
* - default signal (if any)
|
|
344
|
-
* - per-call signal (if any)
|
|
345
|
-
* - timeout signal (if resolved timeout > 0)
|
|
346
|
-
*
|
|
347
|
-
* Returns undefined when none apply. Per-call `timeout: 0` disables an
|
|
348
|
-
* inherited default timeout.
|
|
349
|
-
*
|
|
350
|
-
* @deprecated Prefer `resolveSignalSources` when you need access to individual
|
|
351
|
-
* signal references (e.g. for abort-cause classification).
|
|
352
|
-
*/
|
|
353
|
-
export function resolveSignal(
|
|
354
|
-
defaults: ProcedureCallDefaults | undefined,
|
|
355
|
-
options: ProcedureCallOptions | undefined,
|
|
356
|
-
): AbortSignal | undefined {
|
|
357
|
-
return resolveSignalSources(defaults, options).combined
|
|
358
|
-
}
|
|
359
|
-
|
|
360
334
|
/**
|
|
361
335
|
* Resolves a `ClientHeadersInit` value: a static record passes through, a
|
|
362
336
|
* function is invoked and (if async) awaited — re-evaluated on every call so
|
|
@@ -599,19 +573,32 @@ export async function executeCall<TResponse>(config: ExecuteCallConfig): Promise
|
|
|
599
573
|
procedureName: descriptor.name,
|
|
600
574
|
scope: descriptor.scope,
|
|
601
575
|
})
|
|
576
|
+
let httpError: Error
|
|
602
577
|
if (typed) {
|
|
603
578
|
// Tag so executeSafeCall can distinguish typed registry errors from plain
|
|
604
579
|
// ClientHttpError without re-inspecting the registry.
|
|
605
580
|
;(typed as unknown as { __tsProceduresTyped?: boolean }).__tsProceduresTyped = true
|
|
606
|
-
|
|
581
|
+
httpError = typed
|
|
582
|
+
} else {
|
|
583
|
+
httpError = new ClientHttpError({
|
|
584
|
+
status: response.status,
|
|
585
|
+
headers: response.headers,
|
|
586
|
+
body: response.body,
|
|
587
|
+
procedureName: descriptor.name,
|
|
588
|
+
scope: descriptor.scope,
|
|
589
|
+
})
|
|
607
590
|
}
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
591
|
+
// A non-2xx response is not a thrown adapter error (fetch resolves it), so
|
|
592
|
+
// it bypasses the catch block above. Fire onError here too so the hook is a
|
|
593
|
+
// uniform cross-cutting failure signal across adapter throws AND HTTP error
|
|
594
|
+
// statuses (401/403/5xx). Runs after onAfterResponse, which had its chance
|
|
595
|
+
// to swallow the error by mutating status back into the 2xx range.
|
|
596
|
+
await runOnError(
|
|
597
|
+
{ procedureName: descriptor.name, scope: descriptor.scope, request, error: httpError },
|
|
598
|
+
hooks,
|
|
599
|
+
options,
|
|
600
|
+
)
|
|
601
|
+
throw httpError
|
|
615
602
|
}
|
|
616
603
|
|
|
617
604
|
// 8. Return the body (or { body, headers } when the route declares res.headers)
|
|
@@ -629,7 +616,8 @@ export async function executeCall<TResponse>(config: ExecuteCallConfig): Promise
|
|
|
629
616
|
* 2. Adapter throw, classified → `kind: 'network' | 'timeout' | 'aborted' | <custom> | 'unknown'`
|
|
630
617
|
* 3. Adapter returns non-2xx → `kind: 'typed'` (registry match) or `kind: 'http'`
|
|
631
618
|
*
|
|
632
|
-
* `onError` hook fires on path 2 and 3 (cross-cutting telemetry)
|
|
619
|
+
* `onError` hook fires on path 2 and 3 (cross-cutting telemetry) — including
|
|
620
|
+
* plain non-2xx `ClientHttpError` and typed registry errors — but NOT on
|
|
633
621
|
* path 1 (usage errors bypass the classifier and onError entirely).
|
|
634
622
|
*/
|
|
635
623
|
export async function executeSafeCall<TResponse, ETyped = never>(
|
|
@@ -29,13 +29,6 @@ export class ClientHttpError extends Error {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
/** @deprecated Renamed to `ClientHttpError`. The alias is retained for one minor release after the 7.0.0 major bump and will be removed in a subsequent minor (e.g. 7.1.0). Migrate to `ClientHttpError` now. */
|
|
33
|
-
|
|
34
|
-
export const ClientRequestError = ClientHttpError
|
|
35
|
-
/** @deprecated Renamed to `ClientHttpError`. The alias is retained for one minor release after the 7.0.0 major bump and will be removed in a subsequent minor (e.g. 7.1.0). Migrate to `ClientHttpError` now. */
|
|
36
|
-
// eslint-disable-next-line no-redeclare
|
|
37
|
-
export type ClientRequestError = ClientHttpError
|
|
38
|
-
|
|
39
32
|
export class ClientPathParamError extends Error {
|
|
40
33
|
readonly name = 'ClientPathParamError'
|
|
41
34
|
|
|
@@ -5,6 +5,16 @@ import type { ClientInstance, CreateClientConfig } from './_types'
|
|
|
5
5
|
import * as _users from './users'
|
|
6
6
|
import * as _errorsModule from './_errors'
|
|
7
7
|
|
|
8
|
+
export {
|
|
9
|
+
ClientHttpError,
|
|
10
|
+
ClientPathParamError,
|
|
11
|
+
ClientStreamError,
|
|
12
|
+
ClientNetworkError,
|
|
13
|
+
ClientTimeoutError,
|
|
14
|
+
ClientAbortError,
|
|
15
|
+
ClientParseError,
|
|
16
|
+
} from './_client'
|
|
17
|
+
|
|
8
18
|
export namespace Api {
|
|
9
19
|
export import Users = _users.Users
|
|
10
20
|
export import Errors = _errorsModule.ApiErrors
|
|
@@ -59,13 +59,6 @@ export class ClientHttpError extends Error {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
/** @deprecated Renamed to `ClientHttpError`. The alias is retained for one minor release after the 7.0.0 major bump and will be removed in a subsequent minor (e.g. 7.1.0). Migrate to `ClientHttpError` now. */
|
|
63
|
-
|
|
64
|
-
export const ClientRequestError = ClientHttpError
|
|
65
|
-
/** @deprecated Renamed to `ClientHttpError`. The alias is retained for one minor release after the 7.0.0 major bump and will be removed in a subsequent minor (e.g. 7.1.0). Migrate to `ClientHttpError` now. */
|
|
66
|
-
// eslint-disable-next-line no-redeclare
|
|
67
|
-
export type ClientRequestError = ClientHttpError
|
|
68
|
-
|
|
69
62
|
export class ClientPathParamError extends Error {
|
|
70
63
|
readonly name = 'ClientPathParamError'
|
|
71
64
|
|
|
@@ -305,7 +298,7 @@ export function resolveBasePath(
|
|
|
305
298
|
* - `timeoutMs`: the resolved timeout value (may be 0 if per-call explicitly disables)
|
|
306
299
|
* - `combined`: `AbortSignal.any([...])` of all active signals, or undefined if none
|
|
307
300
|
*
|
|
308
|
-
* Per-call `timeout: 0` disables an inherited default timeout
|
|
301
|
+
* Per-call `timeout: 0` disables an inherited default timeout.
|
|
309
302
|
* Both `defaults.signal` and `options.signal` are included in `combined` when present.
|
|
310
303
|
*/
|
|
311
304
|
export interface SignalSources {
|
|
@@ -338,25 +331,6 @@ export function resolveSignalSources(
|
|
|
338
331
|
return { combined, timeoutSignal, userSignal, timeoutMs }
|
|
339
332
|
}
|
|
340
333
|
|
|
341
|
-
/**
|
|
342
|
-
* Resolves the effective AbortSignal by combining (via `AbortSignal.any`):
|
|
343
|
-
* - default signal (if any)
|
|
344
|
-
* - per-call signal (if any)
|
|
345
|
-
* - timeout signal (if resolved timeout > 0)
|
|
346
|
-
*
|
|
347
|
-
* Returns undefined when none apply. Per-call `timeout: 0` disables an
|
|
348
|
-
* inherited default timeout.
|
|
349
|
-
*
|
|
350
|
-
* @deprecated Prefer `resolveSignalSources` when you need access to individual
|
|
351
|
-
* signal references (e.g. for abort-cause classification).
|
|
352
|
-
*/
|
|
353
|
-
export function resolveSignal(
|
|
354
|
-
defaults: ProcedureCallDefaults | undefined,
|
|
355
|
-
options: ProcedureCallOptions | undefined,
|
|
356
|
-
): AbortSignal | undefined {
|
|
357
|
-
return resolveSignalSources(defaults, options).combined
|
|
358
|
-
}
|
|
359
|
-
|
|
360
334
|
/**
|
|
361
335
|
* Resolves a `ClientHeadersInit` value: a static record passes through, a
|
|
362
336
|
* function is invoked and (if async) awaited — re-evaluated on every call so
|
|
@@ -599,19 +573,32 @@ export async function executeCall<TResponse>(config: ExecuteCallConfig): Promise
|
|
|
599
573
|
procedureName: descriptor.name,
|
|
600
574
|
scope: descriptor.scope,
|
|
601
575
|
})
|
|
576
|
+
let httpError: Error
|
|
602
577
|
if (typed) {
|
|
603
578
|
// Tag so executeSafeCall can distinguish typed registry errors from plain
|
|
604
579
|
// ClientHttpError without re-inspecting the registry.
|
|
605
580
|
;(typed as unknown as { __tsProceduresTyped?: boolean }).__tsProceduresTyped = true
|
|
606
|
-
|
|
581
|
+
httpError = typed
|
|
582
|
+
} else {
|
|
583
|
+
httpError = new ClientHttpError({
|
|
584
|
+
status: response.status,
|
|
585
|
+
headers: response.headers,
|
|
586
|
+
body: response.body,
|
|
587
|
+
procedureName: descriptor.name,
|
|
588
|
+
scope: descriptor.scope,
|
|
589
|
+
})
|
|
607
590
|
}
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
591
|
+
// A non-2xx response is not a thrown adapter error (fetch resolves it), so
|
|
592
|
+
// it bypasses the catch block above. Fire onError here too so the hook is a
|
|
593
|
+
// uniform cross-cutting failure signal across adapter throws AND HTTP error
|
|
594
|
+
// statuses (401/403/5xx). Runs after onAfterResponse, which had its chance
|
|
595
|
+
// to swallow the error by mutating status back into the 2xx range.
|
|
596
|
+
await runOnError(
|
|
597
|
+
{ procedureName: descriptor.name, scope: descriptor.scope, request, error: httpError },
|
|
598
|
+
hooks,
|
|
599
|
+
options,
|
|
600
|
+
)
|
|
601
|
+
throw httpError
|
|
615
602
|
}
|
|
616
603
|
|
|
617
604
|
// 8. Return the body (or { body, headers } when the route declares res.headers)
|
|
@@ -629,7 +616,8 @@ export async function executeCall<TResponse>(config: ExecuteCallConfig): Promise
|
|
|
629
616
|
* 2. Adapter throw, classified → `kind: 'network' | 'timeout' | 'aborted' | <custom> | 'unknown'`
|
|
630
617
|
* 3. Adapter returns non-2xx → `kind: 'typed'` (registry match) or `kind: 'http'`
|
|
631
618
|
*
|
|
632
|
-
* `onError` hook fires on path 2 and 3 (cross-cutting telemetry)
|
|
619
|
+
* `onError` hook fires on path 2 and 3 (cross-cutting telemetry) — including
|
|
620
|
+
* plain non-2xx `ClientHttpError` and typed registry errors — but NOT on
|
|
633
621
|
* path 1 (usage errors bypass the classifier and onError entirely).
|
|
634
622
|
*/
|
|
635
623
|
export async function executeSafeCall<TResponse, ETyped = never>(
|
|
@@ -29,13 +29,6 @@ export class ClientHttpError extends Error {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
/** @deprecated Renamed to `ClientHttpError`. The alias is retained for one minor release after the 7.0.0 major bump and will be removed in a subsequent minor (e.g. 7.1.0). Migrate to `ClientHttpError` now. */
|
|
33
|
-
|
|
34
|
-
export const ClientRequestError = ClientHttpError
|
|
35
|
-
/** @deprecated Renamed to `ClientHttpError`. The alias is retained for one minor release after the 7.0.0 major bump and will be removed in a subsequent minor (e.g. 7.1.0). Migrate to `ClientHttpError` now. */
|
|
36
|
-
// eslint-disable-next-line no-redeclare
|
|
37
|
-
export type ClientRequestError = ClientHttpError
|
|
38
|
-
|
|
39
32
|
export class ClientPathParamError extends Error {
|
|
40
33
|
readonly name = 'ClientPathParamError'
|
|
41
34
|
|
|
@@ -7,6 +7,16 @@ import * as _billing from './billing'
|
|
|
7
7
|
import * as _billingReports from './billing-reports'
|
|
8
8
|
import * as _errorsModule from './_errors'
|
|
9
9
|
|
|
10
|
+
export {
|
|
11
|
+
ClientHttpError,
|
|
12
|
+
ClientPathParamError,
|
|
13
|
+
ClientStreamError,
|
|
14
|
+
ClientNetworkError,
|
|
15
|
+
ClientTimeoutError,
|
|
16
|
+
ClientAbortError,
|
|
17
|
+
ClientParseError,
|
|
18
|
+
} from './_client'
|
|
19
|
+
|
|
10
20
|
export namespace Api {
|
|
11
21
|
export import Orders = _orders.Orders
|
|
12
22
|
export import Billing = _billing.Billing
|
package/src/codegen/e2e.test.ts
CHANGED
|
@@ -494,7 +494,7 @@ describe('E2E: generateClient full pipeline', () => {
|
|
|
494
494
|
expect(content).toContain('ProcedureCallOptions')
|
|
495
495
|
})
|
|
496
496
|
|
|
497
|
-
it('_client.ts is generated and contains createClient, createFetchAdapter, ClientHttpError (
|
|
497
|
+
it('_client.ts is generated and contains createClient, createFetchAdapter, ClientHttpError (no ClientRequestError alias)', async () => {
|
|
498
498
|
tmpDir = makeTmpDir()
|
|
499
499
|
await generateClient({ envelope, outDir: tmpDir, selfContained: true })
|
|
500
500
|
|
|
@@ -503,7 +503,7 @@ describe('E2E: generateClient full pipeline', () => {
|
|
|
503
503
|
expect(content).toContain('createClient')
|
|
504
504
|
expect(content).toContain('createFetchAdapter')
|
|
505
505
|
expect(content).toContain('ClientHttpError')
|
|
506
|
-
expect(content).toContain('ClientRequestError')
|
|
506
|
+
expect(content).not.toContain('ClientRequestError')
|
|
507
507
|
})
|
|
508
508
|
|
|
509
509
|
it('_client.ts imports from ./_types and NOT from ts-procedures/client', async () => {
|
|
@@ -46,14 +46,14 @@ describe('emitClientRuntimeFile', () => {
|
|
|
46
46
|
expect(result).toMatch(/export function createFetchAdapter/)
|
|
47
47
|
})
|
|
48
48
|
|
|
49
|
-
it('contains export class ClientHttpError
|
|
49
|
+
it('contains export class ClientHttpError', async () => {
|
|
50
50
|
const result = await emitClientRuntimeFile()
|
|
51
51
|
expect(result).toMatch(/export class ClientHttpError/)
|
|
52
52
|
})
|
|
53
53
|
|
|
54
|
-
it('
|
|
54
|
+
it('does NOT contain the removed ClientRequestError alias', async () => {
|
|
55
55
|
const result = await emitClientRuntimeFile()
|
|
56
|
-
expect(result).toContain('ClientRequestError')
|
|
56
|
+
expect(result).not.toContain('ClientRequestError')
|
|
57
57
|
})
|
|
58
58
|
|
|
59
59
|
it('contains export class ClientPathParamError', async () => {
|
|
@@ -91,12 +91,31 @@ export function emitIndexFile(groups: ScopeGroup[], options?: EmitIndexOptions):
|
|
|
91
91
|
})
|
|
92
92
|
.join('\n')
|
|
93
93
|
|
|
94
|
+
// Re-export the client error classes so consumers can `instanceof`-narrow
|
|
95
|
+
// failures (e.g. in an `onError` hook) straight from the package index,
|
|
96
|
+
// without reaching into `./_client`. Sourced from the runtime import path so
|
|
97
|
+
// it resolves in both self-contained (`./_client`) and external-runtime
|
|
98
|
+
// (`ts-procedures/client`) modes. Unconditional: even a service with no typed
|
|
99
|
+
// errors throws `ClientHttpError`.
|
|
100
|
+
const errorClassReExport =
|
|
101
|
+
`export {\n` +
|
|
102
|
+
` ClientHttpError,\n` +
|
|
103
|
+
` ClientPathParamError,\n` +
|
|
104
|
+
` ClientStreamError,\n` +
|
|
105
|
+
` ClientNetworkError,\n` +
|
|
106
|
+
` ClientTimeoutError,\n` +
|
|
107
|
+
` ClientAbortError,\n` +
|
|
108
|
+
` ClientParseError,\n` +
|
|
109
|
+
`} from '${clientRuntimeImportPath}'`
|
|
110
|
+
|
|
94
111
|
const pieces: string[] = [
|
|
95
112
|
CODEGEN_HEADER,
|
|
96
113
|
`import { createClient } from '${clientRuntimeImportPath}'`,
|
|
97
114
|
`import type { ClientInstance, CreateClientConfig } from '${clientImportPath}'`,
|
|
98
115
|
importsBlock,
|
|
99
116
|
'',
|
|
117
|
+
errorClassReExport,
|
|
118
|
+
'',
|
|
100
119
|
namespaceBlock,
|
|
101
120
|
`export function ${factoryName}(client: ClientInstance) {`,
|
|
102
121
|
' return {',
|
|
@@ -22,6 +22,24 @@ import { resolveProductionSwiftEmitter } from './targets/swift/ajsc-adapter.js'
|
|
|
22
22
|
* because the header intentionally records the producing version. Everything
|
|
23
23
|
* else — including the envelope-hash line — must match exactly (both sides
|
|
24
24
|
* hash the same fixture envelopes).
|
|
25
|
+
*
|
|
26
|
+
* DOCUMENTED DEVIATIONS from v8.6.0 (intentional bug fixes / major-version
|
|
27
|
+
* removals; the affected golden files were surgically updated, NOT
|
|
28
|
+
* full-recaptured):
|
|
29
|
+
* 1. Bundled client runtime (`_client.ts`, self-contained TS cases only):
|
|
30
|
+
* `executeCall` now fires `onError` on non-2xx HTTP responses (401/403/5xx),
|
|
31
|
+
* not just on adapter throws. v8.6.0 skipped the hook here despite its
|
|
32
|
+
* docstring claiming otherwise. See `src/client/call.ts`.
|
|
33
|
+
* 2. Bundled client runtime (`_client.ts`, self-contained TS cases only), v11
|
|
34
|
+
* major: removed the deprecated `ClientRequestError` alias (`errors.ts`)
|
|
35
|
+
* and the deprecated internal `resolveSignal` helper (`resolve-options.ts`,
|
|
36
|
+
* superseded by `resolveSignalSources`).
|
|
37
|
+
* 3. Generated `index.ts` (ALL TS cases, incl. external-runtime), v11 major:
|
|
38
|
+
* now re-exports the client error classes (`ClientHttpError`, …) so
|
|
39
|
+
* consumers can `instanceof`-narrow failures straight from the package
|
|
40
|
+
* index. See `emit-index.ts`.
|
|
41
|
+
* See the matching notes in `src/client/freeze.test.ts`.
|
|
42
|
+
* Kotlin/Swift goldens are unaffected by all of the above.
|
|
25
43
|
*/
|
|
26
44
|
const here = dirname(fileURLToPath(import.meta.url))
|
|
27
45
|
const fixturesDir = resolve(here, '__fixtures__')
|
package/src/exports.ts
CHANGED
|
@@ -59,7 +59,7 @@ export type {
|
|
|
59
59
|
ValidationOptions,
|
|
60
60
|
TSchemaValidationError,
|
|
61
61
|
} from './schema/compile.js'
|
|
62
|
-
export type { Infer,
|
|
62
|
+
export type { Infer, TJSONSchema, Prettify } from './schema/json-schema.js'
|
|
63
63
|
|
|
64
64
|
// Doc envelope — offline codegen input
|
|
65
65
|
export { writeDocEnvelope } from './server/doc-envelope.js'
|
|
@@ -16,6 +16,3 @@ export type Prettify<TObject> = {
|
|
|
16
16
|
* provided for TypeBox (other schemas infer as `unknown`).
|
|
17
17
|
*/
|
|
18
18
|
export type Infer<SchemaType> = SchemaType extends TSchema ? Static<SchemaType> : unknown
|
|
19
|
-
|
|
20
|
-
/** v8-compatible alias for {@link Infer}. */
|
|
21
|
-
export type TSchemaLib<SchemaType> = Infer<SchemaType>
|