@telorun/templating 0.19.0 → 0.20.1

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 +1 @@
1
- {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/cel/catalog.ts"],"names":[],"mappings":"AAIA;;;0DAG0D;AAC1D,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9B,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5B,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9B,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IAClE,YAAY,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,YAAY,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC;CAClC;AA2CD,MAAM,MAAM,mBAAmB,GAC3B,YAAY,GACZ,MAAM,GACN,MAAM,GACN,QAAQ,GACR,MAAM,GACN,YAAY,GACZ,MAAM,GACN,UAAU,GACV,SAAS,GACT,YAAY,GACZ,MAAM,CAAC;AAEX;;;qBAGqB;AACrB,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;0EACsE;IACtE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;yDAIqD;IACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;wBACoB;IACpB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC;2EACuE;IACvE,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC;IAChE;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,KAAK,MAAM,GAAG,SAAS,CAAC;CAC3E;AAYD,wEAAwE;AACxE,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;AA4X5D,eAAO,MAAM,aAAa,EAAE,SAAS,cAAc,EA8wBlD,CAAC;AAEF,oEAAoE;AACpE,wBAAgB,kBAAkB,IAAI,eAAe,EAAE,CAEtD"}
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/cel/catalog.ts"],"names":[],"mappings":"AAIA;;;0DAG0D;AAC1D,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9B,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5B,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9B,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IAClE,YAAY,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,YAAY,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC;CAClC;AA2CD,MAAM,MAAM,mBAAmB,GAC3B,YAAY,GACZ,MAAM,GACN,MAAM,GACN,QAAQ,GACR,MAAM,GACN,YAAY,GACZ,MAAM,GACN,UAAU,GACV,SAAS,GACT,YAAY,GACZ,MAAM,CAAC;AAEX;;;qBAGqB;AACrB,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;0EACsE;IACtE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;yDAIqD;IACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;wBACoB;IACpB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC;2EACuE;IACvE,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC;IAChE;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,KAAK,MAAM,GAAG,SAAS,CAAC;CAC3E;AAYD,wEAAwE;AACxE,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;AA8Z5D,eAAO,MAAM,aAAa,EAAE,SAAS,cAAc,EAyxBlD,CAAC;AAEF,oEAAoE;AACpE,wBAAgB,kBAAkB,IAAI,eAAe,EAAE,CAEtD"}
@@ -357,6 +357,40 @@ const compactValue = (v) => {
357
357
  }
358
358
  throw new Error(`compact: expected a map or a list, got ${JSON.stringify(v)}`);
359
359
  };
360
+ /** A CEL map as entries. Read the way `compact` reads one — a map arrives as a
361
+ * plain object or a `Map` depending on how it was produced — and refusing
362
+ * anything that is not one, since rebuilding an arbitrary object from its
363
+ * entries is how a byte buffer becomes `{"0":137,…}` silently. A LIST is named
364
+ * rather than coerced: CEL's `+` already concatenates lists, so a list here is
365
+ * a mistake with a spelling that works, not a case to support. */
366
+ const mapEntries = (fn, v) => {
367
+ if (v instanceof Map)
368
+ return [...v.entries()];
369
+ if (Array.isArray(v))
370
+ throw new Error(`${fn}: expected a map, got a list — use '+' to join lists`);
371
+ if (v !== null && typeof v === "object") {
372
+ const proto = Object.getPrototypeOf(v);
373
+ if (proto !== Object.prototype && proto !== null) {
374
+ throw new Error(`${fn}: expected a map, got ${v.constructor?.name ?? "an object"}`);
375
+ }
376
+ return Object.entries(v);
377
+ }
378
+ throw new Error(`${fn}: expected a map, got ${JSON.stringify(v)}`);
379
+ };
380
+ /** Right-hand precedence, so `merge(defaults, overrides)` reads as it looks.
381
+ *
382
+ * The map case is the one with no spelling at all — `+` joins lists and
383
+ * strings and refuses maps — so a child kind inheriting a map-valued field
384
+ * could only REPLACE it. That turns a default the parent set for a reason into
385
+ * something every consumer must restate, and a consumer who restates it
386
+ * incompletely gets a system that works until the omitted entry matters.
387
+ *
388
+ * Follows the LEFT argument's shape: this extends that map, so what comes back
389
+ * is what was extended. */
390
+ const mergeMaps = (a, b) => {
391
+ const entries = [...mapEntries("merge", a), ...mapEntries("merge", b)];
392
+ return a instanceof Map ? new Map(entries) : Object.fromEntries(entries);
393
+ };
360
394
  const BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
