@telorun/templating 0.16.0 → 0.17.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/engine.d.ts +12 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engines/cel.d.ts.map +1 -1
- package/dist/engines/cel.js +21 -0
- package/dist/engines/literal.d.ts.map +1 -1
- package/dist/engines/literal.js +14 -0
- package/package.json +2 -2
- package/src/engine.ts +12 -0
- package/src/engines/cel.ts +21 -0
- package/src/engines/literal.ts +15 -0
package/dist/engine.d.ts
CHANGED
|
@@ -19,6 +19,18 @@ export interface CompileEnv {
|
|
|
19
19
|
export interface AnalyzeEnv {
|
|
20
20
|
readonly celEnv: Environment;
|
|
21
21
|
readonly contextSchema: Record<string, unknown> | null;
|
|
22
|
+
/**
|
|
23
|
+
* The caller vouches that `celEnv` declares EVERY name legal at this site, so
|
|
24
|
+
* a root identifier it does not know is undeclared rather than merely
|
|
25
|
+
* unmodelled.
|
|
26
|
+
*
|
|
27
|
+
* Opt-in because the environment is only that complete when someone built it
|
|
28
|
+
* for a specific site: the base environment declares CEL's own type names and
|
|
29
|
+
* nothing else, so checking roots against it would report `variables` itself
|
|
30
|
+
* as unknown. Absent means the check is skipped, which is what every caller
|
|
31
|
+
* did before it existed.
|
|
32
|
+
*/
|
|
33
|
+
readonly rootsDeclared?: boolean;
|
|
22
34
|
}
|
|
23
35
|
/** A mechanically applicable repair for a diagnostic. `replacement` is the
|
|
24
36
|
* **whole analyzed source**, corrected — never a fragment — so a consumer can
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD;;wEAEwE;AACxE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC9B;AAED;;;;;;;;;eASe;AACf,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD;;wEAEwE;AACxE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC9B;AAED;;;;;;;;;eASe;AACf,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACvD;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;;;;;;;;;;;;0EAa0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;oDAEoD;AACpD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC;CAC9B;AAED;;;;yBAIyB;AACzB,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAC;IACrC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;oDAEgD;IAChD,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;;iFAGiF;AACjF,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAClD,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;CACrC;AAED;;;;;;;;;;;;;;;;4CAgB4C;AAC5C,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;wBAEwB;AACxB,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;;;2EAKuE;IACvE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAE3B;;;yDAGqD;IACrD,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,aAAa,GAAG,OAAO,CAAC;IAElE;;iEAE6D;IAC7D,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,aAAa,CAAC;IAExD;;;;;;;;;;;;uBAYmB;IACnB,UAAU,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,eAAe,EAAE,CAAC;IAExD;;;;;;;;;;;;;;;;;2CAiBuC;IACvC,YAAY,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC1C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cel.d.ts","sourceRoot":"","sources":["../../src/engines/cel.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAoB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAElG;;;;;;;;;;2BAU2B;AAC3B,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"cel.d.ts","sourceRoot":"","sources":["../../src/engines/cel.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAoB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAElG;;;;;;;;;;2BAU2B;AAC3B,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,aAAa,CAqGnF;AAYD;yCACyC;AACzC,eAAO,MAAM,SAAS,EAAE,gBAWvB,CAAC"}
|
package/dist/engines/cel.js
CHANGED
|
@@ -69,6 +69,27 @@ export function analyzeCelExpression(source, env) {
|
|
|
69
69
|
});
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
+
// An undeclared ROOT identifier. cel-js types an unknown name as `dyn` and
|
|
73
|
+
// accepts it, so `!cel "fff"` type-checked, reached the runtime and resolved
|
|
74
|
+
// to nothing — the one CEL mistake with no static report at all. Member
|
|
75
|
+
// access on a KNOWN root was already covered ("No such key"), which is why a
|
|
76
|
+
// typo one level in was caught and a typo at the root was not.
|
|
77
|
+
//
|
|
78
|
+
// Comprehension variables are not roots: `extractAccessChains` drops the
|
|
79
|
+
// names a `.all(x, …)` binds, so the check never sees them.
|
|
80
|
+
if (env.rootsDeclared) {
|
|
81
|
+
const reported = new Set();
|
|
82
|
+
for (const chain of extractAccessChains(parsed.ast)) {
|
|
83
|
+
const root = chain[0];
|
|
84
|
+
if (!root || reported.has(root) || env.celEnv.hasVariable(root))
|
|
85
|
+
continue;
|
|
86
|
+
reported.add(root);
|
|
87
|
+
out.push({
|
|
88
|
+
code: "CEL_UNKNOWN_IDENTIFIER",
|
|
89
|
+
message: `unknown identifier '${root}' — nothing by that name is in scope here.`,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
72
93
|
if (env.contextSchema) {
|
|
73
94
|
const contextSchema = env.contextSchema;
|
|
74
95
|
for (const chain of extractAccessChains(parsed.ast)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"literal.d.ts","sourceRoot":"","sources":["../../src/engines/literal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD;;+CAE+C;AAC/C,eAAO,MAAM,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"literal.d.ts","sourceRoot":"","sources":["../../src/engines/literal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD;;+CAE+C;AAC/C,eAAO,MAAM,aAAa,EAAE,gBAyB3B,CAAC"}
|
package/dist/engines/literal.js
CHANGED
|
@@ -6,6 +6,20 @@ export const literalEngine = {
|
|
|
6
6
|
compile(source) {
|
|
7
7
|
return source;
|
|
8
8
|
},
|
|
9
|
+
/**
|
|
10
|
+
* Opaque text is TEXT — the type is a constant of the tag, exactly as an
|
|
11
|
+
* embed's is, not a function of the slot.
|
|
12
|
+
*
|
|
13
|
+
* Declaring nothing put `!literal` in the other category, the one `!cel` and
|
|
14
|
+
* `!ref` belong to, and everything downstream then treated it as producing
|
|
15
|
+
* whatever the slot asked for. So the editor offered it at a boolean
|
|
16
|
+
* predicate — where opaque text cannot satisfy the slot and `Run.Choice` has
|
|
17
|
+
* a runtime error saying so — and the analyzer type-checked one against a
|
|
18
|
+
* slot-shaped placeholder instead of the string it will actually be.
|
|
19
|
+
*/
|
|
20
|
+
producedType() {
|
|
21
|
+
return { type: "string" };
|
|
22
|
+
},
|
|
9
23
|
analyze() {
|
|
10
24
|
return { diagnostics: [], calls: [] };
|
|
11
25
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telorun/templating",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.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/node": "^20.0.0",
|
|
45
45
|
"typescript": "^5.0.0",
|
|
46
46
|
"vitest": "^2.1.8",
|
|
47
|
-
"@telorun/sdk": "0.
|
|
47
|
+
"@telorun/sdk": "0.82.1"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"@telorun/sdk": "*"
|
package/src/engine.ts
CHANGED
|
@@ -21,6 +21,18 @@ export interface CompileEnv {
|
|
|
21
21
|
export interface AnalyzeEnv {
|
|
22
22
|
readonly celEnv: Environment;
|
|
23
23
|
readonly contextSchema: Record<string, unknown> | null;
|
|
24
|
+
/**
|
|
25
|
+
* The caller vouches that `celEnv` declares EVERY name legal at this site, so
|
|
26
|
+
* a root identifier it does not know is undeclared rather than merely
|
|
27
|
+
* unmodelled.
|
|
28
|
+
*
|
|
29
|
+
* Opt-in because the environment is only that complete when someone built it
|
|
30
|
+
* for a specific site: the base environment declares CEL's own type names and
|
|
31
|
+
* nothing else, so checking roots against it would report `variables` itself
|
|
32
|
+
* as unknown. Absent means the check is skipped, which is what every caller
|
|
33
|
+
* did before it existed.
|
|
34
|
+
*/
|
|
35
|
+
readonly rootsDeclared?: boolean;
|
|
24
36
|
}
|
|
25
37
|
|
|
26
38
|
/** A mechanically applicable repair for a diagnostic. `replacement` is the
|
package/src/engines/cel.ts
CHANGED
|
@@ -79,6 +79,27 @@ export function analyzeCelExpression(source: string, env: AnalyzeEnv): AnalyzeRe
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
// An undeclared ROOT identifier. cel-js types an unknown name as `dyn` and
|
|
83
|
+
// accepts it, so `!cel "fff"` type-checked, reached the runtime and resolved
|
|
84
|
+
// to nothing — the one CEL mistake with no static report at all. Member
|
|
85
|
+
// access on a KNOWN root was already covered ("No such key"), which is why a
|
|
86
|
+
// typo one level in was caught and a typo at the root was not.
|
|
87
|
+
//
|
|
88
|
+
// Comprehension variables are not roots: `extractAccessChains` drops the
|
|
89
|
+
// names a `.all(x, …)` binds, so the check never sees them.
|
|
90
|
+
if (env.rootsDeclared) {
|
|
91
|
+
const reported = new Set<string>();
|
|
92
|
+
for (const chain of extractAccessChains(parsed.ast)) {
|
|
93
|
+
const root = chain[0];
|
|
94
|
+
if (!root || reported.has(root) || env.celEnv.hasVariable(root)) continue;
|
|
95
|
+
reported.add(root);
|
|
96
|
+
out.push({
|
|
97
|
+
code: "CEL_UNKNOWN_IDENTIFIER",
|
|
98
|
+
message: `unknown identifier '${root}' — nothing by that name is in scope here.`,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
82
103
|
if (env.contextSchema) {
|
|
83
104
|
const contextSchema = env.contextSchema as Record<string, any>;
|
|
84
105
|
for (const chain of extractAccessChains(parsed.ast)) {
|
package/src/engines/literal.ts
CHANGED
|
@@ -10,6 +10,21 @@ export const literalEngine: TemplatingEngine = {
|
|
|
10
10
|
return source;
|
|
11
11
|
},
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Opaque text is TEXT — the type is a constant of the tag, exactly as an
|
|
15
|
+
* embed's is, not a function of the slot.
|
|
16
|
+
*
|
|
17
|
+
* Declaring nothing put `!literal` in the other category, the one `!cel` and
|
|
18
|
+
* `!ref` belong to, and everything downstream then treated it as producing
|
|
19
|
+
* whatever the slot asked for. So the editor offered it at a boolean
|
|
20
|
+
* predicate — where opaque text cannot satisfy the slot and `Run.Choice` has
|
|
21
|
+
* a runtime error saying so — and the analyzer type-checked one against a
|
|
22
|
+
* slot-shaped placeholder instead of the string it will actually be.
|
|
23
|
+
*/
|
|
24
|
+
producedType() {
|
|
25
|
+
return { type: "string" };
|
|
26
|
+
},
|
|
27
|
+
|
|
13
28
|
analyze() {
|
|
14
29
|
return { diagnostics: [], calls: [] };
|
|
15
30
|
},
|