galbe 0.1.6 → 0.1.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/schema.ts ADDED
@@ -0,0 +1,378 @@
1
+ export const Kind = Symbol.for('Galbe.SchemaType.Kind')
2
+ export const Optional = Symbol.for('Galbe.SchemaType.Optional')
3
+ export const Stream = Symbol.for('Galbe.SchemaType.Stream')
4
+
5
+ export interface Options {
6
+ title?: string
7
+ description?: string
8
+ default?: any
9
+ examples?: any
10
+ }
11
+ export interface ByteArrayOptions extends Options {
12
+ minLength?: number
13
+ maxLength?: number
14
+ }
15
+ export interface StringOptions extends Options {
16
+ minLength?: number
17
+ maxLength?: number
18
+ pattern?: RegExp
19
+ }
20
+ export interface NumberOptions extends Options {
21
+ min?: number
22
+ max?: number
23
+ exclusiveMin?: number
24
+ exclusiveMax?: number
25
+ }
26
+ export interface ArrayOptions extends Options {
27
+ minLength?: number
28
+ maxLength?: number
29
+ unique?: boolean
30
+ }
31
+ export interface STSchema extends Options {
32
+ [Kind]:
33
+ | 'boolean'
34
+ | 'byteArray'
35
+ | 'number'
36
+ | 'integer'
37
+ | 'string'
38
+ | 'literal'
39
+ | 'array'
40
+ | 'object'
41
+ | 'urlForm'
42
+ | 'multipartForm'
43
+ | 'any'
44
+ | 'union'
45
+ | 'stream'
46
+ [Optional]?: boolean
47
+ [Stream]?: boolean
48
+ params: unknown[]
49
+ static: unknown
50
+ [key: string]: any
51
+ }
52
+ export type STPropsValue =
53
+ | STBoolean
54
+ | STByteArray
55
+ | STNumber
56
+ | STInteger
57
+ | STString
58
+ | STLiteral
59
+ | STArray
60
+ | STObject
61
+ | STUnion
62
+ | STAny
63
+ export type STProps = Record<string | number, STPropsValue>
64
+
65
+ type Evaluate<T> = T extends infer O ? { [K in keyof O]: O[K] } : never
66
+ export type Static<T extends STSchema, P extends unknown[] = unknown[]> = (T & { params: P })['static']
67
+
68
+ // Utils
69
+ export type STOptional<T extends STSchema> = T & {
70
+ [Optional]: true
71
+ }
72
+ export type STStream<T extends STSchema = STSchema> = T & {
73
+ [Stream]: true
74
+ }
75
+
76
+ // ByteArray
77
+ export interface STByteArray extends STSchema, ByteArrayOptions {
78
+ [Kind]: 'byteArray'
79
+ static: Uint8Array
80
+ }
81
+ export function _ByteArray(options: ByteArrayOptions = {}): STByteArray {
82
+ return {
83
+ ...options,
84
+ [Kind]: 'byteArray'
85
+ } as unknown as STByteArray
86
+ }
87
+ // Boolean
88
+ export interface STBoolean extends STSchema, Options {
89
+ [Kind]: 'boolean'
90
+ static: boolean
91
+ }
92
+ export function _Bool(options: Options = {}): STBoolean {
93
+ return {
94
+ ...options,
95
+ [Kind]: 'boolean'
96
+ } as unknown as STBoolean
97
+ }
98
+ // String
99
+ export interface STString extends STSchema, NumberOptions {
100
+ [Kind]: 'string'
101
+ static: string
102
+ }
103
+ export function _String(options: StringOptions = {}): STString {
104
+ return {
105
+ ...options,
106
+ [Kind]: 'string'
107
+ } as unknown as STString
108
+ }
109
+ // Number
110
+ export interface STNumber extends STSchema, NumberOptions {
111
+ [Kind]: 'number'
112
+ static: number
113
+ }
114
+ export function _Number(options: NumberOptions = {}): STNumber {
115
+ return {
116
+ ...options,
117
+ [Kind]: 'number'
118
+ } as unknown as STNumber
119
+ }
120
+ // Integer
121
+ export interface STInteger extends STSchema, NumberOptions {
122
+ [Kind]: 'integer'
123
+ static: number
124
+ }
125
+ export function _Integer(options: NumberOptions = {}): STInteger {
126
+ return {
127
+ ...options,
128
+ [Kind]: 'integer'
129
+ } as unknown as STInteger
130
+ }
131
+ // Literal
132
+ type STLiteralValue = string | number | boolean
133
+ export interface STLiteral<T extends STLiteralValue = STLiteralValue> extends STSchema, Options {
134
+ [Kind]: 'literal'
135
+ static: T
136
+ value: T
137
+ }
138
+ export function _Literal<T extends STLiteralValue>(value: T, options: Options = {}): STLiteral<T> {
139
+ return {
140
+ ...options,
141
+ [Kind]: 'literal',
142
+ static: value,
143
+ value
144
+ } as unknown as STLiteral<T>
145
+ }
146
+ // Any
147
+ export interface STAny extends STSchema, Options {
148
+ [Kind]: 'any'
149
+ static: any
150
+ [key: string]: any
151
+ }
152
+ export function _Any(options: Options = {}): STAny {
153
+ return {
154
+ ...options,
155
+ [Kind]: 'any'
156
+ } as unknown as STAny
157
+ }
158
+
159
+ // Object
160
+ export interface STObject<T extends STProps = STProps> extends STSchema {
161
+ [Kind]: 'object'
162
+ static: ObjectStatic<T, this['params']>
163
+ props: T
164
+ }
165
+ type ObjectStatic<T extends STProps, P extends unknown[]> = ObjectStaticProps<T, { [K in keyof T]: Static<T[K], P> }>
166
+ type OptionalPropertyKeys<T extends STProps> = {
167
+ [K in keyof T]: T[K] extends STOptional<STSchema> ? K : never
168
+ }[keyof T]
169
+ type RequiredPropertyKeys<T extends STProps> = keyof Omit<T, OptionalPropertyKeys<T>>
170
+ type ObjectStaticProps<T extends STProps, R extends Record<keyof any, unknown>> = Evaluate<
171
+ Partial<Pick<R, OptionalPropertyKeys<T>>> & Required<Pick<R, RequiredPropertyKeys<T>>>
172
+ >
173
+ function _Object<T extends STProps>(properties?: T, options: Options = {}): STObject<T> {
174
+ if (!properties) return { ...options, [Kind]: 'object' } as unknown as STObject<T>
175
+ const propertyKeys = globalThis.Object.getOwnPropertyNames(properties)
176
+ const optionalKeys = propertyKeys.filter(key => properties[key]?.[Optional])
177
+ const requiredKeys = propertyKeys.filter(name => !optionalKeys.includes(name))
178
+ const clonedProperties = propertyKeys.reduce((acc, key) => ({ ...acc, [key]: { ...properties[key] } }), {} as STProps)
179
+ return (requiredKeys.length > 0
180
+ ? { ...options, [Kind]: 'object', props: clonedProperties, required: requiredKeys }
181
+ : { ...options, [Kind]: 'object', props: clonedProperties }) as unknown as STObject<T>
182
+ }
183
+
184
+ // UrlForm
185
+ export type STUrlFormValues =
186
+ | STByteArray
187
+ | STString
188
+ | STBoolean
189
+ | STNumber
190
+ | STInteger
191
+ | STString
192
+ | STLiteral
193
+ | STUnion
194
+ | STAny
195
+ | STArray
196
+ export type STUrlFormProps = Record<string, STUrlFormValues>
197
+ export interface STUrlForm<T extends STUrlFormProps = STUrlFormProps> extends STSchema {
198
+ [Kind]: 'urlForm'
199
+ static: T extends undefined ? Record<string, any> : ObjectStatic<T, this['params']>
200
+ props: T
201
+ }
202
+ function _UrlForm<T extends STUrlFormProps>(properties?: T, options: Options = {}): STUrlForm<T> {
203
+ if (!properties) return { ...options, [Kind]: 'urlForm' } as unknown as STUrlForm<T>
204
+ const propertyKeys = globalThis.Object.getOwnPropertyNames(properties)
205
+ const optionalKeys = propertyKeys.filter(key => properties[key]?.[Optional])
206
+ const requiredKeys = propertyKeys.filter(name => !optionalKeys.includes(name))
207
+ const clonedProperties = propertyKeys.reduce(
208
+ (acc, key) => ({ ...acc, [key]: { ...properties[key] } }),
209
+ {} as STUrlFormProps
210
+ )
211
+ return (requiredKeys.length > 0
212
+ ? { ...options, [Kind]: 'urlForm', props: clonedProperties, required: requiredKeys }
213
+ : { ...options, [Kind]: 'urlForm', props: clonedProperties }) as unknown as STUrlForm<T>
214
+ }
215
+
216
+ // MultipartForm
217
+ export type STMultipartFormValues = STSchema
218
+ export interface MultipartFormData<K extends string = string, V extends Static<STMultipartForm> = any> {
219
+ headers: { type?: string; name: K; filename?: string }
220
+ content: V
221
+ }
222
+ export interface STMultipartForm<T extends STProps = STProps> extends STSchema {
223
+ [Kind]: 'multipartForm'
224
+ static: T extends undefined ? Record<string, any> : ObjectStatic<T, this['params']>
225
+ props: T
226
+ }
227
+ function _MultipartForm<T extends STProps>(properties?: T, options: Options = {}): STMultipartForm<T> {
228
+ if (!properties) return { ...options, [Kind]: 'multipartForm' } as unknown as STMultipartForm<T>
229
+ const propertyKeys = globalThis.Object.getOwnPropertyNames(properties)
230
+ const optionalKeys = propertyKeys.filter(key => properties[key]?.[Optional])
231
+ const requiredKeys = propertyKeys.filter(name => !optionalKeys.includes(name))
232
+ const clonedProperties = propertyKeys.reduce((acc, key) => ({ ...acc, [key]: { ...properties[key] } }), {} as STProps)
233
+ return (requiredKeys.length > 0
234
+ ? { ...options, [Kind]: 'multipartForm', props: clonedProperties, required: requiredKeys }
235
+ : { ...options, [Kind]: 'multipartForm', props: clonedProperties }) as unknown as STMultipartForm<T>
236
+ }
237
+
238
+ // Array
239
+ export interface STArray<T extends STSchema = STSchema> extends STSchema {
240
+ [Kind]: 'array'
241
+ static: Static<T>[]
242
+ items: T
243
+ }
244
+ export function _Array<T extends STSchema>(schema?: T, options: ArrayOptions = {}): STArray<T | STAny> {
245
+ return {
246
+ ...options,
247
+ [Kind]: 'array',
248
+ items: schema ?? _Any()
249
+ } as unknown as T extends undefined ? STArray<STAny> : STArray<T>
250
+ }
251
+
252
+ // Union
253
+ type UnionStatic<T extends STSchema[], P extends unknown[]> = {
254
+ [K in keyof T]: T[K] extends STSchema ? Static<T[K], P> : never
255
+ }[number]
256
+ export interface STUnion<T extends STSchema[] = STSchema[]> extends STSchema {
257
+ [Kind]: 'union'
258
+ static: UnionStatic<T, this['params']>
259
+ anyOf: T
260
+ }
261
+ export function _Union<T extends STSchema[]>(schemas: [...T], options: Options): STUnion<T> {
262
+ const s = {
263
+ ...options,
264
+ [Kind]: 'union',
265
+ anyOf: schemas.map(s => ({ ...s, ...options })) as T,
266
+ optional: () => ({ ...s, [Optional]: true })
267
+ }
268
+ return s as unknown as STUnion<T>
269
+ }
270
+ // Stream
271
+ type STStreamable = STByteArray | STString | STUrlForm | STMultipartForm
272
+ export function _Stream<T extends STStreamable>(schema: T): STStream<T> {
273
+ return {
274
+ ...schema,
275
+ [Stream]: true
276
+ } as unknown as STStream<T>
277
+ }
278
+
279
+ export class SchemaType {
280
+ /** Creates an Optional Schema Type Wrapper*/
281
+ public optional<T extends STSchema>(schema: T): STOptional<T> {
282
+ return { ...schema, [Optional]: true }
283
+ }
284
+ /** Creates a ByteArray Schema Type */
285
+ public byteArray(options: ByteArrayOptions = {}): STByteArray {
286
+ return _ByteArray(options)
287
+ }
288
+ /** Creates a Boolean Schema Type */
289
+ public boolean(options: Options = {}): STBoolean {
290
+ return _Bool(options)
291
+ }
292
+ /** Creates a String Schema Type */
293
+ public string(options: StringOptions = {}): STString {
294
+ return _String(options)
295
+ }
296
+ /** Creates a Number Schema Type */
297
+ public number(options: NumberOptions = {}): STNumber {
298
+ return _Number(options)
299
+ }
300
+ /** Creates an Integer Schema Type */
301
+ public integer(options: NumberOptions = {}): STInteger {
302
+ return _Integer(options)
303
+ }
304
+ /** Creates a Literal Schema Type */
305
+ public literal<T extends STLiteralValue>(value: T, options: Options = {}): STLiteral<T> {
306
+ return _Literal(value, options)
307
+ }
308
+ /** Creates an Any Schema Type */
309
+ public any(options: Options = {}): STAny {
310
+ return _Any(options)
311
+ }
312
+ /** Creates an Object Schema Type */
313
+ public object<T extends STProps>(properties?: T, options: Options = {}): STObject<T> {
314
+ return _Object(properties, options)
315
+ }
316
+ /** Alias for Object Schema Type */
317
+ public json<T extends STProps>(properties?: T, options: Options = {}): STObject<T> {
318
+ return _Object(properties, options)
319
+ }
320
+ /** Creates an UrlForm Schema Type */
321
+ public urlForm<T extends STUrlFormProps>(properties?: T, options: Options = {}): STUrlForm<T> {
322
+ return _UrlForm(properties, options)
323
+ }
324
+ /** Creates an MultipartForm Schema Type */
325
+ public multipartForm<T extends STProps>(properties?: T, options: Options = {}): STMultipartForm<T> {
326
+ return _MultipartForm(properties, options)
327
+ }
328
+ /** Crates an Array Schema Type */
329
+ public array<T extends STSchema>(schema?: T, options: Options = {}): STArray<T | STAny> {
330
+ return _Array(schema, options)
331
+ }
332
+ /** Crates an Union Schema Type */
333
+ public union<T extends STSchema[]>(schemas: [...T], options: Options = {}): STUnion<T> {
334
+ return _Union(schemas, options)
335
+ }
336
+ /** Crates an Stream Schema Type */
337
+ public stream<T extends STUrlForm>(
338
+ schema: T
339
+ ): Omit<STStream<T>, 'static'> & {
340
+ static: AsyncGenerator<
341
+ T['props'] extends undefined
342
+ ? { [k: string]: Static<STUrlFormValues> }
343
+ : { [K in keyof T['props']]: [K, Static<T['props'][K]>] }[keyof T['props']]
344
+ >
345
+ params: unknown[]
346
+ }
347
+ public stream<T extends STMultipartForm>(
348
+ schema: T
349
+ ): Omit<STStream<T>, 'static'> & {
350
+ static: AsyncGenerator<
351
+ T['props'] extends undefined
352
+ ? {
353
+ [k: string]: {
354
+ headers: { type?: string; name: string; filename?: string }
355
+ content: Static<STMultipartFormValues>
356
+ }
357
+ }
358
+ : {
359
+ [K in keyof T['props']]: {
360
+ headers: { type?: string; name: K; filename?: string }
361
+ content: Static<T['props'][K]>
362
+ }
363
+ }[keyof T['props']],
364
+ void,
365
+ unknown
366
+ >
367
+ params: unknown[]
368
+ }
369
+ public stream<T extends STByteArray>(
370
+ schema: T
371
+ ): Omit<STStream<T>, 'static'> & { static: AsyncGenerator<Uint8Array>; params: unknown[] }
372
+ public stream<T extends STString>(
373
+ schema: T
374
+ ): Omit<STStream<T>, 'static'> & { static: AsyncGenerator<string>; params: unknown[] }
375
+ public stream<T extends STStreamable>(schema: T): STStream<T> {
376
+ return _Stream(schema)
377
+ }
378
+ }
package/src/server.ts CHANGED
@@ -80,7 +80,7 @@ export default async (galbe: Galbe, port?: number) => {
80
80
  let inParams = requestPathParser(url.pathname, route.path)
81
81
 
82
82
  context.body = await requestBodyParser(req.body, inHeaders, schema.body)
83
- context.headers = { ...context.headers, ...inHeaders }
83
+ context.headers = inHeaders
84
84
  context.query = inQuery
85
85
  context.params = inParams
86
86