361
395
  /** Base64 → bytes, written out rather than delegated: `Buffer` is not browser-
362
396
  * safe and `atob` round-trips through a string, which is the corruption this
@@ -1097,6 +1131,16 @@ export const CEL_FUNCTIONS = [
1097
1131
  hostBacked: false,
1098
1132
  build: () => (v) => compactValue(v),
1099
1133
  },
1134
+ {
1135
+ name: "merge",
1136
+ signature: "merge(map, map): map",
1137
+ register: ["merge(map, map): map"],
1138
+ category: "collection",
1139
+ summary: "Combine two maps, with the right-hand map winning on a shared key. Use it to add to a map rather than replace it — `merge(defaults, overrides)`.",
1140
+ deterministic: true,
1141
+ hostBacked: false,
1142
+ build: () => (a, b) => mergeMaps(a, b),
1143
+ },
1100
1144
  // UUID
1101
1145
  {
1102
1146
  name: "uuidv1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telorun/templating",
3
- "version": "0.19.0",
3
+ "version": "0.20.1",
4
4
  "description": "Telo Templating - Engine registry and shared CEL core for Telo manifests.",
5
5
  "keywords": [
6
6
  "telo",
@@ -46,7 +46,7 @@
46
46
  "@types/node": "^20.0.0",
47
47
  "typescript": "^5.0.0",
48
48
  "vitest": "^2.1.8",
49
- "@telorun/sdk": "0.87.0"
49
+ "@telorun/sdk": "0.90.0"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "@telorun/sdk": "*"
@@ -460,6 +460,40 @@ const compactValue = (v: unknown): unknown => {
460
460
  throw new Error(`compact: expected a map or a list, got ${JSON.stringify(v)}`);
461
461
  };
462
462
 
463
+ /** A CEL map as entries. Read the way `compact` reads one — a map arrives as a
464
+ * plain object or a `Map` depending on how it was produced — and refusing
465
+ * anything that is not one, since rebuilding an arbitrary object from its
466
+ * entries is how a byte buffer becomes `{"0":137,…}` silently. A LIST is named
467
+ * rather than coerced: CEL's `+` already concatenates lists, so a list here is
468
+ * a mistake with a spelling that works, not a case to support. */
469
+ const mapEntries = (fn: string, v: unknown): [string, unknown][] => {
470
+ if (v instanceof Map) return [...v.entries()] as [string, unknown][];
471
+ if (Array.isArray(v)) throw new Error(`${fn}: expected a map, got a list — use '+' to join lists`);
472
+ if (v !== null && typeof v === "object") {
473
+ const proto = Object.getPrototypeOf(v);
474
+ if (proto !== Object.prototype && proto !== null) {
475
+ throw new Error(`${fn}: expected a map, got ${v.constructor?.name ?? "an object"}`);
476
+ }
477
+ return Object.entries(v as Record<string, unknown>);
478
+ }
479
+ throw new Error(`${fn}: expected a map, got ${JSON.stringify(v)}`);
480
+ };
481
+
482
+ /** Right-hand precedence, so `merge(defaults, overrides)` reads as it looks.
483
+ *
484
+ * The map case is the one with no spelling at all — `+` joins lists and
485
+ * strings and refuses maps — so a child kind inheriting a map-valued field
486
+ * could only REPLACE it. That turns a default the parent set for a reason into
487
+ * something every consumer must restate, and a consumer who restates it
488
+ * incompletely gets a system that works until the omitted entry matters.
489
+ *
490
+ * Follows the LEFT argument's shape: this extends that map, so what comes back
491
+ * is what was extended. */
492
+ const mergeMaps = (a: unknown, b: unknown): unknown => {
493
+ const entries = [...mapEntries("merge", a), ...mapEntries("merge", b)];
494
+ return a instanceof Map ? new Map(entries) : Object.fromEntries(entries);
495
+ };
496
+
463
497
  const BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
464
498
 
465
499
  /** Base64 → bytes, written out rather than delegated: `Buffer` is not browser-
@@ -1216,6 +1250,17 @@ export const CEL_FUNCTIONS: readonly CelFunctionDoc[] = [
1216
1250
  hostBacked: false,
1217
1251
  build: () => (v: unknown) => compactValue(v),
1218
1252
  },
1253
+ {
1254
+ name: "merge",
1255
+ signature: "merge(map, map): map",
1256
+ register: ["merge(map, map): map"],
1257
+ category: "collection",
1258
+ summary:
1259
+ "Combine two maps, with the right-hand map winning on a shared key. Use it to add to a map rather than replace it — `merge(defaults, overrides)`.",
1260
+ deterministic: true,
1261
+ hostBacked: false,
1262
+ build: () => (a: unknown, b: unknown) => mergeMaps(a, b),
1263
+ },
1219
1264
  // UUID
1220
1265
  {
1221
1266
  name: "uuidv1",