ts-procedures 8.5.0 → 8.6.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/build/codegen/emit-index.js +13 -0
- package/build/codegen/emit-index.js.map +1 -1
- package/build/codegen/emit-index.test.js +25 -0
- package/build/codegen/emit-index.test.js.map +1 -1
- package/build/codegen/emit-scope.js +45 -8
- package/build/codegen/emit-scope.js.map +1 -1
- package/build/codegen/emit-scope.test.js +86 -4
- package/build/codegen/emit-scope.test.js.map +1 -1
- package/docs/client-error-handling.md +87 -0
- package/docs/handoffs/2026-06-08-dx-round2-declines.md +45 -0
- package/docs/http-integrations.md +25 -0
- package/docs/superpowers/plans/2026-06-08-codegen-dx-surfacing.md +428 -0
- package/docs/superpowers/specs/2026-06-08-dx-feedback-round-2-design.md +376 -0
- package/package.json +1 -1
- package/src/codegen/__fixtures__/users-envelope.json +9 -0
- package/src/codegen/emit-index.test.ts +34 -0
- package/src/codegen/emit-index.ts +19 -0
- package/src/codegen/emit-scope.test.ts +94 -4
- package/src/codegen/emit-scope.ts +53 -8
- package/src/codegen/targets/kotlin/__fixtures__/users-golden.kt +6 -0
- package/src/codegen/targets/swift/__fixtures__/users-golden.swift +6 -0
|
@@ -387,6 +387,35 @@ function injectRouteErrors(
|
|
|
387
387
|
// Route emitters
|
|
388
388
|
// ---------------------------------------------------------------------------
|
|
389
389
|
|
|
390
|
+
/**
|
|
391
|
+
* Builds the multi-line JSDoc comment for a route callable. Surfaces the
|
|
392
|
+
* second `options` argument (the per-call AbortSignal/timeout seam — DX #8) and,
|
|
393
|
+
* for routes that declare typed errors, points at the route's `Errors` type and
|
|
394
|
+
* how to narrow it on the throwing path (DX #10). Indented for placement inside
|
|
395
|
+
* the bind-object (4 spaces).
|
|
396
|
+
*/
|
|
397
|
+
function buildCallableJsDoc(opts: {
|
|
398
|
+
methodLabel: string
|
|
399
|
+
path: string
|
|
400
|
+
errorsRef: string | null
|
|
401
|
+
}): string {
|
|
402
|
+
const lines = [
|
|
403
|
+
` /**`,
|
|
404
|
+
` * ${opts.methodLabel} ${opts.path}`,
|
|
405
|
+
` *`,
|
|
406
|
+
` * @param options Optional per-call {@link ProcedureCallOptions} —`,
|
|
407
|
+
` * \`signal\` (cancel on dispose), \`timeout\`, \`headers\`, \`basePath\`.`,
|
|
408
|
+
]
|
|
409
|
+
if (opts.errorsRef) {
|
|
410
|
+
lines.push(
|
|
411
|
+
` * @throws Declared typed errors: {@link ${opts.errorsRef}}. Narrow with`,
|
|
412
|
+
` * \`instanceof\` on the throwing path, or call \`.safe()\` for a \`Result\`.`,
|
|
413
|
+
)
|
|
414
|
+
}
|
|
415
|
+
lines.push(` */`)
|
|
416
|
+
return lines.join('\n')
|
|
417
|
+
}
|
|
418
|
+
|
|
390
419
|
async function emitRpcRoute(route: RPCHttpRouteDoc, ctx: EmitRouteContext): Promise<RouteChunks> {
|
|
391
420
|
const pascal = versionedPascal(route.name, route.version)
|
|
392
421
|
|
|
@@ -395,7 +424,7 @@ async function emitRpcRoute(route: RPCHttpRouteDoc, ctx: EmitRouteContext): Prom
|
|
|
395
424
|
{ shortName: 'Response', schema: route.jsonSchema.response },
|
|
396
425
|
], ctx)
|
|
397
426
|
|
|
398
|
-
const paramsTypeName = refs['Params'] ?? '
|
|
427
|
+
const paramsTypeName = refs['Params'] ?? 'void'
|
|
399
428
|
const responseTypeName = refs['Response'] ?? 'unknown'
|
|
400
429
|
const scopeStr = Array.isArray(route.scope) ? route.scope.join('-') : route.scope
|
|
401
430
|
|
|
@@ -409,7 +438,11 @@ async function emitRpcRoute(route: RPCHttpRouteDoc, ctx: EmitRouteContext): Prom
|
|
|
409
438
|
: `client.bindCallable<${paramsTypeName}, ${responseTypeName}>`
|
|
410
439
|
|
|
411
440
|
const callable = [
|
|
412
|
-
|
|
441
|
+
buildCallableJsDoc({
|
|
442
|
+
methodLabel: route.method.toUpperCase(),
|
|
443
|
+
path: route.path,
|
|
444
|
+
errorsRef: hasErrors ? errorsRef : null,
|
|
445
|
+
}),
|
|
413
446
|
` ${pascal}: ${helperCall}({`,
|
|
414
447
|
` name: '${pascal}',`,
|
|
415
448
|
` scope: '${scopeStr}',`,
|
|
@@ -533,7 +566,7 @@ async function emitApiRoute(route: APIHttpRouteDoc, ctx: EmitRouteContext): Prom
|
|
|
533
566
|
: `${pascal}Errors`
|
|
534
567
|
|
|
535
568
|
const declarations: string[] = []
|
|
536
|
-
let paramsTypeName = '
|
|
569
|
+
let paramsTypeName = 'void'
|
|
537
570
|
let returnTypeName = 'void'
|
|
538
571
|
|
|
539
572
|
// Track reserved names across all sub-namespaces. Model names are reserved
|
|
@@ -638,7 +671,11 @@ async function emitApiRoute(route: APIHttpRouteDoc, ctx: EmitRouteContext): Prom
|
|
|
638
671
|
]
|
|
639
672
|
|
|
640
673
|
const callable = [
|
|
641
|
-
|
|
674
|
+
buildCallableJsDoc({
|
|
675
|
+
methodLabel: route.method.toUpperCase(),
|
|
676
|
+
path: route.fullPath,
|
|
677
|
+
errorsRef: hasErrors ? errorsRef : null,
|
|
678
|
+
}),
|
|
642
679
|
` ${route.name}: ${helperCall}({`,
|
|
643
680
|
...descriptorLines,
|
|
644
681
|
` }),`,
|
|
@@ -676,7 +713,7 @@ async function emitHttpStreamRoute(route: HttpStreamRouteDoc, ctx: EmitRouteCont
|
|
|
676
713
|
|
|
677
714
|
const scopeStr = route.scope ?? 'default'
|
|
678
715
|
const declarations: string[] = []
|
|
679
|
-
let paramsTypeName = '
|
|
716
|
+
let paramsTypeName = 'void'
|
|
680
717
|
let yieldTypeName = 'unknown'
|
|
681
718
|
let returnTypeName = 'void'
|
|
682
719
|
|
|
@@ -774,7 +811,11 @@ async function emitHttpStreamRoute(route: HttpStreamRouteDoc, ctx: EmitRouteCont
|
|
|
774
811
|
}
|
|
775
812
|
|
|
776
813
|
const callable = [
|
|
777
|
-
|
|
814
|
+
buildCallableJsDoc({
|
|
815
|
+
methodLabel: route.method.toUpperCase(),
|
|
816
|
+
path: route.fullPath,
|
|
817
|
+
errorsRef: null,
|
|
818
|
+
}),
|
|
778
819
|
` ${route.name}(req: ${paramsTypeName}, options?: ProcedureCallOptions): TypedStream<${yieldTypeName}, ${returnTypeName}> {`,
|
|
779
820
|
` return client.stream<${yieldTypeName}, ${returnTypeName}>({`,
|
|
780
821
|
` name: '${route.name}',`,
|
|
@@ -813,13 +854,17 @@ async function emitStreamRoute(route: StreamHttpRouteDoc, ctx: EmitRouteContext)
|
|
|
813
854
|
{ shortName: 'Return', schema: route.jsonSchema.returnType },
|
|
814
855
|
], ctx)
|
|
815
856
|
|
|
816
|
-
const paramsTypeName = refs['Params'] ?? '
|
|
857
|
+
const paramsTypeName = refs['Params'] ?? 'void'
|
|
817
858
|
const yieldTypeName = refs['Yield'] ?? 'unknown'
|
|
818
859
|
const returnTypeName = refs['Return'] ?? 'void'
|
|
819
860
|
const scopeStr = Array.isArray(route.scope) ? route.scope.join('-') : route.scope
|
|
820
861
|
|
|
821
862
|
const callable = [
|
|
822
|
-
|
|
863
|
+
buildCallableJsDoc({
|
|
864
|
+
methodLabel: route.methods.map((m) => m.toUpperCase()).join('|'),
|
|
865
|
+
path: route.path,
|
|
866
|
+
errorsRef: null,
|
|
867
|
+
}),
|
|
823
868
|
` ${pascal}(params: ${paramsTypeName}, options?: ProcedureCallOptions): TypedStream<${yieldTypeName}, ${returnTypeName}> {`,
|
|
824
869
|
` return client.stream<${yieldTypeName}, ${returnTypeName}>({`,
|
|
825
870
|
` name: '${pascal}',`,
|