@narrative.io/data-collaboration-sdk-ts 3.0.0 → 3.1.0
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/build/datasets/types.d.ts +11 -1
- package/build/nql/AstParser.js +77 -5
- package/package.json +2 -2
|
@@ -21,7 +21,17 @@ export interface Dataset {
|
|
|
21
21
|
is_narrative_managed: boolean;
|
|
22
22
|
external_id?: string;
|
|
23
23
|
data_plane?: DataPlane;
|
|
24
|
-
materialized_view_config?:
|
|
24
|
+
materialized_view_config?: {
|
|
25
|
+
nql: string;
|
|
26
|
+
refresh_schedule_config?: {
|
|
27
|
+
schedule: string;
|
|
28
|
+
schedule_zone_id: string;
|
|
29
|
+
status: "active" | "pending" | "archived";
|
|
30
|
+
updated_at: string;
|
|
31
|
+
created_at: string;
|
|
32
|
+
stats_enabled?: boolean;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
25
35
|
compute_pool_config?: {
|
|
26
36
|
default_compute_pool_id?: string;
|
|
27
37
|
};
|
package/build/nql/AstParser.js
CHANGED
|
@@ -32,14 +32,86 @@ export function parseExplain(n) {
|
|
|
32
32
|
return nqlOrFail(n);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
+
function isRecord(value) {
|
|
36
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
37
|
+
}
|
|
38
|
+
function walkNodes(value, visit) {
|
|
39
|
+
if (Array.isArray(value)) {
|
|
40
|
+
for (const item of value)
|
|
41
|
+
walkNodes(item, visit);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (isRecord(value)) {
|
|
45
|
+
visit(value);
|
|
46
|
+
for (const key of Object.keys(value))
|
|
47
|
+
walkNodes(value[key], visit);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// The server qualifies first-party (`company_data`) refs by dataset NAME when a
|
|
51
|
+
// query was written by name (e.g. `company_data.my_dataset`), echoing the name in
|
|
52
|
+
// the `table` field and carrying the numeric dataset id only in a table node's
|
|
53
|
+
// `metadata.id`. `parseTable`/`parseColumnRef` bind a dataset node only when
|
|
54
|
+
// `table` is the numeric id, so we first rewrite name-qualified first-party refs
|
|
55
|
+
// back to their id: build a name/alias -> id map from the FROM tables' metadata,
|
|
56
|
+
// then rewrite both the table refs and the column refs that point at them. Id-form
|
|
57
|
+
// queries are unaffected, and non-`company_data` schemas (e.g. third-party access
|
|
58
|
+
// rules `<slug>.<name>`) are left untouched.
|
|
59
|
+
function resolveFirstPartyDatasetId(node) {
|
|
60
|
+
const table = node.table;
|
|
61
|
+
if (typeof table === "string" && /^\d+$/.test(table)) {
|
|
62
|
+
return Number.parseInt(table, 10);
|
|
63
|
+
}
|
|
64
|
+
const metadata = node.metadata;
|
|
65
|
+
if (isRecord(metadata)) {
|
|
66
|
+
const id = metadata.id;
|
|
67
|
+
if (typeof id === "number")
|
|
68
|
+
return id;
|
|
69
|
+
if (typeof id === "string" && /^\d+$/.test(id)) {
|
|
70
|
+
return Number.parseInt(id, 10);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
function normalizeFirstPartyRefs(n) {
|
|
76
|
+
const clone = JSON.parse(JSON.stringify(n));
|
|
77
|
+
const idByRef = new Map();
|
|
78
|
+
// Pass 1: first-party FROM tables — record name/alias -> id, rewrite to id.
|
|
79
|
+
walkNodes(clone, (node) => {
|
|
80
|
+
if (node.type !== "table" || node.schema !== "company_data")
|
|
81
|
+
return;
|
|
82
|
+
const id = resolveFirstPartyDatasetId(node);
|
|
83
|
+
if (id === undefined)
|
|
84
|
+
return;
|
|
85
|
+
if (typeof node.table === "string")
|
|
86
|
+
idByRef.set(node.table, id);
|
|
87
|
+
if (typeof node.as === "string")
|
|
88
|
+
idByRef.set(node.as, id);
|
|
89
|
+
idByRef.set(String(id), id);
|
|
90
|
+
node.table = String(id);
|
|
91
|
+
});
|
|
92
|
+
if (idByRef.size === 0)
|
|
93
|
+
return clone;
|
|
94
|
+
// Pass 2: first-party column refs still qualified by name -> rewrite to id.
|
|
95
|
+
walkNodes(clone, (node) => {
|
|
96
|
+
if (node.type !== "column" || node.schema !== "company_data")
|
|
97
|
+
return;
|
|
98
|
+
if (typeof node.table !== "string" || /^\d+$/.test(node.table))
|
|
99
|
+
return;
|
|
100
|
+
const id = idByRef.get(node.table);
|
|
101
|
+
if (id !== undefined)
|
|
102
|
+
node.table = String(id);
|
|
103
|
+
});
|
|
104
|
+
return clone;
|
|
105
|
+
}
|
|
35
106
|
export function parseSelect(n) {
|
|
107
|
+
const normalized = normalizeFirstPartyRefs(n);
|
|
36
108
|
const select = {
|
|
37
109
|
type: "select",
|
|
38
|
-
budget:
|
|
39
|
-
columns:
|
|
40
|
-
deduplication: parseDeduplication(
|
|
41
|
-
from:
|
|
42
|
-
where:
|
|
110
|
+
budget: normalized.budget,
|
|
111
|
+
columns: normalized.columns.map((col) => parseOutput(col)),
|
|
112
|
+
deduplication: parseDeduplication(normalized),
|
|
113
|
+
from: normalized.from !== null ? parseFrom(normalized.from) : [],
|
|
114
|
+
where: normalized.where !== null ? parseWhere(normalized.where) : null,
|
|
43
115
|
};
|
|
44
116
|
return select;
|
|
45
117
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@narrative.io/data-collaboration-sdk-ts",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"main": "build/index.js",
|
|
5
5
|
"repository": "github:narrative-io/data-collaboration-sdk-ts",
|
|
6
6
|
"source": "src/index.ts",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"zod": "4.4.3",
|
|
44
|
-
"bignumber.js": "11.1.
|
|
44
|
+
"bignumber.js": "11.1.3"
|
|
45
45
|
},
|
|
46
46
|
"overrides": {
|
|
47
47
|
"semver@<7.5.2": "7.5.2"
|