@spfn/core 0.2.0-beta.9 → 0.3.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.
Files changed (119) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +693 -279
  3. package/dist/app-config/index.d.ts +96 -0
  4. package/dist/app-config/index.js +58 -0
  5. package/dist/app-config/index.js.map +1 -0
  6. package/dist/authz/index.d.ts +34 -0
  7. package/dist/authz/index.js +430 -0
  8. package/dist/authz/index.js.map +1 -0
  9. package/dist/boss-BiDCbbAQ.d.ts +337 -0
  10. package/dist/cache/index.js +42 -30
  11. package/dist/cache/index.js.map +1 -1
  12. package/dist/codegen/index.d.ts +121 -13
  13. package/dist/codegen/index.js +212 -15
  14. package/dist/codegen/index.js.map +1 -1
  15. package/dist/config/index.d.ts +576 -30
  16. package/dist/config/index.js +136 -17
  17. package/dist/config/index.js.map +1 -1
  18. package/dist/contract/index.d.ts +221 -0
  19. package/dist/contract/index.js +558 -0
  20. package/dist/contract/index.js.map +1 -0
  21. package/dist/db/index.d.ts +704 -94
  22. package/dist/db/index.js +1105 -260
  23. package/dist/db/index.js.map +1 -1
  24. package/dist/define-middleware-CVKgqo8S.d.ts +167 -0
  25. package/dist/env/index.d.ts +26 -2
  26. package/dist/env/index.js +15 -5
  27. package/dist/env/index.js.map +1 -1
  28. package/dist/env/loader.d.ts +26 -19
  29. package/dist/env/loader.js +55 -25
  30. package/dist/env/loader.js.map +1 -1
  31. package/dist/errors/index.d.ts +10 -0
  32. package/dist/errors/index.js +40 -7
  33. package/dist/errors/index.js.map +1 -1
  34. package/dist/event/index.d.ts +33 -3
  35. package/dist/event/index.js +24 -3
  36. package/dist/event/index.js.map +1 -1
  37. package/dist/event/sse/client.d.ts +55 -3
  38. package/dist/event/sse/client.js +164 -45
  39. package/dist/event/sse/client.js.map +1 -1
  40. package/dist/event/sse/index.d.ts +12 -5
  41. package/dist/event/sse/index.js +280 -32
  42. package/dist/event/sse/index.js.map +1 -1
  43. package/dist/event/ws/client.d.ts +59 -0
  44. package/dist/event/ws/client.js +273 -0
  45. package/dist/event/ws/client.js.map +1 -0
  46. package/dist/event/ws/index.d.ts +94 -0
  47. package/dist/event/ws/index.js +272 -0
  48. package/dist/event/ws/index.js.map +1 -0
  49. package/dist/job/index.d.ts +48 -3
  50. package/dist/job/index.js +265 -74
  51. package/dist/job/index.js.map +1 -1
  52. package/dist/logger/index.d.ts +5 -0
  53. package/dist/logger/index.js +14 -12
  54. package/dist/logger/index.js.map +1 -1
  55. package/dist/middleware/index.d.ts +352 -10
  56. package/dist/middleware/index.js +1079 -13
  57. package/dist/middleware/index.js.map +1 -1
  58. package/dist/nextjs/index.d.ts +39 -3
  59. package/dist/nextjs/index.js +82 -29
  60. package/dist/nextjs/index.js.map +1 -1
  61. package/dist/nextjs/server.d.ts +69 -52
  62. package/dist/nextjs/server.js +140 -60
  63. package/dist/nextjs/server.js.map +1 -1
  64. package/dist/ops/index.d.ts +208 -0
  65. package/dist/ops/index.js +800 -0
  66. package/dist/ops/index.js.map +1 -0
  67. package/dist/route/index.d.ts +10 -694
  68. package/dist/route/index.js +112 -23
  69. package/dist/route/index.js.map +1 -1
  70. package/dist/route-builder-2ani2jEI.d.ts +553 -0
  71. package/dist/router-DJdpwuB6.d.ts +127 -0
  72. package/dist/security/index.d.ts +83 -0
  73. package/dist/security/index.js +173 -0
  74. package/dist/security/index.js.map +1 -0
  75. package/dist/server/index.d.ts +619 -31
  76. package/dist/server/index.js +2583 -360
  77. package/dist/server/index.js.map +1 -1
  78. package/dist/token-manager-BT5EnUAR.d.ts +278 -0
  79. package/dist/types-2AbaW4Ie.d.ts +205 -0
  80. package/dist/{types-BOPTApC2.d.ts → types-9oszaJqp.d.ts} +7 -2
  81. package/dist/types-ClQVomgV.d.ts +115 -0
  82. package/dist/types-ZQODsBft.d.ts +282 -0
  83. package/docs/file-upload.md +195 -333
  84. package/package.json +250 -208
  85. package/src/cache/README.md +330 -0
  86. package/src/codegen/README.md +516 -0
  87. package/src/config/README.md +326 -0
  88. package/src/contract/README.md +326 -0
  89. package/src/db/README.md +589 -0
  90. package/src/db/manager/README.md +500 -0
  91. package/src/db/schema/README.md +354 -0
  92. package/src/db/transaction/README.md +822 -0
  93. package/src/env/README.md +651 -0
  94. package/src/errors/README.md +429 -0
  95. package/src/event/README.md +741 -0
  96. package/src/job/README.md +613 -0
  97. package/src/logger/README.md +321 -0
  98. package/src/middleware/README.md +634 -0
  99. package/src/nextjs/README.md +608 -0
  100. package/src/route/README.md +738 -0
  101. package/src/security/README.md +100 -0
  102. package/src/server/README.md +704 -0
  103. package/dist/boss-DI1r4kTS.d.ts +0 -244
  104. package/dist/router-Di7ENoah.d.ts +0 -151
  105. package/dist/types-B-e_f2dQ.d.ts +0 -121
  106. package/docs/cache.md +0 -133
  107. package/docs/codegen.md +0 -74
  108. package/docs/database.md +0 -346
  109. package/docs/entity.md +0 -539
  110. package/docs/env.md +0 -477
  111. package/docs/errors.md +0 -319
  112. package/docs/event.md +0 -116
  113. package/docs/job.md +0 -131
  114. package/docs/logger.md +0 -108
  115. package/docs/middleware.md +0 -337
  116. package/docs/nextjs.md +0 -241
  117. package/docs/repository.md +0 -496
  118. package/docs/route.md +0 -497
  119. package/docs/server.md +0 -307
