tplm-lang 0.3.1 → 0.3.3
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 +23 -2
- package/dist/compiler/grid-spec-builder.js +56 -0
- package/dist/executor/index.d.ts +7 -1
- package/dist/executor/index.js +10 -0
- package/dist/index.cjs +11092 -0
- package/dist/index.d.ts +30 -2
- package/dist/index.js +37 -2
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -84,6 +84,16 @@ const tpl = fromBigQueryTable({
|
|
|
84
84
|
credentialsPath: "./credentials.json",
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
+
// Pre-built connection (any Malloy Connection instance)
|
|
88
|
+
import { fromConnection } from "tplm-lang";
|
|
89
|
+
import { BigQueryConnection } from "@malloydata/db-bigquery";
|
|
90
|
+
const conn = new BigQueryConnection("bigquery", {}, { credentials });
|
|
91
|
+
const tpl = fromConnection({
|
|
92
|
+
connection: conn,
|
|
93
|
+
table: "project.dataset.sales",
|
|
94
|
+
dialect: "bigquery",
|
|
95
|
+
});
|
|
96
|
+
|
|
87
97
|
// Then query the same way
|
|
88
98
|
const { html } = await tpl.query("TABLE ROWS region * revenue.sum;");
|
|
89
99
|
```
|
|
@@ -184,18 +194,29 @@ COLS education * (revenue.sum ACROSS COLS | revenue.mean)
|
|
|
184
194
|
### Easy Connectors (Recommended)
|
|
185
195
|
|
|
186
196
|
```typescript
|
|
187
|
-
import {
|
|
197
|
+
import {
|
|
198
|
+
fromCSV, fromDuckDBTable, fromBigQueryTable, fromConnection
|
|
199
|
+
} from "tplm-lang";
|
|
188
200
|
|
|
189
201
|
// CSV or Parquet files
|
|
190
202
|
const tpl = fromCSV("data/sales.csv");
|
|
191
203
|
const tpl = fromDuckDBTable("data/sales.parquet");
|
|
192
204
|
|
|
193
|
-
// BigQuery
|
|
205
|
+
// BigQuery (file-based credentials)
|
|
194
206
|
const tpl = fromBigQueryTable({
|
|
195
207
|
table: "project.dataset.sales",
|
|
196
208
|
credentialsPath: "./credentials.json",
|
|
197
209
|
});
|
|
198
210
|
|
|
211
|
+
// Pre-built connection (inject any Malloy Connection instance)
|
|
212
|
+
import { BigQueryConnection } from "@malloydata/db-bigquery";
|
|
213
|
+
const conn = new BigQueryConnection("bigquery", {}, { credentials });
|
|
214
|
+
const tpl = fromConnection({
|
|
215
|
+
connection: conn,
|
|
216
|
+
table: "project.dataset.sales",
|
|
217
|
+
dialect: "bigquery", // or "duckdb"
|
|
218
|
+
});
|
|
219
|
+
|
|
199
220
|
// Add computed dimensions with .extend()
|
|
200
221
|
const tplWithDims = tpl.extend(`
|
|
201
222
|
dimension: region is pick 'North' when region_code = 1 else 'South'
|
|
@@ -12,6 +12,58 @@
|
|
|
12
12
|
import { collectBranches, } from "./table-spec.js";
|
|
13
13
|
// Module-level reference to ordering provider for definition-order sorting
|
|
14
14
|
let currentOrderingProvider;
|
|
15
|
+
// ---
|
|
16
|
+
// DATE NORMALIZATION
|
|
17
|
+
// ---
|
|
18
|
+
/**
|
|
19
|
+
* Normalize a raw data value: converts Date objects to formatted strings
|
|
20
|
+
* so they display cleanly as headers and work correctly with Set-based
|
|
21
|
+
* deduplication and value-based cell lookup.
|
|
22
|
+
*
|
|
23
|
+
* Dates at midnight UTC (date-only) become "YYYY-MM-DD".
|
|
24
|
+
* Timestamps with a time component become "YYYY-MM-DD HH:MM:SS".
|
|
25
|
+
*/
|
|
26
|
+
function normalizeDimValue(value) {
|
|
27
|
+
if (value instanceof Date) {
|
|
28
|
+
const iso = value.toISOString();
|
|
29
|
+
return iso.endsWith("T00:00:00.000Z")
|
|
30
|
+
? iso.slice(0, 10)
|
|
31
|
+
: iso.slice(0, 19).replace("T", " ");
|
|
32
|
+
}
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Recursively normalize all Date values in query result rows.
|
|
37
|
+
* This ensures Date objects are converted to formatted strings before
|
|
38
|
+
* any downstream processing (header extraction, cell indexing, etc.).
|
|
39
|
+
*/
|
|
40
|
+
function normalizeResultRow(row) {
|
|
41
|
+
const normalized = {};
|
|
42
|
+
for (const key of Object.keys(row)) {
|
|
43
|
+
const val = row[key];
|
|
44
|
+
if (Array.isArray(val)) {
|
|
45
|
+
normalized[key] = val.map((item) => item && typeof item === "object" && !Array.isArray(item) && !(item instanceof Date)
|
|
46
|
+
? normalizeResultRow(item)
|
|
47
|
+
: normalizeDimValue(item));
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
normalized[key] = normalizeDimValue(val);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return normalized;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Normalize all Date objects in query results to formatted strings.
|
|
57
|
+
* Applied once at the entry point so all downstream code sees
|
|
58
|
+
* consistent string values instead of raw Date objects.
|
|
59
|
+
*/
|
|
60
|
+
function normalizeQueryResults(results) {
|
|
61
|
+
const normalized = new Map();
|
|
62
|
+
for (const [queryId, rows] of results) {
|
|
63
|
+
normalized.set(queryId, rows.map(normalizeResultRow));
|
|
64
|
+
}
|
|
65
|
+
return normalized;
|
|
66
|
+
}
|
|
15
67
|
/**
|
|
16
68
|
* Build a GridSpec from a TableSpec and query results.
|
|
17
69
|
*
|
|
@@ -33,6 +85,10 @@ export function buildGridSpec(spec, plan, results, malloyQueriesOrOptions) {
|
|
|
33
85
|
}
|
|
34
86
|
// Set module-level ordering provider for definition-order sorting
|
|
35
87
|
currentOrderingProvider = orderingProvider;
|
|
88
|
+
// Normalize Date objects in results to formatted strings before any processing.
|
|
89
|
+
// Malloy's toObject() returns JS Date objects for date/timestamp columns, which
|
|
90
|
+
// cause issues with Set-based dedup, value comparison, and display formatting.
|
|
91
|
+
results = normalizeQueryResults(results);
|
|
36
92
|
try {
|
|
37
93
|
// Build maps of query ID to special handling flags
|
|
38
94
|
const invertedQueries = new Set();
|
package/dist/executor/index.d.ts
CHANGED
|
@@ -50,6 +50,12 @@ export declare function createLocalConnection(): Promise<Connection>;
|
|
|
50
50
|
*/
|
|
51
51
|
export declare function getConnection(): Promise<Connection>;
|
|
52
52
|
export declare function getConnectionType(): ConnectionType | null;
|
|
53
|
+
/**
|
|
54
|
+
* Inject a pre-built Malloy connection directly.
|
|
55
|
+
* Use this when you already have a configured Connection instance
|
|
56
|
+
* (e.g., a BigQueryConnection with in-memory credentials).
|
|
57
|
+
*/
|
|
58
|
+
export declare function setConnection(conn: Connection, type: ConnectionType): void;
|
|
53
59
|
export declare function listDatasets(): Promise<string[]>;
|
|
54
60
|
export declare function listTables(dataset: string): Promise<{
|
|
55
61
|
name: string;
|
|
@@ -80,4 +86,4 @@ export declare function executeMalloy(malloySource: string, options?: ExecuteOpt
|
|
|
80
86
|
*/
|
|
81
87
|
export declare function executeSQL(sql: string): Promise<any[]>;
|
|
82
88
|
export { Runtime };
|
|
83
|
-
export type { DuckDBConnection, BigQueryConnection };
|
|
89
|
+
export type { Connection, DuckDBConnection, BigQueryConnection };
|
package/dist/executor/index.js
CHANGED
|
@@ -134,6 +134,16 @@ export function getConnectionType() {
|
|
|
134
134
|
}
|
|
135
135
|
return currentConnectionType;
|
|
136
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Inject a pre-built Malloy connection directly.
|
|
139
|
+
* Use this when you already have a configured Connection instance
|
|
140
|
+
* (e.g., a BigQueryConnection with in-memory credentials).
|
|
141
|
+
*/
|
|
142
|
+
export function setConnection(conn, type) {
|
|
143
|
+
connectionInstance = conn;
|
|
144
|
+
currentConnectionType = type;
|
|
145
|
+
pendingOptions = null;
|
|
146
|
+
}
|
|
137
147
|
// ---
|
|
138
148
|
// SCHEMA EXPLORATION (BigQuery only)
|
|
139
149
|
// ---
|