ts-procedures 5.4.0 → 5.4.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.
Files changed (34) hide show
  1. package/package.json +1 -2
  2. package/src/errors.test.ts +0 -163
  3. package/src/errors.ts +0 -107
  4. package/src/exports.ts +0 -7
  5. package/src/implementations/http/README.md +0 -260
  6. package/src/implementations/http/express-rpc/README.md +0 -281
  7. package/src/implementations/http/express-rpc/index.test.ts +0 -957
  8. package/src/implementations/http/express-rpc/index.ts +0 -265
  9. package/src/implementations/http/express-rpc/types.ts +0 -16
  10. package/src/implementations/http/hono-api/index.test.ts +0 -1328
  11. package/src/implementations/http/hono-api/index.ts +0 -461
  12. package/src/implementations/http/hono-api/types.ts +0 -16
  13. package/src/implementations/http/hono-rpc/README.md +0 -358
  14. package/src/implementations/http/hono-rpc/index.test.ts +0 -1075
  15. package/src/implementations/http/hono-rpc/index.ts +0 -237
  16. package/src/implementations/http/hono-rpc/types.ts +0 -16
  17. package/src/implementations/http/hono-stream/README.md +0 -526
  18. package/src/implementations/http/hono-stream/index.test.ts +0 -1676
  19. package/src/implementations/http/hono-stream/index.ts +0 -435
  20. package/src/implementations/http/hono-stream/types.ts +0 -29
  21. package/src/implementations/types.ts +0 -127
  22. package/src/index.test.ts +0 -1194
  23. package/src/index.ts +0 -512
  24. package/src/schema/compute-schema.test.ts +0 -128
  25. package/src/schema/compute-schema.ts +0 -88
  26. package/src/schema/extract-json-schema.test.ts +0 -25
  27. package/src/schema/extract-json-schema.ts +0 -15
  28. package/src/schema/parser.test.ts +0 -182
  29. package/src/schema/parser.ts +0 -215
  30. package/src/schema/resolve-schema-lib.test.ts +0 -19
  31. package/src/schema/resolve-schema-lib.ts +0 -29
  32. package/src/schema/types.ts +0 -20
  33. package/src/stack-utils.test.ts +0 -94
  34. package/src/stack-utils.ts +0 -129
