@lambda-development/erp-core 0.8.28 → 0.8.30

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.
@@ -0,0 +1,97 @@
1
+ export type RuntimeDataset = {
2
+ name: string;
3
+ rows: Array<Record<string, unknown>>;
4
+ };
5
+ type ValueFormat = "currency" | "percent" | "number" | "date" | "string";
6
+ type AggregateOp = "sum" | "count" | "avg" | "min" | "max";
7
+ export type DeclarativeReportDefinition = {
8
+ version: 1;
9
+ summary?: string;
10
+ kpis?: Array<{
11
+ label: string;
12
+ source: string;
13
+ op: AggregateOp;
14
+ field?: string;
15
+ format?: Exclude<ValueFormat, "string">;
16
+ }>;
17
+ tables: Array<{
18
+ id: string;
19
+ title: string;
20
+ source: string;
21
+ dimensions?: Array<{
22
+ field: string;
23
+ key?: string;
24
+ bucket?: "month" | "quarter" | "year";
25
+ fallback?: string;
26
+ }>;
27
+ measures?: Array<{
28
+ key: string;
29
+ label?: string;
30
+ op: AggregateOp;
31
+ field?: string;
32
+ type?: "currency" | "percent" | "number";
33
+ }>;
34
+ columns: Array<{
35
+ key: string;
36
+ label: string;
37
+ type?: ValueFormat;
38
+ }>;
39
+ sort?: Array<{
40
+ field: string;
41
+ direction?: "asc" | "desc";
42
+ }>;
43
+ limit?: number;
44
+ }>;
45
+ charts?: Array<{
46
+ id?: string;
47
+ title: string;
48
+ type: "bar" | "line" | "pie";
49
+ data_table: string;
50
+ x: string;
51
+ y: string;
52
+ }>;
53
+ };
54
+ export type DeclarativeReportSpec = {
55
+ title: string;
56
+ description?: string;
57
+ data_requests: Array<{
58
+ name?: string;
59
+ dataset: string;
60
+ fields?: string[];
61
+ filters?: Record<string, unknown>;
62
+ limit?: number;
63
+ }>;
64
+ report: DeclarativeReportDefinition;
65
+ };
66
+ export type RuntimeReportOutput = {
67
+ title?: string;
68
+ summary?: string;
69
+ kpis?: Array<{
70
+ label: string;
71
+ value: number | string;
72
+ format?: Exclude<ValueFormat, "string">;
73
+ }>;
74
+ tables?: Array<{
75
+ id?: string;
76
+ title: string;
77
+ columns: Array<{
78
+ key: string;
79
+ label: string;
80
+ type?: ValueFormat;
81
+ format?: string;
82
+ }>;
83
+ rows: Array<Record<string, unknown>>;
84
+ }>;
85
+ charts?: Array<{
86
+ id?: string;
87
+ title: string;
88
+ type: "bar" | "line" | "pie";
89
+ dataTable?: string;
90
+ data?: Array<Record<string, unknown>>;
91
+ x: string;
92
+ y: string;
93
+ }>;
94
+ };
95
+ /** Execute a bounded data-description language. No report-provided string is evaluated as code. */
96
+ export declare function executeDeclarativeReport(spec: DeclarativeReportSpec, datasets: RuntimeDataset[]): RuntimeReportOutput;
97
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambda-development/erp-core",
3
- "version": "0.8.28",
3
+ "version": "0.8.30",
4
4
  "description": "Frontend core of Lambda ERP — app shell, document/master pages, chat UI, reports, and extension registries.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -1 +0,0 @@
