@palbase/backend 4.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.d.cts CHANGED
@@ -1,8 +1,8 @@
1
- import { C as CacheClient, b as PalbaseDocsClient, c as PalbaseFlagsClient, L as Logger, d as PalbaseNotificationsClient, Q as QueueClient, D as DBClient, e as PalbaseStorageClient, A as AuthSpec, R as RateLimitConfig, U as User$1 } from './endpoint-2d_DpASt.cjs';
2
- export { f as AuthConfig, B as BadRequest, g as ClientInfo, h as Conflict, i as DBOps, E as ErrorDef, j as ErrorMap, k as ErrorThrowers, F as FileContext, l as Forbidden, H as HttpError, m as HttpMethod, M as Middleware, n as MiddlewareContext, o as MiddlewareHandler, N as NotFound, P as PBRequest, p as PalError, q as PalbaseAnalyticsClient, r as PalbaseAnalyticsManagementNamespace, s as PalbaseAnalyticsProperties, t as PalbaseAnalyticsQueryNamespace, u as PalbaseAttestAndroidParams, v as PalbaseAttestAndroidResult, w as PalbaseAttestiOSParams, x as PalbaseAttestiOSResult, y as PalbaseAuthClient, z as PalbaseBindDeviceParams, G as PalbaseBucketClient, I as PalbaseCmsClient, J as PalbaseCmsFindOneOptions, K as PalbaseCmsFindOptions, O as PalbaseCohortQueryInput, S as PalbaseCohortResult, T as PalbaseCollectionRef, V as PalbaseCountQueryInput, W as PalbaseCountResult, X as PalbaseCreateLinkParams, Y as PalbaseDeviceInfo, Z as PalbaseDeviceTokenView, _ as PalbaseDocumentRef, $ as PalbaseDocumentSnapshot, a0 as PalbaseEmailClient, a1 as PalbaseEmailSendParams, a2 as PalbaseEmailSendResponse, a3 as PalbaseEventNamesResult, a4 as PalbaseEventsQueryInput, a5 as PalbaseEventsResult, a6 as PalbaseFileObject, a7 as PalbaseFlag, a8 as PalbaseFlagContext, a9 as PalbaseFlagVariant, aa as PalbaseFunctionsClient, ab as PalbaseFunnelQueryInput, ac as PalbaseFunnelResult, ad as PalbaseIdentifyTraits, ae as PalbaseInboxClient, af as PalbaseInboxListOptions, ag as PalbaseInboxListResult, ah as PalbaseInboxMessage, ai as PalbaseInboxSendParams, aj as PalbaseInboxSendResponse, ak as PalbaseInitialLink, al as PalbaseInvokeOptions, am as PalbaseLink, an as PalbaseLinkAnalytics, ao as PalbaseLinkDetails, ap as PalbaseLinksClient, aq as PalbaseListLinksOptions, ar as PalbaseListLinksResult, as as PalbaseListOptions, at as PalbaseMatchParams, au as PalbaseMultiChannelResponse, av as PalbaseOverviewResult, aw as PalbasePreferences, ax as PalbasePreferencesClient, ay as PalbasePublicUrlResponse, az as PalbasePushClient, aA as PalbasePushSendParams, aB as PalbasePushSendResponse, aC as PalbaseQrCodeOptions, aD as PalbaseQuerySnapshot, aE as PalbaseRealtimeChannel, aF as PalbaseRealtimeClient, aG as PalbaseRealtimeMessage, aH as PalbaseRegisterDeviceParams, aI as PalbaseResult, aJ as PalbaseRetentionQueryInput, aK as PalbaseRetentionResult, aL as PalbaseSession, aM as PalbaseSignedUrlResponse, aN as PalbaseSmsClient, aO as PalbaseSmsSendParams, aP as PalbaseSmsSendResponse, aQ as PalbaseTransformOptions, aR as PalbaseUpdateLinkParams, aS as PalbaseUploadOptions, aT as PalbaseUser, aU as PalbaseUserDetailResult, aV as PalbaseUsersQueryInput, aW as PalbaseUsersResult, aX as PalbaseVerifyRequestSignatureParams, aY as PalbaseWhereOperator, aZ as TooManyRequests, a_ as TxClient, a$ as Unauthorized, b0 as defineMiddleware } from './endpoint-2d_DpASt.cjs';
1
+ import { C as CacheClient, b as PalbaseDocsClient, c as PalbaseFlagsClient, L as Logger, d as PalbaseNotificationsClient, Q as QueueClient, D as DBClient, e as PalbaseStorageClient, A as AuthSpec, R as RateLimitConfig, U as User$1 } from './endpoint-BEHjfvFH.cjs';
2
+ export { f as AuthConfig, B as BadRequest, g as ClientInfo, h as Conflict, i as DBOps, E as ErrorDef, j as ErrorMap, k as ErrorThrowers, F as FileContext, l as Forbidden, H as HttpError, m as HttpMethod, M as Middleware, n as MiddlewareContext, o as MiddlewareHandler, N as NotFound, P as PBRequest, p as PalError, q as PalbaseAnalyticsClient, r as PalbaseAnalyticsManagementNamespace, s as PalbaseAnalyticsProperties, t as PalbaseAnalyticsQueryNamespace, u as PalbaseAttestAndroidParams, v as PalbaseAttestAndroidResult, w as PalbaseAttestiOSParams, x as PalbaseAttestiOSResult, y as PalbaseAuthClient, z as PalbaseBindDeviceParams, G as PalbaseBucketClient, I as PalbaseCmsClient, J as PalbaseCmsFindOneOptions, K as PalbaseCmsFindOptions, O as PalbaseCohortQueryInput, S as PalbaseCohortResult, T as PalbaseCollectionRef, V as PalbaseCountQueryInput, W as PalbaseCountResult, X as PalbaseCreateLinkParams, Y as PalbaseDeviceInfo, Z as PalbaseDeviceTokenView, _ as PalbaseDocumentRef, $ as PalbaseDocumentSnapshot, a0 as PalbaseEmailClient, a1 as PalbaseEmailSendParams, a2 as PalbaseEmailSendResponse, a3 as PalbaseEventNamesResult, a4 as PalbaseEventsQueryInput, a5 as PalbaseEventsResult, a6 as PalbaseFileObject, a7 as PalbaseFlag, a8 as PalbaseFlagContext, a9 as PalbaseFlagVariant, aa as PalbaseFunctionsClient, ab as PalbaseFunnelQueryInput, ac as PalbaseFunnelResult, ad as PalbaseIdentifyTraits, ae as PalbaseInboxClient, af as PalbaseInboxListOptions, ag as PalbaseInboxListResult, ah as PalbaseInboxMessage, ai as PalbaseInboxSendParams, aj as PalbaseInboxSendResponse, ak as PalbaseInitialLink, al as PalbaseInvokeOptions, am as PalbaseLink, an as PalbaseLinkAnalytics, ao as PalbaseLinkDetails, ap as PalbaseLinksClient, aq as PalbaseListLinksOptions, ar as PalbaseListLinksResult, as as PalbaseListOptions, at as PalbaseMatchParams, au as PalbaseMultiChannelResponse, av as PalbaseOverviewResult, aw as PalbasePreferences, ax as PalbasePreferencesClient, ay as PalbasePublicUrlResponse, az as PalbasePushClient, aA as PalbasePushSendParams, aB as PalbasePushSendResponse, aC as PalbaseQrCodeOptions, aD as PalbaseQuerySnapshot, aE as PalbaseRealtimeChannel, aF as PalbaseRealtimeClient, aG as PalbaseRealtimeMessage, aH as PalbaseRegisterDeviceParams, aI as PalbaseResult, aJ as PalbaseRetentionQueryInput, aK as PalbaseRetentionResult, aL as PalbaseSession, aM as PalbaseSignedUrlResponse, aN as PalbaseSmsClient, aO as PalbaseSmsSendParams, aP as PalbaseSmsSendResponse, aQ as PalbaseTransformOptions, aR as PalbaseUpdateLinkParams, aS as PalbaseUploadOptions, aT as PalbaseUser, aU as PalbaseUserDetailResult, aV as PalbaseUsersQueryInput, aW as PalbaseUsersResult, aX as PalbaseVerifyRequestSignatureParams, aY as PalbaseWhereOperator, aZ as TooManyRequests, a_ as TxClient, a$ as Unauthorized, b0 as defineMiddleware } from './endpoint-BEHjfvFH.cjs';
3
3
  import { AsyncLocalStorage } from 'node:async_hooks';