@@ -1,265 +0,0 @@
1
- import express from 'express'
2
- import { kebabCase } from 'es-toolkit/string'
3
- import { Procedures, TProcedureRegistration } from '../../../index.js'
4
- import {
5
- ExtractConfig,
6
- ExtractContext,
7
- ProceduresFactory,
8
- RPCConfig,
9
- RPCHttpRouteDoc,
10
- } from '../../types.js'
11
- import { castArray } from 'es-toolkit/compat'
12
- import { ExpressFactoryItem } from './types.js'
13
-
14
- export type { RPCConfig, RPCHttpRouteDoc }
15
-
16
- export type ExpressRPCAppBuilderConfig = {
17
- /**
18
- * An existing Express application instance to use.
19
- * When provided, ensure to set up necessary middleware (e.g., json/body parser) beforehand.
20
- * If not provided, a new instance will be created.
21
- */
22
- app?: express.Express
23
- /** Optional path prefix for all RPC routes. */
24
- pathPrefix?: string
25
- onRequestStart?: (req: express.Request) => void
26
- onRequestEnd?: (req: express.Request, res: express.Response) => void
27
- onSuccess?: (
28
- procedure: TProcedureRegistration,
29
- req: express.Request,
30
- res: express.Response
31
- ) => void
32
- /**
33
- * Error handler called when a procedure throws an error.
34
- * @param procedure
35
- * @param req
36
- * @param res
37
- * @param error
38
- */
39
- onError?: (
40
- procedure: TProcedureRegistration,
41
- req: express.Request,
42
- res: express.Response,
43
- error: Error
44
- ) => void
45
- }
46
-
47
- /**
48
- * Builder class for creating an Express application with RPC routes.
49
- *
50
- * Usage:
51
- * const PublicRPC = Procedures<PublicRPCContext, RPCConfig>()
52
- * const ProtectedRPC = Procedures<ProtectedRPCContext, RPCConfig>()
53
- *
54
- * const rpcApp = new ExpressRPCAppBuilder()
55
- * .register(PublicRPC, (req): Promise<PublicRPCContext> => { /* context resolution logic * / })
56
- * .register(ProtectedRPC, (req): Promise<ProtectedRPCContext> => { /* context resolution logic * / })
57
- * .build();
58
- *
59
- * const app = rpcApp.app; // Express application
60
- * const docs = rpcApp.docs; // RPC route documentation
61
- */
62
- export class ExpressRPCAppBuilder {
63
- /**
64
- * Constructor for ExpressRPCAppBuilder.
65
- *
66
- * @param config
67
- */
68
- constructor(readonly config?: ExpressRPCAppBuilderConfig) {
69
- if (config?.app) {
70
- this._app = config.app
71
- } else {
72
- // Default middleware if no app is provided
73
- this._app.use(express.json())
74
- }
75
-
76
- if (config?.onRequestStart) {
77
- this._app.use((req, res, next) => {
78
- config.onRequestStart!(req)
79
- next()
80
- })
81
- }
82
-
83
- if (config?.onRequestEnd) {
84
- this._app.use((req, res, next) => {
85
- res.on('finish', () => {
86
- config.onRequestEnd!(req, res)
87
- })
88
- next()
89
- })
90
- }
91
- }
92
-
93
- /**
94
- * Generates the RPC route path based on the RPC configuration.
95
- * The RPCConfig name can be a string or an array of strings to form nested paths.
96
- *
97
- * Example
98
- * name: ['string', 'string-string', 'string']
99
- * path: /string/string-string/string/version
100
- * @param config
101
- */
102
- static makeRPCHttpRoutePath({
103
- name,
104
- config,
105
- prefix,
106
- }: {
107
- name: string
108
- prefix?: string
109
- config: RPCConfig
110
- }) {
111
- const normalizedPrefix = prefix ? (prefix.startsWith('/') ? prefix : `/${prefix}`) : ''
112
-
113
- return `${normalizedPrefix}/${castArray(config.scope).map(kebabCase).join('/')}/${kebabCase(name)}/${String(config.version).trim()}`
114
- }
115
-
116
- /**
117
- * Instance method wrapper for makeRPCHttpRoutePath that uses the builder's pathPrefix.
118
- * @param config - The RPC configuration
119
- */
120
- makeRPCHttpRoutePath(name: string, config: RPCConfig): string {
121
- return ExpressRPCAppBuilder.makeRPCHttpRoutePath({
122
- name,
123
- config,
124
- prefix: this.config?.pathPrefix,
125
- })
126
- }
127
-
128
- private factories: ExpressFactoryItem<any>[] = []
129
-
130
- private _app: express.Express = express()
131
- private _docs: (RPCHttpRouteDoc & object)[] = []
132
-
133
- get app(): express.Express {
134
- return this._app
135
- }
136
-
137
- get docs(): RPCHttpRouteDoc[] {
138
- return this._docs
139
- }
140
-
141
- /**
142
- * Registers a procedure factory with its context.
143
- * @param factory - The procedure factory created by Procedures<Context, RPCConfig>()
144
- * @param factoryContext - The context for procedure handlers. Can be a direct value,
145
- * a sync function (req) => Context, or an async function (req) => Promise<Context>
146
- * @param extendProcedureDoc - A custom function to extend the generated RPC route documentation for each procedure.
147
- */
148
- register<TFactory extends ProceduresFactory>(
149
- factory: TFactory,
150
- factoryContext:
151
- | ExtractContext<TFactory>
152
- | ((req: express.Request) => ExtractContext<TFactory> | Promise<ExtractContext<TFactory>>),
153
- extendProcedureDoc?: (params: {
154
- /* RPC App builder base http route doc */
155
- base: RPCHttpRouteDoc
156
- /* Procedure registration */
157
- procedure: TProcedureRegistration<any, ExtractConfig<TFactory>>
158
- }) => Record<string, any>
159
- ): this {
160
- this.factories.push({ factory, factoryContext, extendProcedureDoc } as ExpressFactoryItem<any>)
161
- return this
162
- }
163
-
164
- /**
165
- * Builds and returns the Express application with registered RPC routes.
166
- * @return express.Application
167
- */
168
- build(): express.Application {
169
- this.factories.forEach(({ factory, factoryContext, extendProcedureDoc }) => {
170
- factory.getProcedures().map((procedure: TProcedureRegistration<any, RPCConfig>) => {
171
- const route = this.buildRpcHttpRouteDoc(procedure, extendProcedureDoc)
172
-
173
- this._docs.push(route)
174
-
175
- this._app[route.method](route.path, async (req, res) => {
176
- try {
177
- const context =
178
- typeof factoryContext === 'function'
179
- ? await factoryContext(req)
180
- : (factoryContext as ExtractContext<typeof factory>)
181
-
182
- let ac: AbortController | undefined
183
- const ctxWithSignal = Object.defineProperty({ ...context }, 'signal', {
184
- get() {
185
- if (!ac) {
186
- ac = new AbortController()
187
- req.on('close', () => { if (!res.writableFinished) ac!.abort() })
188
- }
189
- return ac.signal
190
- },
191
- enumerable: true,
192
- })
193
-
194
- res.json(await procedure.handler(ctxWithSignal, req.body))
195
- if (this.config?.onSuccess) {
196
- this.config.onSuccess(procedure, req, res)
197
- }
198
- // if status not set, set to 200
199
- if (!res.status) {
200
- res.status(200)
201
- }
202
- } catch (error) {
203
- if (this.config?.onError) {
204
- this.config.onError(procedure, req, res, error as Error)
205
- return
206
- }
207
- if (!res.status) {
208
- res.status(500)
209
- }
210
- // if no res.json set, set default error message
211
- if (!res.headersSent) {
212
- res.json({ error: (error as Error).message })
213
- }
214
- }
215
- })
216
- })
217
- })
218
-
219
- return this._app
220
- }
221
-
222
- /**
223
- * Generates the RPC HTTP route for the given procedure.
224
- * @param procedure
225
- */
226
- private buildRpcHttpRouteDoc(
227
- procedure: TProcedureRegistration<any, RPCConfig>,
228
- extendProcedureDoc: ExpressFactoryItem['extendProcedureDoc']
229
- ): RPCHttpRouteDoc {
230
- const { config } = procedure
231
- const path = ExpressRPCAppBuilder.makeRPCHttpRoutePath({
232
- name: procedure.name,
233
- config,
234
- prefix: this.config?.pathPrefix,
235
- })
236
- const method = 'post' as const // RPCs use POST method
237
- const jsonSchema: { body?: Record<string, unknown>; response?: Record<string, unknown> } = {}
238
-
239
- if (config.schema?.params) {
240
- jsonSchema.body = config.schema.params
241
- }
242
- if (config.schema?.returnType) {
243
- jsonSchema.response = config.schema.returnType
244
- }
245
-
246
- const base = {
247
- name: procedure.name,
248
- version: config.version,
249
- scope: config.scope,
250
- path,
251
- method,
252
- jsonSchema,
253
- }
254
- let extendedDoc: object = {}
255
-
256
- if (extendProcedureDoc) {
257
- extendedDoc = extendProcedureDoc({ base, procedure })
258
- }
259
-
260
- return {
261
- ...extendedDoc,
262
- ...base,
263
- }
264
- }
265
- }
@@ -1,16 +0,0 @@
1
- import { ExtractConfig, ExtractContext, RPCConfig, RPCHttpRouteDoc } from '../../types.js'
2
- import { Procedures, TProcedureRegistration } from '../../../index.js'
3
- import express from 'express'
4
-
5
- export type ExpressFactoryItem<TFactory = ReturnType<typeof Procedures<any, RPCConfig>>> = {
6
- factory: TFactory
7
- factoryContext:
8
- | ExtractContext<TFactory>
9
- | ((req: express.Request) => ExtractContext<TFactory> | Promise<ExtractContext<TFactory>>)
10
- extendProcedureDoc?: (params: {
11
- /* RPC App builder base http route doc */
12
- base: RPCHttpRouteDoc
13
- /* Procedure registration */
14
- procedure: TProcedureRegistration<any, ExtractConfig<TFactory>>
15
- }) => Record<string, any>
16
- }