@palbase/backend 14.1.0 → 14.3.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.
@@ -1,4 +1,4 @@
1
- export { C as ColumnBuilder, a as ColumnDef, b as ColumnMap, c as ColumnType, d as EXTENSION_DEPENDENCIES, e as EnvServiceDatabase, E as EnvTypedDatabase, I as InsertShape, O as OnDeleteAction, P as PALBASE_EXTENSIONS, h as PalbaseExtension, i as PolicyBuilder, j as PolicyCommand, k as PolicyDef, l as PolicyMode, R as RawConstraintDef, m as RowShape, S as SchemaDef, n as SchemaInput, T as TableDef, o as TableInput, p as TxPlan, q as TxTables, r as TypedDB, s as TypedTable, t as TypedTx, u as bigint, v as boolean, w as defineSchema, x as enumType, y as integer, z as isPalbaseExtension, A as jsonb, B as makeTypedDB, F as policy, G as raw, H as text, J as timestamp, K as uuid } from '../index-BcA7wqur.cjs';
2
- export { M as Materialized, b1 as Ref, b3 as TxColumnExpr, b4 as TxInsertShape, b6 as TxNow, b7 as TxPlanBody, b8 as TxPlanError, b9 as TxPlanHandle, ba as TxPlanOpResult, bb as TxPlanRejection, bc as TxPlanResponse, bd as TxRefError, be as TxRow, bf as TxRows, bg as TxSelectOptions, bh as TxSetShape, bj as TxTable, bk as TxWhere, bs as dec, bu as inc, bv as now } from '../endpoint-D2yR2RD1.cjs';
1
+ export { C as ColumnBuilder, a as ColumnDef, b as ColumnMap, c as ColumnType, d as EXTENSION_DEPENDENCIES, e as EnvServiceDatabase, E as EnvTypedDatabase, I as InsertShape, O as OnDeleteAction, P as PALBASE_EXTENSIONS, h as PalbaseExtension, i as PolicyBuilder, j as PolicyCommand, k as PolicyDef, l as PolicyMode, R as RawConstraintDef, m as RowShape, S as SchemaDef, n as SchemaInput, T as TableDef, o as TableInput, p as TxPlan, q as TxTables, r as TypedDB, s as TypedTable, t as TypedTx, u as bigint, v as boolean, w as defineSchema, x as enumType, y as integer, z as isPalbaseExtension, A as jsonb, B as makeTypedDB, F as policy, G as raw, H as text, J as timestamp, K as uuid } from '../index-j3ZZS_VS.cjs';
2
+ export { M as Materialized, b1 as Ref, b3 as TxColumnExpr, b4 as TxInsertShape, b6 as TxNow, b7 as TxPlanBody, b8 as TxPlanError, b9 as TxPlanHandle, ba as TxPlanOpResult, bb as TxPlanRejection, bc as TxPlanResponse, bd as TxRefError, be as TxRow, bf as TxRows, bg as TxSelectOptions, bh as TxSetShape, bj as TxTable, bk as TxWhere, bs as dec, bu as inc, bv as now } from '../endpoint-BG-JVUPL.cjs';
3
3
  import './env.cjs';
4
4
  import 'zod';