4
- import { E as EnvTypedDatabase, S as SchemaDef } from './index-DzRFS3Tl.cjs';
5
- export { C as ColumnBuilder, a as ColumnDef, b as ColumnMap, c as ColumnType, d as EXTENSION_DEPENDENCIES, e as EnvServiceDatabase, f as EnvTables, g as EnvTypedTable, h as EnvTypedTx, I as InsertShape, O as OnDeleteAction, P as PALBASE_EXTENSIONS, i as PalbaseExtension, j as PolicyBuilder, k as PolicyCommand, l as PolicyDef, m as PolicyMode, R as RowShape, n as SchemaInput, T as TableDef, o as TableInput, p as TypedDB, q as TypedTable, r as TypedTx, s as boolean, t as defineSchema, u as enumType, v as integer, w as isPalbaseExtension, x as jsonb, y as makeTypedDB, z as policy, A as text, B as timestamp, D as uuid } from './index-DzRFS3Tl.cjs';
4
+ import { E as EnvTypedDatabase, S as SchemaDef } from './index-mr3Co63T.cjs';
5
+ export { C as ColumnBuilder, a as ColumnDef, b as ColumnMap, c as ColumnType, d as EXTENSION_DEPENDENCIES, e as EnvServiceDatabase, f as EnvTables, g as EnvTypedTable, h as EnvTypedTx, I as InsertShape, O as OnDeleteAction, P as PALBASE_EXTENSIONS, i as PalbaseExtension, j as PolicyBuilder, k as PolicyCommand, l as PolicyDef, m as PolicyMode, R as RowShape, n as SchemaInput, T as TableDef, o as TableInput, p as TypedDB, q as TypedTable, r as TypedTx, s as boolean, t as defineSchema, u as enumType, v as integer, w as isPalbaseExtension, x as jsonb, y as makeTypedDB, z as policy, A as text, B as timestamp, D as uuid } from './index-mr3Co63T.cjs';
6
6
  export { TableTypes, Tables } from './db/env.cjs';
