spiceflow 1.0.6 → 1.0.7

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/src/openapi.ts CHANGED
@@ -1,4 +1,3 @@
1
- /* eslint-disable @typescript-eslint/ban-ts-comment */
2
1
  import { JSONSchemaType } from 'ajv'
3
2
  import { InternalRoute, isZodSchema, Spiceflow } from './spiceflow.js'
4
3
  import { ZodType } from 'zod'
@@ -6,11 +5,8 @@ import { ZodType } from 'zod'
6
5
  import type { OpenAPIV3 } from 'openapi-types'
7
6
 
8
7
  let excludeMethods = ['OPTIONS']
9
- /* eslint-disable @typescript-eslint/ban-ts-comment */
10
- /* eslint-disable @typescript-eslint/no-unused-vars */
11
- import type { HTTPMethod, LocalHook, TypeSchema } from './elysia-fork/types.js'
12
8
 
13
- import { Kind, type TSchema } from '@sinclair/typebox'
9
+ import type { HTTPMethod, LocalHook, TypeSchema } from './elysia-fork/types.js'
14
10
 
15
11
  import deepClone from 'lodash.clonedeep'
16
12
  import { z } from 'zod'
@@ -143,14 +139,19 @@ export const registerSchemaPath = ({
143
139
  ? [contentType]
144
140
  : contentType ?? ['application/json']
145
141
 
146
- const bodySchema = hook?.body
142
+ const bodySchema = getJsonSchema(hook?.body)
147
143
  const paramsSchema = hook?.params
148
144
  // const headerSchema = hook?.headers
149
145
  const querySchema = hook?.query
150
- let responseSchema = hook?.response as unknown as OpenAPIV3.ResponsesObject
146
+ let responseSchema = hook?.response as unknown as TypeSchema
147
+ let openapiResponse: OpenAPIV3.ResponsesObject = {}
151
148
 
152
149
  if (typeof responseSchema === 'object') {
153
- if (Kind in responseSchema) {
150
+ const isStatusMap = Object.keys(responseSchema).every(
151
+ (key) => typeof key === 'number' || Number.isInteger(Number(key)),
152
+ )
153
+ if (!isStatusMap) {
154
+ let jsonSchema = getJsonSchema(responseSchema)
154
155
  const {
155
156
  type,
156
157
  properties,
@@ -158,13 +159,9 @@ export const registerSchemaPath = ({
158
159
  additionalProperties,
159
160
  patternProperties,
160
161
  ...rest
161
- } = responseSchema as typeof responseSchema & {
162
- type: string
163
- properties: Object
164
- required: string[]
165
- }
162
+ } = jsonSchema
166
163
 
167
- responseSchema = {
164
+ openapiResponse = {
168
165
  '200': {
169
166
  ...rest,
170
167
  description: rest.description as any,
@@ -175,71 +172,64 @@ export const registerSchemaPath = ({
175
172
  type,
176
173
  properties,
177
174
  patternProperties,
178
- items: responseSchema.items,
175
+ items: jsonSchema.items,
179
176
  required,
180
177
  } as any)
181
- : responseSchema,
178
+ : jsonSchema,
182
179
  ),
183
180
  },
184
181
  }
185
182
  } else {
186
- Object.entries(responseSchema as Record<string, TSchema>).forEach(
187
- ([key, value]) => {
188
- if (typeof value === 'string') {
189
- if (!models[value]) return
190
-
191
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
192
- const {
193
- type,
194
- properties,
195
- required,
196
- additionalProperties: _1,
197
- patternProperties: _2,
198
- ...rest
199
- } = models[value] as TSchema & {
200
- type: string
201
- properties: Object
202
- required: string[]
203
- }
204
-
205
- responseSchema[key] = {
206
- ...rest,
207
- description: rest.description as any,
208
- content: mapTypesResponse(contentTypes, value),
209
- }
210
- } else {
211
- const {
212
- type,
213
- properties,
214
- required,
215
- additionalProperties,
216
- patternProperties,
217
- ...rest
218
- } = value as typeof value & {
219
- type: string
220
- properties: Object
221
- required: string[]
222
- }
223
-
224
- responseSchema[key] = {
225
- ...rest,
226
- description: rest.description as any,
227
- content: mapTypesResponse(
228
- contentTypes,
229
- type === 'object' || type === 'array'
230
- ? ({
231
- type,
232
- properties,
233
- patternProperties,
234
- items: value.items,
235
- required,
236
- } as any)
237
- : value,
238
- ),
239
- }
183
+ Object.entries(
184
+ responseSchema as Record<string, TypeSchema>,
185
+ ).forEach(([key, value]) => {
186
+ if (typeof value === 'string') {
187
+ if (!models[value]) return
188
+
189
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
190
+ const {
191
+ type,
192
+ properties,
193
+ required,
194
+ additionalProperties: _1,
195
+ patternProperties: _2,
196
+ ...rest
197
+ } = getJsonSchema(models[value])
198
+
199
+ openapiResponse[key] = {
200
+ ...rest,
201
+ description: rest.description as any,
202
+ content: mapTypesResponse(contentTypes, value),
240
203
  }
241
- },
242
- )
204
+ } else {
205
+ const schema = getJsonSchema(value)
206
+ const {
207
+ type,
208
+ properties,
209
+ required,
210
+ additionalProperties,
211
+ patternProperties,
212
+ ...rest
213
+ } = schema
214
+
215
+ openapiResponse[key] = {
216
+ ...rest,
217
+ description: rest.description as any,
218
+ content: mapTypesResponse(
219
+ contentTypes,
220
+ type === 'object' || type === 'array'
221
+ ? ({
222
+ type,
223
+ properties,
224
+ patternProperties,
225
+ items: rest.items,
226
+ required,
227
+ } as any)
228
+ : schema,
229
+ ),
230
+ }
231
+ }
232
+ })
243
233
  }
244
234
  } else if (typeof responseSchema === 'string') {
245
235
  if (!(responseSchema in models)) return
@@ -252,13 +242,9 @@ export const registerSchemaPath = ({
252
242
  additionalProperties: _1,
253
243
  patternProperties: _2,
254
244
  ...rest
255
- } = models[responseSchema] as TSchema & {
256
- type: string
257
- properties: Object
258
- required: string[]
259
- }
245
+ } = getJsonSchema(models[responseSchema])
260
246
 
261
- responseSchema = {
247
+ openapiResponse = {
262
248
  // @ts-ignore
263
249
  '200': {
264
250
  ...rest,
@@ -279,9 +265,9 @@ export const registerSchemaPath = ({
279
265
  ...((paramsSchema || querySchema || bodySchema
280
266
  ? ({ parameters } as any)
281
267
  : {}) satisfies OpenAPIV3.ParameterObject),
282
- ...(responseSchema
268
+ ...(openapiResponse
283
269
  ? {
284
- responses: responseSchema,
270
+ responses: openapiResponse,
285
271
  }
286
272
  : {}),
287
273
  operationId:
@@ -312,10 +298,10 @@ export const registerSchemaPath = ({
312
298
  * @see https://github.com/elysiajs/elysia-swagger
313
299
  */
314
300
  export const openapi = <Path extends string = '/openapi'>({
315
- path,
301
+ path = '/openapi' as Path,
316
302
  documentation = {},
317
303
  }: {
318
- path: Path
304
+ path?: Path
319
305
  /**
320
306
  * Customize Swagger config, refers to Swagger 2.0 config
321
307
  *
@@ -326,7 +312,7 @@ export const openapi = <Path extends string = '/openapi'>({
326
312
  | 'x-express-openapi-additional-middleware'
327
313
  | 'x-express-openapi-validation-strict'
328
314
  >
329
- }) => {
315
+ } = {}) => {
330
316
  const schema = {}
331
317
  let totalRoutes = 0
332
318
 
@@ -392,7 +378,7 @@ export const openapi = <Path extends string = '/openapi'>({
392
378
  // (tag) => !excludeTags?.includes(tag?.name),
393
379
  // ),
394
380
  info: {
395
- title: 'Elysia Documentation',
381
+ title: 'Spiceflow Documentation',
396
382
  description: 'Development documentation',
397
383
  version: '0.0.0',
398
384
  ...documentation.info,
@@ -417,6 +403,7 @@ export const openapi = <Path extends string = '/openapi'>({
417
403
  }
418
404
 
419
405
  function getJsonSchema(schema: TypeSchema): JSONSchemaType<any> {
406
+ if (!schema) return undefined as any
420
407
  if (isZodSchema(schema)) {
421
408
  let fn = zodToJsonSchema.default ?? zodToJsonSchema
422
409
  let jsonSchema = fn(schema, {})
package/src/spiceflow.ts CHANGED
@@ -14,6 +14,7 @@ import {
14
14
  HTTPMethod,
15
15
  InlineHandler,
16
16
  InputSchema,
17
+ IsAny,
17
18
  JoinPath,
18
19
  LocalHook,
19
20
  MaybeArray,
@@ -889,20 +890,8 @@ export class Spiceflow<
889
890
 
890
891
  use<const NewSpiceflow extends AnySpiceflow>(
891
892
  instance: NewSpiceflow,
892
- ): NewSpiceflow['_scoped'] extends false
893
- ? Spiceflow<
894
- BasePath,
895
- Scoped,
896
- // @ts-expect-error - This is truly ideal
897
- Prettify2<Singleton & NewSpiceflow['_types']['Singleton']>,
898
- Prettify2<Definitions & NewSpiceflow['_types']['Definitions']>,
899
- Prettify2<Metadata & NewSpiceflow['_types']['Metadata']>,
900
- BasePath extends ``
901
- ? Routes & NewSpiceflow['_routes']
902
- : Routes & CreateEden<BasePath, NewSpiceflow['_routes']>,
903
- Ephemeral,
904
- Prettify2<Volatile & NewSpiceflow['_ephemeral']>
905
- >
893
+ ): IsAny<NewSpiceflow> extends true
894
+ ? this
906
895
  : Spiceflow<
907
896
  BasePath,
908
897
  Scoped,
@@ -0,0 +1,50 @@
1
+ import { test, describe, expect } from 'vitest'
2
+ import { Type } from '@sinclair/typebox'
3
+ import { bfs, Spiceflow } from './spiceflow.js'
4
+ import { z } from 'zod'
5
+ import { createSpiceflowClient } from './client/index.js'
6
+ import { Prettify } from './elysia-fork/types.js'
7
+
8
+ test('`use` on non Spiceflow return', async () => {
9
+ function nonSpiceflowReturn() {
10
+ return new Spiceflow() as any
11
+ }
12
+ const app = new Spiceflow()
13
+ .use(nonSpiceflowReturn())
14
+ .post('/xxx', () => 'hi')
15
+ const res = await app.handle(
16
+ new Request('http://localhost/xxx', { method: 'POST' }),
17
+ )
18
+
19
+ let client = createSpiceflowClient(app)
20
+
21
+ type ClientType = Prettify<typeof client>
22
+ // @ts-expect-error
23
+ client.something
24
+
25
+ client.xxx.post()
26
+ expect(res.status).toBe(200)
27
+ expect(await res.json()).toEqual('hi')
28
+ })
29
+ test('`use` on Spiceflow return', async () => {
30
+ function nonSpiceflowReturn() {
31
+ return new Spiceflow().post('/usePost', () => 'hi')
32
+ }
33
+ const app = new Spiceflow()
34
+ .use(nonSpiceflowReturn())
35
+ .post('/xxx', () => 'hi')
36
+ const res = await app.handle(
37
+ new Request('http://localhost/xxx', { method: 'POST' }),
38
+ )
39
+
40
+ let client = createSpiceflowClient(app)
41
+ client.xxx.post()
42
+ client.usePost.post()
43
+
44
+ type ClientType = Prettify<typeof client>
45
+ // @ts-expect-error
46
+ client.something
47
+
48
+ expect(res.status).toBe(200)
49
+ expect(await res.json()).toEqual('hi')
50
+ })