@stacksjs/types 0.70.22 → 0.70.25

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 (161) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/src/ai.d.ts +37 -0
  3. package/dist/src/analytics.d.ts +36 -0
  4. package/dist/src/api.d.ts +26 -0
  5. package/dist/src/app.d.ts +28 -0
  6. package/dist/src/attributes.d.ts +1 -0
  7. package/dist/src/auth.d.ts +49 -0
  8. package/dist/src/auto-imports.d.ts +8 -0
  9. package/dist/{binary.d.ts → src/binary.d.ts} +4 -1
  10. package/dist/src/cache.d.ts +79 -0
  11. package/dist/{cdn.d.ts → src/cdn.d.ts} +1 -1
  12. package/dist/{chat.d.ts → src/chat.d.ts} +29 -48
  13. package/dist/src/cli.d.ts +308 -0
  14. package/dist/{cloud.d.ts → src/cloud.d.ts} +81 -26
  15. package/dist/{components.d.ts → src/components.d.ts} +1 -4
  16. package/dist/{configure.d.ts → src/configure.d.ts} +1 -1
  17. package/dist/{cron-jobs.d.ts → src/cron-jobs.d.ts} +33 -37
  18. package/dist/src/dashboard.d.ts +33 -0
  19. package/dist/{database.d.ts → src/database.d.ts} +20 -12
  20. package/dist/src/dependencies.d.ts +17 -0
  21. package/dist/src/deploy.d.ts +16 -0
  22. package/dist/{dns.d.ts → src/dns.d.ts} +59 -59
  23. package/dist/src/docs.d.ts +23 -0
  24. package/dist/src/email.d.ts +201 -0
  25. package/dist/src/env.d.ts +1 -0
  26. package/dist/{errors.d.ts → src/errors.d.ts} +17 -24
  27. package/dist/src/events.d.ts +31 -0
  28. package/dist/src/exit-code.d.ts +10 -0
  29. package/dist/{file-systems.d.ts → src/file-systems.d.ts} +10 -6
  30. package/dist/{git.d.ts → src/git.d.ts} +9 -6
  31. package/dist/src/hashing.d.ts +57 -0
  32. package/dist/src/helpers.d.ts +1 -0
  33. package/dist/src/i18n.d.ts +65 -0
  34. package/dist/src/index.d.ts +70 -0
  35. package/dist/{library.d.ts → src/library.d.ts} +31 -33
  36. package/dist/src/logging.d.ts +12 -0
  37. package/dist/{manifest.d.ts → src/manifest.d.ts} +4 -1
  38. package/dist/src/model-names.d.ts +1 -0
  39. package/dist/src/model.d.ts +251 -0
  40. package/dist/{notifications.d.ts → src/notifications.d.ts} +1 -26
  41. package/dist/src/oauth.d.ts +290 -0
  42. package/dist/{pages.d.ts → src/pages.d.ts} +1 -1
  43. package/dist/src/payments.d.ts +322 -0
  44. package/dist/src/phone.d.ts +52 -0
  45. package/dist/src/ports.d.ts +20 -0
  46. package/dist/src/promise.d.ts +1 -0
  47. package/dist/src/push.d.ts +108 -0
  48. package/dist/src/queue.d.ts +310 -0
  49. package/dist/src/reactivity.d.ts +1 -0
  50. package/dist/src/realtime.d.ts +443 -0
  51. package/dist/src/request.d.ts +154 -0
  52. package/dist/{response.d.ts → src/response.d.ts} +1 -1
  53. package/dist/src/router.d.ts +105 -0
  54. package/dist/{saas.d.ts → src/saas.d.ts} +2 -2
  55. package/dist/src/scheduler.d.ts +1 -0
  56. package/dist/{search-engine.d.ts → src/search-engine.d.ts} +41 -45
  57. package/dist/{security.d.ts → src/security.d.ts} +4 -8
  58. package/dist/{server.d.ts → src/server.d.ts} +1 -1
  59. package/dist/src/services.d.ts +140 -0
  60. package/dist/{settings-config.d.ts → src/settings-config.d.ts} +1 -1
  61. package/dist/src/sms.d.ts +144 -0
  62. package/dist/src/stack-extensions.d.ts +137 -0
  63. package/dist/src/stacks.d.ts +40 -0
  64. package/dist/src/storage.d.ts +105 -0
  65. package/dist/src/table-names.d.ts +1 -0
  66. package/dist/src/tables.d.ts +34 -0
  67. package/dist/src/team.d.ts +7 -0
  68. package/dist/src/ui.d.ts +55 -0
  69. package/dist/src/utils.d.ts +39 -0
  70. package/package.json +13 -32
  71. package/src/ai.ts +20 -6
  72. package/src/analytics.ts +38 -1
  73. package/src/app.ts +38 -0
  74. package/src/attributes.ts +5 -1
  75. package/src/auth.ts +122 -0
  76. package/src/auto-imports.ts +8 -1
  77. package/src/cache.ts +226 -69
  78. package/src/chat.ts +0 -20
  79. package/src/cli.ts +24 -9
  80. package/src/cloud.ts +40 -1
  81. package/src/components.ts +3 -5
  82. package/src/cron-jobs.ts +1 -1
  83. package/src/dashboard.ts +40 -0
  84. package/src/database.ts +18 -2
  85. package/src/dns.ts +1 -1
  86. package/src/docs.ts +3 -3
  87. package/src/email.ts +303 -13
  88. package/src/errors.ts +2 -3
  89. package/src/events.ts +10 -5
  90. package/src/git.ts +3 -3
  91. package/src/hashing.ts +15 -19
  92. package/src/i18n.ts +105 -3
  93. package/src/index.ts +9 -5
  94. package/src/library.ts +0 -5
  95. package/src/model-names.ts +1 -1
  96. package/src/model.ts +94 -11
  97. package/src/oauth.ts +488 -0
  98. package/src/payments.ts +370 -27
  99. package/src/phone.ts +62 -0
  100. package/src/push.ts +107 -0
  101. package/src/queue.ts +386 -28
  102. package/src/reactivity.ts +1 -1
  103. package/src/realtime.ts +584 -0
  104. package/src/request.ts +344 -22
  105. package/src/router.ts +63 -5
  106. package/src/search-engine.ts +13 -13
  107. package/src/services.ts +100 -5
  108. package/src/sms.ts +263 -3
  109. package/src/stack-extensions.ts +184 -0
  110. package/src/stacks.ts +34 -4
  111. package/src/storage.ts +140 -6
  112. package/src/table-names.ts +1 -1
  113. package/src/ui.ts +20 -12
  114. package/src/utils.ts +1 -1
  115. package/dist/ai.d.ts +0 -20
  116. package/dist/analytics.d.ts +0 -13
  117. package/dist/api.d.ts +0 -26
  118. package/dist/app.d.ts +0 -32
  119. package/dist/attributes.d.ts +0 -1
  120. package/dist/auto-imports.d.ts +0 -1
  121. package/dist/build.d.ts +0 -2
  122. package/dist/cache.d.ts +0 -49
  123. package/dist/cli.d.ts +0 -310
  124. package/dist/dependencies.d.ts +0 -16
  125. package/dist/deploy.d.ts +0 -10
  126. package/dist/docs.d.ts +0 -26
  127. package/dist/email.d.ts +0 -107
  128. package/dist/events.d.ts +0 -5
  129. package/dist/exit-code.d.ts +0 -5
  130. package/dist/hashing.d.ts +0 -36
  131. package/dist/helpers.d.ts +0 -1
  132. package/dist/i18n.d.ts +0 -11
  133. package/dist/index.d.ts +0 -65
  134. package/dist/inspect.d.ts +0 -3
  135. package/dist/logging.d.ts +0 -6
  136. package/dist/model-names.d.ts +0 -1
  137. package/dist/model.d.ts +0 -226
  138. package/dist/payments.d.ts +0 -94
  139. package/dist/ports.d.ts +0 -13
  140. package/dist/promise.d.ts +0 -1
  141. package/dist/push.d.ts +0 -35
  142. package/dist/pwa.d.ts +0 -3
  143. package/dist/queue.d.ts +0 -45
  144. package/dist/reactivity.d.ts +0 -1
  145. package/dist/request.d.ts +0 -49
  146. package/dist/router.d.ts +0 -65
  147. package/dist/scheduler.d.ts +0 -1
  148. package/dist/services.d.ts +0 -81
  149. package/dist/ssg.d.ts +0 -3
  150. package/dist/stacks.d.ts +0 -54
  151. package/dist/storage.d.ts +0 -31
  152. package/dist/table-names.d.ts +0 -1
  153. package/dist/tables.d.ts +0 -34
  154. package/dist/team.d.ts +0 -8
  155. package/dist/ui.d.ts +0 -47
  156. package/dist/utils.d.ts +0 -27
  157. package/src/build.ts +0 -2
  158. package/src/inspect.ts +0 -10
  159. package/src/layout.ts +0 -8
  160. package/src/pwa.ts +0 -8
  161. package/src/ssg.ts +0 -3