7
7
  import { ZodTypeAny } from 'zod';
8
8
  export { z } from 'zod';
@@ -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). */
@@ -195,18 +692,6 @@ declare const Put: (subpath: string, options?: RouteOptions) => MethodDecorator;
195
692
  declare const Patch: (subpath: string, options?: RouteOptions) => MethodDecorator;
196
693
  /** `@Delete(subpath, options?)` — declare a DELETE route. */
197
694
  declare const Delete: (subpath: string, options?: RouteOptions) => MethodDecorator;
198
- /**
199
- * `@Returns(schema)` — declare the route's success-response zod schema. The
200
- * method's return TYPE drives compile-time checking; `@Returns` supplies the
201
- * matching zod VALUE the OpenAPI generator reads for the 200 response. Optional:
202
- * a `void` method (no response body) omits it.
203
- *
204
- * @example
205
- * \@Get("/{id}")
206
- * \@Returns(TodoSchema)
207
- * getOne(\@Param("id") id: string): TodoSchema { … }
208
- */
209
- declare function Returns(schema: ZodTypeAny): MethodDecorator;
210
695
 
211
696
  /** A legacy parameter decorator. */
212
697
  type ParameterDecorator = (target: object, propertyKey: string | symbol, parameterIndex: number) => void;
@@ -688,4 +1173,4 @@ declare const documents: {
688
1173
  onDocumentDeleted(handler: HookHandler<DocumentDeletedEvent>): ResolvedHook<DocumentDeletedEvent>;
689
1174
  };
690
1175
 
691
- 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, Returns, 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 };