@stacksjs/types 0.70.88 → 0.70.91

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 (77) hide show
  1. package/dist/ai.d.ts +37 -0
  2. package/dist/analytics.d.ts +36 -0
  3. package/dist/api.d.ts +26 -0
  4. package/dist/app.d.ts +28 -0
  5. package/dist/attributes.d.ts +1 -0
  6. package/dist/auth.d.ts +62 -0
  7. package/dist/auto-imports.d.ts +8 -0
  8. package/dist/binary.d.ts +11 -0
  9. package/dist/cache.d.ts +88 -0
  10. package/dist/cdn.d.ts +4 -0
  11. package/dist/chat.d.ts +69 -0
  12. package/dist/cli.d.ts +316 -0
  13. package/dist/cloud.d.ts +366 -0
  14. package/dist/cms.d.ts +12 -0
  15. package/dist/commerce.d.ts +14 -0
  16. package/dist/components.d.ts +9 -0
  17. package/dist/configure.d.ts +12 -0
  18. package/dist/cors.d.ts +47 -0
  19. package/dist/cron-jobs.d.ts +61 -0
  20. package/dist/dashboard.d.ts +108 -0
  21. package/dist/database.d.ts +76 -0
  22. package/dist/dependencies.d.ts +17 -0
  23. package/dist/deploy.d.ts +16 -0
  24. package/dist/dns.d.ts +362 -0
  25. package/dist/docs.d.ts +23 -0
  26. package/dist/email.d.ts +207 -0
  27. package/dist/env.d.ts +1 -0
  28. package/dist/errors.d.ts +84 -0
  29. package/dist/events.d.ts +31 -0
  30. package/dist/exit-code.d.ts +10 -0
  31. package/dist/feature-flags.d.ts +17 -0
  32. package/dist/file-systems.d.ts +60 -0
  33. package/dist/git.d.ts +60 -0
  34. package/dist/hashing.d.ts +57 -0
  35. package/dist/helpers.d.ts +1 -0
  36. package/dist/i18n.d.ts +65 -0
  37. package/dist/index.d.ts +80 -0
  38. package/dist/index.js +2 -0
  39. package/dist/library.d.ts +799 -0
  40. package/dist/logging.d.ts +15 -0
  41. package/dist/manifest.d.ts +9 -0
  42. package/dist/marketing.d.ts +12 -0
  43. package/dist/model-dashboard-augmentation.d.ts +8 -0
  44. package/dist/model-names.d.ts +1 -0
  45. package/dist/model.d.ts +256 -0
  46. package/dist/monitoring.d.ts +12 -0
  47. package/dist/notifications.d.ts +126 -0
  48. package/dist/oauth.d.ts +290 -0
  49. package/dist/pages.d.ts +10 -0
  50. package/dist/payments.d.ts +322 -0
  51. package/dist/phone.d.ts +65 -0
  52. package/dist/ports.d.ts +20 -0
  53. package/dist/promise.d.ts +1 -0
  54. package/dist/push.d.ts +108 -0
  55. package/dist/queue.d.ts +312 -0
  56. package/dist/reactivity.d.ts +1 -0
  57. package/dist/realtime.d.ts +443 -0
  58. package/dist/request.d.ts +265 -0
  59. package/dist/response.d.ts +15 -0
  60. package/dist/router.d.ts +105 -0
  61. package/dist/saas.d.ts +32 -0
  62. package/dist/scheduler.d.ts +1 -0
  63. package/dist/search-engine.d.ts +129 -0
  64. package/dist/security.d.ts +18 -0
  65. package/dist/server.d.ts +16 -0
  66. package/dist/services.d.ts +149 -0
  67. package/dist/settings-config.d.ts +9 -0
  68. package/dist/sms.d.ts +144 -0
  69. package/dist/stack-extensions.d.ts +137 -0
  70. package/dist/stacks.d.ts +46 -0
  71. package/dist/storage.d.ts +104 -0
  72. package/dist/table-names.d.ts +1 -0
  73. package/dist/tables.d.ts +34 -0
  74. package/dist/team.d.ts +7 -0
  75. package/dist/ui.d.ts +55 -0
  76. package/dist/utils.d.ts +39 -0
  77. package/package.json +3 -3
