spiceflow 1.0.7 → 1.1.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/README.md +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/types.d.ts +1 -2
- package/dist/client/types.d.ts.map +1 -1
- package/dist/client/ws.d.ts +1 -1
- package/dist/client/ws.d.ts.map +1 -1
- package/dist/client.test.js +1 -18
- package/dist/client.test.js.map +1 -1
- package/dist/{elysia-fork/context.d.ts → context.d.ts} +8 -7
- package/dist/context.d.ts.map +1 -0
- package/dist/{elysia-fork/context.js.map → context.js.map} +1 -1
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js.map +1 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware.test.d.ts +2 -0
- package/dist/middleware.test.d.ts.map +1 -0
- package/dist/middleware.test.js +99 -0
- package/dist/middleware.test.js.map +1 -0
- package/dist/openapi.d.ts +23 -3
- package/dist/openapi.d.ts.map +1 -1
- package/dist/openapi.js +2 -2
- package/dist/openapi.js.map +1 -1
- package/dist/openapi.test.js +66 -1
- package/dist/openapi.test.js.map +1 -1
- package/dist/spiceflow.d.ts +44 -125
- package/dist/spiceflow.d.ts.map +1 -1
- package/dist/spiceflow.js +129 -166
- package/dist/spiceflow.js.map +1 -1
- package/dist/spiceflow.test.js +54 -16
- package/dist/spiceflow.test.js.map +1 -1
- package/dist/types.d.ts +406 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +72 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +69 -0
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/client/index.ts +1 -3
- package/src/client/types.ts +6 -13
- package/src/client/ws.ts +1 -1
- package/src/client.test.ts +1 -19
- package/src/context.ts +128 -0
- package/src/index.ts +1 -2
- package/src/middleware.test.ts +107 -0
- package/src/openapi.test.ts +71 -1
- package/src/openapi.ts +1 -1
- package/src/spiceflow.test.ts +74 -16
- package/src/spiceflow.ts +213 -386
- package/src/types.test.ts +1 -1
- package/src/types.ts +926 -0
- package/src/utils.ts +84 -0
- package/dist/elysia-fork/context.d.ts.map +0 -1
- package/dist/elysia-fork/error.d.ts.map +0 -1
- package/dist/elysia-fork/error.js.map +0 -1
- package/dist/elysia-fork/types.d.ts +0 -562
- package/dist/elysia-fork/types.d.ts.map +0 -1
- package/dist/elysia-fork/types.js +0 -2
- package/dist/elysia-fork/types.js.map +0 -1
- package/dist/elysia-fork/utils.d.ts +0 -134
- package/dist/elysia-fork/utils.d.ts.map +0 -1
- package/dist/elysia-fork/utils.js +0 -70
- package/dist/elysia-fork/utils.js.map +0 -1
- package/src/elysia-fork/context.ts +0 -166
- package/src/elysia-fork/types.ts +0 -1281
- package/src/elysia-fork/utils.ts +0 -85
- /package/dist/{elysia-fork/context.js → context.js} +0 -0
- /package/dist/{elysia-fork/error.d.ts → error.d.ts} +0 -0
- /package/dist/{elysia-fork/error.js → error.js} +0 -0
- /package/src/{elysia-fork/error.ts → error.ts} +0 -0
package/src/spiceflow.ts
CHANGED
|
@@ -4,13 +4,12 @@ import { Type } from '@sinclair/typebox'
|
|
|
4
4
|
|
|
5
5
|
export { Type as t }
|
|
6
6
|
|
|
7
|
+
import addFormats from 'ajv-formats'
|
|
7
8
|
import {
|
|
8
9
|
ComposeSpiceflowResponse,
|
|
9
10
|
CreateEden,
|
|
10
11
|
DefinitionBase,
|
|
11
|
-
EphemeralType,
|
|
12
12
|
ErrorHandler,
|
|
13
|
-
Handler,
|
|
14
13
|
HTTPMethod,
|
|
15
14
|
InlineHandler,
|
|
16
15
|
InputSchema,
|
|
@@ -20,8 +19,7 @@ import {
|
|
|
20
19
|
MaybeArray,
|
|
21
20
|
MergeSchema,
|
|
22
21
|
MetadataBase,
|
|
23
|
-
|
|
24
|
-
Prettify2,
|
|
22
|
+
MiddlewareHandler,
|
|
25
23
|
Reconcile,
|
|
26
24
|
ResolvePath,
|
|
27
25
|
RouteBase,
|
|
@@ -29,21 +27,18 @@ import {
|
|
|
29
27
|
SingletonBase,
|
|
30
28
|
TypeSchema,
|
|
31
29
|
UnwrapRoute,
|
|
32
|
-
} from './
|
|
33
|
-
import addFormats from 'ajv-formats'
|
|
30
|
+
} from './types.js'
|
|
34
31
|
let globalIndex = 0
|
|
35
32
|
|
|
36
33
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
37
34
|
// @ts-ignore
|
|
38
35
|
import OriginalRouter from '@medley/router'
|
|
39
|
-
import { TSchema } from '@sinclair/typebox'
|
|
40
36
|
import Ajv, { ValidateFunction } from 'ajv'
|
|
41
|
-
import { Context } from './elysia-fork/context.js'
|
|
42
|
-
import { isAsyncIterable } from './utils.js'
|
|
43
|
-
import { redirect } from './elysia-fork/utils.js'
|
|
44
|
-
import { ValidationError } from './elysia-fork/error.js'
|
|
45
|
-
import { zodToJsonSchema } from 'zod-to-json-schema'
|
|
46
37
|
import { z, ZodType } from 'zod'
|
|
38
|
+
import { zodToJsonSchema } from 'zod-to-json-schema'
|
|
39
|
+
import { Context, MiddlewareContext } from './context.js'
|
|
40
|
+
import { NotFoundError, ValidationError } from './error.js'
|
|
41
|
+
import { isAsyncIterable, redirect } from './utils.js'
|
|
47
42
|
|
|
48
43
|
const ajv = (addFormats.default || addFormats)(
|
|
49
44
|
new (Ajv.default || Ajv)({ useDefaults: true }),
|
|
@@ -67,27 +62,10 @@ const ajv = (addFormats.default || addFormats)(
|
|
|
67
62
|
|
|
68
63
|
// Should be exported from `hono/router`
|
|
69
64
|
|
|
70
|
-
type P = any
|
|
71
|
-
|
|
72
65
|
type AsyncResponse = Response | Promise<Response>
|
|
73
66
|
|
|
74
67
|
type OnError = (x: { error: any; request: Request }) => AsyncResponse
|
|
75
68
|
|
|
76
|
-
type RouterTree = {
|
|
77
|
-
id: number
|
|
78
|
-
router: OriginalRouter
|
|
79
|
-
prefix?: string
|
|
80
|
-
onRequestHandlers: Function[]
|
|
81
|
-
onErrorHandlers: OnError[]
|
|
82
|
-
children: RouterTree[]
|
|
83
|
-
routes: InternalRoute[]
|
|
84
|
-
// default store for the router, used as default for context.store
|
|
85
|
-
store: Record<any, any>
|
|
86
|
-
currentRoot?: RouterTree
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
type OnNoMatch = (request: Request, platform: P) => AsyncResponse
|
|
90
|
-
|
|
91
69
|
export type InternalRoute = {
|
|
92
70
|
method: HTTPMethod
|
|
93
71
|
path: string
|
|
@@ -101,6 +79,11 @@ export type InternalRoute = {
|
|
|
101
79
|
|
|
102
80
|
// store: Record<any, any>
|
|
103
81
|
}
|
|
82
|
+
|
|
83
|
+
type MedleyRouter = {
|
|
84
|
+
find: (path: string) => InternalRoute | undefined
|
|
85
|
+
register: (path: string | undefined) => Record<string, InternalRoute>
|
|
86
|
+
}
|
|
104
87
|
/**
|
|
105
88
|
* Router class
|
|
106
89
|
*/
|
|
@@ -108,10 +91,7 @@ export class Spiceflow<
|
|
|
108
91
|
const in out BasePath extends string = '',
|
|
109
92
|
const in out Scoped extends boolean = true,
|
|
110
93
|
const in out Singleton extends SingletonBase = {
|
|
111
|
-
decorator: {}
|
|
112
94
|
store: {}
|
|
113
|
-
derive: {}
|
|
114
|
-
resolve: {}
|
|
115
95
|
},
|
|
116
96
|
const in out Definitions extends DefinitionBase = {
|
|
117
97
|
type: {}
|
|
@@ -123,30 +103,29 @@ export class Spiceflow<
|
|
|
123
103
|
macroFn: {}
|
|
124
104
|
},
|
|
125
105
|
const out Routes extends RouteBase = {},
|
|
126
|
-
// ? scoped
|
|
127
|
-
const in out Ephemeral extends EphemeralType = {
|
|
128
|
-
derive: {}
|
|
129
|
-
resolve: {}
|
|
130
|
-
schema: {}
|
|
131
|
-
},
|
|
132
|
-
// ? local
|
|
133
|
-
const in out Volatile extends EphemeralType = {
|
|
134
|
-
derive: {}
|
|
135
|
-
resolve: {}
|
|
136
|
-
schema: {}
|
|
137
|
-
},
|
|
138
106
|
> {
|
|
139
|
-
private
|
|
140
|
-
|
|
141
|
-
private
|
|
107
|
+
private id: number = globalIndex++
|
|
108
|
+
private router: MedleyRouter = new OriginalRouter()
|
|
109
|
+
private middlewares: Function[] = []
|
|
110
|
+
private onErrorHandlers: OnError[] = []
|
|
111
|
+
private routes: InternalRoute[] = []
|
|
112
|
+
private defaultStore: Record<any, any> = {}
|
|
113
|
+
private topLevelApp?: AnySpiceflow
|
|
114
|
+
|
|
115
|
+
/** @internal */
|
|
116
|
+
prefix?: string
|
|
117
|
+
|
|
118
|
+
/** @internal */
|
|
119
|
+
childrenApps: AnySpiceflow[] = []
|
|
142
120
|
|
|
121
|
+
/** @internal */
|
|
143
122
|
getAllRoutes() {
|
|
144
|
-
let root = this.
|
|
123
|
+
let root = this.topLevelApp || this
|
|
145
124
|
const allApps = bfs(root) || []
|
|
146
125
|
const allRoutes = allApps.flatMap((x) => {
|
|
147
|
-
const prefix = this.
|
|
126
|
+
const prefix = this.getAppAndParents(x)
|
|
148
127
|
.map((x) => x.prefix)
|
|
149
|
-
|
|
128
|
+
|
|
150
129
|
.join('')
|
|
151
130
|
|
|
152
131
|
return x.routes.map((x) => ({ ...x, path: prefix + x.path }))
|
|
@@ -161,73 +140,58 @@ export class Spiceflow<
|
|
|
161
140
|
handler,
|
|
162
141
|
...rest
|
|
163
142
|
}: Partial<InternalRoute>) {
|
|
164
|
-
const router = this.routerTree
|
|
165
|
-
// if (router.prefix) {
|
|
166
|
-
// path = router.prefix + path
|
|
167
|
-
// }
|
|
168
|
-
|
|
169
143
|
let bodySchema: TypeSchema = hooks?.body
|
|
170
144
|
let validateBody = getValidateFunction(bodySchema)
|
|
171
145
|
let validateQuery = getValidateFunction(hooks?.query)
|
|
172
146
|
let validateParams = getValidateFunction(hooks?.params)
|
|
173
147
|
|
|
174
|
-
const store =
|
|
148
|
+
const store = this.router.register(path)
|
|
175
149
|
let route: InternalRoute = {
|
|
176
150
|
...rest,
|
|
177
151
|
|
|
178
|
-
prefix:
|
|
152
|
+
prefix: this.prefix || '',
|
|
179
153
|
method: (method || '') as any,
|
|
180
154
|
path: path || '',
|
|
181
|
-
// prefix,
|
|
182
155
|
handler: handler!,
|
|
183
156
|
hooks,
|
|
184
157
|
validateBody,
|
|
185
158
|
validateParams,
|
|
186
159
|
validateQuery,
|
|
187
160
|
}
|
|
188
|
-
|
|
189
|
-
store[method] = route
|
|
161
|
+
this.routes.push(route)
|
|
162
|
+
store[method!] = route
|
|
190
163
|
}
|
|
191
164
|
|
|
192
165
|
private match(method: string, path: string) {
|
|
193
|
-
let root = this
|
|
194
|
-
const result = bfsFind(this
|
|
195
|
-
|
|
196
|
-
let prefix = this.
|
|
166
|
+
let root = this
|
|
167
|
+
const result = bfsFind(this, (app) => {
|
|
168
|
+
app.topLevelApp = root
|
|
169
|
+
let prefix = this.getAppAndParents(app)
|
|
197
170
|
.map((x) => x.prefix)
|
|
198
|
-
|
|
171
|
+
|
|
199
172
|
.join('')
|
|
200
173
|
if (prefix && !path.startsWith(prefix)) {
|
|
201
|
-
// console.log(
|
|
202
|
-
// `router prefix: ${router.prefix} does not match path: ${path}`
|
|
203
|
-
// )
|
|
204
174
|
return
|
|
205
175
|
}
|
|
206
176
|
let pathWithoutPrefix = path
|
|
207
177
|
if (prefix) {
|
|
208
178
|
pathWithoutPrefix = path.replace(prefix, '')
|
|
209
179
|
}
|
|
210
|
-
|
|
211
|
-
const route = router.router.find(pathWithoutPrefix)
|
|
180
|
+
const route = app.router.find(pathWithoutPrefix)
|
|
212
181
|
if (!route) {
|
|
213
182
|
return
|
|
214
183
|
}
|
|
215
184
|
|
|
216
|
-
let
|
|
217
|
-
if (
|
|
218
|
-
// console.log(`route found: ${method} ${path}`, route)
|
|
219
|
-
|
|
220
|
-
const { onErrorHandlers, onRequestHandlers } = router
|
|
185
|
+
let internalRoute: InternalRoute = route['store'][method]
|
|
186
|
+
if (internalRoute) {
|
|
221
187
|
const params = route['params'] || {}
|
|
222
188
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
store: router.store,
|
|
227
|
-
onErrorHandlers,
|
|
228
|
-
onRequestHandlers,
|
|
189
|
+
const res = {
|
|
190
|
+
app,
|
|
191
|
+
internalRoute: internalRoute,
|
|
229
192
|
params,
|
|
230
193
|
}
|
|
194
|
+
return res
|
|
231
195
|
}
|
|
232
196
|
})
|
|
233
197
|
|
|
@@ -241,23 +205,18 @@ export class Spiceflow<
|
|
|
241
205
|
BasePath,
|
|
242
206
|
Scoped,
|
|
243
207
|
{
|
|
244
|
-
decorator: Singleton['decorator']
|
|
245
208
|
store: Reconcile<
|
|
246
209
|
Singleton['store'],
|
|
247
210
|
{
|
|
248
211
|
[name in Name]: Value
|
|
249
212
|
}
|
|
250
213
|
>
|
|
251
|
-
derive: Singleton['derive']
|
|
252
|
-
resolve: Singleton['resolve']
|
|
253
214
|
},
|
|
254
215
|
Definitions,
|
|
255
216
|
Metadata,
|
|
256
|
-
Routes
|
|
257
|
-
Ephemeral,
|
|
258
|
-
Volatile
|
|
217
|
+
Routes
|
|
259
218
|
> {
|
|
260
|
-
this.
|
|
219
|
+
this.defaultStore[name] = value
|
|
261
220
|
return this as any
|
|
262
221
|
}
|
|
263
222
|
|
|
@@ -269,31 +228,13 @@ export class Spiceflow<
|
|
|
269
228
|
options: {
|
|
270
229
|
name?: string
|
|
271
230
|
scoped?: Scoped
|
|
272
|
-
|
|
231
|
+
|
|
273
232
|
basePath?: BasePath
|
|
274
233
|
} = {},
|
|
275
234
|
) {
|
|
276
235
|
this.scoped = options.scoped
|
|
277
236
|
|
|
278
|
-
this.
|
|
279
|
-
options.onNoMatch ?? (() => new Response(null, { status: 404 }))
|
|
280
|
-
this.routerTree = {
|
|
281
|
-
id: globalIndex++,
|
|
282
|
-
router: new OriginalRouter(),
|
|
283
|
-
prefix: options.basePath,
|
|
284
|
-
onRequestHandlers: [],
|
|
285
|
-
onErrorHandlers: [],
|
|
286
|
-
children: [],
|
|
287
|
-
store: {},
|
|
288
|
-
routes: [],
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// Bind router methods
|
|
292
|
-
// for (const method of METHODS) {
|
|
293
|
-
// this.#routes.set(method as Method, [])
|
|
294
|
-
// const key = method.toLowerCase() as Lowercase<Method>
|
|
295
|
-
// this[key as any] = this.#add.bind(this, method)
|
|
296
|
-
// }
|
|
237
|
+
this.prefix = options.basePath
|
|
297
238
|
}
|
|
298
239
|
|
|
299
240
|
_routes: Routes = {} as any
|
|
@@ -306,27 +247,15 @@ export class Spiceflow<
|
|
|
306
247
|
Metadata: {} as Metadata,
|
|
307
248
|
}
|
|
308
249
|
|
|
309
|
-
_ephemeral = {} as Ephemeral
|
|
310
|
-
_volatile = {} as Volatile
|
|
311
|
-
|
|
312
250
|
post<
|
|
313
251
|
const Path extends string,
|
|
314
252
|
const LocalSchema extends InputSchema<
|
|
315
253
|
keyof Definitions['type'] & string
|
|
316
254
|
>,
|
|
317
|
-
const Schema extends
|
|
318
|
-
UnwrapRoute<LocalSchema, Definitions['type']>,
|
|
319
|
-
MergeSchema<
|
|
320
|
-
Volatile['schema'],
|
|
321
|
-
MergeSchema<Ephemeral['schema'], Metadata['schema']>
|
|
322
|
-
>
|
|
323
|
-
>,
|
|
255
|
+
const Schema extends UnwrapRoute<LocalSchema, Definitions['type']>,
|
|
324
256
|
const Handle extends InlineHandler<
|
|
325
257
|
Schema,
|
|
326
|
-
Singleton
|
|
327
|
-
derive: Ephemeral['derive'] & Volatile['derive']
|
|
328
|
-
resolve: Ephemeral['resolve'] & Volatile['resolve']
|
|
329
|
-
},
|
|
258
|
+
Singleton,
|
|
330
259
|
JoinPath<BasePath, Path>
|
|
331
260
|
>,
|
|
332
261
|
>(
|
|
@@ -335,10 +264,7 @@ export class Spiceflow<
|
|
|
335
264
|
hook?: LocalHook<
|
|
336
265
|
LocalSchema,
|
|
337
266
|
Schema,
|
|
338
|
-
Singleton
|
|
339
|
-
derive: Ephemeral['derive'] & Volatile['derive']
|
|
340
|
-
resolve: Ephemeral['resolve'] & Volatile['resolve']
|
|
341
|
-
},
|
|
267
|
+
Singleton,
|
|
342
268
|
Definitions['error'],
|
|
343
269
|
Metadata['macro'],
|
|
344
270
|
JoinPath<BasePath, Path>
|
|
@@ -359,16 +285,13 @@ export class Spiceflow<
|
|
|
359
285
|
? ResolvePath<Path>
|
|
360
286
|
: Schema['params']
|
|
361
287
|
query: Schema['query']
|
|
362
|
-
|
|
363
288
|
response: ComposeSpiceflowResponse<
|
|
364
289
|
Schema['response'],
|
|
365
290
|
Handle
|
|
366
291
|
>
|
|
367
292
|
}
|
|
368
293
|
}
|
|
369
|
-
|
|
370
|
-
Ephemeral,
|
|
371
|
-
Volatile
|
|
294
|
+
>
|
|
372
295
|
> {
|
|
373
296
|
this.add({ method: 'POST', path, handler: handler, hooks: hook })
|
|
374
297
|
|
|
@@ -380,20 +303,11 @@ export class Spiceflow<
|
|
|
380
303
|
const LocalSchema extends InputSchema<
|
|
381
304
|
keyof Definitions['type'] & string
|
|
382
305
|
>,
|
|
383
|
-
const Schema extends
|
|
384
|
-
UnwrapRoute<LocalSchema, Definitions['type']>,
|
|
385
|
-
MergeSchema<
|
|
386
|
-
Volatile['schema'],
|
|
387
|
-
MergeSchema<Ephemeral['schema'], Metadata['schema']>
|
|
388
|
-
>
|
|
389
|
-
>,
|
|
306
|
+
const Schema extends UnwrapRoute<LocalSchema, Definitions['type']>,
|
|
390
307
|
const Macro extends Metadata['macro'],
|
|
391
308
|
const Handle extends InlineHandler<
|
|
392
309
|
Schema,
|
|
393
|
-
Singleton
|
|
394
|
-
derive: Ephemeral['derive'] & Volatile['derive']
|
|
395
|
-
resolve: Ephemeral['resolve'] & Volatile['resolve']
|
|
396
|
-
},
|
|
310
|
+
Singleton,
|
|
397
311
|
JoinPath<BasePath, Path>
|
|
398
312
|
>,
|
|
399
313
|
>(
|
|
@@ -402,10 +316,7 @@ export class Spiceflow<
|
|
|
402
316
|
hook?: LocalHook<
|
|
403
317
|
LocalSchema,
|
|
404
318
|
Schema,
|
|
405
|
-
Singleton
|
|
406
|
-
derive: Ephemeral['derive'] & Volatile['derive']
|
|
407
|
-
resolve: Ephemeral['resolve'] & Volatile['resolve']
|
|
408
|
-
},
|
|
319
|
+
Singleton,
|
|
409
320
|
Definitions['error'],
|
|
410
321
|
Macro,
|
|
411
322
|
JoinPath<BasePath, Path>
|
|
@@ -433,9 +344,7 @@ export class Spiceflow<
|
|
|
433
344
|
>
|
|
434
345
|
}
|
|
435
346
|
}
|
|
436
|
-
|
|
437
|
-
Ephemeral,
|
|
438
|
-
Volatile
|
|
347
|
+
>
|
|
439
348
|
> {
|
|
440
349
|
this.add({ method: 'GET', path, handler: handler, hooks: hook })
|
|
441
350
|
return this as any
|
|
@@ -446,19 +355,10 @@ export class Spiceflow<
|
|
|
446
355
|
const LocalSchema extends InputSchema<
|
|
447
356
|
keyof Definitions['type'] & string
|
|
448
357
|
>,
|
|
449
|
-
const Schema extends
|
|
450
|
-
UnwrapRoute<LocalSchema, Definitions['type']>,
|
|
451
|
-
MergeSchema<
|
|
452
|
-
Volatile['schema'],
|
|
453
|
-
MergeSchema<Ephemeral['schema'], Metadata['schema']>
|
|
454
|
-
>
|
|
455
|
-
>,
|
|
358
|
+
const Schema extends UnwrapRoute<LocalSchema, Definitions['type']>,
|
|
456
359
|
const Handle extends InlineHandler<
|
|
457
360
|
Schema,
|
|
458
|
-
Singleton
|
|
459
|
-
derive: Ephemeral['derive'] & Volatile['derive']
|
|
460
|
-
resolve: Ephemeral['resolve'] & Volatile['resolve']
|
|
461
|
-
},
|
|
361
|
+
Singleton,
|
|
462
362
|
JoinPath<BasePath, Path>
|
|
463
363
|
>,
|
|
464
364
|
>(
|
|
@@ -467,10 +367,7 @@ export class Spiceflow<
|
|
|
467
367
|
hook?: LocalHook<
|
|
468
368
|
LocalSchema,
|
|
469
369
|
Schema,
|
|
470
|
-
Singleton
|
|
471
|
-
derive: Ephemeral['derive'] & Volatile['derive']
|
|
472
|
-
resolve: Ephemeral['resolve'] & Volatile['resolve']
|
|
473
|
-
},
|
|
370
|
+
Singleton,
|
|
474
371
|
Definitions['error'],
|
|
475
372
|
Metadata['macro'],
|
|
476
373
|
JoinPath<BasePath, Path>
|
|
@@ -498,9 +395,7 @@ export class Spiceflow<
|
|
|
498
395
|
>
|
|
499
396
|
}
|
|
500
397
|
}
|
|
501
|
-
|
|
502
|
-
Ephemeral,
|
|
503
|
-
Volatile
|
|
398
|
+
>
|
|
504
399
|
> {
|
|
505
400
|
this.add({ method: 'PUT', path, handler: handler, hooks: hook })
|
|
506
401
|
|
|
@@ -512,19 +407,10 @@ export class Spiceflow<
|
|
|
512
407
|
const LocalSchema extends InputSchema<
|
|
513
408
|
keyof Definitions['type'] & string
|
|
514
409
|
>,
|
|
515
|
-
const Schema extends
|
|
516
|
-
UnwrapRoute<LocalSchema, Definitions['type']>,
|
|
517
|
-
MergeSchema<
|
|
518
|
-
Volatile['schema'],
|
|
519
|
-
MergeSchema<Ephemeral['schema'], Metadata['schema']>
|
|
520
|
-
>
|
|
521
|
-
>,
|
|
410
|
+
const Schema extends UnwrapRoute<LocalSchema, Definitions['type']>,
|
|
522
411
|
const Handle extends InlineHandler<
|
|
523
412
|
Schema,
|
|
524
|
-
Singleton
|
|
525
|
-
derive: Ephemeral['derive'] & Volatile['derive']
|
|
526
|
-
resolve: Ephemeral['resolve'] & Volatile['resolve']
|
|
527
|
-
},
|
|
413
|
+
Singleton,
|
|
528
414
|
JoinPath<BasePath, Path>
|
|
529
415
|
>,
|
|
530
416
|
>(
|
|
@@ -533,10 +419,7 @@ export class Spiceflow<
|
|
|
533
419
|
hook?: LocalHook<
|
|
534
420
|
LocalSchema,
|
|
535
421
|
Schema,
|
|
536
|
-
Singleton
|
|
537
|
-
derive: Ephemeral['derive'] & Volatile['derive']
|
|
538
|
-
resolve: Ephemeral['resolve'] & Volatile['resolve']
|
|
539
|
-
},
|
|
422
|
+
Singleton,
|
|
540
423
|
Definitions['error'],
|
|
541
424
|
Metadata['macro'],
|
|
542
425
|
JoinPath<BasePath, Path>
|
|
@@ -564,9 +447,7 @@ export class Spiceflow<
|
|
|
564
447
|
>
|
|
565
448
|
}
|
|
566
449
|
}
|
|
567
|
-
|
|
568
|
-
Ephemeral,
|
|
569
|
-
Volatile
|
|
450
|
+
>
|
|
570
451
|
> {
|
|
571
452
|
this.add({ method: 'PATCH', path, handler: handler, hooks: hook })
|
|
572
453
|
|
|
@@ -578,19 +459,10 @@ export class Spiceflow<
|
|
|
578
459
|
const LocalSchema extends InputSchema<
|
|
579
460
|
keyof Definitions['type'] & string
|
|
580
461
|
>,
|
|
581
|
-
const Schema extends
|
|
582
|
-
UnwrapRoute<LocalSchema, Definitions['type']>,
|
|
583
|
-
MergeSchema<
|
|
584
|
-
Volatile['schema'],
|
|
585
|
-
MergeSchema<Ephemeral['schema'], Metadata['schema']>
|
|
586
|
-
>
|
|
587
|
-
>,
|
|
462
|
+
const Schema extends UnwrapRoute<LocalSchema, Definitions['type']>,
|
|
588
463
|
const Handle extends InlineHandler<
|
|
589
464
|
Schema,
|
|
590
|
-
Singleton
|
|
591
|
-
derive: Ephemeral['derive'] & Volatile['derive']
|
|
592
|
-
resolve: Ephemeral['resolve'] & Volatile['resolve']
|
|
593
|
-
},
|
|
465
|
+
Singleton,
|
|
594
466
|
JoinPath<BasePath, Path>
|
|
595
467
|
>,
|
|
596
468
|
>(
|
|
@@ -599,10 +471,7 @@ export class Spiceflow<
|
|
|
599
471
|
hook?: LocalHook<
|
|
600
472
|
LocalSchema,
|
|
601
473
|
Schema,
|
|
602
|
-
Singleton
|
|
603
|
-
derive: Ephemeral['derive'] & Volatile['derive']
|
|
604
|
-
resolve: Ephemeral['resolve'] & Volatile['resolve']
|
|
605
|
-
},
|
|
474
|
+
Singleton,
|
|
606
475
|
Definitions['error'],
|
|
607
476
|
Metadata['macro'],
|
|
608
477
|
JoinPath<BasePath, Path>
|
|
@@ -630,9 +499,7 @@ export class Spiceflow<
|
|
|
630
499
|
>
|
|
631
500
|
}
|
|
632
501
|
}
|
|
633
|
-
|
|
634
|
-
Ephemeral,
|
|
635
|
-
Volatile
|
|
502
|
+
>
|
|
636
503
|
> {
|
|
637
504
|
this.add({ method: 'DELETE', path, handler: handler, hooks: hook })
|
|
638
505
|
|
|
@@ -644,19 +511,10 @@ export class Spiceflow<
|
|
|
644
511
|
const LocalSchema extends InputSchema<
|
|
645
512
|
keyof Definitions['type'] & string
|
|
646
513
|
>,
|
|
647
|
-
const Schema extends
|
|
648
|
-
UnwrapRoute<LocalSchema, Definitions['type']>,
|
|
649
|
-
MergeSchema<
|
|
650
|
-
Volatile['schema'],
|
|
651
|
-
MergeSchema<Ephemeral['schema'], Metadata['schema']>
|
|
652
|
-
>
|
|
653
|
-
>,
|
|
514
|
+
const Schema extends UnwrapRoute<LocalSchema, Definitions['type']>,
|
|
654
515
|
const Handle extends InlineHandler<
|
|
655
516
|
Schema,
|
|
656
|
-
Singleton
|
|
657
|
-
derive: Ephemeral['derive'] & Volatile['derive']
|
|
658
|
-
resolve: Ephemeral['resolve'] & Volatile['resolve']
|
|
659
|
-
},
|
|
517
|
+
Singleton,
|
|
660
518
|
JoinPath<BasePath, Path>
|
|
661
519
|
>,
|
|
662
520
|
>(
|
|
@@ -665,10 +523,7 @@ export class Spiceflow<
|
|
|
665
523
|
hook?: LocalHook<
|
|
666
524
|
LocalSchema,
|
|
667
525
|
Schema,
|
|
668
|
-
Singleton
|
|
669
|
-
derive: Ephemeral['derive'] & Volatile['derive']
|
|
670
|
-
resolve: Ephemeral['resolve'] & Volatile['resolve']
|
|
671
|
-
},
|
|
526
|
+
Singleton,
|
|
672
527
|
Definitions['error'],
|
|
673
528
|
Metadata['macro'],
|
|
674
529
|
JoinPath<BasePath, Path>
|
|
@@ -696,9 +551,7 @@ export class Spiceflow<
|
|
|
696
551
|
>
|
|
697
552
|
}
|
|
698
553
|
}
|
|
699
|
-
|
|
700
|
-
Ephemeral,
|
|
701
|
-
Volatile
|
|
554
|
+
>
|
|
702
555
|
> {
|
|
703
556
|
this.add({ method: 'OPTIONS', path, handler: handler, hooks: hook })
|
|
704
557
|
|
|
@@ -710,19 +563,10 @@ export class Spiceflow<
|
|
|
710
563
|
const LocalSchema extends InputSchema<
|
|
711
564
|
keyof Definitions['type'] & string
|
|
712
565
|
>,
|
|
713
|
-
const Schema extends
|
|
714
|
-
UnwrapRoute<LocalSchema, Definitions['type']>,
|
|
715
|
-
MergeSchema<
|
|
716
|
-
Volatile['schema'],
|
|
717
|
-
MergeSchema<Ephemeral['schema'], Metadata['schema']>
|
|
718
|
-
>
|
|
719
|
-
>,
|
|
566
|
+
const Schema extends UnwrapRoute<LocalSchema, Definitions['type']>,
|
|
720
567
|
const Handle extends InlineHandler<
|
|
721
568
|
Schema,
|
|
722
|
-
Singleton
|
|
723
|
-
derive: Ephemeral['derive'] & Volatile['derive']
|
|
724
|
-
resolve: Ephemeral['resolve'] & Volatile['resolve']
|
|
725
|
-
},
|
|
569
|
+
Singleton,
|
|
726
570
|
JoinPath<BasePath, Path>
|
|
727
571
|
>,
|
|
728
572
|
>(
|
|
@@ -731,10 +575,7 @@ export class Spiceflow<
|
|
|
731
575
|
hook?: LocalHook<
|
|
732
576
|
LocalSchema,
|
|
733
577
|
Schema,
|
|
734
|
-
Singleton
|
|
735
|
-
derive: Ephemeral['derive'] & Volatile['derive']
|
|
736
|
-
resolve: Ephemeral['resolve'] & Volatile['resolve']
|
|
737
|
-
},
|
|
578
|
+
Singleton,
|
|
738
579
|
Definitions['error'],
|
|
739
580
|
Metadata['macro'],
|
|
740
581
|
JoinPath<BasePath, Path>
|
|
@@ -762,9 +603,7 @@ export class Spiceflow<
|
|
|
762
603
|
>
|
|
763
604
|
}
|
|
764
605
|
}
|
|
765
|
-
|
|
766
|
-
Ephemeral,
|
|
767
|
-
Volatile
|
|
606
|
+
>
|
|
768
607
|
> {
|
|
769
608
|
for (const method of METHODS) {
|
|
770
609
|
this.add({ method, path, handler: handler, hooks: hook })
|
|
@@ -778,19 +617,10 @@ export class Spiceflow<
|
|
|
778
617
|
const LocalSchema extends InputSchema<
|
|
779
618
|
keyof Definitions['type'] & string
|
|
780
619
|
>,
|
|
781
|
-
const Schema extends
|
|
782
|
-
UnwrapRoute<LocalSchema, Definitions['type']>,
|
|
783
|
-
MergeSchema<
|
|
784
|
-
Volatile['schema'],
|
|
785
|
-
MergeSchema<Ephemeral['schema'], Metadata['schema']>
|
|
786
|
-
>
|
|
787
|
-
>,
|
|
620
|
+
const Schema extends UnwrapRoute<LocalSchema, Definitions['type']>,
|
|
788
621
|
const Handle extends InlineHandler<
|
|
789
622
|
Schema,
|
|
790
|
-
Singleton
|
|
791
|
-
derive: Ephemeral['derive'] & Volatile['derive']
|
|
792
|
-
resolve: Ephemeral['resolve'] & Volatile['resolve']
|
|
793
|
-
},
|
|
623
|
+
Singleton,
|
|
794
624
|
JoinPath<BasePath, Path>
|
|
795
625
|
>,
|
|
796
626
|
>(
|
|
@@ -799,10 +629,7 @@ export class Spiceflow<
|
|
|
799
629
|
hook?: LocalHook<
|
|
800
630
|
LocalSchema,
|
|
801
631
|
Schema,
|
|
802
|
-
Singleton
|
|
803
|
-
derive: Ephemeral['derive'] & Volatile['derive']
|
|
804
|
-
resolve: Ephemeral['resolve'] & Volatile['resolve']
|
|
805
|
-
},
|
|
632
|
+
Singleton,
|
|
806
633
|
Definitions['error'],
|
|
807
634
|
Metadata['macro'],
|
|
808
635
|
JoinPath<BasePath, Path>
|
|
@@ -830,24 +657,14 @@ export class Spiceflow<
|
|
|
830
657
|
>
|
|
831
658
|
}
|
|
832
659
|
}
|
|
833
|
-
|
|
834
|
-
Ephemeral,
|
|
835
|
-
Volatile
|
|
660
|
+
>
|
|
836
661
|
> {
|
|
837
662
|
this.add({ method: 'HEAD', path, handler: handler, hooks: hook })
|
|
838
663
|
|
|
839
664
|
return this as any
|
|
840
665
|
}
|
|
841
666
|
|
|
842
|
-
|
|
843
|
-
* If set to true, other Spiceflow handler will not inherits global life-cycle, store, decorators from the current instance
|
|
844
|
-
*
|
|
845
|
-
* @default false
|
|
846
|
-
*/
|
|
847
|
-
private scoped?: Scoped
|
|
848
|
-
get _scoped() {
|
|
849
|
-
return this.scoped as Scoped
|
|
850
|
-
}
|
|
667
|
+
private scoped?: Scoped = true as Scoped
|
|
851
668
|
|
|
852
669
|
// group is not needed, you can add another prefixed app instead
|
|
853
670
|
// group<
|
|
@@ -900,155 +717,153 @@ export class Spiceflow<
|
|
|
900
717
|
Metadata,
|
|
901
718
|
BasePath extends ``
|
|
902
719
|
? Routes & NewSpiceflow['_routes']
|
|
903
|
-
: Routes & CreateEden<BasePath, NewSpiceflow['_routes']
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
> {
|
|
907
|
-
const thisRouter = this.routerTree
|
|
908
|
-
// TODO use scoped logic to add onRequest and onError on all routers if necessary, add them first
|
|
909
|
-
this.routerTree.children.push(instance.routerTree)
|
|
910
|
-
return this as any
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
onError<const Schema extends RouteSchema>(
|
|
720
|
+
: Routes & CreateEden<BasePath, NewSpiceflow['_routes']>
|
|
721
|
+
>
|
|
722
|
+
use<const Schema extends RouteSchema>(
|
|
914
723
|
handler: MaybeArray<
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
Volatile['schema'],
|
|
921
|
-
MergeSchema<Ephemeral['schema'], Metadata['schema']>
|
|
922
|
-
>
|
|
923
|
-
>,
|
|
924
|
-
Singleton,
|
|
925
|
-
Ephemeral,
|
|
926
|
-
Volatile
|
|
724
|
+
MiddlewareHandler<
|
|
725
|
+
Schema,
|
|
726
|
+
{
|
|
727
|
+
store: Singleton['store']
|
|
728
|
+
}
|
|
927
729
|
>
|
|
928
730
|
>,
|
|
929
|
-
): this
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
731
|
+
): this
|
|
732
|
+
|
|
733
|
+
use(appOrHandler) {
|
|
734
|
+
if (appOrHandler instanceof Spiceflow) {
|
|
735
|
+
this.childrenApps.push(appOrHandler)
|
|
736
|
+
} else if (typeof appOrHandler === 'function') {
|
|
737
|
+
this.middlewares ??= []
|
|
738
|
+
this.middlewares.push(appOrHandler)
|
|
739
|
+
}
|
|
935
740
|
return this
|
|
936
741
|
}
|
|
937
742
|
|
|
938
|
-
|
|
743
|
+
onError<const Schema extends RouteSchema>(
|
|
939
744
|
handler: MaybeArray<
|
|
940
|
-
|
|
941
|
-
MergeSchema<
|
|
942
|
-
Schema,
|
|
943
|
-
MergeSchema<
|
|
944
|
-
Volatile['schema'],
|
|
945
|
-
MergeSchema<Ephemeral['schema'], Metadata['schema']>
|
|
946
|
-
>
|
|
947
|
-
>,
|
|
948
|
-
{
|
|
949
|
-
decorator: Singleton['decorator']
|
|
950
|
-
store: Singleton['store']
|
|
951
|
-
derive: {}
|
|
952
|
-
resolve: {}
|
|
953
|
-
}
|
|
954
|
-
>
|
|
745
|
+
ErrorHandler<Definitions['error'], Schema, Singleton>
|
|
955
746
|
>,
|
|
956
|
-
) {
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
router.onRequestHandlers.push(handler as any)
|
|
747
|
+
): this {
|
|
748
|
+
this.onErrorHandlers ??= []
|
|
749
|
+
this.onErrorHandlers.push(handler as any)
|
|
960
750
|
|
|
961
751
|
return this
|
|
962
752
|
}
|
|
753
|
+
|
|
963
754
|
/**
|
|
964
755
|
* Pass a request through all matching route handles and return a response
|
|
965
756
|
* @param request The `Request`
|
|
966
757
|
* @param platform Platform specific context {@link Platform}
|
|
967
758
|
* @returns The final `Response`
|
|
968
759
|
*/
|
|
969
|
-
async handle(request: Request
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
let u = new URL(request.url)
|
|
760
|
+
async handle(request: Request): Promise<Response> {
|
|
761
|
+
let u = new URL(request.url, 'http://localhost')
|
|
973
762
|
let path = u.pathname + u.search
|
|
974
763
|
const defaultContext = {
|
|
975
764
|
redirect,
|
|
976
765
|
error: null,
|
|
977
766
|
path,
|
|
978
767
|
}
|
|
768
|
+
const root = this.topLevelApp || this
|
|
979
769
|
let onErrorHandlers: OnError[] = []
|
|
980
770
|
try {
|
|
981
|
-
let response: Response | undefined
|
|
982
771
|
// Get all middleware and method specific routes in order
|
|
983
772
|
|
|
984
773
|
const route = this.match(request.method, path)
|
|
774
|
+
|
|
985
775
|
if (!route) {
|
|
986
|
-
|
|
776
|
+
const error = new NotFoundError()
|
|
777
|
+
const res = await this.runErrorHandlers({
|
|
778
|
+
onErrorHandlers,
|
|
779
|
+
error,
|
|
780
|
+
request,
|
|
781
|
+
})
|
|
782
|
+
if (res) return res
|
|
783
|
+
return new Response(`Not Found`, {
|
|
784
|
+
status: 404,
|
|
785
|
+
})
|
|
987
786
|
}
|
|
988
|
-
onErrorHandlers = this.
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
let {
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
787
|
+
onErrorHandlers = this.getAppsInScope(route.app).flatMap(
|
|
788
|
+
(x) => x.onErrorHandlers,
|
|
789
|
+
)
|
|
790
|
+
let {
|
|
791
|
+
params,
|
|
792
|
+
app: { defaultStore },
|
|
793
|
+
} = route
|
|
794
|
+
const middlewares = this.getAppsInScope(route.app).flatMap(
|
|
795
|
+
(x) => x.middlewares,
|
|
796
|
+
)
|
|
995
797
|
// console.log({ onReqHandlers })
|
|
996
798
|
let store = { ...defaultStore }
|
|
997
|
-
// TODO add content type
|
|
998
799
|
|
|
999
|
-
let content = route?.hooks?.content
|
|
1000
|
-
// let body = await getRequestBody({ request, content })
|
|
800
|
+
let content = route?.internalRoute?.hooks?.content
|
|
1001
801
|
|
|
1002
|
-
if (route.validateBody) {
|
|
802
|
+
if (route.internalRoute?.validateBody) {
|
|
1003
803
|
// TODO don't clone the request
|
|
1004
804
|
let typedRequest = new TypedRequest(request)
|
|
1005
|
-
typedRequest.validateBody = route.validateBody
|
|
805
|
+
typedRequest.validateBody = route.internalRoute?.validateBody
|
|
1006
806
|
request = typedRequest
|
|
1007
807
|
}
|
|
1008
808
|
|
|
1009
809
|
let query = parseQuery.parse((u.search || '').slice(1))
|
|
1010
810
|
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
811
|
+
let index = 0
|
|
812
|
+
|
|
813
|
+
const next = async () => {
|
|
814
|
+
if (index < middlewares.length) {
|
|
815
|
+
const middleware = middlewares[index]
|
|
816
|
+
index++
|
|
817
|
+
let context = {
|
|
1014
818
|
request,
|
|
1015
|
-
response,
|
|
1016
819
|
store,
|
|
1017
820
|
path,
|
|
1018
821
|
query,
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
822
|
+
params,
|
|
823
|
+
redirect,
|
|
824
|
+
} satisfies MiddlewareContext<any>
|
|
825
|
+
const result = await middleware(context, next)
|
|
826
|
+
|
|
827
|
+
if (!result && index < middlewares.length) {
|
|
828
|
+
return await next()
|
|
829
|
+
} else if (result) {
|
|
830
|
+
return await turnHandlerResultIntoResponse(result)
|
|
1022
831
|
}
|
|
1023
832
|
}
|
|
1024
|
-
}
|
|
1025
833
|
|
|
1026
|
-
|
|
1027
|
-
|
|
834
|
+
query = runValidation(query, route.internalRoute?.validateQuery)
|
|
835
|
+
params = runValidation(
|
|
836
|
+
params,
|
|
837
|
+
route.internalRoute?.validateParams,
|
|
838
|
+
)
|
|
1028
839
|
|
|
1029
|
-
|
|
840
|
+
// console.log(route)
|
|
1030
841
|
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
request,
|
|
1034
|
-
response,
|
|
1035
|
-
params: params as any,
|
|
1036
|
-
store,
|
|
1037
|
-
query,
|
|
1038
|
-
// body,
|
|
1039
|
-
path,
|
|
1040
|
-
|
|
1041
|
-
// platform
|
|
1042
|
-
} satisfies Context<any, any, string>)
|
|
1043
|
-
if (isAsyncIterable(res)) {
|
|
1044
|
-
return await this.handleStream({
|
|
1045
|
-
generator: res,
|
|
842
|
+
const res = route.internalRoute?.handler({
|
|
843
|
+
...defaultContext,
|
|
1046
844
|
request,
|
|
1047
|
-
|
|
1048
|
-
|
|
845
|
+
params: params as any,
|
|
846
|
+
redirect,
|
|
847
|
+
store,
|
|
848
|
+
query,
|
|
849
|
+
// body,
|
|
850
|
+
path,
|
|
851
|
+
|
|
852
|
+
// platform
|
|
853
|
+
} satisfies Context<any, any, any>)
|
|
854
|
+
if (isAsyncIterable(res)) {
|
|
855
|
+
return await this.handleStream({
|
|
856
|
+
generator: res,
|
|
857
|
+
request,
|
|
858
|
+
onErrorHandlers,
|
|
859
|
+
})
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
return await turnHandlerResultIntoResponse(res)
|
|
1049
863
|
}
|
|
864
|
+
const response = await next()
|
|
1050
865
|
|
|
1051
|
-
return
|
|
866
|
+
return response
|
|
1052
867
|
} catch (err: any) {
|
|
1053
868
|
if (err instanceof Response) return err
|
|
1054
869
|
let res = await this.runErrorHandlers({
|
|
@@ -1081,29 +896,48 @@ export class Spiceflow<
|
|
|
1081
896
|
}
|
|
1082
897
|
}
|
|
1083
898
|
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
899
|
+
private getAppAndParents(currentApp?: AnySpiceflow) {
|
|
900
|
+
const parents: AnySpiceflow[] = []
|
|
901
|
+
let current = currentApp
|
|
902
|
+
|
|
903
|
+
let root = this.topLevelApp || this
|
|
1088
904
|
|
|
1089
|
-
|
|
1090
|
-
// Perform BFS once to build a parent map
|
|
1091
|
-
const parentMap = new Map<number, RouterTree>()
|
|
905
|
+
const parentMap = new Map<number, AnySpiceflow>()
|
|
1092
906
|
bfsFind(root, (node) => {
|
|
1093
|
-
for (const child of node.
|
|
907
|
+
for (const child of node.childrenApps) {
|
|
1094
908
|
parentMap.set(child.id, node)
|
|
1095
909
|
}
|
|
1096
910
|
})
|
|
1097
911
|
|
|
1098
912
|
// Traverse the parent map to get the parents
|
|
1099
913
|
while (current) {
|
|
1100
|
-
parents.
|
|
914
|
+
parents.unshift(current)
|
|
1101
915
|
current = parentMap.get(current.id)
|
|
1102
916
|
}
|
|
1103
917
|
|
|
1104
918
|
return parents.filter((x) => x !== undefined)
|
|
1105
919
|
}
|
|
1106
920
|
|
|
921
|
+
private getAppsInScope(currentApp?: AnySpiceflow) {
|
|
922
|
+
const withParents = this.getAppAndParents(currentApp)
|
|
923
|
+
|
|
924
|
+
let root = this.topLevelApp || this
|
|
925
|
+
const wantedOrder = bfs(root)
|
|
926
|
+
const scopeFalseApps = wantedOrder.filter((x) => x.scoped === false)
|
|
927
|
+
let appsInScope = [] as AnySpiceflow[]
|
|
928
|
+
for (const app of wantedOrder) {
|
|
929
|
+
if (scopeFalseApps.includes(app)) {
|
|
930
|
+
appsInScope.push(app)
|
|
931
|
+
continue
|
|
932
|
+
}
|
|
933
|
+
if (withParents.includes(app)) {
|
|
934
|
+
appsInScope.push(app)
|
|
935
|
+
continue
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
return appsInScope
|
|
939
|
+
}
|
|
940
|
+
|
|
1107
941
|
private async handleStream({
|
|
1108
942
|
onErrorHandlers,
|
|
1109
943
|
generator,
|
|
@@ -1264,8 +1098,8 @@ const METHODS = [
|
|
|
1264
1098
|
export type Method = (typeof METHODS)[number]
|
|
1265
1099
|
|
|
1266
1100
|
function bfsFind<T>(
|
|
1267
|
-
tree:
|
|
1268
|
-
onNode: (node:
|
|
1101
|
+
tree: AnySpiceflow,
|
|
1102
|
+
onNode: (node: AnySpiceflow) => T | undefined | void,
|
|
1269
1103
|
): T | undefined {
|
|
1270
1104
|
const queue = [tree]
|
|
1271
1105
|
|
|
@@ -1276,7 +1110,7 @@ function bfsFind<T>(
|
|
|
1276
1110
|
if (result) {
|
|
1277
1111
|
return result
|
|
1278
1112
|
}
|
|
1279
|
-
queue.push(...node.
|
|
1113
|
+
queue.push(...node.childrenApps)
|
|
1280
1114
|
}
|
|
1281
1115
|
return
|
|
1282
1116
|
}
|
|
@@ -1289,9 +1123,9 @@ export class TypedRequest<T = any> extends Request {
|
|
|
1289
1123
|
}
|
|
1290
1124
|
}
|
|
1291
1125
|
|
|
1292
|
-
export function bfs(tree:
|
|
1126
|
+
export function bfs(tree: AnySpiceflow) {
|
|
1293
1127
|
const queue = [tree]
|
|
1294
|
-
let nodes:
|
|
1128
|
+
let nodes: AnySpiceflow[] = []
|
|
1295
1129
|
while (queue.length > 0) {
|
|
1296
1130
|
const node = queue.shift()!
|
|
1297
1131
|
if (node) {
|
|
@@ -1299,19 +1133,12 @@ export function bfs(tree: RouterTree) {
|
|
|
1299
1133
|
}
|
|
1300
1134
|
// const result = onNode(node)
|
|
1301
1135
|
|
|
1302
|
-
|
|
1136
|
+
if (node?.childrenApps?.length) {
|
|
1137
|
+
queue.push(...node.childrenApps)
|
|
1138
|
+
}
|
|
1303
1139
|
}
|
|
1304
1140
|
return nodes
|
|
1305
1141
|
}
|
|
1306
|
-
function mapTree<T>(
|
|
1307
|
-
tree: RouterTree,
|
|
1308
|
-
mapper: (node: RouterTree) => T,
|
|
1309
|
-
): T & { children: (T & { children: any[] })[] } {
|
|
1310
|
-
const mappedNode = mapper(tree) as T & { children: any[] }
|
|
1311
|
-
mappedNode.children = tree.children.map((child) => mapTree(child, mapper))
|
|
1312
|
-
return mappedNode
|
|
1313
|
-
}
|
|
1314
|
-
|
|
1315
1142
|
export async function turnHandlerResultIntoResponse(result: any) {
|
|
1316
1143
|
// if user returns not a response, convert to json
|
|
1317
1144
|
if (result instanceof Response) {
|
|
@@ -1334,7 +1161,7 @@ export async function turnHandlerResultIntoResponse(result: any) {
|
|
|
1334
1161
|
})
|
|
1335
1162
|
}
|
|
1336
1163
|
|
|
1337
|
-
export type AnySpiceflow = Spiceflow<any, any, any, any, any, any
|
|
1164
|
+
export type AnySpiceflow = Spiceflow<any, any, any, any, any, any>
|
|
1338
1165
|
|
|
1339
1166
|
export function isZodSchema(value: unknown): value is ZodType {
|
|
1340
1167
|
return (
|