ts-procedures 7.0.0 → 7.1.1
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/api-reference.md +4 -0
- package/agent_config/copilot/copilot-instructions.md +2 -0
- package/agent_config/cursor/cursorrules +2 -0
- package/build/client/index.js +5 -0
- package/build/client/index.js.map +1 -1
- package/build/client/stream.d.ts +25 -1
- package/build/client/stream.js +48 -5
- package/build/client/stream.js.map +1 -1
- package/build/client/stream.test.js +68 -1
- package/build/client/stream.test.js.map +1 -1
- package/build/codegen/bin/cli.js +91 -0
- package/build/codegen/bin/cli.js.map +1 -1
- package/build/codegen/bin/cli.test.js +15 -0
- package/build/codegen/bin/cli.test.js.map +1 -1
- package/build/codegen/e2e.test.js +97 -74
- package/build/codegen/e2e.test.js.map +1 -1
- package/build/codegen/emit-index.js +11 -1
- package/build/codegen/emit-index.js.map +1 -1
- package/build/codegen/emit-scope.js +58 -16
- package/build/codegen/emit-scope.js.map +1 -1
- package/build/codegen/emit-scope.test.js +164 -2
- package/build/codegen/emit-scope.test.js.map +1 -1
- package/build/codegen/emit-types.d.ts +28 -0
- package/build/codegen/emit-types.js +69 -5
- package/build/codegen/emit-types.js.map +1 -1
- package/build/codegen/emit-types.test.js +30 -0
- package/build/codegen/emit-types.test.js.map +1 -1
- package/build/codegen/resolve-envelope.js +4 -1
- package/build/codegen/resolve-envelope.js.map +1 -1
- package/build/codegen/resolve-envelope.test.js +10 -0
- package/build/codegen/resolve-envelope.test.js.map +1 -1
- package/build/codegen/test-helpers/run-tsc.d.ts +33 -0
- package/build/codegen/test-helpers/run-tsc.js +49 -0
- package/build/codegen/test-helpers/run-tsc.js.map +1 -0
- package/build/implementations/http/doc-registry.js +14 -0
- package/build/implementations/http/doc-registry.js.map +1 -1
- package/build/implementations/http/doc-registry.test.js +37 -1
- package/build/implementations/http/doc-registry.test.js.map +1 -1
- package/build/implementations/http/hono-rpc/index.d.ts +11 -0
- package/build/implementations/http/hono-rpc/index.js +22 -1
- package/build/implementations/http/hono-rpc/index.js.map +1 -1
- package/build/implementations/http/hono-rpc/index.test.js +25 -0
- package/build/implementations/http/hono-rpc/index.test.js.map +1 -1
- package/build/implementations/http/hono-stream/error-taxonomy.test.js +72 -0
- package/build/implementations/http/hono-stream/error-taxonomy.test.js.map +1 -1
- package/build/implementations/http/hono-stream/index.d.ts +18 -4
- package/build/implementations/http/hono-stream/index.js +97 -18
- package/build/implementations/http/hono-stream/index.js.map +1 -1
- package/build/implementations/http/hono-stream/index.test.js +3 -3
- package/build/implementations/http/hono-stream/index.test.js.map +1 -1
- package/build/implementations/types.d.ts +10 -0
- package/build/index.js +22 -17
- package/build/index.js.map +1 -1
- package/build/index.test.js +36 -6
- package/build/index.test.js.map +1 -1
- package/package.json +1 -1
- package/src/client/index.ts +6 -0
- package/src/client/stream.test.ts +82 -1
- package/src/client/stream.ts +67 -4
- package/src/codegen/bin/cli.test.ts +26 -0
- package/src/codegen/bin/cli.ts +91 -0
- package/src/codegen/e2e.test.ts +100 -78
- package/src/codegen/emit-index.ts +11 -1
- package/src/codegen/emit-scope.test.ts +172 -2
- package/src/codegen/emit-scope.ts +66 -13
- package/src/codegen/emit-types.test.ts +34 -0
- package/src/codegen/emit-types.ts +83 -5
- package/src/codegen/resolve-envelope.test.ts +11 -0
- package/src/codegen/resolve-envelope.ts +4 -1
- package/src/codegen/test-helpers/run-tsc.ts +56 -0
- package/src/implementations/http/doc-registry.test.ts +43 -1
- package/src/implementations/http/doc-registry.ts +19 -0
- package/src/implementations/http/hono-rpc/index.test.ts +32 -0
- package/src/implementations/http/hono-rpc/index.ts +27 -1
- package/src/implementations/http/hono-stream/error-taxonomy.test.ts +80 -0
- package/src/implementations/http/hono-stream/index.test.ts +3 -3
- package/src/implementations/http/hono-stream/index.ts +118 -22
- package/src/implementations/types.ts +7 -0
- package/src/index.test.ts +43 -6
- package/src/index.ts +23 -20
|
@@ -168,6 +168,13 @@ export type AnyHttpRouteDoc = RPCHttpRouteDoc | APIHttpRouteDoc | StreamHttpRout
|
|
|
168
168
|
|
|
169
169
|
export interface DocSource<T = AnyHttpRouteDoc> {
|
|
170
170
|
readonly docs: T[]
|
|
171
|
+
/**
|
|
172
|
+
* Optional list of procedures that were registered with this builder but
|
|
173
|
+
* couldn't be served by it (e.g. a streaming procedure registered with an
|
|
174
|
+
* RPC builder). DocRegistry aggregates these across sources and warns at
|
|
175
|
+
* `toJSON()` time so silently-dropped procedures don't slip through.
|
|
176
|
+
*/
|
|
177
|
+
readonly skippedProcedures?: { name: string; reason: string }[]
|
|
171
178
|
}
|
|
172
179
|
|
|
173
180
|
export interface HeaderDoc {
|
package/src/index.test.ts
CHANGED
|
@@ -915,10 +915,19 @@ describe('Streaming Procedures - CreateStream', () => {
|
|
|
915
915
|
expect(values).toEqual(['user-123'])
|
|
916
916
|
})
|
|
917
917
|
|
|
918
|
-
test('CreateStream
|
|
918
|
+
test('CreateStream rethrows the original error preserving class identity', async () => {
|
|
919
|
+
// The streaming wrapper must NOT box user errors inside ProcedureError —
|
|
920
|
+
// doing so would defeat route-declared typed-error dispatch on the client
|
|
921
|
+
// (the HTTP builder's taxonomy would see `ProcedureError` instead of the
|
|
922
|
+
// user's class). Stack annotation is added in place; class identity and
|
|
923
|
+
// custom properties are preserved.
|
|
924
|
+
class MyDomainError extends Error {
|
|
925
|
+
readonly name = 'MyDomainError'
|
|
926
|
+
readonly code = 'STREAM_FAIL'
|
|
927
|
+
}
|
|
928
|
+
|
|
919
929
|
const { CreateStream } = Procedures()
|
|
920
|
-
const originalError = new
|
|
921
|
-
;(originalError as any).code = 'STREAM_FAIL'
|
|
930
|
+
const originalError = new MyDomainError('Stream underlying error')
|
|
922
931
|
|
|
923
932
|
const { StreamCause } = CreateStream(
|
|
924
933
|
'StreamCause',
|
|
@@ -935,12 +944,40 @@ describe('Streaming Procedures - CreateStream', () => {
|
|
|
935
944
|
}
|
|
936
945
|
expect.fail('Should have thrown')
|
|
937
946
|
} catch (e: any) {
|
|
938
|
-
expect(e).
|
|
939
|
-
expect(e
|
|
940
|
-
expect(e.
|
|
947
|
+
expect(e).toBe(originalError)
|
|
948
|
+
expect(e).toBeInstanceOf(MyDomainError)
|
|
949
|
+
expect(e.code).toBe('STREAM_FAIL')
|
|
941
950
|
}
|
|
942
951
|
})
|
|
943
952
|
|
|
953
|
+
test('CreateStream propagates .return() to the user generator', async () => {
|
|
954
|
+
// Consumers that close a stream early (via `iterator.return()` or breaking
|
|
955
|
+
// out of for-await) must trigger the user generator's `finally` block so
|
|
956
|
+
// cleanup (db handles, subscriptions, signal-driven teardown) runs.
|
|
957
|
+
const { CreateStream } = Procedures()
|
|
958
|
+
let finallyRan = false
|
|
959
|
+
|
|
960
|
+
const { EarlyClose } = CreateStream(
|
|
961
|
+
'EarlyClose',
|
|
962
|
+
{},
|
|
963
|
+
async function* () {
|
|
964
|
+
try {
|
|
965
|
+
yield 1
|
|
966
|
+
yield 2
|
|
967
|
+
yield 3
|
|
968
|
+
} finally {
|
|
969
|
+
finallyRan = true
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
)
|
|
973
|
+
|
|
974
|
+
const iter = EarlyClose({}, {})
|
|
975
|
+
const first = await iter.next()
|
|
976
|
+
expect(first.value).toBe(1)
|
|
977
|
+
await iter.return!(undefined)
|
|
978
|
+
expect(finallyRan).toBe(true)
|
|
979
|
+
})
|
|
980
|
+
|
|
944
981
|
test('CreateStream with extended config', () => {
|
|
945
982
|
interface ExtConfig {
|
|
946
983
|
scope: string
|
package/src/index.ts
CHANGED
|
@@ -383,8 +383,8 @@ export function Procedures<TContext = TNoContextProvided, TExtendedConfig = unkn
|
|
|
383
383
|
params as any
|
|
384
384
|
)
|
|
385
385
|
|
|
386
|
+
const userIterator = userGenerator[Symbol.asyncIterator]()
|
|
386
387
|
try {
|
|
387
|
-
const userIterator = userGenerator[Symbol.asyncIterator]()
|
|
388
388
|
let userIterResult = await userIterator.next()
|
|
389
389
|
|
|
390
390
|
while (!userIterResult.done) {
|
|
@@ -411,27 +411,30 @@ export function Procedures<TContext = TNoContextProvided, TExtendedConfig = unkn
|
|
|
411
411
|
// can send it as a special 'return' SSE event
|
|
412
412
|
return userIterResult.value
|
|
413
413
|
} catch (error: any) {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
error.stack +
|
|
428
|
-
`\n--- Procedure "${name}" defined at ---\n at ${file}:${line}:${column}`
|
|
429
|
-
} else if (error.stack) {
|
|
430
|
-
err.stack = error.stack
|
|
431
|
-
}
|
|
432
|
-
throw err
|
|
414
|
+
// Preserve the original error class so HTTP builders' taxonomies and
|
|
415
|
+
// `onMidStreamError` callbacks see the actual thrown type — boxing
|
|
416
|
+
// user-defined errors inside ProcedureError defeats route-declared
|
|
417
|
+
// typed-error dispatch on the client. Augment the stack trace in
|
|
418
|
+
// place with the procedure's definition site when available.
|
|
419
|
+
if (
|
|
420
|
+
definitionInfo.definedAt &&
|
|
421
|
+
error &&
|
|
422
|
+
typeof error.stack === 'string'
|
|
423
|
+
) {
|
|
424
|
+
const { file, line, column } = definitionInfo.definedAt
|
|
425
|
+
error.stack =
|
|
426
|
+
`${error.stack}\n--- Procedure "${name}" defined at ---\n at ${file}:${line}:${column}`
|
|
433
427
|
}
|
|
428
|
+
throw error
|
|
434
429
|
} finally {
|
|
430
|
+
// Propagate `.return()` to the user generator so its `finally`
|
|
431
|
+
// blocks (and any `signal`-driven cleanup) run when the consumer
|
|
432
|
+
// closes the stream early. No-op when iteration already completed.
|
|
433
|
+
try {
|
|
434
|
+
await userIterator.return?.(undefined)
|
|
435
|
+
} catch {
|
|
436
|
+
// Swallow — cleanup must not mask the primary error path
|
|
437
|
+
}
|
|
435
438
|
abortController.abort('stream-completed')
|
|
436
439
|
}
|
|
437
440
|
} as (ctx: TContext, params?: any) => AsyncGenerator<any, any, unknown>,
|