@@ -0,0 +1,443 @@
1
+ /**
2
+ * Realtime configuration presets for common use cases
3
+ */
4
+ export declare const RealtimePresets: {
5
+ /**
6
+ * Server mode presets (ts-broadcasting)
7
+ */
8
+ server: {
9
+ /**
10
+ * Development preset - minimal config, debug enabled
11
+ */
12
+ development: {
13
+ enabled: true;
14
+ mode: 'server';
15
+ debug: true;
16
+ server: {
17
+ host: 'localhost';
18
+ port: 6001;
19
+ scheme: 'ws';
20
+ driver: 'bun';
21
+ rateLimit: {
22
+ enabled: false
23
+ };
24
+ healthCheck: {
25
+ enabled: true;
26
+ path: '/health'
27
+ }
28
+ };
29
+ channels: {
30
+ public: true;
31
+ private: true;
32
+ presence: true
33
+ }
34
+ };
35
+ /**
36
+ * Production preset - optimized for production workloads
37
+ */
38
+ production: {
39
+ enabled: true;
40
+ mode: 'server';
41
+ debug: false;
42
+ server: {
43
+ host: '0.0.0.0';
44
+ port: 6001;
45
+ scheme: 'wss';
46
+ driver: 'bun';
47
+ redis: {
48
+ enabled: true;
49
+ prefix: 'stacks:realtime:'
50
+ };
51
+ rateLimit: {
52
+ enabled: true;
53
+ maxConnectionsPerIp: 100;
54
+ maxMessagesPerSecond: 50;
55
+ maxPayloadSize: 65536
56
+ };
57
+ loadManagement: {
58
+ maxConnections: 10000;
59
+ backpressureThreshold: 1000;
60
+ messageQueueSize: 10000;
61
+ gracefulShutdownTimeout: 30000
62
+ };
63
+ autoScaling: {
64
+ min: 2;
65
+ max: 10;
66
+ targetCPU: 70
67
+ };
68
+ healthCheck: {
69
+ enabled: true;
70
+ path: '/health';
71
+ interval: 30
72
+ };
73
+ metrics: {
74
+ enabled: true;
75
+ port: 9090;
76
+ path: '/metrics'
77
+ }
78
+ };
79
+ channels: {
80
+ public: true;
81
+ private: true;
82
+ presence: true
83
+ }
84
+ };
85
+ /**
86
+ * High performance preset - optimized for high throughput
87
+ */
88
+ highPerformance: {
89
+ enabled: true;
90
+ mode: 'server';
91
+ server: {
92
+ driver: 'bun';
93
+ redis: {
94
+ enabled: true;
95
+ cluster: true
96
+ };
97
+ rateLimit: {
98
+ enabled: true;
99
+ maxConnectionsPerIp: 500;
100
+ maxMessagesPerSecond: 200;
101
+ maxPayloadSize: 131072
102
+ };
103
+ loadManagement: {
104
+ maxConnections: 100000;
105
+ backpressureThreshold: 5000;
106
+ messageQueueSize: 50000;
107
+ gracefulShutdownTimeout: 60000
108
+ };
109
+ autoScaling: {
110
+ min: 4;
111
+ max: 50;
112
+ targetCPU: 60
113
+ }
114
+ }
115
+ };
116
+ /**
117
+ * Chat application preset
118
+ */
119
+ chat: {
120
+ enabled: true;
121
+ mode: 'server';
122
+ server: {
123
+ driver: 'bun';
124
+ redis: {
125
+ enabled: true
126
+ };
127
+ rateLimit: {
128
+ enabled: true;
129
+ maxConnectionsPerIp: 10;
130
+ maxMessagesPerSecond: 20
131
+ };
132
+ loadManagement: {
133
+ maxConnections: 50000
134
+ }
135
+ };
136
+ channels: {
137
+ public: true;
138
+ private: true;
139
+ presence: {
140
+ enabled: true;
141
+ maxMembersPerChannel: 500;
142
+ memberInfoTtl: 60
143
+ }
144
+ }
145
+ };
146
+ /**
147
+ * Gaming preset - low latency, high throughput
148
+ */
149
+ gaming: {
150
+ enabled: true;
151
+ mode: 'server';
152
+ server: {
153
+ driver: 'bun';
154
+ redis: {
155
+ enabled: true;
156
+ cluster: true
157
+ };
158
+ rateLimit: {
159
+ enabled: true;
160
+ maxConnectionsPerIp: 50;
161
+ maxMessagesPerSecond: 100
162
+ };
163
+ loadManagement: {
164
+ maxConnections: 50000;
165
+ backpressureThreshold: 2000;
166
+ messageQueueSize: 20000
167
+ };
168
+ autoScaling: {
169
+ min: 2;
170
+ max: 20;
171
+ targetCPU: 50
172
+ }
173
+ };
174
+ channels: {
175
+ public: true;
176
+ private: true;
177
+ presence: true
178
+ }
179
+ }
180
+ };
181
+ /**
182
+ * Serverless mode presets (API Gateway WebSocket)
183
+ */
184
+ serverless: {
185
+ /**
186
+ * Development preset
187
+ */
188
+ development: {
189
+ enabled: true;
190
+ mode: 'serverless';
191
+ debug: true;
192
+ serverless: {
193
+ connectionTimeout: 3600;
194
+ idleTimeout: 600;
195
+ stageName: 'dev';
196
+ memorySize: 256;
197
+ timeout: 30
198
+ };
199
+ channels: {
200
+ public: true;
201
+ private: true;
202
+ presence: true
203
+ }
204
+ };
205
+ /**
206
+ * Production preset
207
+ */
208
+ production: {
209
+ enabled: true;
210
+ mode: 'serverless';
211
+ debug: false;
212
+ serverless: {
213
+ connectionTimeout: 3600;
214
+ idleTimeout: 600;
215
+ stageName: 'production';
216
+ memorySize: 512;
217
+ timeout: 30;
218
+ provisionedConcurrency: 2
219
+ };
220
+ channels: {
221
+ public: true;
222
+ private: true;
223
+ presence: true
224
+ }
225
+ };
226
+ /**
227
+ * Notifications preset - simple push notifications
228
+ */
229
+ notifications: {
230
+ enabled: true;
231
+ mode: 'serverless';
232
+ serverless: {
233
+ connectionTimeout: 7200;
234
+ idleTimeout: 1800;
235
+ memorySize: 256;
236
+ timeout: 15
237
+ };
238
+ channels: {
239
+ public: true;
240
+ private: true;
241
+ presence: false
242
+ }
243
+ }
244
+ }
245
+ };
246
+ /**
247
+ * Redis adapter configuration for horizontal scaling
248
+ */
249
+ export declare interface RealtimeRedisConfig {
250
+ enabled?: boolean
251
+ host?: string
252
+ port?: number
253
+ password?: string
254
+ prefix?: string
255
+ cluster?: boolean
256
+ sentinels?: Array<{ host: string, port: number }>
257
+ sentinelName?: string
258
+ }
259
+ /**
260
+ * Rate limiting configuration
261
+ */
262
+ export declare interface RealtimeRateLimitConfig {
263
+ enabled?: boolean
264
+ maxConnectionsPerIp?: number
265
+ maxMessagesPerSecond?: number
266
+ maxPayloadSize?: number
267
+ banDuration?: number
268
+ }
269
+ /**
270
+ * Encryption configuration
271
+ */
272
+ export declare interface RealtimeEncryptionConfig {
273
+ enabled?: boolean
274
+ algorithm?: 'aes-256-gcm' | 'chacha20-poly1305'
275
+ keyRotationInterval?: number
276
+ }
277
+ /**
278
+ * Webhook configuration
279
+ */
280
+ export declare interface RealtimeWebhooksConfig {
281
+ enabled?: boolean
282
+ url?: string
283
+ events?: Array<'connection' | 'disconnection' | 'subscription' | 'message' | 'error'>
284
+ headers?: Record<string, string>
285
+ timeout?: number
286
+ retries?: number
287
+ }
288
+ /**
289
+ * Queue integration configuration
290
+ */
291
+ export declare interface RealtimeQueueConfig {
292
+ enabled?: boolean
293
+ driver?: 'redis' | 'sqs' | 'memory'
294
+ batchSize?: number
295
+ flushInterval?: number
296
+ }
297
+ /**
298
+ * Load management configuration
299
+ */
300
+ export declare interface RealtimeLoadConfig {
301
+ maxConnections?: number
302
+ backpressureThreshold?: number
303
+ messageQueueSize?: number
304
+ gracefulShutdownTimeout?: number
305
+ }
306
+ /**
307
+ * Presence channel configuration
308
+ */
309
+ export declare interface RealtimePresenceConfig {
310
+ enabled?: boolean
311
+ maxMembersPerChannel?: number
312
+ memberInfoTtl?: number
313
+ }
314
+ /**
315
+ * Server mode configuration (ts-broadcasting)
316
+ */
317
+ export declare interface RealtimeServerConfig {
318
+ host?: string
319
+ port?: number
320
+ scheme?: 'ws' | 'wss'
321
+ driver?: 'bun' | 'reverb' | 'pusher' | 'ably'
322
+ redis?: RealtimeRedisConfig
323
+ rateLimit?: RealtimeRateLimitConfig
324
+ encryption?: RealtimeEncryptionConfig
325
+ webhooks?: RealtimeWebhooksConfig
326
+ queue?: RealtimeQueueConfig
327
+ loadManagement?: RealtimeLoadConfig
328
+ instances?: number
329
+ autoScaling?: {
330
+ min?: number
331
+ max?: number
332
+ targetCPU?: number
333
+ targetMemory?: number
334
+ }
335
+ healthCheck?: {
336
+ enabled?: boolean
337
+ path?: string
338
+ interval?: number
339
+ }
340
+ metrics?: {
341
+ enabled?: boolean
342
+ port?: number
343
+ path?: string
344
+ }
345
+ tls?: {
346
+ enabled?: boolean
347
+ cert?: string
348
+ key?: string
349
+ }
350
+ }
351
+ /**
352
+ * Serverless mode configuration
353
+ */
354
+ export declare interface RealtimeServerlessConfig {
355
+ connectionTimeout?: number
356
+ idleTimeout?: number
357
+ stageName?: string
358
+ memorySize?: number
359
+ timeout?: number
360
+ provisionedConcurrency?: number
361
+ }
362
+ /**
363
+ * Channel configuration
364
+ */
365
+ export declare interface RealtimeChannelsConfig {
366
+ public?: boolean
367
+ private?: boolean
368
+ presence?: boolean | RealtimePresenceConfig
369
+ }
370
+ export declare interface RealtimeOptions {
371
+ enabled?: boolean
372
+ mode?: RealtimeMode
373
+ driver?: 'socket' | 'pusher' | 'bun' | 'reverb' | 'ably'
374
+ server?: RealtimeServerConfig
375
+ serverless?: RealtimeServerlessConfig
376
+ channels?: RealtimeChannelsConfig
377
+ socket?: {
378
+ port?: number
379
+ host?: string
380
+ cors?: {
381
+ origin: string | string[]
382
+ methods: string[]
383
+ }
384
+ }
385
+ pusher?: {
386
+ appId: string
387
+ key: string
388
+ secret: string
389
+ cluster?: string
390
+ useTLS?: boolean
391
+ }
392
+ app?: {
393
+ id?: string
394
+ key?: string
395
+ secret?: string
396
+ }
397
+ domain?: string
398
+ debug?: boolean
399
+ }
400
+ export declare interface RealtimeInstance {
401
+ event: string
402
+ handle?: (data?: any) => Promise<{ channel: string, type: 'public' | 'private' | 'presence' } | void>
403
+ }
404
+ export declare interface RealtimeDriver {
405
+ connect: () => Promise<void>
406
+ disconnect: () => Promise<void>
407
+ subscribe: (channel: string, callback: (data: any) => void) => void
408
+ unsubscribe: (channel: string) => void
409
+ publish: (channel: string, data: any) => void
410
+ broadcast: (channel: string, event: string, data?: any, type?: ChannelType) => void
411
+ isConnected: () => boolean
412
+ }
413
+ export declare interface Broadcastable {
414
+ broadcastEvent: () => Promise<void>
415
+ broadcastEventNow: () => Promise<void>
416
+ setChannel: (channel: string) => this
417
+ excludeCurrentUser: () => this
418
+ setPresenceChannel: () => this
419
+ setPrivateChannel: () => this
420
+ }
421
+ export declare interface BroadcastInstance {
422
+ channel?: string
423
+ event?: string
424
+ handle?: (data: any) => Promise<void>
425
+ }
426
+ /**
427
+ * Options for the emit function
428
+ */
429
+ export declare interface EmitOptions {
430
+ private?: boolean
431
+ presence?: boolean
432
+ exclude?: string | string[]
433
+ driver?: DriverType
434
+ }
435
+ /**
436
+ * Realtime deployment mode
437
+ * - 'serverless': Uses API Gateway WebSocket + Lambda + DynamoDB
438
+ * - 'server': Uses ts-broadcasting Bun WebSocket server (ECS/Fargate)
439
+ */
440
+ export type RealtimeMode = 'serverless' | 'server';
441
+ export type RealtimeConfig = Partial<RealtimeOptions>;
442
+ export type DriverType = 'socket' | 'pusher' | 'bun' | 'reverb' | 'ably';
443
+ export type ChannelType = 'public' | 'private' | 'presence';
@@ -0,0 +1,265 @@
1
+ import { User } from '@stacksjs/orm';
2
+ import type { AuthToken } from '@stacksjs/types';
3
+ import type { Infer } from '@stacksjs/ts-validation';
4
+ import type { UploadedFile } from '@stacksjs/storage';
5
+ declare interface RequestData {
6
+ [key: string]: any
7
+ }
8
+ /**
9
+ * Cookie-access helper exposed via `request.cookies` on
10
+ * {@link RequestInstance}. The methods mirror bun-router's
11
+ * `CookieAccessor` — duplicated locally so this package doesn't
12
+ * have to depend on bun-router for a single type. Keep the surface
13
+ * in sync if bun-router extends its accessor.
14
+ */
15
+ export declare interface RequestCookies {
16
+ get: (name: string) => string | undefined
17
+ set: (name: string, value: string, options?: {
18
+ path?: string
19
+ domain?: string
20
+ secure?: boolean
21
+ httpOnly?: boolean
22
+ sameSite?: 'strict' | 'lax' | 'none'
23
+ maxAge?: number
24
+ expires?: Date
25
+ }) => void
26
+ delete: (name: string, options?: { path?: string, domain?: string }) => void
27
+ getAll: () => Record<string, string>
28
+ }
29
+ /**
30
+ * Collection interface for array data (Laravel-style)
31
+ */
32
+ export declare interface Collection<T> {
33
+ items: T[]
34
+ count: () => number
35
+ first: () => T | undefined
36
+ last: () => T | undefined
37
+ map: <U>(fn: (item: T, index: number) => U) => Collection<U>
38
+ filter: (fn: (item: T, index: number) => boolean) => Collection<T>
39
+ find: (fn: (item: T, index: number) => boolean) => T | undefined
40
+ reduce: <U>(fn: (acc: U, item: T, index: number) => U, initial: U) => U
41
+ forEach: (fn: (item: T, index: number) => void) => void
42
+ toArray: () => T[]
43
+ isEmpty: () => boolean
44
+ isNotEmpty: () => boolean
45
+ pluck: <K extends keyof T>(key: K) => Collection<T[K]>
46
+ unique: () => Collection<T>
47
+ sortBy: <K extends keyof T>(key: K, direction?: 'asc' | 'desc') => Collection<T>
48
+ groupBy: <K extends keyof T>(key: K) => Map<T[K], Collection<T>>
49
+ chunk: (size: number) => Collection<Collection<T>>
50
+ take: (count: number) => Collection<T>
51
+ skip: (count: number) => Collection<T>
52
+ reverse: () => Collection<T>
53
+ sum: (key?: keyof T) => number
54
+ avg: (key?: keyof T) => number
55
+ min: (key?: keyof T) => T | undefined
56
+ max: (key?: keyof T) => T | undefined
57
+ }
58
+ /**
59
+ * Safe validated data wrapper (Laravel-style)
60
+ */
61
+ export declare interface SafeData<T extends Record<string, any> = Record<string, any>> {
62
+ only: <K extends keyof T>(keys: K[]) => Pick<T, K>
63
+ except: <K extends keyof T>(keys: K[]) => Omit<T, K>
64
+ merge: <U extends Record<string, unknown>>(data: U) => T & U
65
+ all: () => T
66
+ has: (key: keyof T) => boolean
67
+ get: <K extends keyof T>(key: K) => T[K]
68
+ }
69
+ export declare interface RequestInstance<TFields extends Record<string, any> = Record<string, any>, TParams extends Record<string, string> = Record<string, string>,> {
70
+ url: string
71
+ method: string
72
+ headers: Headers
73
+ query: RequestData
74
+ params: TParams
75
+ jsonBody?: any
76
+ formBody?: any
77
+ files: Record<string, File | File[]>
78
+ cookies?: RequestCookies
79
+ get<K extends keyof TFields & string>(key: K, defaultValue?: TFields[K]): TFields[K]
80
+ get<T = any>(key: string, defaultValue?: T): T
81
+ input<K extends keyof TFields & string>(key: K, defaultValue?: TFields[K]): TFields[K]
82
+ input<T = any>(key: string, defaultValue?: T): T
83
+ all: () => TFields
84
+ only: <K extends keyof TFields & string>(keys: K[]) => Pick<TFields, K>
85
+ except: <K extends keyof TFields & string>(keys: K[]) => Omit<TFields, K>
86
+ has: (key: string | string[]) => boolean
87
+ hasAny: (keys: string[]) => boolean
88
+ filled: (key: string | string[]) => boolean
89
+ missing: (key: string | string[]) => boolean
90
+ merge: (data: Partial<TFields>) => void
91
+ keys: () => (keyof TFields & string)[]
92
+ string: (key: keyof TFields & string, defaultValue?: string) => string
93
+ integer: (key: keyof TFields & string, defaultValue?: number) => number
94
+ float: (key: keyof TFields & string, defaultValue?: number) => number
95
+ boolean: (key: keyof TFields & string, defaultValue?: boolean) => boolean
96
+ array: <T = unknown>(key: keyof TFields & string) => T[]
97
+ date: (key: keyof TFields & string, format?: string) => Date | null
98
+ enum: <T extends Record<string, string | number>>(key: keyof TFields & string, enumType: T) => T[keyof T] | null
99
+ collect: <T = unknown>(key: keyof TFields & string) => Collection<T>
100
+ validate: (rules?: RequestValidationRules, messages?: Record<string, string>) => Promise<TFields>
101
+ getValidated: () => TFields
102
+ safe: () => SafeData<TFields>
103
+ whenHas: <T>(key: keyof TFields & string, callback: (value: T) => void, defaultCallback?: () => void) => void
104
+ whenFilled: <T>(key: keyof TFields & string, callback: (value: T) => void, defaultCallback?: () => void) => void
105
+ isValue: (key: keyof TFields & string, value: unknown) => boolean
106
+ file: (key: string) => UploadedFile | null
107
+ getFiles: (key: string) => UploadedFile[]
108
+ hasFile: (key: string) => boolean
109
+ allFiles: () => Record<string, UploadedFile | UploadedFile[]>
110
+ header: (key: string) => string | null
111
+ bearerToken: () => string | null | AuthToken
112
+ param: <K extends keyof TParams | string, D = string>(
113
+ key: K,
114
+ defaultValue?: D,
115
+ ) => K extends keyof TParams ? TParams[K] : (string | D)
116
+ getParam: <K extends string>(key: K) => K extends NumericField ? number : string
117
+ route: (key: string) => number | string | null
118
+ getParams: () => TParams
119
+ getParamAsInt: (key: string) => number | null
120
+ old: <T = unknown>(key: keyof TFields & string, defaultValue?: T) => T
121
+ flashInput: (keys?: (keyof TFields & string)[]) => void
122
+ flashInputOnly: (keys: (keyof TFields & string)[]) => void
123
+ flashInputExcept: (keys: (keyof TFields & string)[]) => void
124
+ json: <T = any>() => Promise<T>
125
+ isEmpty: () => boolean
126
+ browser: () => string | null
127
+ ip: () => string | null
128
+ ipForRateLimit: () => string | null
129
+ getMethod: () => HttpMethod
130
+ user: () => Promise<UserJsonResponse | undefined>
131
+ }
132
+ // Trait methods are attached dynamically by the Stacks model proxy. The
133
+ // open member bag reflects application-level traits that the framework's
134
+ // default User definition cannot know about ahead of time.
135
+ declare type UserJsonResponse = NonNullable<Awaited<ReturnType<typeof User.find>>> & Record<string, any>;
136
+ /**
137
+ * Loose route-param shape kept around for back-compat with code that
138
+ * predates {@link RequestInstance}'s `TParams` generic. New code should
139
+ * rely on the path-extracted `TParams` instead — see {@link ExtractParams}.
140
+ *
141
+ * @deprecated Use {@link ExtractParams}-driven typing on the action /
142
+ * route signature instead. URL route params are always strings at
143
+ * runtime; the `string | number` here misled callers into thinking
144
+ * the framework coerced numbers automatically (it doesn't —
145
+ * `Number(request.params.id)` is the correct pattern).
146
+ */
147
+ declare type RouteParams = { [key: string]: string | number } | null;
148
+ /**
149
+ * Legacy hard-coded list of param names treated as `number` by
150
+ * {@link RequestInstance.getParam}. The name-match heuristic is
151
+ * brittle (`'judgeId'`, `'user_id'`, etc. all silently fall through
152
+ * to `string`) and will be retired in a future release.
153
+ *
154
+ * @deprecated The name-match returns `number` for these specific keys
155
+ * only — pass the value through {@link Number} or
156
+ * {@link RequestInstance.getParamAsInt} for explicit, predictable
157
+ * coercion. See stacksjs/stacks#1851 Phase 3.
158
+ */
159
+ declare type NumericField = 'id' | 'age' | 'count' | 'quantity' | 'amount' | 'price' | 'total' | 'score' | 'rating' | 'duration' | 'size' | 'weight' | 'height' | 'width' | 'length' | 'distance' | 'speed' | 'temperature' | 'volume' | 'capacity' | 'density' | 'pressure' | 'force' | 'energy' | 'power' | 'frequency' | 'voltage' | 'current' | 'resistance' | 'time' | 'date' | 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second' | 'millisecond' | 'microsecond' | 'nanosecond';
160
+ /**
161
+ * Template-literal helper that extracts named route params from a
162
+ * path string (stacksjs/stacks#1851 Phase 2a). Supports both Stacks's
163
+ * brace-style (`/users/{id}`) and Express-style (`/users/:id`) so a
164
+ * project using either gets typed `params` out of the box.
165
+ *
166
+ * @example
167
+ * ExtractParams<'/api/judges/{id}/follow'> // { id: string }
168
+ * ExtractParams<'/api/orders/:orderId/items/:itemId'> // { orderId: string, itemId: string }
169
+ * ExtractParams<'/api/health'> // Record<string, never>
170
+ */
171
+ // Step 1: pull the next param name out of either `{name}` or `:name`,
172
+ // recurse on the rest, and union the keys.
173
+ declare type ExtractParamKeys<S extends string> = S extends `${string}{${infer Key}}${infer Rest}`
174
+ ? Key | ExtractParamKeys<Rest>
175
+ // colon form: `…/:name/…` (colon must be at a segment boundary
176
+ // so we don't match `:` inside e.g. a port number; the `/` before
177
+ // it enforces that)
178
+ : S extends `${string}/:${infer Key}/${infer Rest}`
179
+ ? KeyHead<Key> | ExtractParamKeys<`/${Rest}`>
180
+ // tail colon-form: `…/:name` (no trailing slash)
181
+ : S extends `${string}/:${infer Key}`
182
+ ? KeyHead<Key>
183
+ : never;
184
+ // `KeyHead<'name>'>` → `'name>'` because TS template literal infers
185
+ // the longest possible match. We need to handle params that are at
186
+ // the end of the path AND followed by a query string. This util
187
+ // truncates a captured key at the first non-name character.
188
+ declare type KeyHead<S extends string> = S extends `${infer H}/${string}` ? H :
189
+ S extends `${infer H}?${string}` ? H :
190
+ S extends `${infer H}.${string}` ? H :
191
+ S;
192
+ export type ExtractParams<S extends string> = [ExtractParamKeys<S>] extends [never]
193
+ ? Record<string, never>
194
+ : { [K in ExtractParamKeys<S>]: string }
195
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'CONNECT' | 'TRACE';
196
+ /**
197
+ * RequestInstance - Generic, model-aware request interface with Laravel-style methods.
198
+ *
199
+ * When used bare (`RequestInstance`), all methods accept any string keys (backward compatible).
200
+ * When parameterized with model fields (`RequestInstance<{ title: string, views: number }>`),
201
+ * all input methods narrow to those fields with full autocomplete and type inference.
202
+ *
203
+ * The global type alias connects this to models:
204
+ * `RequestInstance<typeof Post>` → narrows to Post's fields automatically.
205
+ *
206
+ * @example
207
+ * // Untyped (accepts any key)
208
+ * function handle(request: RequestInstance) {
209
+ * request.get('anything') // returns any
210
+ * }
211
+ *
212
+ * @example
213
+ * // Model-aware (narrows to Post's fields)
214
+ * function handle(request: RequestInstance<typeof Post>) {
215
+ * request.get('title') // autocompletes, returns string
216
+ * request.get('views') // autocompletes, returns number
217
+ * request.get('invalid') // TS error!
218
+ * const data = await request.validate() // returns typed Post fields
219
+ * }
220
+ */
221
+ /**
222
+ * Public alias for `RequestInstance<TFields>`. Use this in actions when
223
+ * you want to type the `request` argument explicitly (e.g. without
224
+ * pulling in a model object).
225
+ *
226
+ * @example
227
+ * ```ts
228
+ * import { Action } from '@stacksjs/actions'
229
+ * import type { ActionRequest } from '@stacksjs/types'
230
+ *
231
+ * type CreatePostInput = { title: string; body: string }
232
+ *
233
+ * export default new Action({
234
+ * name: 'CreatePost',
235
+ * handle(request: ActionRequest<CreatePostInput>) {
236
+ * const { title, body } = request.only(['title', 'body'])
237
+ * // ^ inferred as { title: string; body: string }
238
+ * },
239
+ * })
240
+ * ```
241
+ */
242
+ export type ActionRequest<TFields extends Record<string, any> = Record<string, any>, TParams extends Record<string, string> = Record<string, string>,> = RequestInstance<TFields, TParams>;
243
+ /**
244
+ * Read the body shape declared by an action's `validations:` field as
245
+ * a TypeScript object type (stacksjs/stacks#1851 Phase 2b). Threaded
246
+ * into {@link RequestInstance}'s `TFields` so `request.all()` returns
247
+ * the body shape with the field types {@link Infer}'d from each
248
+ * `schema.X()` rule.
249
+ *
250
+ * @example
251
+ * const validations = {
252
+ * email: { rule: schema.string().email() },
253
+ * password: { rule: schema.string().min(8) },
254
+ * remember: { rule: schema.boolean() },
255
+ * } as const
256
+ * type Body = InferValidations<typeof validations>
257
+ * // → { email: string, password: string, remember: boolean }
258
+ */
259
+ export type InferValidations<V extends Record<string, { rule: any }>> = {
260
+ [K in keyof V]: Infer<V[K]['rule']>
261
+ }
262
+ export type RequestValidationRules = Record<string, string | {
263
+ rule: { validate: (value: any) => any }
264
+ message?: string | Record<string, string>
265
+ }>;