tina4-nodejs 3.10.88 → 3.10.89

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tina4-nodejs",
3
- "version": "3.10.88",
3
+ "version": "3.10.89",
4
4
  "type": "module",
5
5
  "description": "Tina4 for Node.js/TypeScript — 54 built-in features, zero dependencies",
6
6
  "keywords": ["tina4", "framework", "web", "api", "orm", "graphql", "websocket", "typescript"],
@@ -30,9 +30,9 @@ class SafeString {
30
30
  * - Date, Map, Set, Error, RegExp (shown with their type and contents)
31
31
  * - Class instances (shown with the class name prefix)
32
32
  *
33
- * Intended for the `|dump` filter in templates. Output is a plain string;
34
- * the filter wraps it in <pre> and marks it safe so the template engine
35
- * doesn't double-escape.
33
+ * Used by both the `|dump` filter and the `dump()` global function.
34
+ * Output is a plain string; callers wrap it in <pre> and mark it safe so
35
+ * the template engine doesn't double-escape.
36
36
  */
37
37
  function inspectValue(value: unknown, seen: WeakSet<object> = new WeakSet(), depth = 0): string {
38
38
  // Primitives
@@ -116,6 +116,29 @@ function inspectValue(value: unknown, seen: WeakSet<object> = new WeakSet(), dep
116
116
  }
117
117
  }
118
118
 
119
+ /**
120
+ * Render a value as a pre-formatted, HTML-escaped dump wrapped in <pre> tags.
121
+ * Returns a SafeString so the template engine does not double-escape the
122
+ * entities. Shared by the `|dump` filter and the `dump()` global function.
123
+ *
124
+ * Gated on TINA4_DEBUG=true. In production (TINA4_DEBUG unset or false)
125
+ * dump output is suppressed entirely to avoid leaking internal state,
126
+ * stack-traceable object shapes, or sensitive values into rendered HTML.
127
+ */
128
+ function renderDump(value: unknown): SafeString {
129
+ const debugMode = (process.env.TINA4_DEBUG ?? "").toLowerCase() === "true";
130
+ if (!debugMode) {
131
+ return new SafeString("");
132
+ }
133
+ const dumped = inspectValue(value);
134
+ const escaped = dumped
135
+ .replace(/&/g, "&amp;")
136
+ .replace(/</g, "&lt;")
137
+ .replace(/>/g, "&gt;")
138
+ .replace(/"/g, "&quot;");
139
+ return new SafeString(`<pre>${escaped}</pre>`);
140
+ }
141
+
119
142
  type TokenType = "TEXT" | "VAR" | "BLOCK" | "COMMENT";
120
143
  type Token = [TokenType, string];
121
144
 
@@ -1264,6 +1287,11 @@ export class Frond {
1264
1287
  this.globals.form_token = (descriptor?: string) => _generateFormToken(descriptor || "");
1265
1288
  this.globals.formTokenValue = (descriptor?: string) => _generateFormTokenValue(descriptor || "");
1266
1289
  this.globals.form_token_value = (descriptor?: string) => _generateFormTokenValue(descriptor || "");
1290
+
1291
+ // Debug helper: {{ dump(x) }} — gated on TINA4_DEBUG, see renderDump().
1292
+ // Available alongside the |dump filter so both styles work:
1293
+ // {{ user|dump }} and {{ dump(user) }}
1294
+ this.globals.dump = (value: unknown) => renderDump(value);
1267
1295
  }
1268
1296
 
1269
1297
  sandbox(filters?: string[], tags?: string[], vars?: string[]): Frond {
@@ -1687,18 +1715,11 @@ export class Frond {
1687
1715
  case "keys": value = (typeof value === "object" && value !== null && !Array.isArray(value)) ? Object.keys(value) : []; continue;
1688
1716
  case "values": value = (typeof value === "object" && value !== null && !Array.isArray(value)) ? Object.values(value) : []; continue;
1689
1717
  case "json_encode": value = JSON.stringify(value); continue;
1690
- case "dump": {
1691
- // Use a safe inspector rather than JSON.stringify — handles
1692
- // circular refs, BigInt, Map/Set, Error, Date, class instances.
1693
- const dumped = inspectValue(value);
1694
- const escaped = dumped
1695
- .replace(/&/g, "&amp;")
1696
- .replace(/</g, "&lt;")
1697
- .replace(/>/g, "&gt;")
1698
- .replace(/"/g, "&quot;");
1699
- value = new SafeString(`<pre>${escaped}</pre>`);
1718
+ case "dump":
1719
+ // Delegates to renderDump(), which is gated on TINA4_DEBUG.
1720
+ // In production this emits an empty SafeString (no leaked state).
1721
+ value = renderDump(value);
1700
1722
  continue;
1701
- }
1702
1723
  case "nl2br": value = String(value).replace(/\n/g, "<br>\n"); continue;
1703
1724
  case "unique": value = Array.isArray(value) ? [...new Set(value)] : value; continue;
1704
1725
  case "sort": value = Array.isArray(value) ? [...value].sort() : value; continue;