@@ -1,4 +1,4 @@
1
- export { C as ColumnBuilder, a as ColumnDef, b as ColumnMap, c as ColumnType, d as EXTENSION_DEPENDENCIES, e as EnvServiceDatabase, E as EnvTypedDatabase, I as InsertShape, O as OnDeleteAction, P as PALBASE_EXTENSIONS, h as PalbaseExtension, i as PolicyBuilder, j as PolicyCommand, k as PolicyDef, l as PolicyMode, R as RawConstraintDef, m as RowShape, S as SchemaDef, n as SchemaInput, T as TableDef, o as TableInput, p as TxPlan, q as TxTables, r as TypedDB, s as TypedTable, t as TypedTx, u as bigint, v as boolean, w as defineSchema, x as enumType, y as integer, z as isPalbaseExtension, A as jsonb, B as makeTypedDB, F as policy, G as raw, H as text, J as timestamp, K as uuid } from '../index-CB8TARW4.js';
2
- export { M as Materialized, b1 as Ref, b3 as TxColumnExpr, b4 as TxInsertShape, b6 as TxNow, b7 as TxPlanBody, b8 as TxPlanError, b9 as TxPlanHandle, ba as TxPlanOpResult, bb as TxPlanRejection, bc as TxPlanResponse, bd as TxRefError, be as TxRow, bf as TxRows, bg as TxSelectOptions, bh as TxSetShape, bj as TxTable, bk as TxWhere, bs as dec, bu as inc, bv as now } from '../endpoint-D2yR2RD1.js';
1
+ export { C as ColumnBuilder, a as ColumnDef, b as ColumnMap, c as ColumnType, d as EXTENSION_DEPENDENCIES, e as EnvServiceDatabase, E as EnvTypedDatabase, I as InsertShape, O as OnDeleteAction, P as PALBASE_EXTENSIONS, h as PalbaseExtension, i as PolicyBuilder, j as PolicyCommand, k as PolicyDef, l as PolicyMode, R as RawConstraintDef, m as RowShape, S as SchemaDef, n as SchemaInput, T as TableDef, o as TableInput, p as TxPlan, q as TxTables, r as TypedDB, s as TypedTable, t as TypedTx, u as bigint, v as boolean, w as defineSchema, x as enumType, y as integer, z as isPalbaseExtension, A as jsonb, B as makeTypedDB, F as policy, G as raw, H as text, J as timestamp, K as uuid } from '../index-QQ2byWrv.js';
2
+ export { M as Materialized, b1 as Ref, b3 as TxColumnExpr, b4 as TxInsertShape, b6 as TxNow, b7 as TxPlanBody, b8 as TxPlanError, b9 as TxPlanHandle, ba as TxPlanOpResult, bb as TxPlanRejection, bc as TxPlanResponse, bd as TxRefError, be as TxRow, bf as TxRows, bg as TxSelectOptions, bh as TxSetShape, bj as TxTable, bk as TxWhere, bs as dec, bu as inc, bv as now } from '../endpoint-BG-JVUPL.js';
3
3
  import './env.js';
4
4
  import 'zod';
@@ -777,6 +777,13 @@ interface PalbaseEmailSendParams {
777
777
  * fields when not overriding template output).
778
778
  */
779
779
  templateSlug?: string;
780
+ /**
781
+ * Which locale of `templateSlug` to render — a BCP47 short tag ("tr").
782
+ * Falls back to "en" when the slug has no row for it. Declaring a locale in
783
+ * config/notifications.ts is only half the feature: without this the extra
784
+ * rows exist and are unreachable.
785
+ */
786
+ locale?: string;
780
787
  variables?: Record<string, unknown>;
781
788
  html?: string;
782
789
  text?: string;
@@ -806,6 +813,8 @@ interface PalbaseSmsSendParams {
806
813
  * template with `variables` and uses the result as the SMS body.
807
814
  */
808
815
  templateSlug?: string;
816
+ /** Which locale of `templateSlug` to render — see PalbaseEmailSendParams.locale. */
817
+ locale?: string;
809
818
  variables?: Record<string, unknown>;
810
819
  category?: string;
811
820
  }
@@ -777,6 +777,13 @@ interface PalbaseEmailSendParams {
777
777
  * fields when not overriding template output).
778
778
  */
779
779
  templateSlug?: string;
780
+ /**
781
+ * Which locale of `templateSlug` to render — a BCP47 short tag ("tr").
782
+ * Falls back to "en" when the slug has no row for it. Declaring a locale in
783
+ * config/notifications.ts is only half the feature: without this the extra
784
+ * rows exist and are unreachable.
785
+ */
786
+ locale?: string;
780
787
  variables?: Record<string, unknown>;
781
788
  html?: string;
782
789
  text?: string;
@@ -806,6 +813,8 @@ interface PalbaseSmsSendParams {
806
813
  * template with `variables` and uses the result as the SMS body.
807
814
  */
808
815
  templateSlug?: string;
816
+ /** Which locale of `templateSlug` to render — see PalbaseEmailSendParams.locale. */
817
+ locale?: string;
809
818
  variables?: Record<string, unknown>;
810
819
  category?: string;
811
820
  }
@@ -1,5 +1,5 @@
1
1
  import { Tables, TableTypes } from './db/env.js';
2
- import { D as DBClient, b9 as TxPlanHandle, bj as TxTable, M as Materialized } from './endpoint-D2yR2RD1.js';
2
+ import { D as DBClient, b9 as TxPlanHandle, bj as TxTable, M as Materialized } from './endpoint-BG-JVUPL.js';
3
3
 