@@ -1,244 +0,0 @@
1
- import { TSchema } from '@sinclair/typebox';
2
- import PgBoss from 'pg-boss';
3
-
4
- /**
5
- * Job System Types
6
- *
7
- * Type definitions for the pg-boss based job system
8
- */
9
-
10
- /**
11
- * Job options passed to pg-boss
12
- */
13
- interface JobOptions {
14
- /**
15
- * Maximum retry attempts
16
- * @default 3
17
- */
18
- retryLimit?: number;
19
- /**
20
- * Delay between retries in milliseconds
21
- * @default 1000
22
- */
23
- retryDelay?: number;
24
- /**
25
- * Job expiration in seconds
26
- * @default 300 (5 minutes)
27
- */
28
- expireInSeconds?: number;
29
- /**
30
- * Job priority (higher = more important)
31
- * @default 0
32
- */
33
- priority?: number;
34
- /**
35
- * Singleton key - only one job with this key can exist
36
- */
37
- singletonKey?: string;
38
- /**
39
- * Keep completed jobs for this many seconds
40
- * @default 604800 (7 days)
41
- */
42
- retentionSeconds?: number;
43
- }
44
- /**
45
- * Send options for individual job dispatch
46
- */
47
- interface JobSendOptions {
48
- /**
49
- * Delay execution by this many seconds
50
- */
51
- startAfter?: number | Date;
52
- /**
53
- * Singleton key for this specific job instance
54
- */
55
- singletonKey?: string;
56
- /**
57
- * Priority override
58
- */
59
- priority?: number;
60
- }
61
- /**
62
- * Job handler function type
63
- */
64
- type JobHandler<TInput, TOutput = void> = TInput extends void ? () => Promise<TOutput> : (input: TInput) => Promise<TOutput>;
65
- /**
66
- * Compensate handler function type (for rollback)
67
- */
68
- type CompensateHandler<TInput, TOutput> = (input: TInput, output: TOutput) => Promise<void>;
69
- /**
70
- * Job definition interface
71
- */
72
- interface JobDef<TInput = void, TOutput = void> {
73
- /**
74
- * Unique job name
75
- */
76
- readonly name: string;
77
- /**
78
- * TypeBox input schema (optional)
79
- */
80
- readonly inputSchema?: TSchema;
81
- /**
82
- * TypeBox output schema (optional, for workflow integration)
83
- */
84
- readonly outputSchema?: TSchema;
85
- /**
86
- * Cron expression for scheduled jobs
87
- */
88
- readonly cronExpression?: string;
89
- /**
90
- * Run once on server start
91
- */
92
- readonly runOnce?: boolean;
93
- /**
94
- * Event name this job subscribes to
95
- */
96
- readonly subscribedEvent?: string;
97
- /**
98
- * Event definition this job subscribes to (internal use)
99
- */
100
- readonly _subscribedEventDef?: unknown;
101
- /**
102
- * Job options
103
- */
104
- readonly options?: JobOptions;
105
- /**
106
- * Job handler
107
- */
108
- readonly handler: JobHandler<TInput, TOutput>;
109
- /**
110
- * Compensate handler for rollback (optional, for workflow integration)
111
- */
112
- readonly compensate?: CompensateHandler<TInput, TOutput>;
113
- /**
114
- * Send job to queue (returns immediately, executes in background)
115
- */
116
- send: TInput extends void ? (options?: JobSendOptions) => Promise<string | null> : (input: TInput, options?: JobSendOptions) => Promise<string | null>;
117
- /**
118
- * Run job synchronously (for testing/debugging)
119
- */
120
- run: TInput extends void ? () => Promise<TOutput> : (input: TInput) => Promise<TOutput>;
121
- /**
122
- * Type inference helpers
123
- */
124
- _input: TInput;
125
- _output: TOutput;
126
- }
127
- /**
128
- * Job router entry - can be a job or nested router
129
- */
130
- type JobRouterEntry = JobDef<any, any> | JobRouter<any>;
131
- /**
132
- * Job router interface
133
- */
134
- interface JobRouter<TJobs extends Record<string, JobRouterEntry> = Record<string, JobRouterEntry>> {
135
- readonly jobs: TJobs;
136
- readonly _jobs: TJobs;
137
- }
138
- /**
139
- * Infer input type from JobDef
140
- */
141
- type InferJobInput<TJob> = TJob extends JobDef<infer TInput, any> ? TInput : never;
142
- /**
143
- * Infer output type from JobDef
144
- */
145
- type InferJobOutput<TJob> = TJob extends JobDef<any, infer TOutput> ? TOutput : never;
146
-
147
- /**
148
- * pg-boss Wrapper
149
- *
150
- * Manages pg-boss instance lifecycle
151
- */
152
-
153
- /**
154
- * Options for pg-boss initialization
155
- *
156
- * @example
157
- * ```typescript
158
- * await initBoss({
159
- * connectionString: process.env.DATABASE_URL,
160
- * schema: 'spfn_queue',
161
- * clearOnStart: process.env.NODE_ENV === 'development',
162
- * });
163
- * ```
164
- */
165
- interface BossOptions {
166
- /**
167
- * PostgreSQL connection string
168
- *
169
- * @example 'postgresql://user:password@localhost:5432/mydb'
170
- */
171
- connectionString: string;
172
- /**
173
- * Schema name for pg-boss tables
174
- *
175
- * pg-boss creates its own tables in this schema.
176
- *
177
- * @default 'spfn_queue'
178
- */
179
- schema?: string;
180
- /**
181
- * Maintenance interval in seconds
182
- *
183
- * pg-boss runs maintenance tasks (cleanup, archiving) at this interval.
184
- *
185
- * @default 120
186
- */
187
- maintenanceIntervalSeconds?: number;
188
- /**
189
- * Monitor state changes interval in seconds
190
- *
191
- * When set, pg-boss emits state change events at this interval.
192
- *
193
- * @default undefined (disabled)
194
- */
195
- monitorIntervalSeconds?: number;
196
- /**
197
- * Clear all pending/scheduled jobs on startup
198
- *
199
- * Useful for development mode to start with a clean queue.
200
- * Should be false in production.
201
- *
202
- * @default false
203
- */
204
- clearOnStart?: boolean;
205
- }
206
- /**
207
- * @deprecated Use BossOptions instead
208
- */
209
- type BossConfig = BossOptions;
210
- /**
211
- * Initialize pg-boss with the given configuration
212
- *
213
- * Must be called before registerJobs(). Typically handled by defineServerConfig().
214
- *
215
- * @param options - pg-boss configuration options
216
- * @returns The pg-boss instance
217
- *
218
- * @example
219
- * ```typescript
220
- * const boss = await initBoss({
221
- * connectionString: process.env.DATABASE_URL!,
222
- * schema: 'spfn_queue',
223
- * });
224
- * ```
225
- */
226
- declare function initBoss(options: BossOptions): Promise<PgBoss>;
227
- /**
228
- * Get the current pg-boss instance
229
- */
230
- declare function getBoss(): PgBoss | null;
231
- /**
232
- * Stop pg-boss gracefully
233
- */
234
- declare function stopBoss(): Promise<void>;
235
- /**
236
- * Check if pg-boss is initialized and running
237
- */
238
- declare function isBossRunning(): boolean;
239
- /**
240
- * Check if jobs should be cleared on start
241
- */
242
- declare function shouldClearOnStart(): boolean;
243
-
244
- export { type BossOptions as B, type CompensateHandler as C, type InferJobInput as I, type JobRouter as J, type JobOptions as a, type JobHandler as b, type JobDef as c, type JobRouterEntry as d, type JobSendOptions as e, type InferJobOutput as f, getBoss as g, isBossRunning as h, initBoss as i, shouldClearOnStart as j, type BossConfig as k, stopBoss as s };
@@ -1,151 +0,0 @@
1
- import { TSchema } from '@sinclair/typebox';
2
-
3
- /**
4
- * Event System Types
5
- */
6
-
7
- /**
8
- * Pub/Sub capable cache interface for multi-instance events
9
- */
10
- interface PubSubCache {
11
- /**
12
- * Publish a message to a channel
13
- */
14
- publish(channel: string, message: unknown): Promise<void>;
15
- /**
16
- * Subscribe to a channel
17
- */
18
- subscribe(channel: string, handler: (message: unknown) => void | Promise<void>): Promise<void>;
19
- }
20
- /**
21
- * Event handler function type
22
- */
23
- type EventHandler<TPayload> = (payload: TPayload) => void | Promise<void>;
24
- /**
25
- * Job queue sender function type (used by job module)
26
- */
27
- type JobQueueSender = (queueName: string, payload: unknown) => Promise<void>;
28
- /**
29
- * Event definition interface
30
- */
31
- interface EventDef<TPayload = void> {
32
- /**
33
- * Unique event name
34
- */
35
- readonly name: string;
36
- /**
37
- * TypeBox payload schema (optional)
38
- */
39
- readonly schema?: TSchema;
40
- /**
41
- * Subscribe to this event (in-memory handler)
42
- */
43
- subscribe: (handler: EventHandler<TPayload>) => () => void;
44
- /**
45
- * Unsubscribe all handlers
46
- */
47
- unsubscribeAll: () => void;
48
- /**
49
- * Emit the event (triggers all subscribers and queued jobs)
50
- */
51
- emit: TPayload extends void ? () => Promise<void> : (payload: TPayload) => Promise<void>;
52
- /**
53
- * Enable cache-based pub/sub for multi-instance support
54
- * Must await before emitting events to ensure subscription is ready
55
- */
56
- useCache: (cache: PubSubCache) => Promise<EventDef<TPayload>>;
57
- /**
58
- * Internal: Register a job queue to receive this event
59
- * Called by job registration system
60
- */
61
- _registerJobQueue: (queueName: string, sender: JobQueueSender) => void;
62
- /**
63
- * Type inference helper
64
- */
65
- _payload: TPayload;
66
- }
67
- /**
68
- * Infer payload type from EventDef
69
- */
70
- type InferEventPayload$1<TEvent> = TEvent extends EventDef<infer TPayload> ? TPayload : never;
71
-
72
- /**
73
- * Event Router
74
- *
75
- * Type-safe event router for SSE subscription
76
- *
77
- * @example
78
- * ```typescript
79
- * import { defineEvent, defineEventRouter } from '@spfn/core/event';
80
- * import { Type } from '@sinclair/typebox';
81
- *
82
- * const userCreated = defineEvent('user.created', Type.Object({
83
- * userId: Type.String(),
84
- * }));
85
- *
86
- * const orderPlaced = defineEvent('order.placed', Type.Object({
87
- * orderId: Type.String(),
88
- * amount: Type.Number(),
89
- * }));
90
- *
91
- * export const eventRouter = defineEventRouter({
92
- * userCreated,
93
- * orderPlaced,
94
- * });
95
- *
96
- * export type EventRouter = typeof eventRouter;
97
- * ```
98
- */
99
-
100
- /**
101
- * Event Router Definition
102
- */
103
- interface EventRouterDef<TEvents extends Record<string, EventDef<any>>> {
104
- /**
105
- * Event definitions
106
- */
107
- readonly events: TEvents;
108
- /**
109
- * Event names as array
110
- */
111
- readonly eventNames: (keyof TEvents)[];
112
- /**
113
- * Type inference helper - payload types by event name
114
- */
115
- readonly _types: {
116
- [K in keyof TEvents]: TEvents[K]['_payload'];
117
- };
118
- }
119
- /**
120
- * Infer event names from EventRouter
121
- */
122
- type InferEventNames<T> = T extends EventRouterDef<infer E> ? keyof E & string : never;
123
- /**
124
- * Infer payload type for specific event
125
- */
126
- type InferEventPayload<T extends EventRouterDef<any>, K extends InferEventNames<T>> = T['_types'][K];
127
- /**
128
- * Infer all event payloads map
129
- */
130
- type InferEventPayloads<T extends EventRouterDef<any>> = T['_types'];
131
- /**
132
- * Define an event router for SSE subscription
133
- *
134
- * @example
135
- * ```typescript
136
- * export const eventRouter = defineEventRouter({
137
- * userCreated,
138
- * orderPlaced,
139
- * });
140
- *
141
- * // Type inference
142
- * type Names = InferEventNames<typeof eventRouter>;
143
- * // 'userCreated' | 'orderPlaced'
144
- *
145
- * type Payload = InferEventPayload<typeof eventRouter, 'userCreated'>;
146
- * // { userId: string }
147
- * ```
148
- */
149
- declare function defineEventRouter<TEvents extends Record<string, EventDef<any>>>(events: TEvents): EventRouterDef<TEvents>;
150
-
151
- export { type EventRouterDef as E, type InferEventNames as I, type JobQueueSender as J, type PubSubCache as P, type EventDef as a, type InferEventPayload as b, type InferEventPayloads as c, defineEventRouter as d, type EventHandler as e, type InferEventPayload$1 as f };
@@ -1,121 +0,0 @@
1
- import { E as EventRouterDef, I as InferEventNames, b as InferEventPayload } from './router-Di7ENoah.js';
2
-
3
- /**
4
- * SSE Types
5
- *
6
- * Type definitions for Server-Sent Events
7
- */
8
-
9
- /**
10
- * SSE message sent from server
11
- */
12
- interface SSEMessage<TEvent extends string = string, TPayload = unknown> {
13
- /** Event name */
14
- event: TEvent;
15
- /** Event payload */
16
- data: TPayload;
17
- /** Optional message ID for reconnection */
18
- id?: string;
19
- }
20
- /**
21
- * SSE Handler configuration
22
- */
23
- interface SSEHandlerConfig {
24
- /**
25
- * Keep-alive ping interval in milliseconds
26
- * @default 30000
27
- */
28
- pingInterval?: number;
29
- /**
30
- * Custom headers for SSE response
31
- */
32
- headers?: Record<string, string>;
33
- }
34
- /**
35
- * SSE Client configuration
36
- */
37
- interface SSEClientConfig {
38
- /**
39
- * Backend API host URL
40
- * @default NEXT_PUBLIC_SPFN_API_URL || 'http://localhost:8790'
41
- * @example 'http://localhost:8790'
42
- * @example 'https://api.example.com'
43
- */
44
- host?: string;
45
- /**
46
- * SSE endpoint pathname
47
- * @default '/events/stream'
48
- */
49
- pathname?: string;
50
- /**
51
- * Full URL (overrides host + pathname)
52
- * @deprecated Use host and pathname instead
53
- * @example 'http://localhost:8790/events/stream'
54
- */
55
- url?: string;
56
- /**
57
- * Auto reconnect on disconnect
58
- * @default true
59
- */
60
- reconnect?: boolean;
61
- /**
62
- * Reconnect delay in milliseconds
63
- * @default 3000
64
- */
65
- reconnectDelay?: number;
66
- /**
67
- * Maximum reconnect attempts (0 = infinite)
68
- * @default 0
69
- */
70
- maxReconnectAttempts?: number;
71
- /**
72
- * Include credentials (cookies) in request
73
- * @default false
74
- */
75
- withCredentials?: boolean;
76
- }
77
- /**
78
- * Event handler function
79
- */
80
- type SSEEventHandler<TPayload> = (payload: TPayload) => void;
81
- /**
82
- * Event handlers map for EventRouter
83
- */
84
- type SSEEventHandlers<TRouter extends EventRouterDef<any>> = {
85
- [K in InferEventNames<TRouter>]?: SSEEventHandler<InferEventPayload<TRouter, K>>;
86
- };
87
- /**
88
- * Subscription options
89
- */
90
- interface SSESubscribeOptions<TRouter extends EventRouterDef<any>> {
91
- /**
92
- * Events to subscribe
93
- */
94
- events: InferEventNames<TRouter>[];
95
- /**
96
- * Event handlers
97
- */
98
- handlers: SSEEventHandlers<TRouter>;
99
- /**
100
- * Called when connection opens
101
- */
102
- onOpen?: () => void;
103
- /**
104
- * Called on connection error
105
- */
106
- onError?: (error: Event) => void;
107
- /**
108
- * Called when reconnecting
109
- */
110
- onReconnect?: (attempt: number) => void;
111
- }
112
- /**
113
- * SSE connection state
114
- */
115
- type SSEConnectionState = 'connecting' | 'open' | 'closed' | 'error';
116
- /**
117
- * Unsubscribe function
118
- */
119
- type SSEUnsubscribe = () => void;
120
-
121
- export type { SSEHandlerConfig as S, SSEMessage as a, SSEClientConfig as b, SSEEventHandler as c, SSEEventHandlers as d, SSESubscribeOptions as e, SSEConnectionState as f, SSEUnsubscribe as g };
package/docs/cache.md DELETED
@@ -1,133 +0,0 @@
1
- # Cache
2
-
3
- Redis caching with type-safe operations.
4
-
5
- ## Setup
6
-
7
- ```bash
8
- REDIS_URL=redis://localhost:6379
9
- ```
10
-
11
- ## Basic Usage
12
-
13
- ```typescript
14
- import { cache } from '@spfn/core/cache';
15
-
16
- // Set
17
- await cache.set('user:123', { id: '123', name: 'John' });
18
- await cache.set('session:abc', data, { ttl: 3600 }); // 1 hour
19
-
20
- // Get
21
- const user = await cache.get<User>('user:123');
22
-
23
- // Delete
24
- await cache.del('user:123');
25
-
26
- // Check existence
27
- const exists = await cache.exists('user:123');
28
- ```
29
-
30
- ## TTL Options
31
-
32
- ```typescript
33
- // Set with TTL (seconds)
34
- await cache.set('key', value, { ttl: 60 }); // 1 minute
35
- await cache.set('key', value, { ttl: 3600 }); // 1 hour
36
- await cache.set('key', value, { ttl: 86400 }); // 1 day
37
-
38
- // No expiration
39
- await cache.set('key', value); // Permanent until deleted
40
- ```
41
-
42
- ## Patterns
43
-
44
- ### Cache-Aside
45
-
46
- ```typescript
47
- async function getUser(id: string): Promise<User>
48
- {
49
- const cached = await cache.get<User>(`user:${id}`);
50
- if (cached)
51
- {
52
- return cached;
53
- }
54
-
55
- const user = await userRepo.findById(id);
56
- if (user)
57
- {
58
- await cache.set(`user:${id}`, user, { ttl: 3600 });
59
- }
60
-
61
- return user;
62
- }
63
- ```
64
-
65
- ### Cache Invalidation
66
-
67
- ```typescript
68
- async function updateUser(id: string, data: Partial<User>)
69
- {
70
- const user = await userRepo.update(id, data);
71
- await cache.del(`user:${id}`); // Invalidate cache
72
- return user;
73
- }
74
- ```
75
-
76
- ### Cache with Prefix
77
-
78
- ```typescript
79
- const userCache = cache.prefix('user');
80
-
81
- await userCache.set('123', user); // Key: user:123
82
- await userCache.get('123');
83
- await userCache.del('123');
84
- ```
85
-
86
- ## Hash Operations
87
-
88
- ```typescript
89
- // Set hash field
90
- await cache.hset('user:123', 'name', 'John');
91
-
92
- // Get hash field
93
- const name = await cache.hget('user:123', 'name');
94
-
95
- // Get all hash fields
96
- const user = await cache.hgetall('user:123');
97
-
98
- // Delete hash field
99
- await cache.hdel('user:123', 'name');
100
- ```
101
-
102
- ## List Operations
103
-
104
- ```typescript
105
- // Push to list
106
- await cache.lpush('queue', item);
107
- await cache.rpush('queue', item);
108
-
109
- // Pop from list
110
- const item = await cache.lpop('queue');
111
- const item = await cache.rpop('queue');
112
-
113
- // Get list range
114
- const items = await cache.lrange('queue', 0, -1); // All items
115
- ```
116
-
117
- ## Best Practices
118
-
119
- ```typescript
120
- // 1. Use consistent key naming
121
- `user:${id}`
122
- `session:${token}`
123
- `cache:posts:${page}`
124
-
125
- // 2. Set appropriate TTL
126
- { ttl: 300 } // 5 min for frequently changing data
127
- { ttl: 3600 } // 1 hour for stable data
128
- { ttl: 86400 } // 1 day for rarely changing data
129
-
130
- // 3. Invalidate on write
131
- await userRepo.update(id, data);
132
- await cache.del(`user:${id}`);
133
- ```
package/docs/codegen.md DELETED
@@ -1,74 +0,0 @@
1
- # Codegen
2
-
3
- Automatic API client generation from route definitions.
4
-
5
- ## Setup
6
-
7
- ### Configure Generator
8
-
9
- ```typescript
10
- // codegen.config.ts
11
- import { defineCodegenConfig } from '@spfn/core/codegen';
12
-
13
- export default defineCodegenConfig({
14
- generators: [
15
- {
16
- name: 'api-client',
17
- output: './src/client/api.ts',
18
- router: './src/server/server.config.ts'
19
- }
20
- ]
21
- });
22
- ```
23
-
24
- ## Generate Client
25
-
26
- ```bash
27
- # Generate once
28
- pnpm spfn codegen run
29
-
30
- # Watch mode (dev server includes this)
31
- pnpm spfn:dev
32
- ```
33
-
34
- ## Generated Client
35
-
36
- ```typescript
37
- // src/client/api.ts (generated)
38
- import { createApi } from '@spfn/core/nextjs';
39
- import type { AppRouter } from '@/server/server.config';
40
-
41
- export const api = createApi<AppRouter>();
42
- ```
43
-
44
- ## Usage
45
-
46
- ```typescript
47
- import { api } from '@/client/api';
48
-
49
- // Type-safe API calls
50
- const user = await api.getUser.call({
51
- params: { id: '123' }
52
- });
53
-
54
- const users = await api.getUsers.call({
55
- query: { page: 1, limit: 20 }
56
- });
57
-
58
- const created = await api.createUser.call({
59
- body: { email: 'user@example.com', name: 'User' }
60
- });
61
- ```
62
-
63
- ## CLI Commands
64
-
65
- ```bash
66
- # Generate API client
67
- pnpm spfn codegen run
68
-
69
- # List registered generators
70
- pnpm spfn codegen list
71
-
72
- # Run specific generator
73
- pnpm spfn codegen run --name api-client
74
- ```