yaml-flow 2.6.0 → 2.6.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.
@@ -300,10 +300,142 @@ function resolve(node, path) {
300
300
  function registerFunction(name, fn) {
301
301
  _customFns[name] = fn;
302
302
  }
303
+ var VALID_ELEMENT_KINDS = /* @__PURE__ */ new Set([
304
+ "metric",
305
+ "table",
306
+ "chart",
307
+ "form",
308
+ "filter",
309
+ "list",
310
+ "notes",
311
+ "todo",
312
+ "alert",
313
+ "narrative",
314
+ "badge",
315
+ "text",
316
+ "markdown",
317
+ "custom"
318
+ ]);
319
+ var VALID_SOURCE_KINDS = /* @__PURE__ */ new Set(["api", "websocket", "static", "llm"]);
320
+ var VALID_STATUSES = /* @__PURE__ */ new Set(["fresh", "stale", "loading", "error"]);
321
+ var CARD_ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "type", "meta", "data", "view", "state", "compute"]);
322
+ var SOURCE_ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "type", "meta", "data", "source", "state", "compute"]);
323
+ function validateNode(node) {
324
+ const errors = [];
325
+ if (!node || typeof node !== "object" || Array.isArray(node)) {
326
+ return { ok: false, errors: ["Node must be a non-null object"] };
327
+ }
328
+ const n = node;
329
+ if (typeof n.id !== "string" || !n.id) {
330
+ errors.push("id: required, must be a non-empty string");
331
+ }
332
+ if (n.type !== "card" && n.type !== "source") {
333
+ errors.push('type: must be "card" or "source"');
334
+ return { ok: false, errors };
335
+ }
336
+ const allowed = n.type === "card" ? CARD_ALLOWED_KEYS : SOURCE_ALLOWED_KEYS;
337
+ for (const key of Object.keys(n)) {
338
+ if (!allowed.has(key)) errors.push(`Unknown top-level key: "${key}"`);
339
+ }
340
+ if (n.state == null || typeof n.state !== "object" || Array.isArray(n.state)) {
341
+ errors.push("state: required, must be an object");
342
+ } else {
343
+ const state = n.state;
344
+ if (state.status != null && !VALID_STATUSES.has(state.status)) {
345
+ errors.push(`state.status: must be one of: ${[...VALID_STATUSES].join(", ")}`);
346
+ }
347
+ }
348
+ if (n.meta != null) {
349
+ if (typeof n.meta !== "object" || Array.isArray(n.meta)) {
350
+ errors.push("meta: must be an object");
351
+ } else {
352
+ const meta = n.meta;
353
+ if (meta.title != null && typeof meta.title !== "string") errors.push("meta.title: must be a string");
354
+ if (meta.tags != null && !Array.isArray(meta.tags)) errors.push("meta.tags: must be an array");
355
+ }
356
+ }
357
+ if (n.data != null) {
358
+ if (typeof n.data !== "object" || Array.isArray(n.data)) {
359
+ errors.push("data: must be an object");
360
+ } else {
361
+ const data = n.data;
362
+ if (data.requires != null && !Array.isArray(data.requires)) errors.push("data.requires: must be an array of strings");
363
+ if (data.provides != null && (typeof data.provides !== "object" || Array.isArray(data.provides))) errors.push("data.provides: must be an object");
364
+ }
365
+ }
366
+ if (n.compute != null) {
367
+ if (typeof n.compute !== "object" || Array.isArray(n.compute)) {
368
+ errors.push("compute: must be an object");
369
+ } else {
370
+ for (const [key, expr] of Object.entries(n.compute)) {
371
+ if (!expr || typeof expr !== "object" || Array.isArray(expr)) {
372
+ errors.push(`compute.${key}: must be a compute expression object`);
373
+ } else if (!expr.fn) {
374
+ errors.push(`compute.${key}: missing required "fn" property`);
375
+ } else {
376
+ const fn = expr.fn;
377
+ if (!_fns[fn] && !_customFns[fn]) {
378
+ errors.push(`compute.${key}: unknown function "${fn}"`);
379
+ }
380
+ }
381
+ }
382
+ }
383
+ }
384
+ if (n.type === "card") {
385
+ if (n.source != null) errors.push('Card nodes must not have "source" \u2014 use type "source" instead');
386
+ if (n.view == null || typeof n.view !== "object" || Array.isArray(n.view)) {
387
+ errors.push("view: required for card nodes, must be an object");
388
+ } else {
389
+ const view = n.view;
390
+ if (!Array.isArray(view.elements) || view.elements.length === 0) {
391
+ errors.push("view.elements: required, must be a non-empty array");
392
+ } else {
393
+ view.elements.forEach((elem, i) => {
394
+ if (!elem || typeof elem !== "object") {
395
+ errors.push(`view.elements[${i}]: must be an object`);
396
+ return;
397
+ }
398
+ if (!elem.kind || typeof elem.kind !== "string") {
399
+ errors.push(`view.elements[${i}].kind: required, must be a string`);
400
+ } else if (!VALID_ELEMENT_KINDS.has(elem.kind)) {
401
+ errors.push(`view.elements[${i}].kind: unknown kind "${elem.kind}". Valid: ${[...VALID_ELEMENT_KINDS].join(", ")}`);
402
+ }
403
+ if (elem.data != null && (typeof elem.data !== "object" || Array.isArray(elem.data))) {
404
+ errors.push(`view.elements[${i}].data: must be an object`);
405
+ }
406
+ });
407
+ }
408
+ if (view.layout != null && (typeof view.layout !== "object" || Array.isArray(view.layout))) {
409
+ errors.push("view.layout: must be an object");
410
+ }
411
+ if (view.features != null && (typeof view.features !== "object" || Array.isArray(view.features))) {
412
+ errors.push("view.features: must be an object");
413
+ }
414
+ }
415
+ }
416
+ if (n.type === "source") {
417
+ if (n.view != null) errors.push('Source nodes must not have "view" \u2014 use type "card" instead');
418
+ if (n.source == null || typeof n.source !== "object" || Array.isArray(n.source)) {
419
+ errors.push("source: required for source nodes, must be an object");
420
+ } else {
421
+ const src = n.source;
422
+ if (!src.kind || !VALID_SOURCE_KINDS.has(src.kind)) {
423
+ errors.push(`source.kind: required, must be one of: ${[...VALID_SOURCE_KINDS].join(", ")}`);
424
+ }
425
+ if (typeof src.bindTo !== "string" || !src.bindTo) {
426
+ errors.push("source.bindTo: required, must be a state path string");
427
+ } else if (!src.bindTo.startsWith("state.")) {
428
+ errors.push('source.bindTo: must start with "state."');
429
+ }
430
+ }
431
+ }
432
+ return { ok: errors.length === 0, errors };
433
+ }
303
434
  var CardCompute = {
304
435
  run,
305
436
  eval: evalExpr,
306
437
  resolve,
438
+ validate: validateNode,
307
439
  registerFunction,
308
440
  get functions() {
309
441
  const all = {};
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/card-compute/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * card-compute — Pure JSON expression evaluator for node-based cards.\n *\n * Isomorphic: works in browser, Node.js, and bundlers.\n * No DOM dependency. No eval(). Pure declarative JSON expressions.\n *\n * @example\n * ```typescript\n * import { CardCompute } from 'yaml-flow/card-compute';\n *\n * const node = {\n * id: 'sales',\n * state: { data: [{ revenue: 100 }, { revenue: 200 }] },\n * compute: {\n * total: { fn: 'sum', input: 'state.data', field: 'revenue' },\n * avg: { fn: 'avg', input: 'state.data', field: 'revenue' },\n * },\n * };\n * CardCompute.run(node);\n * // node.state.total === 300\n * // node.state.avg === 150\n * ```\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** A compute expression — pure JSON, arbitrarily nestable. */\nexport interface ComputeExpr {\n fn: string;\n input?: string | number | boolean | ComputeExpr | (string | number | boolean | ComputeExpr)[];\n field?: string;\n where?: ComputeExpr;\n apply?: ComputeExpr;\n cond?: ComputeExpr;\n then?: unknown;\n else?: unknown;\n format?: string;\n decimals?: number;\n separator?: string;\n direction?: 'asc' | 'desc';\n start?: number;\n end?: number;\n depth?: number;\n path?: string;\n value?: unknown;\n [key: string]: unknown;\n}\n\n/** Minimal node shape expected by CardCompute. */\nexport interface ComputeNode {\n id?: string;\n state?: Record<string, unknown>;\n compute?: Record<string, ComputeExpr>;\n [key: string]: unknown;\n}\n\n/** Internal evaluator signature passed to compute functions. */\nexport type EvalFn = (expr: unknown, node: ComputeNode) => unknown;\n\n/** A compute function implementation. */\nexport type ComputeFn = (input: unknown, evalFn: EvalFn, opts: ComputeExpr) => unknown;\n\n// ---------------------------------------------------------------------------\n// Deep path utilities\n// ---------------------------------------------------------------------------\n\nfunction deepGet(obj: unknown, path: string): unknown {\n if (!path || !obj) return undefined;\n const parts = path.split('.');\n let cur: unknown = obj;\n for (let i = 0; i < parts.length; i++) {\n if (cur == null) return undefined;\n cur = (cur as Record<string, unknown>)[parts[i]];\n }\n return cur;\n}\n\nfunction deepSet(obj: Record<string, unknown>, path: string, value: unknown): void {\n const parts = path.split('.');\n let cur: Record<string, unknown> = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n if (cur[parts[i]] == null || typeof cur[parts[i]] !== 'object') cur[parts[i]] = {};\n cur = cur[parts[i]] as Record<string, unknown>;\n }\n cur[parts[parts.length - 1]] = value;\n}\n\n// ---------------------------------------------------------------------------\n// Built-in functions (53)\n// ---------------------------------------------------------------------------\n\nconst _fns: Record<string, ComputeFn> = {};\n\n// ---- Aggregates ----\n\n_fns.sum = (input, _e, opts) => {\n const a = Array.isArray(input) ? input : [];\n return opts.field\n ? a.reduce((s, r) => s + (Number(r[opts.field!]) || 0), 0)\n : a.reduce((s, v) => s + (Number(v) || 0), 0);\n};\n\n_fns.avg = (input, _e, opts) => {\n const s = _fns.sum(input, _e, opts) as number;\n const n = Array.isArray(input) ? input.length : 1;\n return n ? s / n : 0;\n};\n\n_fns.min = (input, _e, opts) => {\n const a = Array.isArray(input) ? input : [];\n const vals = opts.field ? a.map(r => Number(r[opts.field!])) : a.map(Number);\n return vals.length ? Math.min(...vals) : 0;\n};\n\n_fns.max = (input, _e, opts) => {\n const a = Array.isArray(input) ? input : [];\n const vals = opts.field ? a.map(r => Number(r[opts.field!])) : a.map(Number);\n return vals.length ? Math.max(...vals) : 0;\n};\n\n_fns.count = (input) => Array.isArray(input) ? input.length : (input != null ? 1 : 0);\n_fns.first = (input) => Array.isArray(input) ? input[0] : input;\n_fns.last = (input) => Array.isArray(input) ? input[input.length - 1] : input;\n\n// ---- Math ----\n\n_fns.add = (input) => { const a = Array.isArray(input) ? input : []; return a.reduce((s, v) => s + Number(v), 0); };\n_fns.sub = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 ? Number(a[0]) - Number(a[1]) : 0; };\n_fns.mul = (input) => { const a = Array.isArray(input) ? input : []; return a.reduce((s, v) => s * Number(v), 1); };\n_fns.div = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 && Number(a[1]) !== 0 ? Number(a[0]) / Number(a[1]) : 0; };\n\n_fns.round = (input, _e, opts) => {\n const decimals = opts.decimals != null ? (opts.decimals as number) : 0;\n const factor = Math.pow(10, decimals);\n return Math.round(Number(input) * factor) / factor;\n};\n\n_fns.abs = (input) => Math.abs(Number(input));\n_fns.mod = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 ? Number(a[0]) % Number(a[1]) : 0; };\n\n// ---- Compare ----\n\n_fns.gt = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 && Number(a[0]) > Number(a[1]); };\n_fns.gte = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 && Number(a[0]) >= Number(a[1]); };\n_fns.lt = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 && Number(a[0]) < Number(a[1]); };\n_fns.lte = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 && Number(a[0]) <= Number(a[1]); };\n_fns.eq = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 && a[0] === a[1]; };\n_fns.neq = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 && a[0] !== a[1]; };\n\n// ---- Logic ----\n\n_fns.and = (input) => { const a = Array.isArray(input) ? input : []; return a.every(Boolean); };\n_fns.or = (input) => { const a = Array.isArray(input) ? input : []; return a.some(Boolean); };\n_fns.not = (input) => !input;\n// \"if\" is handled in evalExpr\n\n// ---- String ----\n\n_fns.concat = (input) => {\n const a = Array.isArray(input) ? input : [];\n return a.map(v => v != null ? String(v) : '').join('');\n};\n\n_fns.upper = (input) => String(input || '').toUpperCase();\n_fns.lower = (input) => String(input || '').toLowerCase();\n\n_fns.template = (input, _e, opts) => {\n let t = String(opts.format || '');\n if (input && typeof input === 'object' && !Array.isArray(input)) {\n for (const k of Object.keys(input as Record<string, unknown>)) {\n const v = (input as Record<string, unknown>)[k];\n t = t.split('{{' + k + '}}').join(v != null ? String(v) : '');\n }\n }\n return t;\n};\n\n_fns.join = (input, _e, opts) => {\n const a = Array.isArray(input) ? input : [];\n const sep = opts.separator != null ? String(opts.separator) : ', ';\n return a.map(v => v != null ? String(v) : '').join(sep);\n};\n\n_fns.split = (input, _e, opts) => {\n const sep = opts.separator != null ? String(opts.separator) : ',';\n return String(input || '').split(sep).map(s => s.trim());\n};\n\n_fns.trim = (input) => String(input || '').trim();\n\n// ---- Collection ----\n\n_fns.pluck = (input, _e, opts) => Array.isArray(input) ? input.map(r => r[opts.field!]) : [];\n\n_fns.filter = (input, _e, opts) => {\n if (!Array.isArray(input)) return [];\n if (opts.field) return input.filter(r => !!r[opts.field!]);\n return input.filter(Boolean);\n};\n\n_fns.map = (input) => Array.isArray(input) ? input.slice() : [];\n\n_fns.sort = (input, _e, opts) => {\n const a = Array.isArray(input) ? input.slice() : [];\n const f = opts.field;\n const dir = opts.direction === 'desc' ? -1 : 1;\n if (f) return a.sort((x, y) => x[f] > y[f] ? dir : x[f] < y[f] ? -dir : 0);\n return a.sort((x, y) => x > y ? dir : x < y ? -dir : 0);\n};\n\n_fns.slice = (input, _e, opts) => Array.isArray(input) ? input.slice(opts.start || 0, opts.end as number | undefined) : input;\n_fns.flat = (input, _e, opts) => {\n const depth = opts.depth != null ? (opts.depth as number) : 1;\n return Array.isArray(input) ? input.flat(depth) : [input];\n};\n\n_fns.unique = (input) => {\n if (!Array.isArray(input)) return [input];\n const seen = new Set<unknown>();\n return input.filter(v => {\n const key = typeof v === 'object' ? JSON.stringify(v) : v;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n};\n\n_fns.group = (input, _e, opts) => {\n const a = Array.isArray(input) ? input : [];\n const g: Record<string, unknown[]> = {};\n a.forEach(r => { const k = String(r[opts.field!] || ''); if (!g[k]) g[k] = []; g[k].push(r); });\n return g;\n};\n\n_fns.flatten_keys = (input) => {\n if (!input || typeof input !== 'object' || Array.isArray(input)) return [];\n const result: { key: string; value: unknown }[] = [];\n for (const k of Object.keys(input as Record<string, unknown>)) {\n const vals = Array.isArray((input as Record<string, unknown>)[k])\n ? (input as Record<string, unknown>)[k] as unknown[]\n : [(input as Record<string, unknown>)[k]];\n vals.forEach(v => result.push({ key: k, value: v }));\n }\n return result;\n};\n\n_fns.entries = (input) => {\n if (!input || typeof input !== 'object' || Array.isArray(input)) return [];\n return Object.keys(input as Record<string, unknown>).map(k => ({ key: k, value: (input as Record<string, unknown>)[k] }));\n};\n\n_fns.from_entries = (input) => {\n if (!Array.isArray(input)) return {};\n const obj: Record<string, unknown> = {};\n input.forEach(item => { if (item.key != null) obj[item.key] = item.value; });\n return obj;\n};\n\n_fns.length = (input) => {\n if (Array.isArray(input)) return input.length;\n if (typeof input === 'string') return input.length;\n if (input && typeof input === 'object') return Object.keys(input).length;\n return 0;\n};\n\n// ---- Lookup ----\n\n_fns.get = (input, _e, opts) => deepGet(input, opts.field || opts.path || '');\n_fns.default = (input, _e, opts) => input != null ? input : opts.value;\n_fns.coalesce = (input) => {\n const a = Array.isArray(input) ? input : [];\n for (let i = 0; i < a.length; i++) { if (a[i] != null) return a[i]; }\n return null;\n};\n\n// ---- Date ----\n\n_fns.now = () => new Date().toISOString();\n_fns.diff_days = (input) => {\n const a = Array.isArray(input) ? input : [];\n return a.length >= 2 ? Math.floor((new Date(a[0]).getTime() - new Date(a[1]).getTime()) / 86400000) : 0;\n};\n\n_fns.format_date = (input, _e, opts) => {\n try {\n const d = new Date(input as string);\n if (opts.format === 'iso') return d.toISOString();\n if (opts.format === 'date') return d.toLocaleDateString();\n if (opts.format === 'time') return d.toLocaleTimeString();\n return d.toLocaleDateString();\n } catch { return String(input); }\n};\n\n_fns.parse_date = (input) => {\n try { return new Date(input as string).toISOString(); } catch { return null; }\n};\n\n// ---- Type ----\n\n_fns.to_number = (input) => Number(input) || 0;\n_fns.to_string = (input) => input != null ? String(input) : '';\n_fns.to_bool = (input) => !!input;\n_fns.type_of = (input) => Array.isArray(input) ? 'array' : typeof input;\n_fns.is_null = (input) => input == null;\n_fns.is_empty = (input) => {\n if (input == null) return true;\n if (Array.isArray(input)) return input.length === 0;\n if (typeof input === 'string') return input.length === 0;\n if (typeof input === 'object') return Object.keys(input).length === 0;\n return false;\n};\n\n// ---------------------------------------------------------------------------\n// Custom function registry\n// ---------------------------------------------------------------------------\n\nconst _customFns: Record<string, ComputeFn> = {};\n\n// ---------------------------------------------------------------------------\n// Expression evaluator\n// ---------------------------------------------------------------------------\n\nfunction evalExpr(expr: unknown, node: ComputeNode): unknown {\n if (expr == null) return expr;\n if (typeof expr !== 'object' || Array.isArray(expr)) return expr;\n\n const e = expr as ComputeExpr;\n if (!e.fn) return expr;\n\n // Resolve input\n let input: unknown = e.input;\n if (typeof input === 'string' && input.startsWith('state.')) {\n input = deepGet(node, input);\n } else if (Array.isArray(input)) {\n input = input.map(v => {\n if (typeof v === 'string' && (v as string).startsWith('state.')) return deepGet(node, v as string);\n if (v && typeof v === 'object' && (v as ComputeExpr).fn) return evalExpr(v, node);\n return v;\n });\n } else if (input && typeof input === 'object' && (input as ComputeExpr).fn) {\n input = evalExpr(input, node);\n }\n\n // Special: if\n if (e.fn === 'if') {\n const cond = evalExpr(e.cond, node);\n if (cond) {\n return (e.then && typeof e.then === 'object' && (e.then as ComputeExpr).fn) ? evalExpr(e.then, node) : e.then;\n } else {\n return (e.else && typeof e.else === 'object' && (e.else as ComputeExpr).fn) ? evalExpr(e.else, node) : e.else;\n }\n }\n\n // Special: filter with where\n if (e.fn === 'filter' && Array.isArray(input) && e.where) {\n return (input as unknown[]).filter(item => {\n const tmp: ComputeNode = { state: { ...node.state, $: item } };\n return evalExpr(e.where, tmp);\n });\n }\n\n // Special: map with apply\n if (e.fn === 'map' && Array.isArray(input) && e.apply) {\n return (input as unknown[]).map(item => {\n const tmp: ComputeNode = { state: { ...node.state, $: item } };\n return evalExpr(e.apply as ComputeExpr, tmp);\n });\n }\n\n const fn = _customFns[e.fn] || _fns[e.fn];\n if (!fn) {\n console.warn('CardCompute: unknown function \"' + e.fn + '\"');\n return undefined;\n }\n\n return fn(input, evalExpr, e);\n}\n\n// ---------------------------------------------------------------------------\n// run — evaluate all node.compute declarations\n// ---------------------------------------------------------------------------\n\nfunction run(node: ComputeNode): ComputeNode {\n if (!node || !node.compute) return node;\n if (!node.state) node.state = {};\n\n for (const key of Object.keys(node.compute)) {\n try {\n const val = evalExpr(node.compute[key], node);\n deepSet(node.state, key, val);\n } catch (err) {\n console.error(`CardCompute.run error on \"${node.id || '?'}.${key}\":`, err);\n }\n }\n\n return node;\n}\n\n// ---------------------------------------------------------------------------\n// resolve — deep get from node\n// ---------------------------------------------------------------------------\n\nfunction resolve(node: ComputeNode, path: string): unknown {\n return deepGet(node, path);\n}\n\n// ---------------------------------------------------------------------------\n// registerFunction — extend the vocabulary\n// ---------------------------------------------------------------------------\n\nfunction registerFunction(name: string, fn: ComputeFn): void {\n _customFns[name] = fn;\n}\n\n// ---------------------------------------------------------------------------\n// Export\n// ---------------------------------------------------------------------------\n\nexport const CardCompute = {\n run,\n eval: evalExpr,\n resolve,\n registerFunction,\n get functions(): Record<string, ComputeFn> {\n const all: Record<string, ComputeFn> = {};\n for (const k of Object.keys(_fns)) all[k] = _fns[k];\n for (const k of Object.keys(_customFns)) all[k] = _customFns[k];\n return all;\n },\n};\n\nexport default CardCompute;\n"]}
1
+ {"version":3,"sources":["../../src/card-compute/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * card-compute — Pure JSON expression evaluator for node-based cards.\n *\n * Isomorphic: works in browser, Node.js, and bundlers.\n * No DOM dependency. No eval(). Pure declarative JSON expressions.\n *\n * @example\n * ```typescript\n * import { CardCompute } from 'yaml-flow/card-compute';\n *\n * const node = {\n * id: 'sales',\n * state: { data: [{ revenue: 100 }, { revenue: 200 }] },\n * compute: {\n * total: { fn: 'sum', input: 'state.data', field: 'revenue' },\n * avg: { fn: 'avg', input: 'state.data', field: 'revenue' },\n * },\n * };\n * CardCompute.run(node);\n * // node.state.total === 300\n * // node.state.avg === 150\n * ```\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** A compute expression — pure JSON, arbitrarily nestable. */\nexport interface ComputeExpr {\n fn: string;\n input?: string | number | boolean | ComputeExpr | (string | number | boolean | ComputeExpr)[];\n field?: string;\n where?: ComputeExpr;\n apply?: ComputeExpr;\n cond?: ComputeExpr;\n then?: unknown;\n else?: unknown;\n format?: string;\n decimals?: number;\n separator?: string;\n direction?: 'asc' | 'desc';\n start?: number;\n end?: number;\n depth?: number;\n path?: string;\n value?: unknown;\n [key: string]: unknown;\n}\n\n/** Minimal node shape expected by CardCompute. */\nexport interface ComputeNode {\n id?: string;\n state?: Record<string, unknown>;\n compute?: Record<string, ComputeExpr>;\n [key: string]: unknown;\n}\n\n/** Internal evaluator signature passed to compute functions. */\nexport type EvalFn = (expr: unknown, node: ComputeNode) => unknown;\n\n/** A compute function implementation. */\nexport type ComputeFn = (input: unknown, evalFn: EvalFn, opts: ComputeExpr) => unknown;\n\n// ---------------------------------------------------------------------------\n// Deep path utilities\n// ---------------------------------------------------------------------------\n\nfunction deepGet(obj: unknown, path: string): unknown {\n if (!path || !obj) return undefined;\n const parts = path.split('.');\n let cur: unknown = obj;\n for (let i = 0; i < parts.length; i++) {\n if (cur == null) return undefined;\n cur = (cur as Record<string, unknown>)[parts[i]];\n }\n return cur;\n}\n\nfunction deepSet(obj: Record<string, unknown>, path: string, value: unknown): void {\n const parts = path.split('.');\n let cur: Record<string, unknown> = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n if (cur[parts[i]] == null || typeof cur[parts[i]] !== 'object') cur[parts[i]] = {};\n cur = cur[parts[i]] as Record<string, unknown>;\n }\n cur[parts[parts.length - 1]] = value;\n}\n\n// ---------------------------------------------------------------------------\n// Built-in functions (53)\n// ---------------------------------------------------------------------------\n\nconst _fns: Record<string, ComputeFn> = {};\n\n// ---- Aggregates ----\n\n_fns.sum = (input, _e, opts) => {\n const a = Array.isArray(input) ? input : [];\n return opts.field\n ? a.reduce((s, r) => s + (Number(r[opts.field!]) || 0), 0)\n : a.reduce((s, v) => s + (Number(v) || 0), 0);\n};\n\n_fns.avg = (input, _e, opts) => {\n const s = _fns.sum(input, _e, opts) as number;\n const n = Array.isArray(input) ? input.length : 1;\n return n ? s / n : 0;\n};\n\n_fns.min = (input, _e, opts) => {\n const a = Array.isArray(input) ? input : [];\n const vals = opts.field ? a.map(r => Number(r[opts.field!])) : a.map(Number);\n return vals.length ? Math.min(...vals) : 0;\n};\n\n_fns.max = (input, _e, opts) => {\n const a = Array.isArray(input) ? input : [];\n const vals = opts.field ? a.map(r => Number(r[opts.field!])) : a.map(Number);\n return vals.length ? Math.max(...vals) : 0;\n};\n\n_fns.count = (input) => Array.isArray(input) ? input.length : (input != null ? 1 : 0);\n_fns.first = (input) => Array.isArray(input) ? input[0] : input;\n_fns.last = (input) => Array.isArray(input) ? input[input.length - 1] : input;\n\n// ---- Math ----\n\n_fns.add = (input) => { const a = Array.isArray(input) ? input : []; return a.reduce((s, v) => s + Number(v), 0); };\n_fns.sub = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 ? Number(a[0]) - Number(a[1]) : 0; };\n_fns.mul = (input) => { const a = Array.isArray(input) ? input : []; return a.reduce((s, v) => s * Number(v), 1); };\n_fns.div = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 && Number(a[1]) !== 0 ? Number(a[0]) / Number(a[1]) : 0; };\n\n_fns.round = (input, _e, opts) => {\n const decimals = opts.decimals != null ? (opts.decimals as number) : 0;\n const factor = Math.pow(10, decimals);\n return Math.round(Number(input) * factor) / factor;\n};\n\n_fns.abs = (input) => Math.abs(Number(input));\n_fns.mod = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 ? Number(a[0]) % Number(a[1]) : 0; };\n\n// ---- Compare ----\n\n_fns.gt = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 && Number(a[0]) > Number(a[1]); };\n_fns.gte = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 && Number(a[0]) >= Number(a[1]); };\n_fns.lt = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 && Number(a[0]) < Number(a[1]); };\n_fns.lte = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 && Number(a[0]) <= Number(a[1]); };\n_fns.eq = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 && a[0] === a[1]; };\n_fns.neq = (input) => { const a = Array.isArray(input) ? input : []; return a.length >= 2 && a[0] !== a[1]; };\n\n// ---- Logic ----\n\n_fns.and = (input) => { const a = Array.isArray(input) ? input : []; return a.every(Boolean); };\n_fns.or = (input) => { const a = Array.isArray(input) ? input : []; return a.some(Boolean); };\n_fns.not = (input) => !input;\n// \"if\" is handled in evalExpr\n\n// ---- String ----\n\n_fns.concat = (input) => {\n const a = Array.isArray(input) ? input : [];\n return a.map(v => v != null ? String(v) : '').join('');\n};\n\n_fns.upper = (input) => String(input || '').toUpperCase();\n_fns.lower = (input) => String(input || '').toLowerCase();\n\n_fns.template = (input, _e, opts) => {\n let t = String(opts.format || '');\n if (input && typeof input === 'object' && !Array.isArray(input)) {\n for (const k of Object.keys(input as Record<string, unknown>)) {\n const v = (input as Record<string, unknown>)[k];\n t = t.split('{{' + k + '}}').join(v != null ? String(v) : '');\n }\n }\n return t;\n};\n\n_fns.join = (input, _e, opts) => {\n const a = Array.isArray(input) ? input : [];\n const sep = opts.separator != null ? String(opts.separator) : ', ';\n return a.map(v => v != null ? String(v) : '').join(sep);\n};\n\n_fns.split = (input, _e, opts) => {\n const sep = opts.separator != null ? String(opts.separator) : ',';\n return String(input || '').split(sep).map(s => s.trim());\n};\n\n_fns.trim = (input) => String(input || '').trim();\n\n// ---- Collection ----\n\n_fns.pluck = (input, _e, opts) => Array.isArray(input) ? input.map(r => r[opts.field!]) : [];\n\n_fns.filter = (input, _e, opts) => {\n if (!Array.isArray(input)) return [];\n if (opts.field) return input.filter(r => !!r[opts.field!]);\n return input.filter(Boolean);\n};\n\n_fns.map = (input) => Array.isArray(input) ? input.slice() : [];\n\n_fns.sort = (input, _e, opts) => {\n const a = Array.isArray(input) ? input.slice() : [];\n const f = opts.field;\n const dir = opts.direction === 'desc' ? -1 : 1;\n if (f) return a.sort((x, y) => x[f] > y[f] ? dir : x[f] < y[f] ? -dir : 0);\n return a.sort((x, y) => x > y ? dir : x < y ? -dir : 0);\n};\n\n_fns.slice = (input, _e, opts) => Array.isArray(input) ? input.slice(opts.start || 0, opts.end as number | undefined) : input;\n_fns.flat = (input, _e, opts) => {\n const depth = opts.depth != null ? (opts.depth as number) : 1;\n return Array.isArray(input) ? input.flat(depth) : [input];\n};\n\n_fns.unique = (input) => {\n if (!Array.isArray(input)) return [input];\n const seen = new Set<unknown>();\n return input.filter(v => {\n const key = typeof v === 'object' ? JSON.stringify(v) : v;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n};\n\n_fns.group = (input, _e, opts) => {\n const a = Array.isArray(input) ? input : [];\n const g: Record<string, unknown[]> = {};\n a.forEach(r => { const k = String(r[opts.field!] || ''); if (!g[k]) g[k] = []; g[k].push(r); });\n return g;\n};\n\n_fns.flatten_keys = (input) => {\n if (!input || typeof input !== 'object' || Array.isArray(input)) return [];\n const result: { key: string; value: unknown }[] = [];\n for (const k of Object.keys(input as Record<string, unknown>)) {\n const vals = Array.isArray((input as Record<string, unknown>)[k])\n ? (input as Record<string, unknown>)[k] as unknown[]\n : [(input as Record<string, unknown>)[k]];\n vals.forEach(v => result.push({ key: k, value: v }));\n }\n return result;\n};\n\n_fns.entries = (input) => {\n if (!input || typeof input !== 'object' || Array.isArray(input)) return [];\n return Object.keys(input as Record<string, unknown>).map(k => ({ key: k, value: (input as Record<string, unknown>)[k] }));\n};\n\n_fns.from_entries = (input) => {\n if (!Array.isArray(input)) return {};\n const obj: Record<string, unknown> = {};\n input.forEach(item => { if (item.key != null) obj[item.key] = item.value; });\n return obj;\n};\n\n_fns.length = (input) => {\n if (Array.isArray(input)) return input.length;\n if (typeof input === 'string') return input.length;\n if (input && typeof input === 'object') return Object.keys(input).length;\n return 0;\n};\n\n// ---- Lookup ----\n\n_fns.get = (input, _e, opts) => deepGet(input, opts.field || opts.path || '');\n_fns.default = (input, _e, opts) => input != null ? input : opts.value;\n_fns.coalesce = (input) => {\n const a = Array.isArray(input) ? input : [];\n for (let i = 0; i < a.length; i++) { if (a[i] != null) return a[i]; }\n return null;\n};\n\n// ---- Date ----\n\n_fns.now = () => new Date().toISOString();\n_fns.diff_days = (input) => {\n const a = Array.isArray(input) ? input : [];\n return a.length >= 2 ? Math.floor((new Date(a[0]).getTime() - new Date(a[1]).getTime()) / 86400000) : 0;\n};\n\n_fns.format_date = (input, _e, opts) => {\n try {\n const d = new Date(input as string);\n if (opts.format === 'iso') return d.toISOString();\n if (opts.format === 'date') return d.toLocaleDateString();\n if (opts.format === 'time') return d.toLocaleTimeString();\n return d.toLocaleDateString();\n } catch { return String(input); }\n};\n\n_fns.parse_date = (input) => {\n try { return new Date(input as string).toISOString(); } catch { return null; }\n};\n\n// ---- Type ----\n\n_fns.to_number = (input) => Number(input) || 0;\n_fns.to_string = (input) => input != null ? String(input) : '';\n_fns.to_bool = (input) => !!input;\n_fns.type_of = (input) => Array.isArray(input) ? 'array' : typeof input;\n_fns.is_null = (input) => input == null;\n_fns.is_empty = (input) => {\n if (input == null) return true;\n if (Array.isArray(input)) return input.length === 0;\n if (typeof input === 'string') return input.length === 0;\n if (typeof input === 'object') return Object.keys(input).length === 0;\n return false;\n};\n\n// ---------------------------------------------------------------------------\n// Custom function registry\n// ---------------------------------------------------------------------------\n\nconst _customFns: Record<string, ComputeFn> = {};\n\n// ---------------------------------------------------------------------------\n// Expression evaluator\n// ---------------------------------------------------------------------------\n\nfunction evalExpr(expr: unknown, node: ComputeNode): unknown {\n if (expr == null) return expr;\n if (typeof expr !== 'object' || Array.isArray(expr)) return expr;\n\n const e = expr as ComputeExpr;\n if (!e.fn) return expr;\n\n // Resolve input\n let input: unknown = e.input;\n if (typeof input === 'string' && input.startsWith('state.')) {\n input = deepGet(node, input);\n } else if (Array.isArray(input)) {\n input = input.map(v => {\n if (typeof v === 'string' && (v as string).startsWith('state.')) return deepGet(node, v as string);\n if (v && typeof v === 'object' && (v as ComputeExpr).fn) return evalExpr(v, node);\n return v;\n });\n } else if (input && typeof input === 'object' && (input as ComputeExpr).fn) {\n input = evalExpr(input, node);\n }\n\n // Special: if\n if (e.fn === 'if') {\n const cond = evalExpr(e.cond, node);\n if (cond) {\n return (e.then && typeof e.then === 'object' && (e.then as ComputeExpr).fn) ? evalExpr(e.then, node) : e.then;\n } else {\n return (e.else && typeof e.else === 'object' && (e.else as ComputeExpr).fn) ? evalExpr(e.else, node) : e.else;\n }\n }\n\n // Special: filter with where\n if (e.fn === 'filter' && Array.isArray(input) && e.where) {\n return (input as unknown[]).filter(item => {\n const tmp: ComputeNode = { state: { ...node.state, $: item } };\n return evalExpr(e.where, tmp);\n });\n }\n\n // Special: map with apply\n if (e.fn === 'map' && Array.isArray(input) && e.apply) {\n return (input as unknown[]).map(item => {\n const tmp: ComputeNode = { state: { ...node.state, $: item } };\n return evalExpr(e.apply as ComputeExpr, tmp);\n });\n }\n\n const fn = _customFns[e.fn] || _fns[e.fn];\n if (!fn) {\n console.warn('CardCompute: unknown function \"' + e.fn + '\"');\n return undefined;\n }\n\n return fn(input, evalExpr, e);\n}\n\n// ---------------------------------------------------------------------------\n// run — evaluate all node.compute declarations\n// ---------------------------------------------------------------------------\n\nfunction run(node: ComputeNode): ComputeNode {\n if (!node || !node.compute) return node;\n if (!node.state) node.state = {};\n\n for (const key of Object.keys(node.compute)) {\n try {\n const val = evalExpr(node.compute[key], node);\n deepSet(node.state, key, val);\n } catch (err) {\n console.error(`CardCompute.run error on \"${node.id || '?'}.${key}\":`, err);\n }\n }\n\n return node;\n}\n\n// ---------------------------------------------------------------------------\n// resolve — deep get from node\n// ---------------------------------------------------------------------------\n\nfunction resolve(node: ComputeNode, path: string): unknown {\n return deepGet(node, path);\n}\n\n// ---------------------------------------------------------------------------\n// registerFunction — extend the vocabulary\n// ---------------------------------------------------------------------------\n\nfunction registerFunction(name: string, fn: ComputeFn): void {\n _customFns[name] = fn;\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\n/** Result of validateNode — ok: true means valid, ok: false has errors[]. */\nexport interface ValidationResult {\n ok: boolean;\n errors: string[];\n}\n\nconst VALID_ELEMENT_KINDS = new Set([\n 'metric', 'table', 'chart', 'form', 'filter', 'list',\n 'notes', 'todo', 'alert', 'narrative', 'badge', 'text',\n 'markdown', 'custom',\n]);\n\nconst VALID_SOURCE_KINDS = new Set(['api', 'websocket', 'static', 'llm']);\nconst VALID_STATUSES = new Set(['fresh', 'stale', 'loading', 'error']);\n\nconst CARD_ALLOWED_KEYS = new Set(['id', 'type', 'meta', 'data', 'view', 'state', 'compute']);\nconst SOURCE_ALLOWED_KEYS = new Set(['id', 'type', 'meta', 'data', 'source', 'state', 'compute']);\n\n/**\n * Validate a node against the LiveCards schema.\n * Lightweight structural check — no external dependencies.\n *\n * @example\n * ```typescript\n * const result = CardCompute.validate(node);\n * if (!result.ok) console.error(result.errors);\n * ```\n */\nfunction validateNode(node: unknown): ValidationResult {\n const errors: string[] = [];\n\n if (!node || typeof node !== 'object' || Array.isArray(node)) {\n return { ok: false, errors: ['Node must be a non-null object'] };\n }\n\n const n = node as Record<string, unknown>;\n\n // id\n if (typeof n.id !== 'string' || !n.id) {\n errors.push('id: required, must be a non-empty string');\n }\n\n // type\n if (n.type !== 'card' && n.type !== 'source') {\n errors.push('type: must be \"card\" or \"source\"');\n return { ok: false, errors }; // Can't validate further without type\n }\n\n // Check for unknown top-level keys\n const allowed = n.type === 'card' ? CARD_ALLOWED_KEYS : SOURCE_ALLOWED_KEYS;\n for (const key of Object.keys(n)) {\n if (!allowed.has(key)) errors.push(`Unknown top-level key: \"${key}\"`);\n }\n\n // state (required)\n if (n.state == null || typeof n.state !== 'object' || Array.isArray(n.state)) {\n errors.push('state: required, must be an object');\n } else {\n const state = n.state as Record<string, unknown>;\n if (state.status != null && !VALID_STATUSES.has(state.status as string)) {\n errors.push(`state.status: must be one of: ${[...VALID_STATUSES].join(', ')}`);\n }\n }\n\n // meta (optional)\n if (n.meta != null) {\n if (typeof n.meta !== 'object' || Array.isArray(n.meta)) {\n errors.push('meta: must be an object');\n } else {\n const meta = n.meta as Record<string, unknown>;\n if (meta.title != null && typeof meta.title !== 'string') errors.push('meta.title: must be a string');\n if (meta.tags != null && !Array.isArray(meta.tags)) errors.push('meta.tags: must be an array');\n }\n }\n\n // data (optional)\n if (n.data != null) {\n if (typeof n.data !== 'object' || Array.isArray(n.data)) {\n errors.push('data: must be an object');\n } else {\n const data = n.data as Record<string, unknown>;\n if (data.requires != null && !Array.isArray(data.requires)) errors.push('data.requires: must be an array of strings');\n if (data.provides != null && (typeof data.provides !== 'object' || Array.isArray(data.provides))) errors.push('data.provides: must be an object');\n }\n }\n\n // compute (optional)\n if (n.compute != null) {\n if (typeof n.compute !== 'object' || Array.isArray(n.compute)) {\n errors.push('compute: must be an object');\n } else {\n for (const [key, expr] of Object.entries(n.compute as Record<string, unknown>)) {\n if (!expr || typeof expr !== 'object' || Array.isArray(expr)) {\n errors.push(`compute.${key}: must be a compute expression object`);\n } else if (!(expr as Record<string, unknown>).fn) {\n errors.push(`compute.${key}: missing required \"fn\" property`);\n } else {\n const fn = (expr as Record<string, unknown>).fn as string;\n if (!_fns[fn] && !_customFns[fn]) {\n errors.push(`compute.${key}: unknown function \"${fn}\"`);\n }\n }\n }\n }\n }\n\n // ---- Card-specific ----\n if (n.type === 'card') {\n if (n.source != null) errors.push('Card nodes must not have \"source\" — use type \"source\" instead');\n\n // view (required for cards)\n if (n.view == null || typeof n.view !== 'object' || Array.isArray(n.view)) {\n errors.push('view: required for card nodes, must be an object');\n } else {\n const view = n.view as Record<string, unknown>;\n\n // view.elements\n if (!Array.isArray(view.elements) || view.elements.length === 0) {\n errors.push('view.elements: required, must be a non-empty array');\n } else {\n (view.elements as Record<string, unknown>[]).forEach((elem, i) => {\n if (!elem || typeof elem !== 'object') {\n errors.push(`view.elements[${i}]: must be an object`);\n return;\n }\n if (!elem.kind || typeof elem.kind !== 'string') {\n errors.push(`view.elements[${i}].kind: required, must be a string`);\n } else if (!VALID_ELEMENT_KINDS.has(elem.kind as string)) {\n errors.push(`view.elements[${i}].kind: unknown kind \"${elem.kind}\". Valid: ${[...VALID_ELEMENT_KINDS].join(', ')}`);\n }\n if (elem.data != null && (typeof elem.data !== 'object' || Array.isArray(elem.data))) {\n errors.push(`view.elements[${i}].data: must be an object`);\n }\n });\n }\n\n // view.layout (optional)\n if (view.layout != null && (typeof view.layout !== 'object' || Array.isArray(view.layout))) {\n errors.push('view.layout: must be an object');\n }\n\n // view.features (optional)\n if (view.features != null && (typeof view.features !== 'object' || Array.isArray(view.features))) {\n errors.push('view.features: must be an object');\n }\n }\n }\n\n // ---- Source-specific ----\n if (n.type === 'source') {\n if (n.view != null) errors.push('Source nodes must not have \"view\" — use type \"card\" instead');\n\n // source (required for source nodes)\n if (n.source == null || typeof n.source !== 'object' || Array.isArray(n.source)) {\n errors.push('source: required for source nodes, must be an object');\n } else {\n const src = n.source as Record<string, unknown>;\n if (!src.kind || !VALID_SOURCE_KINDS.has(src.kind as string)) {\n errors.push(`source.kind: required, must be one of: ${[...VALID_SOURCE_KINDS].join(', ')}`);\n }\n if (typeof src.bindTo !== 'string' || !src.bindTo) {\n errors.push('source.bindTo: required, must be a state path string');\n } else if (!(src.bindTo as string).startsWith('state.')) {\n errors.push('source.bindTo: must start with \"state.\"');\n }\n }\n }\n\n return { ok: errors.length === 0, errors };\n}\n\nexport const CardCompute = {\n run,\n eval: evalExpr,\n resolve,\n validate: validateNode,\n registerFunction,\n get functions(): Record<string, ComputeFn> {\n const all: Record<string, ComputeFn> = {};\n for (const k of Object.keys(_fns)) all[k] = _fns[k];\n for (const k of Object.keys(_customFns)) all[k] = _customFns[k];\n return all;\n },\n};\n\nexport default CardCompute;\n"]}
package/dist/index.cjs CHANGED
@@ -3584,10 +3584,142 @@ function resolve(node, path) {
3584
3584
  function registerFunction(name, fn) {
3585
3585
  _customFns[name] = fn;
3586
3586
  }
3587
+ var VALID_ELEMENT_KINDS = /* @__PURE__ */ new Set([
3588
+ "metric",
3589
+ "table",
3590
+ "chart",
3591
+ "form",
3592
+ "filter",
3593
+ "list",
3594
+ "notes",
3595
+ "todo",
3596
+ "alert",
3597
+ "narrative",
3598
+ "badge",
3599
+ "text",
3600
+ "markdown",
3601
+ "custom"
3602
+ ]);
3603
+ var VALID_SOURCE_KINDS = /* @__PURE__ */ new Set(["api", "websocket", "static", "llm"]);
3604
+ var VALID_STATUSES = /* @__PURE__ */ new Set(["fresh", "stale", "loading", "error"]);
3605
+ var CARD_ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "type", "meta", "data", "view", "state", "compute"]);
3606
+ var SOURCE_ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "type", "meta", "data", "source", "state", "compute"]);
3607
+ function validateNode(node) {
3608
+ const errors = [];
3609
+ if (!node || typeof node !== "object" || Array.isArray(node)) {
3610
+ return { ok: false, errors: ["Node must be a non-null object"] };
3611
+ }
3612
+ const n = node;
3613
+ if (typeof n.id !== "string" || !n.id) {
3614
+ errors.push("id: required, must be a non-empty string");
3615
+ }
3616
+ if (n.type !== "card" && n.type !== "source") {
3617
+ errors.push('type: must be "card" or "source"');
3618
+ return { ok: false, errors };
3619
+ }
3620
+ const allowed = n.type === "card" ? CARD_ALLOWED_KEYS : SOURCE_ALLOWED_KEYS;
3621
+ for (const key of Object.keys(n)) {
3622
+ if (!allowed.has(key)) errors.push(`Unknown top-level key: "${key}"`);
3623
+ }
3624
+ if (n.state == null || typeof n.state !== "object" || Array.isArray(n.state)) {
3625
+ errors.push("state: required, must be an object");
3626
+ } else {
3627
+ const state = n.state;
3628
+ if (state.status != null && !VALID_STATUSES.has(state.status)) {
3629
+ errors.push(`state.status: must be one of: ${[...VALID_STATUSES].join(", ")}`);
3630
+ }
3631
+ }
3632
+ if (n.meta != null) {
3633
+ if (typeof n.meta !== "object" || Array.isArray(n.meta)) {
3634
+ errors.push("meta: must be an object");
3635
+ } else {
3636
+ const meta = n.meta;
3637
+ if (meta.title != null && typeof meta.title !== "string") errors.push("meta.title: must be a string");
3638
+ if (meta.tags != null && !Array.isArray(meta.tags)) errors.push("meta.tags: must be an array");
3639
+ }
3640
+ }
3641
+ if (n.data != null) {
3642
+ if (typeof n.data !== "object" || Array.isArray(n.data)) {
3643
+ errors.push("data: must be an object");
3644
+ } else {
3645
+ const data = n.data;
3646
+ if (data.requires != null && !Array.isArray(data.requires)) errors.push("data.requires: must be an array of strings");
3647
+ if (data.provides != null && (typeof data.provides !== "object" || Array.isArray(data.provides))) errors.push("data.provides: must be an object");
3648
+ }
3649
+ }
3650
+ if (n.compute != null) {
3651
+ if (typeof n.compute !== "object" || Array.isArray(n.compute)) {
3652
+ errors.push("compute: must be an object");
3653
+ } else {
3654
+ for (const [key, expr] of Object.entries(n.compute)) {
3655
+ if (!expr || typeof expr !== "object" || Array.isArray(expr)) {
3656
+ errors.push(`compute.${key}: must be a compute expression object`);
3657
+ } else if (!expr.fn) {
3658
+ errors.push(`compute.${key}: missing required "fn" property`);
3659
+ } else {
3660
+ const fn = expr.fn;
3661
+ if (!_fns[fn] && !_customFns[fn]) {
3662
+ errors.push(`compute.${key}: unknown function "${fn}"`);
3663
+ }
3664
+ }
3665
+ }
3666
+ }
3667
+ }
3668
+ if (n.type === "card") {
3669
+ if (n.source != null) errors.push('Card nodes must not have "source" \u2014 use type "source" instead');
3670
+ if (n.view == null || typeof n.view !== "object" || Array.isArray(n.view)) {
3671
+ errors.push("view: required for card nodes, must be an object");
3672
+ } else {
3673
+ const view = n.view;
3674
+ if (!Array.isArray(view.elements) || view.elements.length === 0) {
3675
+ errors.push("view.elements: required, must be a non-empty array");
3676
+ } else {
3677
+ view.elements.forEach((elem, i) => {
3678
+ if (!elem || typeof elem !== "object") {
3679
+ errors.push(`view.elements[${i}]: must be an object`);
3680
+ return;
3681
+ }
3682
+ if (!elem.kind || typeof elem.kind !== "string") {
3683
+ errors.push(`view.elements[${i}].kind: required, must be a string`);
3684
+ } else if (!VALID_ELEMENT_KINDS.has(elem.kind)) {
3685
+ errors.push(`view.elements[${i}].kind: unknown kind "${elem.kind}". Valid: ${[...VALID_ELEMENT_KINDS].join(", ")}`);
3686
+ }
3687
+ if (elem.data != null && (typeof elem.data !== "object" || Array.isArray(elem.data))) {
3688
+ errors.push(`view.elements[${i}].data: must be an object`);
3689
+ }
3690
+ });
3691
+ }
3692
+ if (view.layout != null && (typeof view.layout !== "object" || Array.isArray(view.layout))) {
3693
+ errors.push("view.layout: must be an object");
3694
+ }
3695
+ if (view.features != null && (typeof view.features !== "object" || Array.isArray(view.features))) {
3696
+ errors.push("view.features: must be an object");
3697
+ }
3698
+ }
3699
+ }
3700
+ if (n.type === "source") {
3701
+ if (n.view != null) errors.push('Source nodes must not have "view" \u2014 use type "card" instead');
3702
+ if (n.source == null || typeof n.source !== "object" || Array.isArray(n.source)) {
3703
+ errors.push("source: required for source nodes, must be an object");
3704
+ } else {
3705
+ const src = n.source;
3706
+ if (!src.kind || !VALID_SOURCE_KINDS.has(src.kind)) {
3707
+ errors.push(`source.kind: required, must be one of: ${[...VALID_SOURCE_KINDS].join(", ")}`);
3708
+ }
3709
+ if (typeof src.bindTo !== "string" || !src.bindTo) {
3710
+ errors.push("source.bindTo: required, must be a state path string");
3711
+ } else if (!src.bindTo.startsWith("state.")) {
3712
+ errors.push('source.bindTo: must start with "state."');
3713
+ }
3714
+ }
3715
+ }
3716
+ return { ok: errors.length === 0, errors };
3717
+ }
3587
3718
  var CardCompute = {
3588
3719
  run,
3589
3720
  eval: evalExpr,
3590
3721
  resolve,
3722
+ validate: validateNode,
3591
3723
  registerFunction,
3592
3724
  get functions() {
3593
3725
  const all = {};