4
4
  /** On delete action for foreign key references. */
5
5
  type OnDeleteAction = 'cascade' | 'set null' | 'restrict' | 'no action';
@@ -1,5 +1,5 @@
1
1
  import { Tables, TableTypes } from './db/env.cjs';
2
- import { D as DBClient, b9 as TxPlanHandle, bj as TxTable, M as Materialized } from './endpoint-D2yR2RD1.cjs';
2
+ import { D as DBClient, b9 as TxPlanHandle, bj as TxTable, M as Materialized } from './endpoint-BG-JVUPL.cjs';
3
3
 
4
4
  /** On delete action for foreign key references. */
5
5
  type OnDeleteAction = 'cascade' | 'set null' | 'restrict' | 'no action';
package/dist/index.cjs CHANGED
@@ -26,6 +26,7 @@ __export(src_exports, {
26
26
  Client: () => Client,
27
27
  Conflict: () => Conflict,
28
28
  Controller: () => Controller,
29
+ DEFAULT_TEMPLATE_LOCALE: () => DEFAULT_TEMPLATE_LOCALE,
29
30
  Database: () => Database,
30
31
  Delete: () => Delete,
31
32
  Documents: () => Documents,
@@ -101,6 +102,7 @@ __export(src_exports, {
101
102
  documents: () => documents,
102
103
  entitlementFor: () => entitlementFor,
103
104
  enumType: () => enumType,
105
+ extractVariables: () => extractVariables,
104
106
  flag: () => flag,
105
107
  getErrorRegistry: () => getErrorRegistry,
106
108
  getJobConfig: () => getJobConfig,
@@ -1525,6 +1527,82 @@ var PROVIDER_CATALOG = {
1525
1527
  secrets: ["authToken"]
1526
1528
  }
1527
1529
  };
1530
+ var DEFAULT_TEMPLATE_LOCALE = "en";
1531
+ function extractVariables(...sources) {
1532
+ const found = /* @__PURE__ */ new Set();
1533
+ for (const src of sources) {
1534
+ if (!src) continue;
1535
+ for (const match of src.matchAll(/\{\{\{?\s*([^{}]+?)\s*\}?\}\}/g)) {
1536
+ const token = (match[1] ?? "").trim();
1537
+ if (token === "" || "#/^!>&".includes(token.charAt(0)) || token === "else") continue;
1538
+ if (/\s/.test(token)) continue;
1539
+ const root = token.split(".")[0] ?? "";
1540
+ if (root === "" || root === "this" || root.startsWith("@")) continue;
1541
+ found.add(root);
1542
+ }
1543
+ }
1544
+ return [...found].sort();
1545
+ }
1546
+ function buildEmailTemplate(slug, opts) {
1547
+ const row = (locale, c) => {
1548
+ if (!c.subject) throw new Error(`notifications: email template "${slug}" (${locale}) needs a subject`);
1549
+ if (!c.html) throw new Error(`notifications: email template "${slug}" (${locale}) needs an html body`);
1550
+ const def = {
1551
+ slug,
1552
+ locale,
1553
+ subject: c.subject,
1554
+ html_body: c.html,
1555
+ variables: c.variables ? [...c.variables] : extractVariables(c.subject, c.html, c.text)
1556
+ };
1557
+ if (c.text !== void 0) def.text_body = c.text;
1558
+ return def;
1559
+ };
1560
+ const rows = [row(opts.locale ?? DEFAULT_TEMPLATE_LOCALE, opts)];
1561
+ for (const [locale, content] of Object.entries(opts.locales ?? {})) {
1562
+ rows.push(row(locale, content));
1563
+ }
1564
+ return rows;
1565
+ }
1566
+ function buildSmsTemplate(slug, opts) {
1567
+ const row = (locale, c) => {
1568
+ if (!c.body) throw new Error(`notifications: sms template "${slug}" (${locale}) needs a body`);
1569
+ return {
1570
+ slug,
1571
+ locale,
1572
+ body: c.body,
1573
+ variables: c.variables ? [...c.variables] : extractVariables(c.body)
1574
+ };
1575
+ };
1576
+ const rows = [row(opts.locale ?? DEFAULT_TEMPLATE_LOCALE, opts)];
1577
+ for (const [locale, content] of Object.entries(opts.locales ?? {})) {
1578
+ rows.push(row(locale, content));
1579
+ }
1580
+ return rows;
1581
+ }
1582
+ function buildTemplates(input) {
1583
+ const out = { email: [], sms: [] };
1584
+ const seen = /* @__PURE__ */ new Set();
1585
+ const claim = (channel, slug, locale) => {
1586
+ const key = `${channel}/${slug}/${locale}`;
1587
+ if (seen.has(key)) {
1588
+ throw new Error(`notifications: ${channel} template "${slug}" declares locale "${locale}" twice`);
1589
+ }
1590
+ seen.add(key);
1591
+ };
1592
+ for (const [slug, opts] of Object.entries(input.email ?? {})) {
1593
+ for (const row of buildEmailTemplate(slug, opts)) {
1594
+ claim("email", row.slug, row.locale);
1595
+ out.email.push(row);
1596
+ }
1597
+ }
1598
+ for (const [slug, opts] of Object.entries(input.sms ?? {})) {
1599
+ for (const row of buildSmsTemplate(slug, opts)) {
1600
+ claim("sms", row.slug, row.locale);
1601
+ out.sms.push(row);
1602
+ }
1603
+ }
1604
+ return out;
1605
+ }
1528
1606
  function buildProvider(name, opts) {
1529
1607
  const entry = PROVIDER_CATALOG[name];
1530
1608
  const src = { ...opts };
@@ -1566,7 +1644,8 @@ function defineNotifications(input) {
1566
1644
  __config: NOTIFICATIONS_CONFIG_KIND,
1567
1645
  push: {},
1568
1646
  email: {},
1569
- sms: {}
1647
+ sms: {},
1648
+ templates: buildTemplates(input.templates ?? {})
1570
1649
  };
1571
1650
  const push = input.push ?? {};
1572
1651
  if (push.apns !== void 0) config.push.apns = buildProvider("apns", push.apns);
@@ -1756,6 +1835,33 @@ function flag(opts) {
1756
1835
  );
1757
1836
  }
1758
1837
  }
1838
+ let conditions = null;
1839
+ if (opts.conditions !== void 0) {
1840
+ if (!Array.isArray(opts.conditions)) {
1841
+ throw new Error("flag conditions must be an array of { when, value }");
1842
+ }
1843
+ const compiled = [];
1844
+ for (const [i, branch] of opts.conditions.entries()) {
1845
+ if (branch === null || typeof branch !== "object") {
1846
+ throw new Error(`flag condition ${i} must be an object { when, value }`);
1847
+ }
1848
+ if (typeof branch.when !== "string" || branch.when.trim().length === 0) {
1849
+ throw new Error(`flag condition ${i} needs a non-empty "when" expression`);
1850
+ }
1851
+ if (!valueMatchesType(type, branch.value)) {
1852
+ throw new Error(
1853
+ `flag condition ${i} value ${JSON.stringify(branch.value)} does not match type "${type}"`
1854
+ );
1855
+ }
1856
+ if (variants !== null && !variants.includes(branch.value)) {
1857
+ throw new Error(
1858
+ `flag condition ${i} value ${JSON.stringify(branch.value)} is not one of its variants [${variants.map((v) => JSON.stringify(v)).join(", ")}]`
1859
+ );
1860
+ }
1861
+ compiled.push({ when: branch.when.trim(), value: branch.value });
1862
+ }
1863
+ conditions = compiled.length > 0 ? compiled : null;
1864
+ }
1759
1865
  let description = null;
1760
1866
  if (opts.description !== void 0) {
1761
1867
  if (typeof opts.description !== "string") {
@@ -1768,6 +1874,7 @@ function flag(opts) {
1768
1874
  type,
1769
1875
  default: opts.default,
1770
1876
  variants,
1877
+ conditions,
1771
1878
  description
1772
1879
  };
1773
1880
  }
@@ -2468,6 +2575,7 @@ var import_zod2 = require("zod");
2468
2575
  Client,
2469
2576
  Conflict,
2470
2577
  Controller,
2578
+ DEFAULT_TEMPLATE_LOCALE,
2471
2579
  Database,
2472
2580
  Delete,
2473
2581
  Documents,
@@ -2543,6 +2651,7 @@ var import_zod2 = require("zod");
2543
2651
  documents,
2544
2652
  entitlementFor,
2545
2653
  enumType,
2654
+ extractVariables,
2546
2655
  flag,
2547
2656
  getErrorRegistry,
2548
2657
  getJobConfig,