@stacksjs/types 0.70.44 → 0.70.53
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/LICENSE.md +21 -0
- package/dist/auth.d.ts +7 -0
- package/dist/cache.d.ts +10 -1
- package/dist/cli.d.ts +3 -1
- package/dist/cms.d.ts +12 -0
- package/dist/commerce.d.ts +14 -0
- package/dist/cors.d.ts +47 -0
- package/dist/dashboard.d.ts +75 -0
- package/dist/database.d.ts +10 -0
- package/dist/email.d.ts +6 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +1 -1
- package/dist/logging.d.ts +3 -0
- package/dist/marketing.d.ts +12 -0
- package/dist/model-dashboard-augmentation.d.ts +8 -0
- package/dist/model.d.ts +4 -1
- package/dist/monitoring.d.ts +12 -0
- package/dist/queue.d.ts +2 -0
- package/dist/realtime.d.ts +8 -8
- package/dist/request.d.ts +107 -4
- package/dist/search-engine.d.ts +8 -1
- package/dist/services.d.ts +9 -0
- package/dist/stacks.d.ts +6 -1
- package/package.json +5 -5
- package/src/auth.ts +39 -0
- package/src/cache.ts +49 -2
- package/src/cli.ts +2 -0
- package/src/cms.ts +14 -0
- package/src/commerce.ts +18 -0
- package/src/cors.ts +86 -0
- package/src/dashboard.ts +178 -0
- package/src/database.ts +14 -0
- package/src/email.ts +94 -0
- package/src/index.ts +9 -0
- package/src/logging.ts +32 -0
- package/src/marketing.ts +14 -0
- package/src/model-dashboard-augmentation.ts +51 -0
- package/src/model.ts +33 -1
- package/src/monitoring.ts +14 -0
- package/src/queue.ts +8 -0
- package/src/request.ts +166 -5
- package/src/search-engine.ts +32 -1
- package/src/services.ts +26 -0
- package/src/stacks.ts +46 -3
package/src/request.ts
CHANGED
|
@@ -2,6 +2,10 @@ import type { ModelRow } from '@stacksjs/orm'
|
|
|
2
2
|
import { User } from '@stacksjs/orm'
|
|
3
3
|
import type { UploadedFile } from '@stacksjs/storage'
|
|
4
4
|
import type { AuthToken, RouteParam } from '@stacksjs/types'
|
|
5
|
+
// `Infer<T extends Validator<U>>` resolves to the validator's output
|
|
6
|
+
// type — `Infer<typeof schema.string()> → string`. Type-only import
|
|
7
|
+
// keeps this package free of a runtime ts-validation dependency.
|
|
8
|
+
import type { Infer } from '@stacksjs/ts-validation'
|
|
5
9
|
|
|
6
10
|
type UserJsonResponse = ModelRow<typeof User>
|
|
7
11
|
|
|
@@ -9,10 +13,96 @@ interface RequestData {
|
|
|
9
13
|
[key: string]: any
|
|
10
14
|
}
|
|
11
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Loose route-param shape kept around for back-compat with code that
|
|
18
|
+
* predates {@link RequestInstance}'s `TParams` generic. New code should
|
|
19
|
+
* rely on the path-extracted `TParams` instead — see {@link ExtractParams}.
|
|
20
|
+
*
|
|
21
|
+
* @deprecated Use {@link ExtractParams}-driven typing on the action /
|
|
22
|
+
* route signature instead. URL route params are always strings at
|
|
23
|
+
* runtime; the `string | number` here misled callers into thinking
|
|
24
|
+
* the framework coerced numbers automatically (it doesn't —
|
|
25
|
+
* `Number(request.params.id)` is the correct pattern).
|
|
26
|
+
*/
|
|
12
27
|
type RouteParams = { [key: string]: string | number } | null
|
|
13
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Legacy hard-coded list of param names treated as `number` by
|
|
31
|
+
* {@link RequestInstance.getParam}. The name-match heuristic is
|
|
32
|
+
* brittle (`'judgeId'`, `'user_id'`, etc. all silently fall through
|
|
33
|
+
* to `string`) and will be retired in a future release.
|
|
34
|
+
*
|
|
35
|
+
* @deprecated The name-match returns `number` for these specific keys
|
|
36
|
+
* only — pass the value through {@link Number} or
|
|
37
|
+
* {@link RequestInstance.getParamAsInt} for explicit, predictable
|
|
38
|
+
* coercion. See stacksjs/stacks#1851 Phase 3.
|
|
39
|
+
*/
|
|
14
40
|
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
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Cookie-access helper exposed via `request.cookies` on
|
|
44
|
+
* {@link RequestInstance}. The methods mirror bun-router's
|
|
45
|
+
* `CookieAccessor` — duplicated locally so this package doesn't
|
|
46
|
+
* have to depend on bun-router for a single type. Keep the surface
|
|
47
|
+
* in sync if bun-router extends its accessor.
|
|
48
|
+
*/
|
|
49
|
+
export interface RequestCookies {
|
|
50
|
+
get: (name: string) => string | undefined
|
|
51
|
+
set: (name: string, value: string, options?: {
|
|
52
|
+
path?: string
|
|
53
|
+
domain?: string
|
|
54
|
+
secure?: boolean
|
|
55
|
+
httpOnly?: boolean
|
|
56
|
+
sameSite?: 'strict' | 'lax' | 'none'
|
|
57
|
+
maxAge?: number
|
|
58
|
+
expires?: Date
|
|
59
|
+
}) => void
|
|
60
|
+
delete: (name: string, options?: { path?: string, domain?: string }) => void
|
|
61
|
+
getAll: () => Record<string, string>
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Template-literal helper that extracts named route params from a
|
|
66
|
+
* path string (stacksjs/stacks#1851 Phase 2a). Supports both Stacks's
|
|
67
|
+
* brace-style (`/users/{id}`) and Express-style (`/users/:id`) so a
|
|
68
|
+
* project using either gets typed `params` out of the box.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ExtractParams<'/api/judges/{id}/follow'> // { id: string }
|
|
72
|
+
* ExtractParams<'/api/orders/:orderId/items/:itemId'> // { orderId: string, itemId: string }
|
|
73
|
+
* ExtractParams<'/api/health'> // Record<string, never>
|
|
74
|
+
*/
|
|
75
|
+
// Step 1: pull the next param name out of either `{name}` or `:name`,
|
|
76
|
+
// recurse on the rest, and union the keys.
|
|
77
|
+
type ExtractParamKeys<S extends string> =
|
|
78
|
+
// brace form: `…/{name}/…`
|
|
79
|
+
S extends `${string}{${infer Key}}${infer Rest}`
|
|
80
|
+
? Key | ExtractParamKeys<Rest>
|
|
81
|
+
// colon form: `…/:name/…` (colon must be at a segment boundary
|
|
82
|
+
// so we don't match `:` inside e.g. a port number; the `/` before
|
|
83
|
+
// it enforces that)
|
|
84
|
+
: S extends `${string}/:${infer Key}/${infer Rest}`
|
|
85
|
+
? KeyHead<Key> | ExtractParamKeys<`/${Rest}`>
|
|
86
|
+
// tail colon-form: `…/:name` (no trailing slash)
|
|
87
|
+
: S extends `${string}/:${infer Key}`
|
|
88
|
+
? KeyHead<Key>
|
|
89
|
+
: never
|
|
90
|
+
|
|
91
|
+
// `KeyHead<'name>'>` → `'name>'` because TS template literal infers
|
|
92
|
+
// the longest possible match. We need to handle params that are at
|
|
93
|
+
// the end of the path AND followed by a query string. This util
|
|
94
|
+
// truncates a captured key at the first non-name character.
|
|
95
|
+
type KeyHead<S extends string> =
|
|
96
|
+
S extends `${infer H}/${string}` ? H :
|
|
97
|
+
S extends `${infer H}?${string}` ? H :
|
|
98
|
+
S extends `${infer H}.${string}` ? H :
|
|
99
|
+
S
|
|
100
|
+
|
|
101
|
+
export type ExtractParams<S extends string> =
|
|
102
|
+
[ExtractParamKeys<S>] extends [never]
|
|
103
|
+
? Record<string, never>
|
|
104
|
+
: { [K in ExtractParamKeys<S>]: string }
|
|
105
|
+
|
|
16
106
|
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'CONNECT' | 'TRACE'
|
|
17
107
|
|
|
18
108
|
/**
|
|
@@ -103,9 +193,35 @@ export interface SafeData<T extends Record<string, any> = Record<string, any>> {
|
|
|
103
193
|
* })
|
|
104
194
|
* ```
|
|
105
195
|
*/
|
|
106
|
-
export type ActionRequest<
|
|
196
|
+
export type ActionRequest<
|
|
197
|
+
TFields extends Record<string, any> = Record<string, any>,
|
|
198
|
+
TParams extends Record<string, string> = Record<string, string>,
|
|
199
|
+
> = RequestInstance<TFields, TParams>
|
|
107
200
|
|
|
108
|
-
|
|
201
|
+
/**
|
|
202
|
+
* Read the body shape declared by an action's `validations:` field as
|
|
203
|
+
* a TypeScript object type (stacksjs/stacks#1851 Phase 2b). Threaded
|
|
204
|
+
* into {@link RequestInstance}'s `TFields` so `request.all()` returns
|
|
205
|
+
* the body shape with the field types {@link Infer}'d from each
|
|
206
|
+
* `schema.X()` rule.
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* const validations = {
|
|
210
|
+
* email: { rule: schema.string().email() },
|
|
211
|
+
* password: { rule: schema.string().min(8) },
|
|
212
|
+
* remember: { rule: schema.boolean() },
|
|
213
|
+
* } as const
|
|
214
|
+
* type Body = InferValidations<typeof validations>
|
|
215
|
+
* // → { email: string, password: string, remember: boolean }
|
|
216
|
+
*/
|
|
217
|
+
export type InferValidations<V extends Record<string, { rule: any }>> = {
|
|
218
|
+
[K in keyof V]: Infer<V[K]['rule']>
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export interface RequestInstance<
|
|
222
|
+
TFields extends Record<string, any> = Record<string, any>,
|
|
223
|
+
TParams extends Record<string, string> = Record<string, string>,
|
|
224
|
+
> {
|
|
109
225
|
// ==========================================================================
|
|
110
226
|
// Native Request properties
|
|
111
227
|
// ==========================================================================
|
|
@@ -116,10 +232,28 @@ export interface RequestInstance<TFields extends Record<string, any> = Record<st
|
|
|
116
232
|
|
|
117
233
|
// Raw data access (always untyped — use get()/input() for typed access)
|
|
118
234
|
query: RequestData
|
|
119
|
-
|
|
235
|
+
/**
|
|
236
|
+
* Route parameters from the URL. When the action is bound to a path
|
|
237
|
+
* literal (via {@link ActionOptions.path} or a typed
|
|
238
|
+
* `route.get<TPath>(...)` overload), `TParams` narrows to the
|
|
239
|
+
* extracted keys so `request.params.id` is `string` with no `as any`.
|
|
240
|
+
*
|
|
241
|
+
* For un-narrowed callers (bare `RequestInstance`), this falls
|
|
242
|
+
* back to `Record<string, string>` — the runtime shape is always
|
|
243
|
+
* string-keyed even for "numeric" params, since URL segments are
|
|
244
|
+
* never coerced.
|
|
245
|
+
*/
|
|
246
|
+
params: TParams
|
|
120
247
|
jsonBody?: any
|
|
121
248
|
formBody?: any
|
|
122
249
|
files: Record<string, File | File[]>
|
|
250
|
+
/**
|
|
251
|
+
* Cookies parsed from the request. The accessor exposes
|
|
252
|
+
* `get`/`set`/`delete`/`getAll` helpers that mirror bun-router's
|
|
253
|
+
* cookie handling. Optional because not every request middleware
|
|
254
|
+
* stack runs the cookie parser.
|
|
255
|
+
*/
|
|
256
|
+
cookies?: RequestCookies
|
|
123
257
|
|
|
124
258
|
// ==========================================================================
|
|
125
259
|
// Model-aware Input Methods
|
|
@@ -325,12 +459,39 @@ export interface RequestInstance<TFields extends Record<string, any> = Record<st
|
|
|
325
459
|
bearerToken: () => string | null | AuthToken
|
|
326
460
|
|
|
327
461
|
// ==========================================================================
|
|
328
|
-
// Route & Param Methods
|
|
462
|
+
// Route & Param Methods
|
|
463
|
+
//
|
|
464
|
+
// `params` (the field above) is the typed primary surface — narrow
|
|
465
|
+
// it via the action's `path:` literal for full inference. These
|
|
466
|
+
// method-form helpers stay around for back-compat and for cases
|
|
467
|
+
// where the param key isn't statically known.
|
|
329
468
|
// ==========================================================================
|
|
330
469
|
|
|
470
|
+
/**
|
|
471
|
+
* Look up a single route param, optionally with a default. Narrows
|
|
472
|
+
* to {@link TParams} when the key is part of the path-extracted
|
|
473
|
+
* keyset; falls back to `string | undefined` otherwise (covers
|
|
474
|
+
* dynamic key access without `as any`).
|
|
475
|
+
*
|
|
476
|
+
* @example
|
|
477
|
+
* const id = request.param('id') // typed string (from path)
|
|
478
|
+
* const note = request.param('note', '') // string with default
|
|
479
|
+
*/
|
|
480
|
+
param: <K extends keyof TParams | string, D = string>(
|
|
481
|
+
key: K,
|
|
482
|
+
defaultValue?: D,
|
|
483
|
+
) => K extends keyof TParams ? TParams[K] : (string | D)
|
|
484
|
+
/**
|
|
485
|
+
* @deprecated Use {@link param} for typed param lookups, or
|
|
486
|
+
* `Number(request.params.id)` for explicit numeric coercion.
|
|
487
|
+
* The name-match heuristic returning `number` for {@link NumericField}
|
|
488
|
+
* keys (`id`, `count`, `amount`, …) is brittle: it silently falls
|
|
489
|
+
* through to `string` for `judgeId`, `user_id`, etc.
|
|
490
|
+
* See stacksjs/stacks#1851 Phase 3.
|
|
491
|
+
*/
|
|
331
492
|
getParam: <K extends string>(key: K) => K extends NumericField ? number : string
|
|
332
493
|
route: (key: string) => number | string | null
|
|
333
|
-
getParams: () =>
|
|
494
|
+
getParams: () => TParams
|
|
334
495
|
getParamAsInt: (key: string) => number | null
|
|
335
496
|
|
|
336
497
|
// ==========================================================================
|
package/src/search-engine.ts
CHANGED
|
@@ -40,7 +40,7 @@ export interface SearchEngineOptions {
|
|
|
40
40
|
* @default string 'meilisearch'
|
|
41
41
|
* @see https://stacksjs.com/docs/search-engine
|
|
42
42
|
*/
|
|
43
|
-
driver: 'meilisearch' | 'algolia' | 'opensearch'
|
|
43
|
+
driver: 'meilisearch' | 'algolia' | 'opensearch' | 'typesense'
|
|
44
44
|
|
|
45
45
|
opensearch?: {
|
|
46
46
|
host: string
|
|
@@ -63,6 +63,13 @@ export interface SearchEngineOptions {
|
|
|
63
63
|
searchOnlyApiKey?: string
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
typesense?: {
|
|
67
|
+
host?: string
|
|
68
|
+
port?: number
|
|
69
|
+
protocol?: string
|
|
70
|
+
apiKey?: string
|
|
71
|
+
}
|
|
72
|
+
|
|
66
73
|
filters?: {
|
|
67
74
|
[key: string]: string
|
|
68
75
|
}
|
|
@@ -204,6 +211,30 @@ export interface SearchOptions {
|
|
|
204
211
|
sortable: string[]
|
|
205
212
|
filterable: string[]
|
|
206
213
|
options?: SearchEngineOptions
|
|
214
|
+
/**
|
|
215
|
+
* Cross-table denormalisation for searchable fields that live on a
|
|
216
|
+
* related model (stacksjs/stacks#1918). Maps an indexed-document
|
|
217
|
+
* field name to a dot-path resolved against the model instance's
|
|
218
|
+
* `_relations`. Without this, `toSearchableObject` only reads from
|
|
219
|
+
* `_attributes` and silently emits `undefined` for any field that
|
|
220
|
+
* exists on a `belongsTo` / `hasOne` / `hasMany` relation.
|
|
221
|
+
*
|
|
222
|
+
* Example: a `Judge` belongsTo a `CourtHouse`. To make the court
|
|
223
|
+
* house's `name` searchable on the judge index:
|
|
224
|
+
*
|
|
225
|
+
* useSearch: {
|
|
226
|
+
* searchable: ['name', 'court_name'],
|
|
227
|
+
* displayable: ['id', 'name', 'court_name'],
|
|
228
|
+
* denormalize: { court_name: 'court_house.name' },
|
|
229
|
+
* }
|
|
230
|
+
*
|
|
231
|
+
* The caller is responsible for eager-loading the named relations
|
|
232
|
+
* (e.g. via `Judge.query().with('court_house').get()`) — the live
|
|
233
|
+
* observer hook and the CLI bulk-index path do this automatically
|
|
234
|
+
* for every distinct head segment in the `denormalize` map.
|
|
235
|
+
* `toSearchableObject` stays synchronous; no per-row database lookup.
|
|
236
|
+
*/
|
|
237
|
+
denormalize?: Record<string, string>
|
|
207
238
|
}
|
|
208
239
|
|
|
209
240
|
export type {
|
package/src/services.ts
CHANGED
|
@@ -25,6 +25,24 @@ export interface ServicesOptions {
|
|
|
25
25
|
scopes?: string[]
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Sign in with Apple. Apple has no static client secret — the driver
|
|
30
|
+
* signs a short-lived ES256 JWT from teamId + keyId + privateKey
|
|
31
|
+
* (the .p8 file's contents) instead.
|
|
32
|
+
*/
|
|
33
|
+
apple?: {
|
|
34
|
+
/** The Services ID identifier, e.g. `org.example.web` */
|
|
35
|
+
clientId: string
|
|
36
|
+
/** Apple Developer Team ID (10 chars) */
|
|
37
|
+
teamId: string
|
|
38
|
+
/** Key ID of the "Sign in with Apple" key */
|
|
39
|
+
keyId: string
|
|
40
|
+
/** Contents of the downloaded .p8 private key */
|
|
41
|
+
privateKey: string
|
|
42
|
+
redirectUrl: string
|
|
43
|
+
scopes?: string[]
|
|
44
|
+
}
|
|
45
|
+
|
|
28
46
|
facebook?: {
|
|
29
47
|
clientId: string
|
|
30
48
|
clientSecret: string
|
|
@@ -168,6 +186,14 @@ export interface ServicesOptions {
|
|
|
168
186
|
stripe?: {
|
|
169
187
|
secretKey?: string
|
|
170
188
|
publicKey?: string
|
|
189
|
+
/**
|
|
190
|
+
* Signing secret for verifying inbound Stripe webhook requests
|
|
191
|
+
* (`whsec_...`, from the Stripe dashboard's webhook endpoint
|
|
192
|
+
* config). Required by any app receiving Stripe webhooks —
|
|
193
|
+
* without it, `stripe.webhooks.constructEvent` has nothing to
|
|
194
|
+
* verify the `stripe-signature` header against.
|
|
195
|
+
*/
|
|
196
|
+
webhookSecret?: string
|
|
171
197
|
/**
|
|
172
198
|
* Pinned Stripe API version. Defaults to whatever the bundled SDK
|
|
173
199
|
* was compiled against; override here when rolling forward without
|
package/src/stacks.ts
CHANGED
|
@@ -6,6 +6,9 @@ import type {
|
|
|
6
6
|
BinaryConfig,
|
|
7
7
|
CacheConfig,
|
|
8
8
|
CloudConfig,
|
|
9
|
+
CmsConfig,
|
|
10
|
+
CommerceConfig,
|
|
11
|
+
CorsConfig,
|
|
9
12
|
DashboardConfig,
|
|
10
13
|
DatabaseConfig,
|
|
11
14
|
DnsConfig,
|
|
@@ -17,6 +20,8 @@ import type {
|
|
|
17
20
|
HashingConfig,
|
|
18
21
|
LibraryConfig,
|
|
19
22
|
LoggingConfig,
|
|
23
|
+
MarketingConfig,
|
|
24
|
+
MonitoringConfig,
|
|
20
25
|
NotificationConfig,
|
|
21
26
|
PaymentConfig,
|
|
22
27
|
Ports,
|
|
@@ -67,6 +72,14 @@ export interface StacksOptions {
|
|
|
67
72
|
*/
|
|
68
73
|
auth: AuthConfig
|
|
69
74
|
|
|
75
|
+
/**
|
|
76
|
+
* **CORS Options**
|
|
77
|
+
*
|
|
78
|
+
* Cross-origin resource sharing policy applied to API responses.
|
|
79
|
+
* Configured via `config/cors.ts`. See {@link CorsConfig}.
|
|
80
|
+
*/
|
|
81
|
+
cors?: CorsConfig
|
|
82
|
+
|
|
70
83
|
/**
|
|
71
84
|
* **Realtime Options**
|
|
72
85
|
*
|
|
@@ -103,12 +116,26 @@ export interface StacksOptions {
|
|
|
103
116
|
*/
|
|
104
117
|
cloud: CloudConfig
|
|
105
118
|
|
|
119
|
+
/**
|
|
120
|
+
* **CMS Options**
|
|
121
|
+
*
|
|
122
|
+
* Top-level feature gate for the CMS bundle (Post / Page / Author /
|
|
123
|
+
* Comment / Tag / Category models + content-edit dashboards).
|
|
124
|
+
*/
|
|
125
|
+
cms: CmsConfig
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* **Commerce Options**
|
|
129
|
+
*
|
|
130
|
+
* Top-level feature gate for the commerce bundle plus storefront defaults.
|
|
131
|
+
*/
|
|
132
|
+
commerce: CommerceConfig
|
|
133
|
+
|
|
106
134
|
/**
|
|
107
135
|
* **Dashboard Options**
|
|
108
136
|
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
* project doesn't use (e.g. `commerce.enabled: false`).
|
|
137
|
+
* Top-level feature gate plus per-section visibility toggles for the
|
|
138
|
+
* `buddy dev --dashboard` sidebar.
|
|
112
139
|
*/
|
|
113
140
|
dashboard: DashboardConfig
|
|
114
141
|
|
|
@@ -193,6 +220,22 @@ export interface StacksOptions {
|
|
|
193
220
|
*/
|
|
194
221
|
logging: LoggingConfig
|
|
195
222
|
|
|
223
|
+
/**
|
|
224
|
+
* **Marketing Options**
|
|
225
|
+
*
|
|
226
|
+
* Top-level feature gate for the marketing bundle (`/api/email/subscribe`,
|
|
227
|
+
* `/api/contact`, Campaign / EmailList / SocialPost).
|
|
228
|
+
*/
|
|
229
|
+
marketing: MarketingConfig
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* **Monitoring Options**
|
|
233
|
+
*
|
|
234
|
+
* Top-level feature gate for the monitoring bundle (Error model +
|
|
235
|
+
* error-tracking views and actions).
|
|
236
|
+
*/
|
|
237
|
+
monitoring: MonitoringConfig
|
|
238
|
+
|
|
196
239
|
/**
|
|
197
240
|
* **Notification Options**
|
|
198
241
|
*
|