@palbase/backend 5.0.0 → 5.1.0
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/dist/index.cjs +297 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +498 -1
- package/dist/index.d.ts +498 -1
- package/dist/index.js +284 -0
- package/dist/index.js.map +1 -1
- package/docs/config.md +100 -0
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -154,6 +154,503 @@ declare const Flags: PalbaseFlagsClient;
|
|
|
154
154
|
*/
|
|
155
155
|
declare function makeEnvDts(schema: SchemaDef): string;
|
|
156
156
|
|
|
157
|
+
/**
|
|
158
|
+
* storage.ts — the storage-buckets config-as-code DSL.
|
|
159
|
+
*
|
|
160
|
+
* `defineStorage({ buckets })` is the first MODULE config-as-code surface (the
|
|
161
|
+
* sibling of `db/schema.ts`'s `defineSchema`). A `config/storage.ts` file
|
|
162
|
+
* default-exports a `defineStorage(...)` result; on deploy the br-pod evaluates
|
|
163
|
+
* it to JSON and reconciles the declared buckets against the tenant's live
|
|
164
|
+
* buckets via the Storage admin API (create missing, update changed; never
|
|
165
|
+
* auto-delete — dropping a bucket is destructive and warned only).
|
|
166
|
+
*
|
|
167
|
+
* Buckets are DECLARATIVE: name + access + size/mime limits. The FILES inside a
|
|
168
|
+
* bucket are runtime state (uploaded via the SDK), never in git.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* import { defineStorage, bucket } from "@palbase/backend";
|
|
172
|
+
*
|
|
173
|
+
* export default defineStorage({
|
|
174
|
+
* buckets: {
|
|
175
|
+
* avatars: bucket({
|
|
176
|
+
* public: true,
|
|
177
|
+
* fileSizeLimit: "5MB",
|
|
178
|
+
* allowedMimeTypes: ["image/png", "image/jpeg", "image/webp"],
|
|
179
|
+
* }),
|
|
180
|
+
* invoices: bucket({
|
|
181
|
+
* public: false,
|
|
182
|
+
* fileSizeLimit: "20MB",
|
|
183
|
+
* allowedMimeTypes: ["application/pdf"],
|
|
184
|
+
* }),
|
|
185
|
+
* },
|
|
186
|
+
* });
|
|
187
|
+
*
|
|
188
|
+
* The returned value is the EXACT JSON shape the runtime's generic config
|
|
189
|
+
* extractor (`config_extract.js`) emits and the Go apply step parses:
|
|
190
|
+
* { __config: "storage", buckets: { avatars: { public, fileSizeLimit, allowedMimeTypes }, ... } }
|
|
191
|
+
* `fileSizeLimit` is always normalized to a number of bytes (or null when
|
|
192
|
+
* omitted, meaning "no limit"); the apply step maps it to the Storage API's
|
|
193
|
+
* `file_size_limit` field. `allowedMimeTypes` is the allowlist or null (any).
|
|
194
|
+
*/
|
|
195
|
+
/** The discriminant written under `__config` so the eval/apply can tell which
|
|
196
|
+
* module config a `config/*.ts` file describes. Storage is `"storage"`. */
|
|
197
|
+
declare const STORAGE_CONFIG_KIND: "storage";
|
|
198
|
+
/**
|
|
199
|
+
* The author-facing options for a single bucket.
|
|
200
|
+
*
|
|
201
|
+
* - `public`: when true the bucket is served without a signed URL. Defaults to
|
|
202
|
+
* `false` (private — signed URLs only).
|
|
203
|
+
* - `fileSizeLimit`: the per-object upload cap. Accepts a human string
|
|
204
|
+
* (`"5MB"`, `"20MB"`, `"1GB"`) or a bare number of BYTES. Omit for no limit.
|
|
205
|
+
* - `allowedMimeTypes`: an allowlist of MIME types accepted on upload. Omit to
|
|
206
|
+
* allow any type. Each entry must look like `type/subtype` (e.g. `image/png`,
|
|
207
|
+
* `application/pdf`, or a wildcard `image/*`).
|
|
208
|
+
*/
|
|
209
|
+
interface BucketOptions {
|
|
210
|
+
public?: boolean;
|
|
211
|
+
fileSizeLimit?: string | number;
|
|
212
|
+
allowedMimeTypes?: string[];
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* The compiled, serializable bucket definition — the EXACT shape emitted to
|
|
216
|
+
* JSON and consumed by the Go apply step.
|
|
217
|
+
*
|
|
218
|
+
* - `public`: always present (defaulted to `false`).
|
|
219
|
+
* - `fileSizeLimit`: bytes as a number, or `null` for "no limit".
|
|
220
|
+
* - `allowedMimeTypes`: the MIME allowlist, or `null` for "any type".
|
|
221
|
+
*/
|
|
222
|
+
interface BucketDef {
|
|
223
|
+
public: boolean;
|
|
224
|
+
fileSizeLimit: number | null;
|
|
225
|
+
allowedMimeTypes: string[] | null;
|
|
226
|
+
}
|
|
227
|
+
/** A storage config definition: the discriminant + a map of bucket name →
|
|
228
|
+
* {@link BucketDef}. This is the value `defineStorage` returns and the runtime
|
|
229
|
+
* config extractor serializes. */
|
|
230
|
+
interface StorageConfig {
|
|
231
|
+
__config: typeof STORAGE_CONFIG_KIND;
|
|
232
|
+
buckets: Record<string, BucketDef>;
|
|
233
|
+
}
|
|
234
|
+
/** The author-facing input to `defineStorage`: a `buckets` map whose keys are
|
|
235
|
+
* the bucket names and whose values are `bucket({...})` builders. */
|
|
236
|
+
interface StorageInput {
|
|
237
|
+
buckets: Record<string, BucketDef>;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Parse a `fileSizeLimit` into a number of bytes.
|
|
241
|
+
*
|
|
242
|
+
* - A bare number is taken as bytes verbatim (must be a non-negative integer).
|
|
243
|
+
* - A string is `<number><unit>` (e.g. `"5MB"`, `"1.5GB"`, `"500kb"`); the unit
|
|
244
|
+
* is case-insensitive and optional (a bare numeric string = bytes). Binary
|
|
245
|
+
* units (1 MB = 1024 squared bytes) to match the Storage module's parser.
|
|
246
|
+
*
|
|
247
|
+
* Throws on a negative value, a non-finite number, or an unrecognized unit so a
|
|
248
|
+
* bad limit fails at config-author time, not silently at deploy.
|
|
249
|
+
*/
|
|
250
|
+
declare function parseFileSizeLimit(input: string | number): number;
|
|
251
|
+
/**
|
|
252
|
+
* Define a single bucket. The bucket NAME is supplied by the key in
|
|
253
|
+
* `defineStorage({ buckets: { <name>: bucket({...}) } })`, so `bucket()` takes
|
|
254
|
+
* only the options.
|
|
255
|
+
*
|
|
256
|
+
* Validates eagerly (at config-author time):
|
|
257
|
+
* - `fileSizeLimit` parses to a valid non-negative byte count.
|
|
258
|
+
* - each `allowedMimeTypes` entry is a `type/subtype` MIME string.
|
|
259
|
+
*
|
|
260
|
+
* Returns a normalized {@link BucketDef}: `public` defaulted to `false`,
|
|
261
|
+
* `fileSizeLimit` as bytes-or-null, `allowedMimeTypes` deduped-or-null.
|
|
262
|
+
*/
|
|
263
|
+
declare function bucket(opts?: BucketOptions): BucketDef;
|
|
264
|
+
/**
|
|
265
|
+
* Define the storage config for a project. The bucket NAME comes from each
|
|
266
|
+
* object key (authors never repeat the name). Returns the discriminated
|
|
267
|
+
* {@link StorageConfig} the runtime config extractor serializes and the Go
|
|
268
|
+
* apply step reconciles.
|
|
269
|
+
*
|
|
270
|
+
* @example
|
|
271
|
+
* export default defineStorage({
|
|
272
|
+
* buckets: { avatars: bucket({ public: true, fileSizeLimit: "5MB" }) },
|
|
273
|
+
* });
|
|
274
|
+
*/
|
|
275
|
+
declare function defineStorage(input: StorageInput): StorageConfig;
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* notifications.ts — the notification-providers config-as-code DSL.
|
|
279
|
+
*
|
|
280
|
+
* `defineNotifications({ push, email, sms })` is the second MODULE config-as-code
|
|
281
|
+
* surface (the sibling of `config/storage.ts`'s `defineStorage`). A
|
|
282
|
+
* `config/notifications.ts` file default-exports a `defineNotifications(...)`
|
|
283
|
+
* result; on deploy the br-pod evaluates it to JSON and reconciles the declared
|
|
284
|
+
* providers against the tenant's live providers via the PalNotify admin API
|
|
285
|
+
* (create missing; never auto-delete — dropping a provider is destructive and
|
|
286
|
+
* warned only).
|
|
287
|
+
*
|
|
288
|
+
* SECRETS ARE NEVER IN THE FILE. Each provider's NON-SECRET fields (team id, key
|
|
289
|
+
* id, bundle id, region, host, port, from address, account sid, …) are literals
|
|
290
|
+
* in the config. Each provider's SECRET material (the APNs .p8 key, the FCM
|
|
291
|
+
* service-account JSON, an api_key, an auth token, the SMTP/ACS password, …) is
|
|
292
|
+
* NOT a field here — it is bound BY CONVENTION to a RESERVED encrypted env var
|
|
293
|
+
* and resolved at deploy from control-pg. The env-key convention is:
|
|
294
|
+
*
|
|
295
|
+
* PB_NOTIFICATIONS_<PROVIDER>_<FIELD> (UPPER_SNAKE_CASE)
|
|
296
|
+
*
|
|
297
|
+
* e.g. `PB_NOTIFICATIONS_APNS_P8`, `PB_NOTIFICATIONS_FCM_SERVICE_ACCOUNT`,
|
|
298
|
+
* `PB_NOTIFICATIONS_TWILIO_AUTH_TOKEN`. The `PB_` namespace is reserved (the CLI
|
|
299
|
+
* refuses a hand-set `palbase secret set PB_*`); the CLI's `palbase notifications
|
|
300
|
+
* add <provider>` derives the key and uploads the secret for you, so an author
|
|
301
|
+
* never types either the secret or the env-key name into git.
|
|
302
|
+
*
|
|
303
|
+
* @example
|
|
304
|
+
* import { defineNotifications } from "@palbase/backend";
|
|
305
|
+
*
|
|
306
|
+
* export default defineNotifications({
|
|
307
|
+
* push: {
|
|
308
|
+
* apns: { enabled: true, teamId: "ABCDE12345", keyId: "KEY1234567", bundleId: "com.acme.app" },
|
|
309
|
+
* fcm: { enabled: true },
|
|
310
|
+
* },
|
|
311
|
+
* email: {
|
|
312
|
+
* sendgrid: { enabled: true, fromDomain: "mail.acme.com" },
|
|
313
|
+
* },
|
|
314
|
+
* sms: {
|
|
315
|
+
* twilio: { enabled: true, accountSid: "ACxxxxxxxx", messagingServiceSid: "MGxxxxxxxx" },
|
|
316
|
+
* },
|
|
317
|
+
* });
|
|
318
|
+
*
|
|
319
|
+
* The returned value is the EXACT JSON shape the runtime's generic config
|
|
320
|
+
* extractor (`config_extract.js`) emits and the Go apply step parses:
|
|
321
|
+
* { __config: "notifications", push: {...}, email: {...}, sms: {...} }
|
|
322
|
+
* Only ENABLED providers carry their non-secret fields; a disabled (or absent)
|
|
323
|
+
* provider serializes as `{ enabled: false }` so the apply step skips it.
|
|
324
|
+
*/
|
|
325
|
+
/** The `__config` discriminant the eval/apply reads to confirm a config/*.ts is
|
|
326
|
+
* a notifications config. Notifications is `"notifications"`. */
|
|
327
|
+
declare const NOTIFICATIONS_CONFIG_KIND: "notifications";
|
|
328
|
+
/** The reserved env-var prefix that backs provider secrets. A `palbase secret
|
|
329
|
+
* set` of a key under this prefix is REFUSED by the CLI (it is managed by
|
|
330
|
+
* `palbase notifications add`). Both the CLI and the br-pod apply step derive a
|
|
331
|
+
* provider's secret env key as `${RESERVED_SECRET_PREFIX}_<PROVIDER>_<FIELD>`. */
|
|
332
|
+
declare const RESERVED_SECRET_PREFIX: "PB_NOTIFICATIONS";
|
|
333
|
+
/** One provider's catalog entry: which non-secret fields are required, which are
|
|
334
|
+
* optional, and which secret field-name(s) bind to reserved env vars. */
|
|
335
|
+
interface ProviderCatalogEntry {
|
|
336
|
+
/** The channel this provider serves (`push` | `email` | `sms`). */
|
|
337
|
+
readonly channel: "push" | "email" | "sms";
|
|
338
|
+
/** Non-secret config fields the author MUST supply (validated eagerly). */
|
|
339
|
+
readonly required: readonly string[];
|
|
340
|
+
/** Non-secret config fields the author MAY supply. */
|
|
341
|
+
readonly optional: readonly string[];
|
|
342
|
+
/** Secret field name(s) — each backed by `PB_NOTIFICATIONS_<PROVIDER>_<FIELD>`
|
|
343
|
+
* (FIELD is the UPPER_SNAKE of the name here). NOT a config field. */
|
|
344
|
+
readonly secrets: readonly string[];
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* The provider catalog: provider key → fields. The non-secret field names are
|
|
348
|
+
* the camelCase keys an author writes in `config/notifications.ts`; the secret
|
|
349
|
+
* names are the snake-ish tokens that become the reserved env-var suffix.
|
|
350
|
+
*
|
|
351
|
+
* apns: team_id / key_id / bundle_id (+ optional is_production); secret = p8.
|
|
352
|
+
* fcm: no non-secret fields; secret = service_account (the full JSON).
|
|
353
|
+
* sendgrid: from_domain; secret = api_key.
|
|
354
|
+
* ses: region / from_domain / access_key_id; secret = secret_access_key.
|
|
355
|
+
* smtp: host / port / from_email (+ optional username, use_starttls); secret = password.
|
|
356
|
+
* acs: from_email (+ optional from_name); secret = connection_string.
|
|
357
|
+
* twilio: account_sid + (from_number OR messaging_service_sid); secret = auth_token.
|
|
358
|
+
*/
|
|
359
|
+
declare const PROVIDER_CATALOG: {
|
|
360
|
+
readonly apns: {
|
|
361
|
+
readonly channel: "push";
|
|
362
|
+
readonly required: readonly ["teamId", "keyId", "bundleId"];
|
|
363
|
+
readonly optional: readonly ["isProduction"];
|
|
364
|
+
readonly secrets: readonly ["p8"];
|
|
365
|
+
};
|
|
366
|
+
readonly fcm: {
|
|
367
|
+
readonly channel: "push";
|
|
368
|
+
readonly required: readonly [];
|
|
369
|
+
readonly optional: readonly [];
|
|
370
|
+
readonly secrets: readonly ["serviceAccount"];
|
|
371
|
+
};
|
|
372
|
+
readonly sendgrid: {
|
|
373
|
+
readonly channel: "email";
|
|
374
|
+
readonly required: readonly ["fromDomain"];
|
|
375
|
+
readonly optional: readonly [];
|
|
376
|
+
readonly secrets: readonly ["apiKey"];
|
|
377
|
+
};
|
|
378
|
+
readonly ses: {
|
|
379
|
+
readonly channel: "email";
|
|
380
|
+
readonly required: readonly ["region", "accessKeyId", "fromDomain"];
|
|
381
|
+
readonly optional: readonly [];
|
|
382
|
+
readonly secrets: readonly ["secretAccessKey"];
|
|
383
|
+
};
|
|
384
|
+
readonly smtp: {
|
|
385
|
+
readonly channel: "email";
|
|
386
|
+
readonly required: readonly ["host", "port", "fromEmail"];
|
|
387
|
+
readonly optional: readonly ["username", "useStarttls"];
|
|
388
|
+
readonly secrets: readonly ["password"];
|
|
389
|
+
};
|
|
390
|
+
readonly acs: {
|
|
391
|
+
readonly channel: "email";
|
|
392
|
+
readonly required: readonly ["fromEmail"];
|
|
393
|
+
readonly optional: readonly ["fromName"];
|
|
394
|
+
readonly secrets: readonly ["connectionString"];
|
|
395
|
+
};
|
|
396
|
+
readonly twilio: {
|
|
397
|
+
readonly channel: "sms";
|
|
398
|
+
readonly required: readonly ["accountSid"];
|
|
399
|
+
readonly optional: readonly ["fromNumber", "messagingServiceSid"];
|
|
400
|
+
readonly secrets: readonly ["authToken"];
|
|
401
|
+
};
|
|
402
|
+
};
|
|
403
|
+
/** A provider key (`"apns" | "fcm" | "sendgrid" | …`). */
|
|
404
|
+
type ProviderName = keyof typeof PROVIDER_CATALOG;
|
|
405
|
+
/** APNs (Apple Push) — non-secret fields. The `.p8` key is the reserved secret
|
|
406
|
+
* `PB_NOTIFICATIONS_APNS_P8` (uploaded via `palbase notifications add apns`). */
|
|
407
|
+
interface ApnsOptions {
|
|
408
|
+
enabled?: boolean;
|
|
409
|
+
teamId: string;
|
|
410
|
+
keyId: string;
|
|
411
|
+
bundleId: string;
|
|
412
|
+
/** APNs production gateway vs sandbox. Defaults to true (production). */
|
|
413
|
+
isProduction?: boolean;
|
|
414
|
+
}
|
|
415
|
+
/** FCM (Firebase Cloud Messaging) — no non-secret fields; the service-account
|
|
416
|
+
* JSON is the reserved secret `PB_NOTIFICATIONS_FCM_SERVICE_ACCOUNT`. */
|
|
417
|
+
interface FcmOptions {
|
|
418
|
+
enabled?: boolean;
|
|
419
|
+
}
|
|
420
|
+
/** SendGrid email — non-secret `fromDomain`; api_key is the reserved secret. */
|
|
421
|
+
interface SendgridOptions {
|
|
422
|
+
enabled?: boolean;
|
|
423
|
+
fromDomain: string;
|
|
424
|
+
}
|
|
425
|
+
/** Amazon SES email — secret_access_key is the reserved secret. */
|
|
426
|
+
interface SesOptions {
|
|
427
|
+
enabled?: boolean;
|
|
428
|
+
region: string;
|
|
429
|
+
accessKeyId: string;
|
|
430
|
+
fromDomain: string;
|
|
431
|
+
}
|
|
432
|
+
/** SMTP email — password is the reserved secret. */
|
|
433
|
+
interface SmtpOptions {
|
|
434
|
+
enabled?: boolean;
|
|
435
|
+
host: string;
|
|
436
|
+
port: number;
|
|
437
|
+
fromEmail: string;
|
|
438
|
+
username?: string;
|
|
439
|
+
useStarttls?: boolean;
|
|
440
|
+
}
|
|
441
|
+
/** Azure Communication Services email — connection_string is the reserved secret. */
|
|
442
|
+
interface AcsOptions {
|
|
443
|
+
enabled?: boolean;
|
|
444
|
+
fromEmail: string;
|
|
445
|
+
fromName?: string;
|
|
446
|
+
}
|
|
447
|
+
/** Twilio SMS — auth_token is the reserved secret. Exactly one of `fromNumber`
|
|
448
|
+
* or `messagingServiceSid` must be supplied. */
|
|
449
|
+
interface TwilioOptions {
|
|
450
|
+
enabled?: boolean;
|
|
451
|
+
accountSid: string;
|
|
452
|
+
fromNumber?: string;
|
|
453
|
+
messagingServiceSid?: string;
|
|
454
|
+
}
|
|
455
|
+
/** The union of every provider's author-facing options. `buildProvider` accepts
|
|
456
|
+
* this so each provider's typed options pass without a cast. */
|
|
457
|
+
type ProviderOptions = ApnsOptions | FcmOptions | SendgridOptions | SesOptions | SmtpOptions | AcsOptions | TwilioOptions;
|
|
458
|
+
/** The author-facing input to `defineNotifications`. Every provider + every
|
|
459
|
+
* channel is optional — declare only what you use. */
|
|
460
|
+
interface NotificationsInput {
|
|
461
|
+
push?: {
|
|
462
|
+
apns?: ApnsOptions;
|
|
463
|
+
fcm?: FcmOptions;
|
|
464
|
+
};
|
|
465
|
+
email?: {
|
|
466
|
+
sendgrid?: SendgridOptions;
|
|
467
|
+
ses?: SesOptions;
|
|
468
|
+
smtp?: SmtpOptions;
|
|
469
|
+
acs?: AcsOptions;
|
|
470
|
+
};
|
|
471
|
+
sms?: {
|
|
472
|
+
twilio?: TwilioOptions;
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
/** A compiled provider def. `enabled` is always present; the remaining keys are
|
|
476
|
+
* the provider's non-secret fields (verbatim from the catalog). A disabled
|
|
477
|
+
* provider is `{ enabled: false }` with no other fields. */
|
|
478
|
+
type ProviderDef = {
|
|
479
|
+
enabled: boolean;
|
|
480
|
+
} & Record<string, unknown>;
|
|
481
|
+
/** The compiled notifications config — the discriminant + per-channel maps of
|
|
482
|
+
* provider name → {@link ProviderDef}. This is what `defineNotifications`
|
|
483
|
+
* returns and the runtime extractor serializes. */
|
|
484
|
+
interface NotificationsConfig {
|
|
485
|
+
__config: typeof NOTIFICATIONS_CONFIG_KIND;
|
|
486
|
+
push: Record<string, ProviderDef>;
|
|
487
|
+
email: Record<string, ProviderDef>;
|
|
488
|
+
sms: Record<string, ProviderDef>;
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Compile + validate one provider's author options into a {@link ProviderDef}.
|
|
492
|
+
*
|
|
493
|
+
* - A provider with `enabled === false` (or omitted) compiles to `{ enabled:
|
|
494
|
+
* false }` and its required fields are NOT enforced (you can declare a disabled
|
|
495
|
+
* provider as a placeholder without filling it in).
|
|
496
|
+
* - An ENABLED provider must supply every `required` non-secret field from the
|
|
497
|
+
* catalog; a missing one throws at config-author time (not silently at deploy).
|
|
498
|
+
* - Only the catalog's non-secret fields (required + optional) are copied into
|
|
499
|
+
* the def — an unknown extra key is ignored (it would have no effect on the
|
|
500
|
+
* live provider). Secrets are never read here.
|
|
501
|
+
*/
|
|
502
|
+
declare function buildProvider(name: ProviderName, opts: ProviderOptions): ProviderDef;
|
|
503
|
+
/**
|
|
504
|
+
* Define the notification-provider config for a project. Returns the
|
|
505
|
+
* discriminated {@link NotificationsConfig} the runtime config extractor
|
|
506
|
+
* serializes and the Go apply step reconciles. Validates eagerly: an enabled
|
|
507
|
+
* provider missing a required non-secret field throws here (config-author time),
|
|
508
|
+
* not at deploy.
|
|
509
|
+
*
|
|
510
|
+
* @example
|
|
511
|
+
* export default defineNotifications({
|
|
512
|
+
* push: { apns: { enabled: true, teamId: "T", keyId: "K", bundleId: "com.x" } },
|
|
513
|
+
* });
|
|
514
|
+
*/
|
|
515
|
+
declare function defineNotifications(input: NotificationsInput): NotificationsConfig;
|
|
516
|
+
/**
|
|
517
|
+
* Derive the RESERVED env-var key that backs a provider's secret field, e.g.
|
|
518
|
+
* `reservedSecretKey("apns", "p8")` → `"PB_NOTIFICATIONS_APNS_P8"`. The CLI uses
|
|
519
|
+
* this to upload the secret and the br-pod apply step uses the same derivation
|
|
520
|
+
* to resolve it — they never hand-type the key, so they cannot drift.
|
|
521
|
+
*/
|
|
522
|
+
declare function reservedSecretKey(provider: ProviderName, secretField: string): string;
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* flags.ts — the feature-flag-definitions config-as-code DSL.
|
|
526
|
+
*
|
|
527
|
+
* `defineFlags({ flags })` is the third MODULE config-as-code surface (a sibling
|
|
528
|
+
* of `config/storage.ts`'s `defineStorage` and `config/notifications.ts`'s
|
|
529
|
+
* `defineNotifications`). A `config/flags.ts` file default-exports a
|
|
530
|
+
* `defineFlags(...)` result; on deploy the br-pod evaluates it to JSON and
|
|
531
|
+
* UPSERTS the declared flag DEFINITIONS into PalFlags (the user-flags module's
|
|
532
|
+
* system-flags admin API) — create-or-update, idempotent. A live flag NOT in
|
|
533
|
+
* config is NEVER auto-deleted (an orphan flag is harmless; upsert-only).
|
|
534
|
+
*
|
|
535
|
+
* Flags are DECLARATIVE: a flag is a typed project-wide DEFAULT (its key, type,
|
|
536
|
+
* default value, an optional description, and — for string flags — an optional
|
|
537
|
+
* list of allowed `variants`). The VALUE of a flag for a specific USER (a
|
|
538
|
+
* per-user override / A-B assignment) is runtime state set via the SDK, NEVER in
|
|
539
|
+
* git. `variants` here is part of the DEFINITION (the allowed values a string
|
|
540
|
+
* flag may take), not a per-user assignment.
|
|
541
|
+
*
|
|
542
|
+
* NO SECRETS. Unlike notifications, a flag carries no credentials — this is the
|
|
543
|
+
* simplest module config (pure declarative data).
|
|
544
|
+
*
|
|
545
|
+
* @example
|
|
546
|
+
* import { defineFlags, flag } from "@palbase/backend";
|
|
547
|
+
*
|
|
548
|
+
* export default defineFlags({
|
|
549
|
+
* flags: {
|
|
550
|
+
* new_dashboard: flag({ type: "boolean", default: false, description: "Roll out the new dashboard" }),
|
|
551
|
+
* max_uploads: flag({ type: "number", default: 10 }),
|
|
552
|
+
* theme: flag({ type: "string", default: "light", variants: ["light", "dark", "system"] }),
|
|
553
|
+
* },
|
|
554
|
+
* });
|
|
555
|
+
*
|
|
556
|
+
* The returned value is the EXACT JSON shape the runtime's generic config
|
|
557
|
+
* extractor (`config_extract.js`) emits and the Go apply step parses:
|
|
558
|
+
* { __config: "flags", flags: { <key>: { type, default, variants, description }, ... } }
|
|
559
|
+
* `variants` is the allowed-values list for a string flag, or `null` (any
|
|
560
|
+
* string). `description` is the doc string, or `null`. The apply step maps the
|
|
561
|
+
* author-facing `type` ("boolean") to PalFlags' `value_type` ("bool").
|
|
562
|
+
*/
|
|
563
|
+
/** The `__config` discriminant the eval/apply reads to confirm a config/*.ts is
|
|
564
|
+
* a flags config. Flags is `"flags"`. */
|
|
565
|
+
declare const FLAGS_CONFIG_KIND: "flags";
|
|
566
|
+
/**
|
|
567
|
+
* A flag's type. The author-facing vocabulary is `"boolean" | "number" |
|
|
568
|
+
* "string"`. (The br-pod maps `"boolean"` to PalFlags' `value_type: "bool"` on
|
|
569
|
+
* apply — the SDK keeps the JS-natural `"boolean"` so the DSL reads cleanly.)
|
|
570
|
+
*
|
|
571
|
+
* PalFlags also supports an `object` value type, but config-as-code flags are
|
|
572
|
+
* deliberately scoped to the three SCALAR types — an object default is awkward
|
|
573
|
+
* to author on the CLI and rare for a feature flag, so it is intentionally
|
|
574
|
+
* omitted here (set an object flag via the Studio / API directly if needed).
|
|
575
|
+
*/
|
|
576
|
+
type FlagType = "boolean" | "number" | "string";
|
|
577
|
+
/** The runtime JSON value a flag's `default` may hold (matches {@link FlagType}). */
|
|
578
|
+
type FlagValue = boolean | number | string;
|
|
579
|
+
/**
|
|
580
|
+
* The author-facing options for a single flag.
|
|
581
|
+
*
|
|
582
|
+
* - `type`: the flag's type — `"boolean" | "number" | "string"`.
|
|
583
|
+
* - `default`: the project-wide default value. MUST match `type` (a `number`
|
|
584
|
+
* default with `type: "boolean"` throws).
|
|
585
|
+
* - `variants`: ONLY valid for `type: "string"` — the allowed values the string
|
|
586
|
+
* flag may take (a DEFINITION, not a per-user assignment). When given, the
|
|
587
|
+
* `default` MUST be one of the variants. Supplying `variants` on a non-string
|
|
588
|
+
* type throws.
|
|
589
|
+
* - `description`: an optional human description of what the flag controls.
|
|
590
|
+
*/
|
|
591
|
+
interface FlagOptions {
|
|
592
|
+
type: FlagType;
|
|
593
|
+
default: FlagValue;
|
|
594
|
+
variants?: string[];
|
|
595
|
+
description?: string;
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* The compiled, serializable flag definition — the EXACT shape emitted to JSON
|
|
599
|
+
* and consumed by the Go apply step.
|
|
600
|
+
*
|
|
601
|
+
* - `type`: the author-facing type verbatim (`"boolean" | "number" | "string"`).
|
|
602
|
+
* - `default`: the default value (matches `type`).
|
|
603
|
+
* - `variants`: the allowed-values list for a string flag, or `null` (any).
|
|
604
|
+
* - `description`: the doc string, or `null`.
|
|
605
|
+
*/
|
|
606
|
+
interface FlagDef {
|
|
607
|
+
type: FlagType;
|
|
608
|
+
default: FlagValue;
|
|
609
|
+
variants: string[] | null;
|
|
610
|
+
description: string | null;
|
|
611
|
+
}
|
|
612
|
+
/** A flags config definition: the discriminant + a map of flag key →
|
|
613
|
+
* {@link FlagDef}. This is the value `defineFlags` returns and the runtime
|
|
614
|
+
* config extractor serializes. */
|
|
615
|
+
interface FlagsConfig {
|
|
616
|
+
__config: typeof FLAGS_CONFIG_KIND;
|
|
617
|
+
flags: Record<string, FlagDef>;
|
|
618
|
+
}
|
|
619
|
+
/** The author-facing input to `defineFlags`: a `flags` map whose keys are the
|
|
620
|
+
* flag keys and whose values are `flag({...})` builders. */
|
|
621
|
+
interface FlagsInput {
|
|
622
|
+
flags: Record<string, FlagDef>;
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* Define a single flag. The flag KEY is supplied by the object key in
|
|
626
|
+
* `defineFlags({ flags: { <key>: flag({...}) } })`, so `flag()` takes only the
|
|
627
|
+
* options.
|
|
628
|
+
*
|
|
629
|
+
* Validates eagerly (at config-author time):
|
|
630
|
+
* - `type` is one of `"boolean" | "number" | "string"`.
|
|
631
|
+
* - `default` matches `type` (e.g. a `number` default with `type: "boolean"`
|
|
632
|
+
* throws).
|
|
633
|
+
* - `variants` is ONLY allowed for a string flag (variants on a non-string
|
|
634
|
+
* type throws); each entry is a non-empty string; the `default` must be one
|
|
635
|
+
* of the variants.
|
|
636
|
+
*
|
|
637
|
+
* Returns a normalized {@link FlagDef}: `variants` deduped-or-null,
|
|
638
|
+
* `description` trimmed-or-null.
|
|
639
|
+
*/
|
|
640
|
+
declare function flag(opts: FlagOptions): FlagDef;
|
|
641
|
+
/**
|
|
642
|
+
* Define the feature-flag definitions for a project. The flag KEY comes from
|
|
643
|
+
* each object key (authors never repeat the key). Returns the discriminated
|
|
644
|
+
* {@link FlagsConfig} the runtime config extractor serializes and the Go apply
|
|
645
|
+
* step UPSERTS into PalFlags.
|
|
646
|
+
*
|
|
647
|
+
* @example
|
|
648
|
+
* export default defineFlags({
|
|
649
|
+
* flags: { dark_mode: flag({ type: "boolean", default: false }) },
|
|
650
|
+
* });
|
|
651
|
+
*/
|
|
652
|
+
declare function defineFlags(input: FlagsInput): FlagsConfig;
|
|
653
|
+
|
|
157
654
|
/** Options accepted by `@Controller`. */
|
|
158
655
|
interface ControllerOptions {
|
|
159
656
|
/** Default auth for ALL routes in this controller (route-level overrides). */
|
|
@@ -676,4 +1173,4 @@ declare const documents: {
|
|
|
676
1173
|
onDocumentDeleted(handler: HookHandler<DocumentDeletedEvent>): ResolvedHook<DocumentDeletedEvent>;
|
|
677
1174
|
};
|
|
678
1175
|
|
|
679
|
-
export { type BackoffStrategy, Body, Cache, CacheClient, Client, Controller, type ControllerOptions, type CustomWebhookConfig, DBClient, Database, Delete, type DocumentCreatedEvent, type DocumentDeletedEvent, type DocumentUpdatedEvent, Documents, type EnvSecretRef, EnvTypedDatabase, type FileDeletedEvent, type FileUploadedEvent, Flags, Get, Headers, type HookHandler, type HookMeta, type HttpMethodUpper, type JobConfig, type JobMeta, Log, Logger, Notifications, OptionalUser, PalbaseDocsClient, PalbaseFlagsClient, PalbaseNotificationsClient, PalbaseStorageClient, Param, type PasswordResetEvent, Patch, Post, type ProviderEventMap, type ProviderWebhookConfig, Put, Query, Queue, QueueClient, RateLimitConfig, Req, RequestId, type ResolvedCustomWebhook, type ResolvedHook, type ResolvedJobConfig, type ResolvedProviderWebhook, type ResolvedWebhookConfig, type ResolvedWorkerConfig, Resource, type ResourceEnv, type RouteOptions, type RuntimeServices, SchemaDef, type SignInEvent, type SignOutEvent, Storage, TraceId, User, type UserCreatedEvent, User$1 as UserT, type WebhookEventHandler, type WebhookMeta, type WebhookProvider, type WebhookRequest, type WorkerConfig, type WorkerMeta, __getRuntime, __registerResource, __requestALS, __runResourceBoot, __runWithRuntime, __setRuntime, __shutdownResources, auth, defineJob, defineWebhook, defineWorker, documents, makeEnvDts, storage };
|
|
1176
|
+
export { type AcsOptions, type ApnsOptions, type BackoffStrategy, Body, type BucketDef, type BucketOptions, Cache, CacheClient, Client, Controller, type ControllerOptions, type CustomWebhookConfig, DBClient, Database, Delete, type DocumentCreatedEvent, type DocumentDeletedEvent, type DocumentUpdatedEvent, Documents, type EnvSecretRef, EnvTypedDatabase, FLAGS_CONFIG_KIND, type FcmOptions, type FileDeletedEvent, type FileUploadedEvent, type FlagDef, type FlagOptions, type FlagType, type FlagValue, Flags, type FlagsConfig, type FlagsInput, Get, Headers, type HookHandler, type HookMeta, type HttpMethodUpper, type JobConfig, type JobMeta, Log, Logger, NOTIFICATIONS_CONFIG_KIND, Notifications, type NotificationsConfig, type NotificationsInput, OptionalUser, PROVIDER_CATALOG, PalbaseDocsClient, PalbaseFlagsClient, PalbaseNotificationsClient, PalbaseStorageClient, Param, type PasswordResetEvent, Patch, Post, type ProviderCatalogEntry, type ProviderDef, type ProviderEventMap, type ProviderName, type ProviderOptions, type ProviderWebhookConfig, Put, Query, Queue, QueueClient, RESERVED_SECRET_PREFIX, RateLimitConfig, Req, RequestId, type ResolvedCustomWebhook, type ResolvedHook, type ResolvedJobConfig, type ResolvedProviderWebhook, type ResolvedWebhookConfig, type ResolvedWorkerConfig, Resource, type ResourceEnv, type RouteOptions, type RuntimeServices, STORAGE_CONFIG_KIND, SchemaDef, type SendgridOptions, type SesOptions, type SignInEvent, type SignOutEvent, type SmtpOptions, Storage, type StorageConfig, type StorageInput, TraceId, type TwilioOptions, User, type UserCreatedEvent, User$1 as UserT, type WebhookEventHandler, type WebhookMeta, type WebhookProvider, type WebhookRequest, type WorkerConfig, type WorkerMeta, __getRuntime, __registerResource, __requestALS, __runResourceBoot, __runWithRuntime, __setRuntime, __shutdownResources, auth, bucket, buildProvider, defineFlags, defineJob, defineNotifications, defineStorage, defineWebhook, defineWorker, documents, flag, makeEnvDts, parseFileSizeLimit, reservedSecretKey, storage };
|