package/src/request.ts CHANGED
@@ -1,49 +1,371 @@
1
- import type { VineType } from '@stacksjs/types'
1
+ import type { ModelRow } from '@stacksjs/orm'
2
+ import { User } from '@stacksjs/orm'
3
+ import type { UploadedFile } from '@stacksjs/storage'
4
+ import type { AuthToken, RouteParam } from '@stacksjs/types'
5
+
6
+ type UserJsonResponse = ModelRow<typeof User>
2
7
 
3
- export type * from '../../../types/requests'
4
8
  interface RequestData {
5
9
  [key: string]: any
6
10
  }
7
11
 
8
12
  type RouteParams = { [key: string]: string | number } | null
9
13
 
10
- interface ValidationField {
11
- rule: VineType
12
- message: Record<string, string>
14
+ 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'
15
+
16
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'CONNECT' | 'TRACE'
17
+
18
+ /**
19
+ * Collection interface for array data (Laravel-style)
20
+ */
21
+ export interface Collection<T> {
22
+ items: T[]
23
+ count: () => number
24
+ first: () => T | undefined
25
+ last: () => T | undefined
26
+ map: <U>(fn: (item: T, index: number) => U) => Collection<U>
27
+ filter: (fn: (item: T, index: number) => boolean) => Collection<T>
28
+ find: (fn: (item: T, index: number) => boolean) => T | undefined
29
+ reduce: <U>(fn: (acc: U, item: T, index: number) => U, initial: U) => U
30
+ forEach: (fn: (item: T, index: number) => void) => void
31
+ toArray: () => T[]
32
+ isEmpty: () => boolean
33
+ isNotEmpty: () => boolean
34
+ pluck: <K extends keyof T>(key: K) => Collection<T[K]>
35
+ unique: () => Collection<T>
36
+ sortBy: <K extends keyof T>(key: K, direction?: 'asc' | 'desc') => Collection<T>
37
+ groupBy: <K extends keyof T>(key: K) => Map<T[K], Collection<T>>
38
+ chunk: (size: number) => Collection<Collection<T>>
39
+ take: (count: number) => Collection<T>
40
+ skip: (count: number) => Collection<T>
41
+ reverse: () => Collection<T>
42
+ sum: (key?: keyof T) => number
43
+ avg: (key?: keyof T) => number
44
+ min: (key?: keyof T) => T | undefined
45
+ max: (key?: keyof T) => T | undefined
13
46
  }
14
47
 
15
- interface CustomAttributes {
16
- [key: string]: ValidationField
48
+ /**
49
+ * Safe validated data wrapper (Laravel-style)
50
+ */
51
+ export interface SafeData<T extends Record<string, any> = Record<string, any>> {
52
+ only: <K extends keyof T>(keys: K[]) => Pick<T, K>
53
+ except: <K extends keyof T>(keys: K[]) => Omit<T, K>
54
+ merge: <U extends Record<string, unknown>>(data: U) => T & U
55
+ all: () => T
56
+ has: (key: keyof T) => boolean
57
+ get: <K extends keyof T>(key: K) => T[K]
17
58
  }
18
59
 
19
- export interface RequestInstance {
20
- addQuery: (url: URL) => void
60
+ /**
61
+ * RequestInstance - Generic, model-aware request interface with Laravel-style methods.
62
+ *
63
+ * When used bare (`RequestInstance`), all methods accept any string keys (backward compatible).
64
+ * When parameterized with model fields (`RequestInstance<{ title: string, views: number }>`),
65
+ * all input methods narrow to those fields with full autocomplete and type inference.
66
+ *
67
+ * The global type alias connects this to models:
68
+ * `RequestInstance<typeof Post>` → narrows to Post's fields automatically.
69
+ *
70
+ * @example
71
+ * // Untyped (accepts any key)
72
+ * function handle(request: RequestInstance) {
73
+ * request.get('anything') // returns any
74
+ * }
75
+ *
76
+ * @example
77
+ * // Model-aware (narrows to Post's fields)
78
+ * function handle(request: RequestInstance<typeof Post>) {
79
+ * request.get('title') // autocompletes, returns string
80
+ * request.get('views') // autocompletes, returns number
81
+ * request.get('invalid') // TS error!
82
+ * const data = await request.validate() // returns typed Post fields
83
+ * }
84
+ */
85
+ /**
86
+ * Public alias for `RequestInstance<TFields>`. Use this in actions when
87
+ * you want to type the `request` argument explicitly (e.g. without
88
+ * pulling in a model object).
89
+ *
90
+ * @example
91
+ * ```ts
92
+ * import { Action } from '@stacksjs/actions'
93
+ * import type { ActionRequest } from '@stacksjs/types'
94
+ *
95
+ * type CreatePostInput = { title: string; body: string }
96
+ *
97
+ * export default new Action({
98
+ * name: 'CreatePost',
99
+ * handle(request: ActionRequest<CreatePostInput>) {
100
+ * const { title, body } = request.only(['title', 'body'])
101
+ * // ^ inferred as { title: string; body: string }
102
+ * },
103
+ * })
104
+ * ```
105
+ */
106
+ export type ActionRequest<TFields extends Record<string, any> = Record<string, any>> = RequestInstance<TFields>
21
107
 
22
- addBodies: (params: any) => void
108
+ export interface RequestInstance<TFields extends Record<string, any> = Record<string, any>> {
109
+ // ==========================================================================
110
+ // Native Request properties
111
+ // ==========================================================================
23
112
 
24
- addParam: (param: RouteParams) => void
113
+ url: string
114
+ method: string
115
+ headers: Headers
25
116
 
26
- get: <T>(element: string, defaultValue?: T) => T
117
+ // Raw data access (always untyped use get()/input() for typed access)
118
+ query: RequestData
119
+ params: RouteParams
120
+ jsonBody?: any
121
+ formBody?: any
122
+ files: Record<string, File | File[]>
27
123
 
28
- header: (element: string) => string | number | boolean | null
124
+ // ==========================================================================
125
+ // Model-aware Input Methods
126
+ //
127
+ // Keys narrow to `keyof TFields` when a model type is provided.
128
+ // Return types narrow to the field's actual type.
129
+ // ==========================================================================
29
130
 
30
- Header: (element: string) => string | number | boolean | null
131
+ /**
132
+ * Get input value from any source (query, body, params)
133
+ * @example request.get('title') // returns string (when model-aware)
134
+ * @example request.get('views', 0) // returns number with default
135
+ */
136
+ get: <K extends keyof TFields & string>(key: K, defaultValue?: TFields[K]) => TFields[K]
31
137
 
32
- all: () => RequestData
138
+ /**
139
+ * Alias for get() - Laravel compatibility
140
+ */
141
+ input: <K extends keyof TFields & string>(key: K, defaultValue?: TFields[K]) => TFields[K]
33
142
 
34
- validate: (attributes: CustomAttributes) => void
143
+ /**
144
+ * Get all input data (typed to model fields when model-aware)
145
+ */
146
+ all: () => TFields
35
147
 
36
- has: (element: string) => boolean
148
+ /**
149
+ * Get only specified keys — returns a precisely picked type
150
+ * @example request.only(['title', 'views']) // { title: string, views: number }
151
+ */
152
+ only: <K extends keyof TFields & string>(keys: K[]) => Pick<TFields, K>
37
153
 
38
- isEmpty: () => boolean
154
+ /**
155
+ * Get all except specified keys — returns a precisely omitted type
156
+ * @example request.except(['id', 'created_at']) // omits those fields
157
+ */
158
+ except: <K extends keyof TFields & string>(keys: K[]) => Omit<TFields, K>
39
159
 
40
- extractParamsFromRoute: (routePattern: string, pathname: string) => void
160
+ /**
161
+ * Check if input has a key (or all keys if array) — keys narrowed to model fields
162
+ * @example request.has('title')
163
+ * @example request.has(['title', 'views'])
164
+ */
165
+ has: (key: (keyof TFields & string) | (keyof TFields & string)[]) => boolean
41
166
 
42
- getParam: (key: string) => number | string | null
167
+ /**
168
+ * Check if input has any of the specified keys
169
+ * @example request.hasAny(['title', 'views'])
170
+ */
171
+ hasAny: (keys: (keyof TFields & string)[]) => boolean
43
172
 
44
- route: (key: string) => number | string | null
173
+ /**
174
+ * Check if input is filled (present and not empty)
175
+ * @example request.filled('title')
176
+ */
177
+ filled: (key: (keyof TFields & string) | (keyof TFields & string)[]) => boolean
45
178
 
46
- getParams: () => RouteParams
179
+ /**
180
+ * Check if input is missing
181
+ * @example request.missing('title')
182
+ */
183
+ missing: (key: (keyof TFields & string) | (keyof TFields & string)[]) => boolean
184
+
185
+ /**
186
+ * Merge additional data into input — accepts partial model fields
187
+ */
188
+ merge: (data: Partial<TFields>) => void
189
+
190
+ /**
191
+ * Get all input keys — returns model field names when model-aware
192
+ */
193
+ keys: () => (keyof TFields & string)[]
194
+
195
+ // ==========================================================================
196
+ // Type-casting Methods — keys narrowed to model fields
197
+ // ==========================================================================
198
+
199
+ /**
200
+ * Get string input
201
+ * @example request.string('title')
202
+ */
203
+ string: (key: keyof TFields & string, defaultValue?: string) => string
204
+
205
+ /**
206
+ * Get integer input
207
+ * @example request.integer('views', 0)
208
+ */
209
+ integer: (key: keyof TFields & string, defaultValue?: number) => number
210
+
211
+ /**
212
+ * Get float input
213
+ * @example request.float('price', 0.0)
214
+ */
215
+ float: (key: keyof TFields & string, defaultValue?: number) => number
216
+
217
+ /**
218
+ * Get boolean input
219
+ * @example request.boolean('is_active', false)
220
+ */
221
+ boolean: (key: keyof TFields & string, defaultValue?: boolean) => boolean
222
+
223
+ /**
224
+ * Get input as array
225
+ * @example request.array('tags')
226
+ */
227
+ array: <T = unknown>(key: keyof TFields & string) => T[]
228
+
229
+ /**
230
+ * Parse date input
231
+ * @example request.date('published_at')
232
+ */
233
+ date: (key: keyof TFields & string, format?: string) => Date | null
234
+
235
+ /**
236
+ * Parse enum input
237
+ * @example request.enum('status', StatusEnum)
238
+ */
239
+ enum: <T extends Record<string, string | number>>(key: keyof TFields & string, enumType: T) => T[keyof T] | null
240
+
241
+ /**
242
+ * Get input as collection
243
+ * @example request.collect('items')
244
+ */
245
+ collect: <T = unknown>(key: keyof TFields & string) => Collection<T>
246
+
247
+ // ==========================================================================
248
+ // Validation Methods — returns typed model fields when model-aware
249
+ // ==========================================================================
250
+
251
+ /**
252
+ * Validate the request data.
253
+ * When model-aware, rules are optional (uses model's attribute validation).
254
+ * Returns the validated data typed to model fields.
255
+ *
256
+ * @example await request.validate() // uses model rules
257
+ * @example await request.validate({ name: 'required' }) // custom rules
258
+ */
259
+ validate: (rules?: Record<string, string>, messages?: Record<string, string>) => Promise<TFields>
260
+
261
+ /**
262
+ * Get previously validated data, typed to model fields
263
+ */
264
+ getValidated: () => TFields
265
+
266
+ /**
267
+ * Get safe validated data wrapper with typed access
268
+ * @example request.safe().only(['title', 'views']) // Pick<TFields, 'title' | 'views'>
269
+ * @example request.safe().get('title') // string
270
+ */
271
+ safe: () => SafeData<TFields>
47
272
 
273
+ // ==========================================================================
274
+ // Conditional Methods — keys narrowed to model fields
275
+ // ==========================================================================
276
+
277
+ /**
278
+ * Execute callback when input has a value
279
+ * @example request.whenHas('title', (value) => console.log(value))
280
+ */
281
+ whenHas: <T>(key: keyof TFields & string, callback: (value: T) => void, defaultCallback?: () => void) => void
282
+
283
+ /**
284
+ * Execute callback when input is filled
285
+ * @example request.whenFilled('title', (value) => console.log(value))
286
+ */
287
+ whenFilled: <T>(key: keyof TFields & string, callback: (value: T) => void, defaultCallback?: () => void) => void
288
+
289
+ /**
290
+ * Check if input matches a value
291
+ */
292
+ isValue: (key: keyof TFields & string, value: unknown) => boolean
293
+
294
+ // ==========================================================================
295
+ // File Methods — not narrowed to model fields (files are independent)
296
+ // ==========================================================================
297
+
298
+ /**
299
+ * Get an uploaded file by key
300
+ * @example const avatar = request.file('avatar')
301
+ * @example await avatar?.store('avatars')
302
+ */
303
+ file: (key: string) => UploadedFile | null
304
+
305
+ /**
306
+ * Get all uploaded files for a key (for multiple file inputs)
307
+ */
308
+ getFiles: (key: string) => UploadedFile[]
309
+
310
+ /**
311
+ * Check if a file was uploaded
312
+ */
313
+ hasFile: (key: string) => boolean
314
+
315
+ /**
316
+ * Get all uploaded files
317
+ */
318
+ allFiles: () => Record<string, UploadedFile | UploadedFile[]>
319
+
320
+ // ==========================================================================
321
+ // Header Methods
322
+ // ==========================================================================
323
+
324
+ header: (key: string) => string | null
325
+ bearerToken: () => string | null | AuthToken
326
+
327
+ // ==========================================================================
328
+ // Route & Param Methods — not narrowed to model fields
329
+ // ==========================================================================
330
+
331
+ getParam: <K extends string>(key: K) => K extends NumericField ? number : string
332
+ route: (key: string) => number | string | null
333
+ getParams: () => RouteParams
48
334
  getParamAsInt: (key: string) => number | null
335
+
336
+ // ==========================================================================
337
+ // Session/Flash Methods — keys narrowed to model fields
338
+ // ==========================================================================
339
+
340
+ /**
341
+ * Get old input (for form repopulation)
342
+ */
343
+ old: <T = unknown>(key: keyof TFields & string, defaultValue?: T) => T
344
+
345
+ /**
346
+ * Flash input to session for form repopulation
347
+ */
348
+ flashInput: (keys?: (keyof TFields & string)[]) => void
349
+
350
+ /**
351
+ * Flash only specific keys
352
+ */
353
+ flashInputOnly: (keys: (keyof TFields & string)[]) => void
354
+
355
+ /**
356
+ * Flash except specific keys
357
+ */
358
+ flashInputExcept: (keys: (keyof TFields & string)[]) => void
359
+
360
+ // ==========================================================================
361
+ // Utility Methods
362
+ // ==========================================================================
363
+
364
+ json: <T = any>() => Promise<T>
365
+ isEmpty: () => boolean
366
+ browser: () => string | null
367
+ ip: () => string | null
368
+ ipForRateLimit: () => string | null
369
+ getMethod: () => HttpMethod
370
+ user: () => Promise<UserJsonResponse | undefined>
49
371
  }
package/src/router.ts CHANGED
@@ -1,10 +1,30 @@
1
1
  import type { Action } from '@stacksjs/actions'
2
+ type Request = any
3
+ import type { ValidationType } from '@stacksjs/ts-validation'
4
+ import type { HttpMethod } from './request'
2
5
 
3
6
  type ActionPath = string
4
7
  // need to refactor before, after, view to be a part of some other type
5
- export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'before' | 'after' | 'view'
8
+ export type RouteCallback = ((_params?: Record<string, any>) => any | string | object) | ((req: any, res: any) => Promise<void>)
6
9
 
7
- export type RouteCallback = (params?: Record<string, any>) => any | string | object
10
+ export interface RequestData {
11
+ [key: string]: any
12
+ }
13
+
14
+ export interface ValidationField {
15
+ rule: ValidationType
16
+ message: Record<string, string>
17
+ }
18
+
19
+ export type RouterAuthToken = `${number}:${number}:${string}`
20
+
21
+ export interface CustomAttributes {
22
+ [key: string]: ValidationField
23
+ }
24
+
25
+ export interface RouteParams { [key: string]: string | number }
26
+
27
+ export 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'
8
28
 
9
29
  export interface Route {
10
30
  name: string
@@ -20,19 +40,30 @@ export interface Route {
20
40
  statusCode?: StatusCode
21
41
  }
22
42
 
43
+ export interface ServeOptions {
44
+ host?: string
45
+ port?: number
46
+ debug?: boolean
47
+ timezone?: string
48
+ }
49
+
50
+ export interface Options {
51
+ statusCode?: StatusCode
52
+ }
53
+
23
54
  export interface MiddlewareOptions {
24
55
  name: string
25
56
  description?: string
26
57
  priority: number
27
- handle: () => Promise<void>
58
+ handle: (request: Request) => Promise<void> | void
28
59
  }
29
60
 
30
61
  export type StatusCode = 200 | 201 | 202 | 204 | 301 | 302 | 304 | 400 | 401 | 403 | 404 | 500
31
62
  export type RedirectCode = Extract<StatusCode, 301 | 302>
32
63
 
33
- export type RouteParam = { [key: string]: string | number } | null
64
+ export interface RouteParam { [key: string]: string | number }
34
65
 
35
- export type MiddlewareFn = () => void
66
+ export type MiddlewareFn = (_request: Request) => Promise<void>
36
67
 
37
68
  export interface Middlewares {
38
69
  logger: MiddlewareFn
@@ -64,3 +95,30 @@ export interface RouterInterface {
64
95
  middleware: (middleware: Route['middleware']) => this
65
96
  getRoutes: () => Promise<Route[]>
66
97
  }
98
+
99
+ export interface RouterInstance {
100
+ query: any
101
+ params: RouteParams
102
+ headers: any
103
+ addQuery: (url: URL) => void
104
+ addBodies: (params: any) => void
105
+ addParam: (param: RouteParam) => void
106
+ addHeaders: (headerParams: Headers) => void
107
+ get: <K extends string>(element: K, defaultValue?: K extends NumericField ? number : string) => K extends NumericField ? number : string
108
+ all: () => any
109
+ validate: (attributes?: CustomAttributes) => Promise<void>
110
+ has: (element: string) => boolean
111
+ isEmpty: () => boolean
112
+ extractParamsFromRoute: (routePattern: string, pathname: string) => void
113
+ header: (headerParam: string) => string | number | boolean | null
114
+ getHeaders: () => any
115
+ Header: (headerParam: string) => string | number | boolean | null
116
+ getParam: <T>(key: string) => T
117
+ route: (key: string) => number | string | null
118
+ bearerToken: () => string | null | RouterAuthToken
119
+ getParams: () => RouteParams
120
+ getParamAsInt: (key: string) => number | null
121
+ browser: () => string | null
122
+ ip: () => string | null
123
+ ipForRateLimit: () => string | null
124
+ }
@@ -37,16 +37,10 @@ export interface SearchEngineOptions {
37
37
  *
38
38
  * The search engine to utilize.
39
39
  *
40
- * @default string 'opensearch'
41
- * @see https://stacksjs.org/docs/search-engine
40
+ * @default string 'meilisearch'
41
+ * @see https://stacksjs.com/docs/search-engine
42
42
  */
43
- driver: 'opensearch'
44
- // driver: 'meilisearch' | 'algolia' | 'typesense' | 'opensearch' wip
45
-
46
- // meilisearch?: {
47
- // host: string
48
- // apiKey: string
49
- // }
43
+ driver: 'meilisearch' | 'algolia' | 'opensearch'
50
44
 
51
45
  opensearch?: {
52
46
  host: string
@@ -57,10 +51,16 @@ export interface SearchEngineOptions {
57
51
 
58
52
  meilisearch?: {
59
53
  host: string
60
- protocol: number
61
- port: number
62
- auth: string
54
+ protocol?: number
55
+ port?: number
56
+ auth?: string
57
+ apiKey: string
58
+ }
59
+
60
+ algolia?: {
61
+ appId: string
63
62
  apiKey: string
63
+ searchOnlyApiKey?: string
64
64
  }
65
65
 
66
66
  filters?: {
@@ -79,6 +79,7 @@ export type SearchEngineConfig = Partial<SearchEngineOptions>
79
79
 
80
80
  export interface SearchEngineDriver {
81
81
  client: () => MeiliSearch
82
+ resetClient?: () => void
82
83
 
83
84
  search: (index: string, params: any) => Promise<SearchResponse<Record<string, any>>>
84
85
 
@@ -116,7 +117,6 @@ export interface SearchEngineDriver {
116
117
  getSettings: (index: string) => Promise<Settings>
117
118
  updateSettings: (index: string, settings: Settings) => Promise<EnqueuedTask>
118
119
  resetSettings: (index: string) => Promise<EnqueuedTask>
119
- å
120
120
  getPagination: (index: string) => Promise<PaginationSettings>
121
121
  updatePagination: (index: string, pagination: PaginationSettings) => Promise<EnqueuedTask>
122
122
  resetPagination: (index: string) => Promise<EnqueuedTask>
package/src/services.ts CHANGED
@@ -11,6 +11,34 @@ export interface ServicesOptions {
11
11
  region: string
12
12
  }
13
13
 
14
+ github?: {
15
+ clientId: string
16
+ clientSecret: string
17
+ redirectUrl: string
18
+ scopes?: string[]
19
+ }
20
+
21
+ google?: {
22
+ clientId: string
23
+ clientSecret: string
24
+ redirectUrl: string
25
+ scopes?: string[]
26
+ }
27
+
28
+ facebook?: {
29
+ clientId: string
30
+ clientSecret: string
31
+ redirectUrl: string
32
+ scopes?: string[]
33
+ }
34
+
35
+ twitter?: {
36
+ clientId: string
37
+ clientSecret: string
38
+ redirectUrl: string
39
+ scopes?: string[]
40
+ }
41
+
14
42
  godaddy?: {
15
43
  apiKey: string
16
44
  apiSecret: string
@@ -68,17 +96,84 @@ export interface ServicesOptions {
68
96
  retryTimeout?: number
69
97
  }
70
98
 
99
+ /**
100
+ * SMTP Configuration for local development
101
+ * Works with HELO, Mailtrap Desktop, Mailhog, etc.
102
+ */
103
+ smtp?: {
104
+ host: string
105
+ port: number
106
+ username?: string
107
+ password?: string
108
+ encryption?: 'tls' | 'ssl' | null
109
+ maxRetries?: number
110
+ retryTimeout?: number
111
+ }
112
+
71
113
  slack?: {
72
- appId: string
73
- clientId: string
74
- secretKey: string
114
+ appId?: string
115
+ clientId?: string
116
+ secretKey?: string
117
+ webhookUrl?: string
118
+ botToken?: string
75
119
  maxRetries?: number
76
120
  retryTimeout?: number
77
121
  }
78
122
 
123
+ discord?: {
124
+ webhookUrl?: string
125
+ botToken?: string
126
+ maxRetries?: number
127
+ retryTimeout?: number
128
+ }
129
+
130
+ teams?: {
131
+ webhookUrl?: string
132
+ maxRetries?: number
133
+ retryTimeout?: number
134
+ }
135
+
136
+ // Push Notification Services
137
+ expo?: {
138
+ accessToken?: string
139
+ }
140
+
141
+ fcm?: {
142
+ serverKey?: string
143
+ projectId?: string
144
+ clientEmail?: string
145
+ privateKey?: string
146
+ }
147
+
148
+ // AI Services
149
+ openai?: {
150
+ apiKey?: string
151
+ model?: string
152
+ embeddingModel?: string
153
+ baseUrl?: string
154
+ }
155
+
156
+ anthropic?: {
157
+ apiKey?: string
158
+ model?: string
159
+ maxTokens?: number
160
+ }
161
+
162
+ ollama?: {
163
+ host?: string
164
+ model?: string
165
+ embeddingModel?: string
166
+ }
167
+
79
168
  stripe?: {
80
- appId: string
81
- apiKey: string
169
+ secretKey?: string
170
+ publicKey?: string
171
+ /**
172
+ * Pinned Stripe API version. Defaults to whatever the bundled SDK
173
+ * was compiled against; override here when rolling forward without
174
+ * a code change. Format: 'YYYY-MM-DD' or 'YYYY-MM-DD.preview'.
175
+ */
176
+ apiVersion?: string
82
177
  }
83
178
 
84
179
  // supabase?: {