@spfn/core 0.2.0-beta.1 → 0.2.0-beta.10
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 +262 -1092
- package/dist/{boss-D-fGtVgM.d.ts → boss-DI1r4kTS.d.ts} +68 -11
- package/dist/codegen/index.d.ts +55 -8
- package/dist/codegen/index.js +159 -5
- package/dist/codegen/index.js.map +1 -1
- package/dist/config/index.d.ts +36 -0
- package/dist/config/index.js +15 -6
- package/dist/config/index.js.map +1 -1
- package/dist/db/index.d.ts +13 -0
- package/dist/db/index.js +40 -6
- package/dist/db/index.js.map +1 -1
- package/dist/env/index.d.ts +82 -3
- package/dist/env/index.js +81 -14
- package/dist/env/index.js.map +1 -1
- package/dist/env/loader.d.ts +87 -0
- package/dist/env/loader.js +70 -0
- package/dist/env/loader.js.map +1 -0
- package/dist/event/index.d.ts +3 -70
- package/dist/event/index.js +10 -1
- package/dist/event/index.js.map +1 -1
- package/dist/event/sse/client.d.ts +82 -0
- package/dist/event/sse/client.js +115 -0
- package/dist/event/sse/client.js.map +1 -0
- package/dist/event/sse/index.d.ts +40 -0
- package/dist/event/sse/index.js +92 -0
- package/dist/event/sse/index.js.map +1 -0
- package/dist/job/index.d.ts +54 -8
- package/dist/job/index.js +61 -12
- package/dist/job/index.js.map +1 -1
- package/dist/middleware/index.d.ts +102 -11
- package/dist/middleware/index.js +2 -2
- package/dist/middleware/index.js.map +1 -1
- package/dist/nextjs/index.d.ts +2 -2
- package/dist/nextjs/index.js +36 -4
- package/dist/nextjs/index.js.map +1 -1
- package/dist/nextjs/server.d.ts +62 -15
- package/dist/nextjs/server.js +102 -33
- package/dist/nextjs/server.js.map +1 -1
- package/dist/route/index.d.ts +227 -15
- package/dist/route/index.js +307 -31
- package/dist/route/index.js.map +1 -1
- package/dist/route/types.d.ts +2 -31
- package/dist/router-Di7ENoah.d.ts +151 -0
- package/dist/server/index.d.ts +153 -6
- package/dist/server/index.js +216 -14
- package/dist/server/index.js.map +1 -1
- package/dist/types-B-e_f2dQ.d.ts +121 -0
- package/dist/{types-DRG2XMTR.d.ts → types-BOPTApC2.d.ts} +91 -3
- package/docs/cache.md +133 -0
- package/docs/codegen.md +74 -0
- package/docs/database.md +346 -0
- package/docs/entity.md +539 -0
- package/docs/env.md +477 -0
- package/docs/errors.md +319 -0
- package/docs/event.md +116 -0
- package/docs/file-upload.md +717 -0
- package/docs/job.md +131 -0
- package/docs/logger.md +108 -0
- package/docs/middleware.md +337 -0
- package/docs/nextjs.md +241 -0
- package/docs/repository.md +496 -0
- package/docs/route.md +497 -0
- package/docs/server.md +307 -0
- package/package.json +18 -3
package/dist/route/index.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import * as _sinclair_typebox from '@sinclair/typebox';
|
|
2
|
-
import { TSchema, Static } from '@sinclair/typebox';
|
|
2
|
+
import { TSchema, Static, Kind } from '@sinclair/typebox';
|
|
3
3
|
import { Context, MiddlewareHandler, Hono } from 'hono';
|
|
4
|
-
import { ContentfulStatusCode } from 'hono/utils/http-status';
|
|
4
|
+
import { ContentfulStatusCode, RedirectStatusCode } from 'hono/utils/http-status';
|
|
5
5
|
import { HttpMethod } from './types.js';
|
|
6
|
-
export { HeaderRecord, InferResponseData, RouteMeta, RouteMetadata, RouterMetadata } from './types.js';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Route Input Types
|
|
@@ -23,6 +22,8 @@ type RouteInput = {
|
|
|
23
22
|
query?: TSchema;
|
|
24
23
|
/** Request body (JSON) */
|
|
25
24
|
body?: TSchema;
|
|
25
|
+
/** Form data (multipart/form-data) for file uploads */
|
|
26
|
+
formData?: TSchema;
|
|
26
27
|
/** HTTP headers */
|
|
27
28
|
headers?: TSchema;
|
|
28
29
|
/** Cookies */
|
|
@@ -35,6 +36,18 @@ type RouteInput = {
|
|
|
35
36
|
* Provides structured input access and response helpers for route handlers
|
|
36
37
|
*/
|
|
37
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Paginated response structure
|
|
41
|
+
*/
|
|
42
|
+
type PaginatedResult<T> = {
|
|
43
|
+
items: T[];
|
|
44
|
+
pagination: {
|
|
45
|
+
page: number;
|
|
46
|
+
limit: number;
|
|
47
|
+
total: number;
|
|
48
|
+
totalPages: number;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
38
51
|
/**
|
|
39
52
|
* Merge input with interceptor-injected fields
|
|
40
53
|
* Server receives both client input and interceptor-injected fields
|
|
@@ -50,6 +63,7 @@ type MergedInput<TInput extends RouteInput, TInterceptor extends RouteInput> = {
|
|
|
50
63
|
params: (TInput['params'] extends TSchema ? Static<TInput['params']> : {}) & (TInterceptor['params'] extends TSchema ? Static<TInterceptor['params']> : {});
|
|
51
64
|
query: (TInput['query'] extends TSchema ? Static<TInput['query']> : {}) & (TInterceptor['query'] extends TSchema ? Static<TInterceptor['query']> : {});
|
|
52
65
|
body: (TInput['body'] extends TSchema ? Static<TInput['body']> : {}) & (TInterceptor['body'] extends TSchema ? Static<TInterceptor['body']> : {});
|
|
66
|
+
formData: (TInput['formData'] extends TSchema ? Static<TInput['formData']> : {}) & (TInterceptor['formData'] extends TSchema ? Static<TInterceptor['formData']> : {});
|
|
53
67
|
headers: (TInput['headers'] extends TSchema ? Static<TInput['headers']> : {}) & (TInterceptor['headers'] extends TSchema ? Static<TInterceptor['headers']> : {});
|
|
54
68
|
cookies: (TInput['cookies'] extends TSchema ? Static<TInput['cookies']> : {}) & (TInterceptor['cookies'] extends TSchema ? Static<TInterceptor['cookies']> : {});
|
|
55
69
|
};
|
|
@@ -94,7 +108,7 @@ type RouteBuilderContext<TInput extends RouteInput = RouteInput, TInterceptor ex
|
|
|
94
108
|
json(data: unknown, status?: ContentfulStatusCode, headers?: Record<string, string | string[]>): Response;
|
|
95
109
|
/**
|
|
96
110
|
* Return 201 Created response with optional Location header
|
|
97
|
-
* Returns data directly
|
|
111
|
+
* Returns data directly for type inference
|
|
98
112
|
*
|
|
99
113
|
* @example
|
|
100
114
|
* ```ts
|
|
@@ -103,25 +117,29 @@ type RouteBuilderContext<TInput extends RouteInput = RouteInput, TInterceptor ex
|
|
|
103
117
|
* // Response: 201 Created
|
|
104
118
|
* // Header: Location: /users/123
|
|
105
119
|
* // Body: { id: '123', name: 'John' }
|
|
120
|
+
* // Type: User (inferred from data)
|
|
106
121
|
* ```
|
|
107
122
|
*/
|
|
108
|
-
created(data:
|
|
123
|
+
created<T>(data: T, location?: string): T;
|
|
109
124
|
/**
|
|
110
125
|
* Return 202 Accepted response
|
|
111
|
-
* Returns data directly
|
|
126
|
+
* Returns data directly for type inference
|
|
112
127
|
*
|
|
113
128
|
* @example
|
|
114
129
|
* ```ts
|
|
115
130
|
* // With data
|
|
116
131
|
* return c.accepted({ jobId: '123' });
|
|
117
132
|
* // Response: 202 Accepted, Body: { jobId: '123' }
|
|
133
|
+
* // Type: { jobId: string }
|
|
118
134
|
*
|
|
119
135
|
* // Without data
|
|
120
136
|
* return c.accepted();
|
|
121
137
|
* // Response: 202 Accepted, Body: (empty)
|
|
138
|
+
* // Type: void
|
|
122
139
|
* ```
|
|
123
140
|
*/
|
|
124
|
-
accepted(
|
|
141
|
+
accepted(): void;
|
|
142
|
+
accepted<T>(data: T): T;
|
|
125
143
|
/**
|
|
126
144
|
* Return 204 No Content response (empty body)
|
|
127
145
|
*
|
|
@@ -130,9 +148,10 @@ type RouteBuilderContext<TInput extends RouteInput = RouteInput, TInterceptor ex
|
|
|
130
148
|
* await deleteUser(id);
|
|
131
149
|
* return c.noContent();
|
|
132
150
|
* // Response: 204 No Content, Body: (empty)
|
|
151
|
+
* // Type: void
|
|
133
152
|
* ```
|
|
134
153
|
*/
|
|
135
|
-
noContent():
|
|
154
|
+
noContent(): void;
|
|
136
155
|
/**
|
|
137
156
|
* Return 304 Not Modified response (empty body)
|
|
138
157
|
*
|
|
@@ -142,12 +161,13 @@ type RouteBuilderContext<TInput extends RouteInput = RouteInput, TInterceptor ex
|
|
|
142
161
|
* return c.notModified();
|
|
143
162
|
* }
|
|
144
163
|
* // Response: 304 Not Modified, Body: (empty)
|
|
164
|
+
* // Type: void
|
|
145
165
|
* ```
|
|
146
166
|
*/
|
|
147
|
-
notModified():
|
|
167
|
+
notModified(): void;
|
|
148
168
|
/**
|
|
149
169
|
* Return paginated response with metadata
|
|
150
|
-
* Returns `{ items: [...], pagination: {...} }` format
|
|
170
|
+
* Returns `{ items: [...], pagination: {...} }` format with type inference
|
|
151
171
|
*
|
|
152
172
|
* @example
|
|
153
173
|
* ```ts
|
|
@@ -163,9 +183,29 @@ type RouteBuilderContext<TInput extends RouteInput = RouteInput, TInterceptor ex
|
|
|
163
183
|
* // totalPages: 5
|
|
164
184
|
* // }
|
|
165
185
|
* // }
|
|
186
|
+
* // Type: PaginatedResult<User>
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
paginated<T>(data: T[], page: number, limit: number, total: number): PaginatedResult<T>;
|
|
190
|
+
/**
|
|
191
|
+
* Redirect to another URL
|
|
192
|
+
*
|
|
193
|
+
* @param url - Target URL to redirect to
|
|
194
|
+
* @param status - HTTP status code (301, 302, 303, 307, 308). Default: 302
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```ts
|
|
198
|
+
* // Temporary redirect (302)
|
|
199
|
+
* return c.redirect('/login');
|
|
200
|
+
*
|
|
201
|
+
* // Permanent redirect (301)
|
|
202
|
+
* return c.redirect('/new-path', 301);
|
|
203
|
+
*
|
|
204
|
+
* // See Other (303) - useful after POST
|
|
205
|
+
* return c.redirect('/success', 303);
|
|
166
206
|
* ```
|
|
167
207
|
*/
|
|
168
|
-
|
|
208
|
+
redirect(url: string, status?: RedirectStatusCode): Response;
|
|
169
209
|
raw: Context;
|
|
170
210
|
};
|
|
171
211
|
|
|
@@ -482,14 +522,46 @@ declare class RouteBuilder<TInput extends RouteInput = {}, TInterceptor extends
|
|
|
482
522
|
/**
|
|
483
523
|
* Define handler function
|
|
484
524
|
*
|
|
525
|
+
* Response type is automatically inferred from the return value.
|
|
526
|
+
* Use helper methods like `c.created()`, `c.paginated()` for proper type inference.
|
|
527
|
+
*
|
|
485
528
|
* @example
|
|
486
529
|
* ```ts
|
|
530
|
+
* // Direct return - type inferred from data
|
|
487
531
|
* route.get('/users/:id')
|
|
488
532
|
* .input({ params: Type.Object({ id: Type.String() }) })
|
|
489
533
|
* .handler(async (c) => {
|
|
490
534
|
* const { params } = await c.data();
|
|
491
|
-
*
|
|
492
|
-
*
|
|
535
|
+
* return await getUser(params.id); // Type: User
|
|
536
|
+
* })
|
|
537
|
+
*
|
|
538
|
+
* // Using c.created() - returns data with 201 status, type preserved
|
|
539
|
+
* route.post('/users')
|
|
540
|
+
* .input({ body: Type.Object({ name: Type.String() }) })
|
|
541
|
+
* .handler(async (c) => {
|
|
542
|
+
* const { body } = await c.data();
|
|
543
|
+
* return c.created(await createUser(body)); // Type: User
|
|
544
|
+
* })
|
|
545
|
+
*
|
|
546
|
+
* // Using c.paginated() - returns PaginatedResult<T>
|
|
547
|
+
* route.get('/users')
|
|
548
|
+
* .handler(async (c) => {
|
|
549
|
+
* const users = await getUsers();
|
|
550
|
+
* return c.paginated(users, 1, 20, 100); // Type: PaginatedResult<User>
|
|
551
|
+
* })
|
|
552
|
+
*
|
|
553
|
+
* // Using c.noContent() - returns void
|
|
554
|
+
* route.delete('/users/:id')
|
|
555
|
+
* .handler(async (c) => {
|
|
556
|
+
* await deleteUser(params.id);
|
|
557
|
+
* return c.noContent(); // Type: void
|
|
558
|
+
* })
|
|
559
|
+
*
|
|
560
|
+
* // Using c.json() - returns Response (type inference lost)
|
|
561
|
+
* // Use only when you need custom status codes not covered by helpers
|
|
562
|
+
* route.get('/custom')
|
|
563
|
+
* .handler(async (c) => {
|
|
564
|
+
* return c.json({ data }, 418); // Type: Response
|
|
493
565
|
* })
|
|
494
566
|
* ```
|
|
495
567
|
*/
|
|
@@ -627,6 +699,14 @@ declare function defineRouter<TRoutes extends Record<string, RouteDef<any, any,
|
|
|
627
699
|
* Registers routes defined with route.get()...handler() to Hono app
|
|
628
700
|
*/
|
|
629
701
|
|
|
702
|
+
/**
|
|
703
|
+
* Registered route information for logging
|
|
704
|
+
*/
|
|
705
|
+
interface RegisteredRoute {
|
|
706
|
+
method: HttpMethod;
|
|
707
|
+
path: string;
|
|
708
|
+
name: string;
|
|
709
|
+
}
|
|
630
710
|
/**
|
|
631
711
|
* Register routes from defineRouter() to Hono app
|
|
632
712
|
*
|
|
@@ -634,6 +714,7 @@ declare function defineRouter<TRoutes extends Record<string, RouteDef<any, any,
|
|
|
634
714
|
* @param router - Router definition
|
|
635
715
|
* @param namedMiddlewares - Optional server-level named middlewares
|
|
636
716
|
*
|
|
717
|
+
* @param collectedRoutes
|
|
637
718
|
* @example
|
|
638
719
|
* ```ts
|
|
639
720
|
* const appRouter = defineRouter({
|
|
@@ -652,7 +733,7 @@ declare function defineRouter<TRoutes extends Record<string, RouteDef<any, any,
|
|
|
652
733
|
declare function registerRoutes<TRoutes extends Record<string, RouteDef<any> | Router<any>>>(app: Hono, router: Router<TRoutes>, namedMiddlewares?: ReadonlyArray<{
|
|
653
734
|
name: string;
|
|
654
735
|
handler: MiddlewareHandler;
|
|
655
|
-
}
|
|
736
|
+
}>, collectedRoutes?: RegisteredRoute[]): RegisteredRoute[];
|
|
656
737
|
|
|
657
738
|
/**
|
|
658
739
|
* Type guard for HttpMethod
|
|
@@ -679,4 +760,135 @@ declare const Nullable: <T extends TSchema>(schema: T) => _sinclair_typebox.TUni
|
|
|
679
760
|
*/
|
|
680
761
|
declare const OptionalNullable: <T extends TSchema>(schema: T) => _sinclair_typebox.TOptional<_sinclair_typebox.TUnion<[T, _sinclair_typebox.TNull]>>;
|
|
681
762
|
|
|
682
|
-
|
|
763
|
+
/**
|
|
764
|
+
* File Schema Helpers for TypeBox
|
|
765
|
+
*
|
|
766
|
+
* Provides TypeBox schema definitions for file upload handling
|
|
767
|
+
* with optional validation constraints.
|
|
768
|
+
*/
|
|
769
|
+
|
|
770
|
+
/**
|
|
771
|
+
* File validation options
|
|
772
|
+
*/
|
|
773
|
+
interface FileSchemaOptions {
|
|
774
|
+
/**
|
|
775
|
+
* Maximum file size in bytes
|
|
776
|
+
*
|
|
777
|
+
* @example 5 * 1024 * 1024 // 5MB
|
|
778
|
+
*/
|
|
779
|
+
maxSize?: number;
|
|
780
|
+
/**
|
|
781
|
+
* Allowed MIME types
|
|
782
|
+
*
|
|
783
|
+
* @example ['image/jpeg', 'image/png', 'image/webp']
|
|
784
|
+
*/
|
|
785
|
+
allowedTypes?: string[];
|
|
786
|
+
/**
|
|
787
|
+
* Minimum file size in bytes (optional)
|
|
788
|
+
*
|
|
789
|
+
* @example 1024 // 1KB minimum
|
|
790
|
+
*/
|
|
791
|
+
minSize?: number;
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* File array validation options
|
|
795
|
+
*/
|
|
796
|
+
interface FileArraySchemaOptions extends FileSchemaOptions {
|
|
797
|
+
/**
|
|
798
|
+
* Maximum number of files
|
|
799
|
+
*
|
|
800
|
+
* @example 5
|
|
801
|
+
*/
|
|
802
|
+
maxFiles?: number;
|
|
803
|
+
/**
|
|
804
|
+
* Minimum number of files (optional)
|
|
805
|
+
*
|
|
806
|
+
* @example 1
|
|
807
|
+
*/
|
|
808
|
+
minFiles?: number;
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* Internal schema type with file validation metadata
|
|
812
|
+
*/
|
|
813
|
+
interface FileSchemaType extends TSchema {
|
|
814
|
+
[Kind]: 'File';
|
|
815
|
+
fileOptions?: FileSchemaOptions;
|
|
816
|
+
}
|
|
817
|
+
interface FileArraySchemaType extends TSchema {
|
|
818
|
+
[Kind]: 'FileArray';
|
|
819
|
+
fileOptions?: FileArraySchemaOptions;
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Create a File schema with optional validation
|
|
823
|
+
*
|
|
824
|
+
* @example
|
|
825
|
+
* ```ts
|
|
826
|
+
* // Basic usage (no validation)
|
|
827
|
+
* formData: Type.Object({
|
|
828
|
+
* file: FileSchema()
|
|
829
|
+
* })
|
|
830
|
+
*
|
|
831
|
+
* // With validation
|
|
832
|
+
* formData: Type.Object({
|
|
833
|
+
* avatar: FileSchema({
|
|
834
|
+
* maxSize: 5 * 1024 * 1024, // 5MB
|
|
835
|
+
* allowedTypes: ['image/jpeg', 'image/png', 'image/webp']
|
|
836
|
+
* })
|
|
837
|
+
* })
|
|
838
|
+
* ```
|
|
839
|
+
*/
|
|
840
|
+
declare function FileSchema(options?: FileSchemaOptions): FileSchemaType;
|
|
841
|
+
/**
|
|
842
|
+
* Create a File array schema with optional validation
|
|
843
|
+
*
|
|
844
|
+
* @example
|
|
845
|
+
* ```ts
|
|
846
|
+
* // Basic usage (no validation)
|
|
847
|
+
* formData: Type.Object({
|
|
848
|
+
* files: FileArraySchema()
|
|
849
|
+
* })
|
|
850
|
+
*
|
|
851
|
+
* // With validation
|
|
852
|
+
* formData: Type.Object({
|
|
853
|
+
* documents: FileArraySchema({
|
|
854
|
+
* maxSize: 10 * 1024 * 1024, // 10MB per file
|
|
855
|
+
* maxFiles: 5,
|
|
856
|
+
* allowedTypes: ['application/pdf', 'application/msword']
|
|
857
|
+
* })
|
|
858
|
+
* })
|
|
859
|
+
* ```
|
|
860
|
+
*/
|
|
861
|
+
declare function FileArraySchema(options?: FileArraySchemaOptions): FileArraySchemaType;
|
|
862
|
+
/**
|
|
863
|
+
* Create an optional File schema with validation
|
|
864
|
+
*
|
|
865
|
+
* @example
|
|
866
|
+
* ```ts
|
|
867
|
+
* formData: Type.Object({
|
|
868
|
+
* name: Type.String(),
|
|
869
|
+
* avatar: OptionalFileSchema({
|
|
870
|
+
* maxSize: 2 * 1024 * 1024,
|
|
871
|
+
* allowedTypes: ['image/jpeg', 'image/png']
|
|
872
|
+
* })
|
|
873
|
+
* })
|
|
874
|
+
* ```
|
|
875
|
+
*/
|
|
876
|
+
declare function OptionalFileSchema(options?: FileSchemaOptions): TSchema;
|
|
877
|
+
/**
|
|
878
|
+
* Check if a schema is a File schema
|
|
879
|
+
*/
|
|
880
|
+
declare function isFileSchema(schema: TSchema): schema is FileSchemaType;
|
|
881
|
+
/**
|
|
882
|
+
* Check if a schema is a FileArray schema
|
|
883
|
+
*/
|
|
884
|
+
declare function isFileArraySchema(schema: TSchema): schema is FileArraySchemaType;
|
|
885
|
+
/**
|
|
886
|
+
* Get file options from schema
|
|
887
|
+
*/
|
|
888
|
+
declare function getFileOptions(schema: TSchema): FileSchemaOptions | FileArraySchemaOptions | undefined;
|
|
889
|
+
/**
|
|
890
|
+
* Format file size for error messages
|
|
891
|
+
*/
|
|
892
|
+
declare function formatFileSize(bytes: number): string;
|
|
893
|
+
|
|
894
|
+
export { type ExtractMiddlewareNames, FileArraySchema, type FileArraySchemaOptions, type FileArraySchemaType, FileSchema, type FileSchemaOptions, type FileSchemaType, HttpMethod, type MergedInput, type NamedMiddleware, type NamedMiddlewareFactory, Nullable, OptionalFileSchema, OptionalNullable, type PaginatedResult, type RegisteredRoute, type RouteBuilderContext, type RouteDef, type RouteHandlerFn, type RouteInput, type Router, defineMiddleware, defineMiddlewareFactory, defineRouter, formatFileSize, getFileOptions, isFileArraySchema, isFileSchema, isHttpMethod, registerRoutes, route };
|