@telorun/templating 0.8.0 → 0.9.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/README.md +2 -2
- package/dist/cel/catalog.d.ts.map +1 -1
- package/dist/cel/catalog.js +78 -0
- package/package.json +2 -2
- package/src/cel/catalog.ts +85 -0
package/README.md
CHANGED
|
@@ -55,8 +55,8 @@ metadata:
|
|
|
55
55
|
A complete feedback collection REST API — no code, pure YAML.
|
|
56
56
|
Persists entries to SQLite and serves them over HTTP.
|
|
57
57
|
imports:
|
|
58
|
-
Http: std/http-server@0.
|
|
59
|
-
Sql: std/sql@0.
|
|
58
|
+
Http: std/http-server@0.11.0
|
|
59
|
+
Sql: std/sql@0.9.0
|
|
60
60
|
targets:
|
|
61
61
|
- !ref Migrations
|
|
62
62
|
- !ref Server
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/cel/catalog.ts"],"names":[],"mappings":"AAEA;;;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;AAED,MAAM,MAAM,mBAAmB,GAC3B,YAAY,GACZ,MAAM,GACN,MAAM,GACN,QAAQ,GACR,MAAM,GACN,YAAY,GACZ,MAAM,GACN,UAAU,GACV,SAAS,GACT,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;CACjE;AAED,wEAAwE;AACxE,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/cel/catalog.ts"],"names":[],"mappings":"AAEA;;;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;AAED,MAAM,MAAM,mBAAmB,GAC3B,YAAY,GACZ,MAAM,GACN,MAAM,GACN,QAAQ,GACR,MAAM,GACN,YAAY,GACZ,MAAM,GACN,UAAU,GACV,SAAS,GACT,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;CACjE;AAED,wEAAwE;AACxE,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;AA8E5D,eAAO,MAAM,aAAa,EAAE,SAAS,cAAc,EAoelD,CAAC;AAEF,oEAAoE;AACpE,wBAAgB,kBAAkB,IAAI,eAAe,EAAE,CAEtD"}
|
package/dist/cel/catalog.js
CHANGED
|
@@ -14,6 +14,9 @@ const minMax = (list, isMin) => {
|
|
|
14
14
|
}
|
|
15
15
|
return best;
|
|
16
16
|
};
|
|
17
|
+
/** Ensure a regex replaces every match: append the global flag unless the
|
|
18
|
+
* caller already passed it. */
|
|
19
|
+
const withGlobal = (flags) => flags && flags.includes("g") ? flags : `${flags ?? ""}g`;
|
|
17
20
|
const sortList = (list) => [...list].sort((a, b) => {
|
|
18
21
|
if (typeof a === "number" || typeof a === "bigint") {
|
|
19
22
|
const d = num(a) - num(b);
|
|
@@ -130,6 +133,24 @@ export const CEL_FUNCTIONS = [
|
|
|
130
133
|
hostBacked: false,
|
|
131
134
|
build: () => (list) => sortList(list),
|
|
132
135
|
},
|
|
136
|
+
{
|
|
137
|
+
name: "range",
|
|
138
|
+
signature: "range(int): list<int>",
|
|
139
|
+
category: "collection",
|
|
140
|
+
summary: "Integers [0, n-1] (empty for n <= 0); materializes indices for an unknown-length list.",
|
|
141
|
+
deterministic: true,
|
|
142
|
+
hostBacked: false,
|
|
143
|
+
build: () => (n) => Array.from({ length: Math.max(0, Math.trunc(num(n))) }, (_unused, i) => BigInt(i)),
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
name: "enumerate",
|
|
147
|
+
signature: "enumerate(list): list",
|
|
148
|
+
category: "collection",
|
|
149
|
+
summary: "Pair each element with its zero-based position as {index, value}.",
|
|
150
|
+
deterministic: true,
|
|
151
|
+
hostBacked: false,
|
|
152
|
+
build: () => (list) => list.map((value, i) => ({ index: BigInt(i), value })),
|
|
153
|
+
},
|
|
133
154
|
// Strings
|
|
134
155
|
{
|
|
135
156
|
name: "lower",
|
|
@@ -176,6 +197,63 @@ export const CEL_FUNCTIONS = [
|
|
|
176
197
|
hostBacked: false,
|
|
177
198
|
build: () => (s, sep) => s.split(sep),
|
|
178
199
|
},
|
|
200
|
+
{
|
|
201
|
+
name: "regexReplace",
|
|
202
|
+
signature: "regexReplace(string, string, string, string?): string",
|
|
203
|
+
category: "string",
|
|
204
|
+
summary: "Replace every regex match with a replacement ($1 backrefs); flags like 'i', 'm', 's'.",
|
|
205
|
+
deterministic: true,
|
|
206
|
+
hostBacked: false,
|
|
207
|
+
build: () => (s, pattern, replacement, flags) => s.replace(new RegExp(pattern, withGlobal(flags)), replacement),
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: "regexExtract",
|
|
211
|
+
signature: "regexExtract(string, string): string",
|
|
212
|
+
category: "string",
|
|
213
|
+
summary: "First whole match of a regex, or '' when there is none.",
|
|
214
|
+
deterministic: true,
|
|
215
|
+
hostBacked: false,
|
|
216
|
+
build: () => (s, pattern) => s.match(new RegExp(pattern))?.[0] ?? "",
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
name: "regexExtractAll",
|
|
220
|
+
signature: "regexExtractAll(string, string): list<string>",
|
|
221
|
+
category: "string",
|
|
222
|
+
summary: "Every whole match of a regex, in order.",
|
|
223
|
+
deterministic: true,
|
|
224
|
+
hostBacked: false,
|
|
225
|
+
build: () => (s, pattern) => [...s.matchAll(new RegExp(pattern, "g"))].map((m) => m[0]),
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: "regexGroups",
|
|
229
|
+
signature: "regexGroups(string, string): list<string>",
|
|
230
|
+
category: "string",
|
|
231
|
+
summary: "Capture groups of the first regex match (empty list when there is no match).",
|
|
232
|
+
deterministic: true,
|
|
233
|
+
hostBacked: false,
|
|
234
|
+
build: () => (s, pattern) => {
|
|
235
|
+
const m = s.match(new RegExp(pattern));
|
|
236
|
+
return m ? m.slice(1).map((g) => g ?? "") : [];
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
name: "trimPrefix",
|
|
241
|
+
signature: "trimPrefix(string, string): string",
|
|
242
|
+
category: "string",
|
|
243
|
+
summary: "Strip a leading prefix if present.",
|
|
244
|
+
deterministic: true,
|
|
245
|
+
hostBacked: false,
|
|
246
|
+
build: () => (s, prefix) => (s.startsWith(prefix) ? s.slice(prefix.length) : s),
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
name: "trimSuffix",
|
|
250
|
+
signature: "trimSuffix(string, string): string",
|
|
251
|
+
category: "string",
|
|
252
|
+
summary: "Strip a trailing suffix if present.",
|
|
253
|
+
deterministic: true,
|
|
254
|
+
hostBacked: false,
|
|
255
|
+
build: () => (s, suffix) => suffix && s.endsWith(suffix) ? s.slice(0, s.length - suffix.length) : s,
|
|
256
|
+
},
|
|
179
257
|
// Math
|
|
180
258
|
{
|
|
181
259
|
name: "abs",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telorun/templating",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Telo Templating - Engine registry and shared CEL core for Telo manifests.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"telo",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@types/uuid": "^10.0.0",
|
|
45
45
|
"typescript": "^5.0.0",
|
|
46
46
|
"vitest": "^2.1.8",
|
|
47
|
-
"@telorun/sdk": "0.
|
|
47
|
+
"@telorun/sdk": "0.26.0"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"@telorun/sdk": "*"
|
package/src/cel/catalog.ts
CHANGED
|
@@ -73,6 +73,11 @@ const minMax = (list: unknown[], isMin: boolean): unknown => {
|
|
|
73
73
|
return best;
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
+
/** Ensure a regex replaces every match: append the global flag unless the
|
|
77
|
+
* caller already passed it. */
|
|
78
|
+
const withGlobal = (flags?: string): string =>
|
|
79
|
+
flags && flags.includes("g") ? flags : `${flags ?? ""}g`;
|
|
80
|
+
|
|
76
81
|
const sortList = (list: unknown[]): unknown[] =>
|
|
77
82
|
[...list].sort((a, b) => {
|
|
78
83
|
if (typeof a === "number" || typeof a === "bigint") {
|
|
@@ -195,6 +200,26 @@ export const CEL_FUNCTIONS: readonly CelFunctionDoc[] = [
|
|
|
195
200
|
hostBacked: false,
|
|
196
201
|
build: () => (list: unknown[]) => sortList(list),
|
|
197
202
|
},
|
|
203
|
+
{
|
|
204
|
+
name: "range",
|
|
205
|
+
signature: "range(int): list<int>",
|
|
206
|
+
category: "collection",
|
|
207
|
+
summary: "Integers [0, n-1] (empty for n <= 0); materializes indices for an unknown-length list.",
|
|
208
|
+
deterministic: true,
|
|
209
|
+
hostBacked: false,
|
|
210
|
+
build: () => (n: unknown) =>
|
|
211
|
+
Array.from({ length: Math.max(0, Math.trunc(num(n))) }, (_unused, i) => BigInt(i)),
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
name: "enumerate",
|
|
215
|
+
signature: "enumerate(list): list",
|
|
216
|
+
category: "collection",
|
|
217
|
+
summary: "Pair each element with its zero-based position as {index, value}.",
|
|
218
|
+
deterministic: true,
|
|
219
|
+
hostBacked: false,
|
|
220
|
+
build: () => (list: unknown[]) =>
|
|
221
|
+
list.map((value, i) => ({ index: BigInt(i), value })),
|
|
222
|
+
},
|
|
198
223
|
// Strings
|
|
199
224
|
{
|
|
200
225
|
name: "lower",
|
|
@@ -241,6 +266,66 @@ export const CEL_FUNCTIONS: readonly CelFunctionDoc[] = [
|
|
|
241
266
|
hostBacked: false,
|
|
242
267
|
build: () => (s: string, sep: string) => s.split(sep),
|
|
243
268
|
},
|
|
269
|
+
{
|
|
270
|
+
name: "regexReplace",
|
|
271
|
+
signature: "regexReplace(string, string, string, string?): string",
|
|
272
|
+
category: "string",
|
|
273
|
+
summary: "Replace every regex match with a replacement ($1 backrefs); flags like 'i', 'm', 's'.",
|
|
274
|
+
deterministic: true,
|
|
275
|
+
hostBacked: false,
|
|
276
|
+
build: () => (s: string, pattern: string, replacement: string, flags?: string) =>
|
|
277
|
+
s.replace(new RegExp(pattern, withGlobal(flags)), replacement),
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
name: "regexExtract",
|
|
281
|
+
signature: "regexExtract(string, string): string",
|
|
282
|
+
category: "string",
|
|
283
|
+
summary: "First whole match of a regex, or '' when there is none.",
|
|
284
|
+
deterministic: true,
|
|
285
|
+
hostBacked: false,
|
|
286
|
+
build: () => (s: string, pattern: string) => s.match(new RegExp(pattern))?.[0] ?? "",
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
name: "regexExtractAll",
|
|
290
|
+
signature: "regexExtractAll(string, string): list<string>",
|
|
291
|
+
category: "string",
|
|
292
|
+
summary: "Every whole match of a regex, in order.",
|
|
293
|
+
deterministic: true,
|
|
294
|
+
hostBacked: false,
|
|
295
|
+
build: () => (s: string, pattern: string) =>
|
|
296
|
+
[...s.matchAll(new RegExp(pattern, "g"))].map((m) => m[0]),
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
name: "regexGroups",
|
|
300
|
+
signature: "regexGroups(string, string): list<string>",
|
|
301
|
+
category: "string",
|
|
302
|
+
summary: "Capture groups of the first regex match (empty list when there is no match).",
|
|
303
|
+
deterministic: true,
|
|
304
|
+
hostBacked: false,
|
|
305
|
+
build: () => (s: string, pattern: string) => {
|
|
306
|
+
const m = s.match(new RegExp(pattern));
|
|
307
|
+
return m ? m.slice(1).map((g) => g ?? "") : [];
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
name: "trimPrefix",
|
|
312
|
+
signature: "trimPrefix(string, string): string",
|
|
313
|
+
category: "string",
|
|
314
|
+
summary: "Strip a leading prefix if present.",
|
|
315
|
+
deterministic: true,
|
|
316
|
+
hostBacked: false,
|
|
317
|
+
build: () => (s: string, prefix: string) => (s.startsWith(prefix) ? s.slice(prefix.length) : s),
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
name: "trimSuffix",
|
|
321
|
+
signature: "trimSuffix(string, string): string",
|
|
322
|
+
category: "string",
|
|
323
|
+
summary: "Strip a trailing suffix if present.",
|
|
324
|
+
deterministic: true,
|
|
325
|
+
hostBacked: false,
|
|
326
|
+
build: () => (s: string, suffix: string) =>
|
|
327
|
+
suffix && s.endsWith(suffix) ? s.slice(0, s.length - suffix.length) : s,
|
|
328
|
+
},
|
|
244
329
|
// Math
|
|
245
330
|
{
|
|
246
331
|
name: "abs",
|