@metaobjectsdev/render 1.0.8 → 1.0.9-rc.2
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 +4 -0
- package/dist/filesystem-provider.d.ts +10 -0
- package/dist/filesystem-provider.d.ts.map +1 -0
- package/dist/filesystem-provider.js +42 -0
- package/dist/filesystem-provider.js.map +1 -0
- package/dist/prompt/output-format-renderer.d.ts.map +1 -1
- package/dist/prompt/output-format-renderer.js +14 -3
- package/dist/prompt/output-format-renderer.js.map +1 -1
- package/dist/providers.d.ts +3 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/providers.js +7 -0
- package/dist/providers.js.map +1 -0
- package/package.json +6 -1
- package/src/filesystem-provider.ts +44 -0
- package/src/prompt/output-format-renderer.ts +13 -2
- package/src/providers.ts +6 -0
package/README.md
CHANGED
|
@@ -14,6 +14,10 @@ npm install @metaobjectsdev/render
|
|
|
14
14
|
|
|
15
15
|
- **`render()`** — render a MetaObjects `template.output` / `template.prompt` against a typed payload. Deterministic and cache-stable (no whitespace drift that would silently break exact-prefix prompt-cache hits), so output is snapshot-testable.
|
|
16
16
|
- **Provider-resolved partials + format-driven escaping** (text / html / xml / csv / json / markdown).
|
|
17
|
+
- **Providers** — `InMemoryProvider` (root entry, browser-safe) and `FilesystemProvider`
|
|
18
|
+
(Node-only, on the `@metaobjectsdev/render/providers` subpath so the root entry never
|
|
19
|
+
pulls in `node:fs`). `new FilesystemProvider("./prompts").resolve("lobby/welcome")` reads
|
|
20
|
+
`./prompts/lobby/welcome.mustache`, exactly as the C#, Java and Python ports do.
|
|
17
21
|
- **`verify()`** — a build-time drift check that every `{{field}}` referenced by a template resolves to a field on its payload value-object; a renamed field fails the build instead of silently degrading a prompt.
|
|
18
22
|
|
|
19
23
|
This engine backs the prompt-construction pillar — the generated `render<Name>()` helpers emitted by `@metaobjectsdev/codegen-ts` wrap it. See the **metaobjects-prompts** skill and the repo `docs/` for authoring `template.*` and payload VOs.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Provider } from "./provider.js";
|
|
2
|
+
/** The default template file extension, shared with every other port. */
|
|
3
|
+
export declare const DEFAULT_TEMPLATE_EXTENSION = ".mustache";
|
|
4
|
+
export declare class FilesystemProvider implements Provider {
|
|
5
|
+
private readonly extension;
|
|
6
|
+
private readonly root;
|
|
7
|
+
constructor(root: string, extension?: string);
|
|
8
|
+
resolve(ref: string): string | undefined;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=filesystem-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filesystem-provider.d.ts","sourceRoot":"","sources":["../src/filesystem-provider.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,yEAAyE;AACzE,eAAO,MAAM,0BAA0B,cAAc,CAAC;AAKtD,qBAAa,kBAAmB,YAAW,QAAQ;IAGvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAFpD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAElB,IAAI,EAAE,MAAM,EAAmB,SAAS,GAAE,MAAmC;IAIzF,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;CAezC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Filesystem-backed provider: resolves a `group/source` reference to
|
|
2
|
+
// <root>/<group>/<source>.mustache. NODE-ONLY — it is reachable solely through
|
|
3
|
+
// the `@metaobjectsdev/render/providers` subpath so the package's root entry
|
|
4
|
+
// stays importable in a browser bundle.
|
|
5
|
+
//
|
|
6
|
+
// Mirrors the C# MetaObjects.Render.FilesystemProvider, the Java
|
|
7
|
+
// com.metaobjects.render.FilesystemProvider and the Python
|
|
8
|
+
// metaobjects.render.FilesystemProvider: read the file when present, return
|
|
9
|
+
// undefined when absent / unreadable / not a regular file, and refuse a ref that
|
|
10
|
+
// escapes the root (undefined, never a throw).
|
|
11
|
+
import { readFileSync, statSync } from "node:fs";
|
|
12
|
+
import { resolve, sep } from "node:path";
|
|
13
|
+
/** The default template file extension, shared with every other port. */
|
|
14
|
+
export const DEFAULT_TEMPLATE_EXTENSION = ".mustache";
|
|
15
|
+
const REF_SEPARATOR = "/";
|
|
16
|
+
const PARENT_SEGMENT = "..";
|
|
17
|
+
export class FilesystemProvider {
|
|
18
|
+
extension;
|
|
19
|
+
root;
|
|
20
|
+
constructor(root, extension = DEFAULT_TEMPLATE_EXTENSION) {
|
|
21
|
+
this.extension = extension;
|
|
22
|
+
this.root = resolve(root);
|
|
23
|
+
}
|
|
24
|
+
resolve(ref) {
|
|
25
|
+
const segments = ref.split(REF_SEPARATOR).filter((s) => s.length > 0);
|
|
26
|
+
if (segments.length === 0 || segments.includes(PARENT_SEGMENT))
|
|
27
|
+
return undefined;
|
|
28
|
+
const candidate = resolve(this.root, ...segments) + this.extension;
|
|
29
|
+
// Path-traversal guard (belt-and-suspenders after the `..` check).
|
|
30
|
+
if (!candidate.startsWith(this.root + sep))
|
|
31
|
+
return undefined;
|
|
32
|
+
try {
|
|
33
|
+
if (!statSync(candidate).isFile())
|
|
34
|
+
return undefined;
|
|
35
|
+
return readFileSync(candidate, "utf8");
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=filesystem-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filesystem-provider.js","sourceRoot":"","sources":["../src/filesystem-provider.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,+EAA+E;AAC/E,6EAA6E;AAC7E,wCAAwC;AACxC,EAAE;AACF,iEAAiE;AACjE,2DAA2D;AAC3D,4EAA4E;AAC5E,iFAAiF;AACjF,+CAA+C;AAE/C,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAGzC,yEAAyE;AACzE,MAAM,CAAC,MAAM,0BAA0B,GAAG,WAAW,CAAC;AAEtD,MAAM,aAAa,GAAG,GAAG,CAAC;AAC1B,MAAM,cAAc,GAAG,IAAI,CAAC;AAE5B,MAAM,OAAO,kBAAkB;IAGc;IAF1B,IAAI,CAAS;IAE9B,YAAY,IAAY,EAAmB,YAAoB,0BAA0B;QAA9C,cAAS,GAAT,SAAS,CAAqC;QACvF,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,CAAC,GAAW;QACjB,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACtE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC;YAAE,OAAO,SAAS,CAAC;QAEjF,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC;QACnE,mEAAmE;QACnE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QAE7D,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE;gBAAE,OAAO,SAAS,CAAC;YACpD,OAAO,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output-format-renderer.d.ts","sourceRoot":"","sources":["../../src/prompt/output-format-renderer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"output-format-renderer.d.ts","sourceRoot":"","sources":["../../src/prompt/output-format-renderer.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAoB7D;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,EAAE,SAAS,EAAE,eAAe,GAAG,MAAM,CAU7F"}
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
//
|
|
8
8
|
// Cross-port INVARIANT: the rendered text is byte-identical to the Java/C#/Kotlin
|
|
9
9
|
// reference (com.metaobjects.render.prompt.OutputFormatRenderer). Do not change
|
|
10
|
-
// the verbatim prose, skeleton shapes, or numeric-vs-quoted decision
|
|
10
|
+
// the verbatim prose, skeleton shapes, or numeric-vs-quoted decision (a number /
|
|
11
|
+
// boolean is never quoted, placeholder or not).
|
|
11
12
|
import { ESCAPERS } from "../escapers.js";
|
|
12
13
|
import { FieldKind, Format } from "../extract/types.js";
|
|
13
14
|
import { PromptStyle } from "./prompt-style.js";
|
|
@@ -131,9 +132,19 @@ function jsonValue(field, overrides, indent, mode, path, depth) {
|
|
|
131
132
|
return jsonObjectField(field, overrides, indent, mode, path, depth);
|
|
132
133
|
return jsonLeaf(field, overrides, mode);
|
|
133
134
|
}
|
|
135
|
+
// A number or boolean is shown UNQUOTED wherever the skeleton holds a placeholder for it
|
|
136
|
+
// — the inline hint (`{Integer 1-5.}`, `true | false`) and the no-example fallback
|
|
137
|
+
// (`{averageRating}`). A quoted placeholder taught the model to answer a number as a
|
|
138
|
+
// JSON string, which the generated response parser then rejected. Only STRING / ENUM
|
|
139
|
+
// values (and OBJECT past the depth guard) are quoted.
|
|
134
140
|
function jsonLeaf(field, overrides, mode) {
|
|
135
|
-
|
|
136
|
-
|
|
141
|
+
const unquoted = NUMERIC_KINDS.has(field.kind);
|
|
142
|
+
if (mode === "inline") {
|
|
143
|
+
const content = inlineContent(field, overrides);
|
|
144
|
+
return unquoted ? content : `"${escapeJson(content)}"`;
|
|
145
|
+
}
|
|
146
|
+
if (unquoted && exampleValueIfDeclared(field, overrides) == null)
|
|
147
|
+
return `{${field.name}}`;
|
|
137
148
|
const value = exampleValue(field, overrides);
|
|
138
149
|
return isNumericOrBoolean(field.kind, value) ? value : `"${escapeJson(value)}"`;
|
|
139
150
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output-format-renderer.js","sourceRoot":"","sources":["../../src/prompt/output-format-renderer.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,EAAE;AACF,gFAAgF;AAChF,+EAA+E;AAC/E,iFAAiF;AACjF,8DAA8D;AAC9D,EAAE;AACF,kFAAkF;AAClF,gFAAgF;AAChF,
|
|
1
|
+
{"version":3,"file":"output-format-renderer.js","sourceRoot":"","sources":["../../src/prompt/output-format-renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAC1F,OAAO,EAAE,KAAK,QAAQ,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// `@metaobjectsdev/render/providers` — the NODE-ONLY provider entry.
|
|
2
|
+
//
|
|
3
|
+
// The root entry (`@metaobjectsdev/render`) is browser-safe and must stay that
|
|
4
|
+
// way; anything that touches the filesystem lives behind this subpath.
|
|
5
|
+
export { FilesystemProvider, DEFAULT_TEMPLATE_EXTENSION } from "./filesystem-provider.js";
|
|
6
|
+
export { InMemoryProvider } from "./provider.js";
|
|
7
|
+
//# sourceMappingURL=providers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,+EAA+E;AAC/E,uEAAuE;AACvE,OAAO,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAC1F,OAAO,EAAiB,gBAAgB,EAAE,MAAM,eAAe,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metaobjectsdev/render",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9-rc.2",
|
|
4
4
|
"description": "Logic-less, deterministic text render engine (Mustache) for MetaObjects templates — provider-resolved partials, format-driven escaping, zero core dependency.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
"bun": "./src/index.ts",
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./providers": {
|
|
15
|
+
"bun": "./src/providers.ts",
|
|
16
|
+
"types": "./dist/providers.d.ts",
|
|
17
|
+
"default": "./dist/providers.js"
|
|
13
18
|
}
|
|
14
19
|
},
|
|
15
20
|
"files": [
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Filesystem-backed provider: resolves a `group/source` reference to
|
|
2
|
+
// <root>/<group>/<source>.mustache. NODE-ONLY — it is reachable solely through
|
|
3
|
+
// the `@metaobjectsdev/render/providers` subpath so the package's root entry
|
|
4
|
+
// stays importable in a browser bundle.
|
|
5
|
+
//
|
|
6
|
+
// Mirrors the C# MetaObjects.Render.FilesystemProvider, the Java
|
|
7
|
+
// com.metaobjects.render.FilesystemProvider and the Python
|
|
8
|
+
// metaobjects.render.FilesystemProvider: read the file when present, return
|
|
9
|
+
// undefined when absent / unreadable / not a regular file, and refuse a ref that
|
|
10
|
+
// escapes the root (undefined, never a throw).
|
|
11
|
+
|
|
12
|
+
import { readFileSync, statSync } from "node:fs";
|
|
13
|
+
import { resolve, sep } from "node:path";
|
|
14
|
+
import type { Provider } from "./provider.js";
|
|
15
|
+
|
|
16
|
+
/** The default template file extension, shared with every other port. */
|
|
17
|
+
export const DEFAULT_TEMPLATE_EXTENSION = ".mustache";
|
|
18
|
+
|
|
19
|
+
const REF_SEPARATOR = "/";
|
|
20
|
+
const PARENT_SEGMENT = "..";
|
|
21
|
+
|
|
22
|
+
export class FilesystemProvider implements Provider {
|
|
23
|
+
private readonly root: string;
|
|
24
|
+
|
|
25
|
+
constructor(root: string, private readonly extension: string = DEFAULT_TEMPLATE_EXTENSION) {
|
|
26
|
+
this.root = resolve(root);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
resolve(ref: string): string | undefined {
|
|
30
|
+
const segments = ref.split(REF_SEPARATOR).filter((s) => s.length > 0);
|
|
31
|
+
if (segments.length === 0 || segments.includes(PARENT_SEGMENT)) return undefined;
|
|
32
|
+
|
|
33
|
+
const candidate = resolve(this.root, ...segments) + this.extension;
|
|
34
|
+
// Path-traversal guard (belt-and-suspenders after the `..` check).
|
|
35
|
+
if (!candidate.startsWith(this.root + sep)) return undefined;
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
if (!statSync(candidate).isFile()) return undefined;
|
|
39
|
+
return readFileSync(candidate, "utf8");
|
|
40
|
+
} catch {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
//
|
|
8
8
|
// Cross-port INVARIANT: the rendered text is byte-identical to the Java/C#/Kotlin
|
|
9
9
|
// reference (com.metaobjects.render.prompt.OutputFormatRenderer). Do not change
|
|
10
|
-
// the verbatim prose, skeleton shapes, or numeric-vs-quoted decision
|
|
10
|
+
// the verbatim prose, skeleton shapes, or numeric-vs-quoted decision (a number /
|
|
11
|
+
// boolean is never quoted, placeholder or not).
|
|
11
12
|
|
|
12
13
|
import { ESCAPERS } from "../escapers.js";
|
|
13
14
|
import { FieldKind, Format } from "../extract/types.js";
|
|
@@ -160,8 +161,18 @@ function jsonValue(
|
|
|
160
161
|
return jsonLeaf(field, overrides, mode);
|
|
161
162
|
}
|
|
162
163
|
|
|
164
|
+
// A number or boolean is shown UNQUOTED wherever the skeleton holds a placeholder for it
|
|
165
|
+
// — the inline hint (`{Integer 1-5.}`, `true | false`) and the no-example fallback
|
|
166
|
+
// (`{averageRating}`). A quoted placeholder taught the model to answer a number as a
|
|
167
|
+
// JSON string, which the generated response parser then rejected. Only STRING / ENUM
|
|
168
|
+
// values (and OBJECT past the depth guard) are quoted.
|
|
163
169
|
function jsonLeaf(field: PromptField, overrides: PromptOverrides, mode: SkelMode): string {
|
|
164
|
-
|
|
170
|
+
const unquoted = NUMERIC_KINDS.has(field.kind);
|
|
171
|
+
if (mode === "inline") {
|
|
172
|
+
const content = inlineContent(field, overrides);
|
|
173
|
+
return unquoted ? content : `"${escapeJson(content)}"`;
|
|
174
|
+
}
|
|
175
|
+
if (unquoted && exampleValueIfDeclared(field, overrides) == null) return `{${field.name}}`;
|
|
165
176
|
const value = exampleValue(field, overrides);
|
|
166
177
|
return isNumericOrBoolean(field.kind, value) ? value : `"${escapeJson(value)}"`;
|
|
167
178
|
}
|
package/src/providers.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// `@metaobjectsdev/render/providers` — the NODE-ONLY provider entry.
|
|
2
|
+
//
|
|
3
|
+
// The root entry (`@metaobjectsdev/render`) is browser-safe and must stay that
|
|
4
|
+
// way; anything that touches the filesystem lives behind this subpath.
|
|
5
|
+
export { FilesystemProvider, DEFAULT_TEMPLATE_EXTENSION } from "./filesystem-provider.js";
|
|
6
|
+
export { type Provider, InMemoryProvider } from "./provider.js";
|