1
- {"version":3,"file":"report-runtime.worker-DrBTCfV6.js","sources":["../src/workers/report-runtime.worker.ts"],"sourcesContent":["type RuntimeDataset = {\n name: string;\n dataset: string;\n rows: Array<Record<string, unknown>>;\n fields: Record<string, string>;\n};\n\ntype RuntimeMessage = {\n datasets: RuntimeDataset[];\n params?: Record<string, unknown>;\n transformJs: string;\n};\n\nfunction flt(value: unknown, precision?: number) {\n const n = Number(value ?? 0) || 0;\n return precision == null ? n : Number(n.toFixed(precision));\n}\n\nconst helpers = {\n flt,\n sum<T extends Record<string, unknown>>(rows: T[], fieldOrFn?: string | ((row: T) => unknown)) {\n return rows.reduce((acc, row) => {\n if (typeof fieldOrFn === \"function\") return acc + flt(fieldOrFn(row));\n if (typeof fieldOrFn === \"string\") return acc + flt(row[fieldOrFn]);\n return acc + flt(row as unknown);\n }, 0);\n },\n count<T>(rows: T[]) {\n return rows.length;\n },\n sortBy<T extends Record<string, unknown>>(rows: T[], field: string, dir: \"asc\" | \"desc\" | boolean = \"asc\") {\n const normalizedDir = dir === true ? \"desc\" : dir === false ? \"asc\" : dir;\n const factor = normalizedDir === \"desc\" ? -1 : 1;\n return [...rows].sort((a, b) => {\n const av = a[field];\n const bv = b[field];\n if (av == null && bv == null) return 0;\n if (av == null) return 1;\n if (bv == null) return -1;\n if (av < bv) return -1 * factor;\n if (av > bv) return 1 * factor;\n return 0;\n });\n },\n topN<T extends Record<string, unknown>>(rows: T[], fieldOrN: string | number, n = 10) {\n if (typeof fieldOrN === \"number\") return rows.slice(0, fieldOrN);\n return helpers.sortBy(rows, fieldOrN, \"desc\").slice(0, n);\n },\n group<T extends Record<string, unknown>>(\n rows: T[],\n keysOrFn: string[] | ((row: T) => unknown),\n measures?: Record<string, [\"sum\" | \"count\", string?]>,\n ) {\n if (typeof keysOrFn === \"function\") {\n const map = new Map<string, { key: unknown; rows: T[] }>();\n for (const row of rows) {\n const key = keysOrFn(row);\n const mapKey = JSON.stringify(key);\n if (!map.has(mapKey)) {\n map.set(mapKey, { key, rows: [] });\n }\n map.get(mapKey)!.rows.push(row);\n }\n return Array.from(map.values());\n }\n\n const keys = keysOrFn;\n const map = new Map<string, Record<string, unknown>>();\n for (const row of rows) {\n const keyValues = keys.map((key) => row[key]);\n const mapKey = JSON.stringify(keyValues);\n if (!map.has(mapKey)) {\n const seed: Record<string, unknown> = {};\n keys.forEach((key, idx) => {\n seed[key] = keyValues[idx];\n });\n for (const [alias, [op]] of Object.entries(measures || {})) {\n seed[alias] = op === \"count\" ? 0 : 0;\n }\n map.set(mapKey, seed);\n }\n const bucket = map.get(mapKey)!;\n for (const [alias, [op, field]] of Object.entries(measures || {})) {\n if (op === \"count\") {\n bucket[alias] = flt(bucket[alias]) + 1;\n } else {\n bucket[alias] = flt(bucket[alias]) + flt(row[field || alias]);\n }\n }\n }\n return Array.from(map.values());\n },\n leftJoin<\n TLeft extends Record<string, unknown>,\n TRight extends Record<string, unknown>,\n >(left: TLeft[], right: TRight[], leftKey: string, rightKey = leftKey) {\n const index = new Map(right.map((row) => [row[rightKey], row]));\n return left.map((row) => ({\n ...row,\n ...(index.get(row[leftKey]) || {}),\n }));\n },\n monthKey(value: unknown) {\n return String(value ?? \"\").slice(0, 7);\n },\n quarterKey(value: unknown) {\n const s = String(value ?? \"\");\n const year = s.slice(0, 4);\n const month = Number(s.slice(5, 7));\n if (!year || !month) return \"\";\n return `${year}-Q${Math.floor((month + 2) / 3)}`;\n },\n yearKey(value: unknown) {\n return String(value ?? \"\").slice(0, 4);\n },\n pivot(\n rows: Array<Record<string, unknown>>,\n indexField: string,\n columnField: string,\n valueField: string,\n ) {\n const buckets = new Map<string, Record<string, unknown>>();\n for (const row of rows) {\n const index = String(row[indexField] ?? \"—\");\n const column = String(row[columnField] ?? \"—\");\n if (!buckets.has(index)) {\n buckets.set(index, { [indexField]: index });\n }\n const bucket = buckets.get(index)!;\n bucket[column] = flt(bucket[column]) + flt(row[valueField]);\n }\n return Array.from(buckets.values());\n },\n};\n\nfunction validateOutput(output: any) {\n if (!output || typeof output !== \"object\") {\n throw new Error(\"Transform must return an object\");\n }\n if (output.tables && !Array.isArray(output.tables)) {\n throw new Error(\"tables must be an array\");\n }\n if (output.charts && !Array.isArray(output.charts)) {\n throw new Error(\"charts must be an array\");\n }\n if (output.kpis && !Array.isArray(output.kpis)) {\n throw new Error(\"kpis must be an array\");\n }\n return output;\n}\n\nself.onmessage = (event: MessageEvent<RuntimeMessage>) => {\n try {\n const datasetMap = Object.fromEntries(event.data.datasets.map((d) => [d.name, d.rows]));\n const scopeDecl = event.data.datasets\n .map((d) => d.name)\n .filter((name) => /^[$A-Z_][0-9A-Z_$]*$/i.test(name))\n .map((name) => `const ${name} = datasets[${JSON.stringify(name)}];`)\n .join(\"\\n\");\n const transform = new Function(\n \"datasets\",\n \"params\",\n \"helpers\",\n `\"use strict\";\\n${scopeDecl}\\n${event.data.transformJs}`,\n );\n const output = transform(datasetMap, event.data.params || {}, helpers);\n self.postMessage({ ok: true, output: validateOutput(output) });\n } catch (error) {\n self.postMessage({\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n};\n"],"names":["flt","value","precision","n","helpers","rows","fieldOrFn","acc","row","field","dir","factor","a","b","av","bv","fieldOrN","keysOrFn","measures","map","key","mapKey","keys","keyValues","seed","idx","alias","op","bucket","left","right","leftKey","rightKey","index","s","year","month","indexField","columnField","valueField","buckets","column","validateOutput","output","event","datasetMap","d","scopeDecl","name","error"],"mappings":"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"}
@@ -1 +0,0 @@
1
- export {};