@ai-matrx/records 0.93.1 → 0.93.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/CHANGELOG.md +29 -0
- package/dist/{client-D4mLGnph.d.ts → client-DM3dRewB.d.ts} +1 -1
- package/dist/{client-BPcc-V2O.d.cts → client-icpxhaRE.d.cts} +1 -1
- package/dist/core/index.d.cts +3 -3
- package/dist/core/index.d.ts +3 -3
- package/dist/data/index.d.cts +2 -2
- package/dist/data/index.d.ts +2 -2
- package/dist/{declareTable-BSHX1Abl.d.cts → declareTable-BtpsSJCr.d.cts} +1 -1
- package/dist/{declareTable-Br_4v6L7.d.ts → declareTable-MN4WuhWK.d.ts} +1 -1
- package/dist/first-page/index.cjs +627 -0
- package/dist/first-page/index.cjs.map +1 -0
- package/dist/first-page/index.d.cts +1298 -0
- package/dist/first-page/index.d.ts +1298 -0
- package/dist/first-page/index.js +604 -0
- package/dist/first-page/index.js.map +1 -0
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/memory/index.d.cts +2 -2
- package/dist/memory/index.d.ts +2 -2
- package/dist/questions/index.cjs +7 -2
- package/dist/questions/index.cjs.map +1 -1
- package/dist/questions/index.d.cts +2 -2
- package/dist/questions/index.d.ts +2 -2
- package/dist/questions/index.js +7 -2
- package/dist/questions/index.js.map +1 -1
- package/dist/setup/index.d.cts +2 -2
- package/dist/setup/index.d.ts +2 -2
- package/dist/{subscription-BGgwsJ8c.d.ts → subscription-DucBLG-Y.d.ts} +1 -1
- package/dist/{subscription-DVM2vL4e.d.cts → subscription-ycCVo9e2.d.cts} +1 -1
- package/dist/templates/index.d.cts +3 -3
- package/dist/templates/index.d.ts +3 -3
- package/dist/typed-table/index.d.cts +3 -3
- package/dist/typed-table/index.d.ts +3 -3
- package/dist/{types-C3ywxkho.d.ts → types-Cl0b_Hy8.d.ts} +1 -1
- package/dist/{types-reNR-zMe.d.cts → types-SezYoQ5_.d.cts} +1 -1
- package/dist/views/index.cjs +102 -0
- package/dist/views/index.cjs.map +1 -1
- package/dist/views/index.d.cts +46 -3
- package/dist/views/index.d.ts +46 -3
- package/dist/views/index.js +102 -0
- package/dist/views/index.js.map +1 -1
- package/package.json +12 -2
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
// src/aggregate.ts
|
|
2
|
+
function isRuleFilter(filter) {
|
|
3
|
+
if (!filter || typeof filter !== "object" || Array.isArray(filter)) return false;
|
|
4
|
+
const node = filter;
|
|
5
|
+
return typeof node.op === "string" && Array.isArray(node.args);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// src/coerce.ts
|
|
9
|
+
import { isUuidShape } from "@ai-matrx/kit/uuid";
|
|
10
|
+
function fieldKindFor(field, kernel) {
|
|
11
|
+
const format = (field.format ?? "").toLowerCase();
|
|
12
|
+
const config = field.config ?? {};
|
|
13
|
+
switch (field.type) {
|
|
14
|
+
case "boolean":
|
|
15
|
+
return "checkbox";
|
|
16
|
+
case "text":
|
|
17
|
+
if (format === "email") return "email";
|
|
18
|
+
if (format === "phone") return "phone";
|
|
19
|
+
if (format === "url") return "url";
|
|
20
|
+
if (format === "json" || config["json"] === true) return "json";
|
|
21
|
+
if (format === "long" || config["multiline"] === true) return "long_text";
|
|
22
|
+
return "text";
|
|
23
|
+
case "range": {
|
|
24
|
+
const kind = String(config["kind"] ?? "number");
|
|
25
|
+
if (kind === "date" || kind === "datetime") return "datetime";
|
|
26
|
+
if (format === "currency") return "currency";
|
|
27
|
+
if (format === "percent" || field.unit === "%") return "percent";
|
|
28
|
+
return "number";
|
|
29
|
+
}
|
|
30
|
+
case "list":
|
|
31
|
+
return field.multi ? "multi_select" : "select";
|
|
32
|
+
case "relation": {
|
|
33
|
+
if (isEntityReferenceConfig(config)) return "entity_reference";
|
|
34
|
+
const parity = String(config["parity"] ?? "");
|
|
35
|
+
if (parity === "attachment" || parity === "member") return parity;
|
|
36
|
+
if (kernel?.file && field.relation_target === kernel.file) return "attachment";
|
|
37
|
+
if (kernel?.person && field.relation_target === kernel.person) return "member";
|
|
38
|
+
return "relation";
|
|
39
|
+
}
|
|
40
|
+
case "formula": {
|
|
41
|
+
const via = config["via"];
|
|
42
|
+
if (via && config["agg"]) return "rollup";
|
|
43
|
+
if (via) return "lookup";
|
|
44
|
+
return "formula";
|
|
45
|
+
}
|
|
46
|
+
default:
|
|
47
|
+
return "text";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function isEntityReferenceConfig(config) {
|
|
51
|
+
const allowed = config?.["allowed_types"];
|
|
52
|
+
return Array.isArray(allowed) && allowed.length > 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/store.generated.ts
|
|
56
|
+
var KERNEL_TABLES = [
|
|
57
|
+
{ id: "11111111-0000-4000-8000-000000000002", name: "Field" },
|
|
58
|
+
{ id: "11111111-0000-4000-8000-000000000006", name: "File" },
|
|
59
|
+
{ id: "11111111-0000-4000-8000-000000000009", name: "Merge Field" },
|
|
60
|
+
{ id: "11111111-0000-4000-8000-000000000004", name: "Organization" },
|
|
61
|
+
{ id: "11111111-0000-4000-8000-000000000005", name: "Person" },
|
|
62
|
+
{ id: "11111111-0000-4000-8000-000000000007", name: "Presentation" },
|
|
63
|
+
{ id: "11111111-0000-4000-8000-000000000003", name: "Rule" },
|
|
64
|
+
{ id: "11111111-0000-4000-8000-000000000001", name: "Table" },
|
|
65
|
+
{ id: "11111111-0000-4000-8000-000000000008", name: "Widget" }
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
// src/fieldKind.ts
|
|
69
|
+
var kernelId = (name) => KERNEL_TABLES.find((t) => t.name === name)?.id ?? "";
|
|
70
|
+
var KERNEL = { file: kernelId("File"), person: kernelId("Person") };
|
|
71
|
+
function storeFieldKind(field) {
|
|
72
|
+
return fieldKindFor(field, KERNEL);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/first-page/reads.ts
|
|
76
|
+
function holdsNumbers(field) {
|
|
77
|
+
const kind = String(storeFieldKind(field));
|
|
78
|
+
if (kind === "number" || kind === "currency" || kind === "percent") return true;
|
|
79
|
+
return String((field.config ?? {})["system"] ?? "") === "autonumber";
|
|
80
|
+
}
|
|
81
|
+
function sortAsFor(field) {
|
|
82
|
+
if (holdsNumbers(field)) return "number";
|
|
83
|
+
if (String(storeFieldKind(field)) === "datetime") return "date";
|
|
84
|
+
return "text";
|
|
85
|
+
}
|
|
86
|
+
function pageSortFor(fields, sort) {
|
|
87
|
+
if (!sort) return [];
|
|
88
|
+
const field = fields.find((f) => f.key === sort.id);
|
|
89
|
+
if (!field) return [];
|
|
90
|
+
return [{ field: field.key, direction: sort.direction === "desc" ? "desc" : "asc", as: sortAsFor(field) }];
|
|
91
|
+
}
|
|
92
|
+
function defaultSortOf(table, fields) {
|
|
93
|
+
const raw = table?.default_sort ?? null;
|
|
94
|
+
const first = Array.isArray(raw) ? raw[0] : raw;
|
|
95
|
+
let name = null;
|
|
96
|
+
let direction = "asc";
|
|
97
|
+
if (typeof first === "string") {
|
|
98
|
+
const trimmed = first.trim();
|
|
99
|
+
if (trimmed === "") return null;
|
|
100
|
+
if (trimmed.startsWith("-")) {
|
|
101
|
+
name = trimmed.slice(1).trim();
|
|
102
|
+
direction = "desc";
|
|
103
|
+
} else {
|
|
104
|
+
const [head, tail] = trimmed.split(/\s+/);
|
|
105
|
+
name = head ?? null;
|
|
106
|
+
if (tail && tail.toLowerCase() === "desc") direction = "desc";
|
|
107
|
+
}
|
|
108
|
+
} else if (first && typeof first === "object") {
|
|
109
|
+
const entry = first;
|
|
110
|
+
const named = entry["field"] ?? entry["key"] ?? entry["id"];
|
|
111
|
+
name = typeof named === "string" ? named : null;
|
|
112
|
+
if (String(entry["direction"] ?? "").toLowerCase() === "desc") direction = "desc";
|
|
113
|
+
}
|
|
114
|
+
if (!name) return null;
|
|
115
|
+
const field = fields.find((f) => f.key === name) ?? fields.find((f) => f.id === name);
|
|
116
|
+
return field ? { id: field.key, direction } : null;
|
|
117
|
+
}
|
|
118
|
+
function isPlainGrouping(grouping) {
|
|
119
|
+
return Boolean(grouping) && !(grouping.then && grouping.then.length > 0) && !grouping.across && !(grouping.trail && grouping.trail.length > 0);
|
|
120
|
+
}
|
|
121
|
+
function groupedPageSort(fields, groupKey, sort) {
|
|
122
|
+
if (!groupKey) return sort;
|
|
123
|
+
const field = fields.find((f) => f.key === groupKey);
|
|
124
|
+
if (!field) return sort;
|
|
125
|
+
return [{ field: groupKey, direction: "asc", as: sortAsFor(field) }, ...sort.filter((s) => s.field !== groupKey)];
|
|
126
|
+
}
|
|
127
|
+
var SUMMARY_OPERATIONS = [
|
|
128
|
+
"count",
|
|
129
|
+
"sum",
|
|
130
|
+
"avg",
|
|
131
|
+
"min",
|
|
132
|
+
"max",
|
|
133
|
+
"median",
|
|
134
|
+
"filled",
|
|
135
|
+
"empty",
|
|
136
|
+
"unique",
|
|
137
|
+
"percent_empty",
|
|
138
|
+
"percent_filled",
|
|
139
|
+
"range"
|
|
140
|
+
];
|
|
141
|
+
function chosenEntries(chosen) {
|
|
142
|
+
return JSON.parse(JSON.stringify(Object.entries(chosen).sort())).filter(
|
|
143
|
+
([, op]) => SUMMARY_OPERATIONS.includes(op)
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
function groupFactMeasures(chosen) {
|
|
147
|
+
return [{ op: "count" }, ...chosenEntries(chosen).filter(([, op]) => op !== "count").map(([key, op]) => ({ op, key }))];
|
|
148
|
+
}
|
|
149
|
+
function summaryBarMeasures(chosen) {
|
|
150
|
+
return chosenEntries(chosen).map(([key, op]) => op === "count" ? { op: "count" } : { op, key });
|
|
151
|
+
}
|
|
152
|
+
function choiceFieldKeys(fields) {
|
|
153
|
+
return fields.filter((f) => {
|
|
154
|
+
const kind = String(storeFieldKind(f));
|
|
155
|
+
return kind === "select" || kind === "multi_select";
|
|
156
|
+
}).map((f) => f.key);
|
|
157
|
+
}
|
|
158
|
+
var REVERSE_CELL_CHIPS = 3;
|
|
159
|
+
function viewFilterOf(shown, _fields) {
|
|
160
|
+
if (!shown) return void 0;
|
|
161
|
+
const base = shown.where ?? (shown.filters && Object.keys(shown.filters).length > 0 ? shown.filters : void 0);
|
|
162
|
+
if (!base) return void 0;
|
|
163
|
+
if (isRuleFilter(base)) return base;
|
|
164
|
+
return Object.keys(base).length > 0 ? base : void 0;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// src/first-page/seed.ts
|
|
168
|
+
import { isUuidShape as isUuidShape2 } from "@ai-matrx/kit/uuid";
|
|
169
|
+
import { asRecordsDataSource, createRecordsClient, recordingDataSource } from "@ai-matrx/records/core";
|
|
170
|
+
import { createSeedPort } from "@ai-matrx/records/entity";
|
|
171
|
+
|
|
172
|
+
// src/versions/rowVersion.ts
|
|
173
|
+
function ownVersion(row) {
|
|
174
|
+
const v = row.version;
|
|
175
|
+
return typeof v === "number" ? v : null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// src/views/keys.ts
|
|
179
|
+
var plainPresentation = {
|
|
180
|
+
parse: (raw) => raw && typeof raw === "object" && !Array.isArray(raw) ? { ...raw } : {},
|
|
181
|
+
isEmpty: (presentation) => Object.keys(presentation).length === 0,
|
|
182
|
+
toDocument: (presentation) => ({ ...presentation })
|
|
183
|
+
};
|
|
184
|
+
function plainCodec() {
|
|
185
|
+
return plainPresentation;
|
|
186
|
+
}
|
|
187
|
+
var STORE_KEEPS_TIMELINE = true;
|
|
188
|
+
var ALL = ["grid", "kanban", "calendar", "gallery", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list"];
|
|
189
|
+
var HIDES = ["grid", "gallery", "kanban", "calendar", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list"];
|
|
190
|
+
var GRIDS = ["grid"];
|
|
191
|
+
var VIEW_KEYS = [
|
|
192
|
+
{ path: "layout", shape: "kind", layouts: ALL, writer: "caller" },
|
|
193
|
+
{ path: "filters", shape: "filter", layouts: ALL, writer: "caller" },
|
|
194
|
+
{ path: "where", shape: "rule", layouts: ALL, writer: "caller" },
|
|
195
|
+
{ path: "group_field", shape: "field", layouts: ["kanban", ...STORE_KEEPS_TIMELINE ? ["timeline"] : []], writer: "caller" },
|
|
196
|
+
{ path: "swimlane_field", shape: "field:lane", layouts: ["kanban"], writer: "caller" },
|
|
197
|
+
{ path: "collapsed_columns", shape: "values", layouts: ["kanban"], writer: "caller" },
|
|
198
|
+
{ path: "measure", shape: "field:number", layouts: ["kanban"], writer: "caller" },
|
|
199
|
+
{ path: "date_field", shape: "field:date", layouts: ["calendar"], writer: "caller" },
|
|
200
|
+
...STORE_KEEPS_TIMELINE ? [
|
|
201
|
+
{ path: "start_field", shape: "field:date", layouts: ["timeline"], writer: "caller" },
|
|
202
|
+
{ path: "end_field", shape: "field:date", layouts: ["calendar", "timeline"], writer: "caller" }
|
|
203
|
+
] : [],
|
|
204
|
+
{ path: "image_field", shape: "field", layouts: ["gallery"], writer: "caller" },
|
|
205
|
+
{ path: "sorts", shape: "sorts", layouts: ALL, writer: "caller" },
|
|
206
|
+
{ path: "rule_id", shape: "uuid", layouts: ALL, writer: "caller" },
|
|
207
|
+
{ path: "is_default", shape: "boolean", layouts: ALL, writer: "caller" },
|
|
208
|
+
{ path: "presentation", shape: "presentation", layouts: ALL, writer: "caller" },
|
|
209
|
+
{ path: "presentation.style", shape: "style", layouts: ALL, writer: "caller" },
|
|
210
|
+
{ path: "presentation.formats", shape: "object", layouts: GRIDS, writer: "caller" },
|
|
211
|
+
{ path: "presentation.frozen", shape: "fields", layouts: GRIDS, writer: "caller" },
|
|
212
|
+
{ path: "presentation.grouping", shape: "grouping", layouts: ["grid", "gallery", "list"], writer: "caller" },
|
|
213
|
+
{ path: "presentation.widths", shape: "widths", layouts: GRIDS, writer: "caller" },
|
|
214
|
+
{ path: "presentation.rowHeight", shape: "row_height", layouts: GRIDS, writer: "caller" },
|
|
215
|
+
{ path: "presentation.hiddenFields", shape: "fields", layouts: HIDES, writer: "caller" },
|
|
216
|
+
{ path: "presentation.cardHidden", shape: "fields", layouts: ["kanban", "calendar", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list", "gallery"], writer: "caller" },
|
|
217
|
+
{ path: "presentation.columnOrder", shape: "fields", layouts: GRIDS, writer: "caller" },
|
|
218
|
+
{ path: "presentation.gallerySize", shape: "gallery_size", layouts: ["gallery"], writer: "caller" },
|
|
219
|
+
{ path: "presentation.wrap", shape: "boolean", layouts: GRIDS, writer: "caller" },
|
|
220
|
+
{ path: "presentation.wrapColumns", shape: "fields", layouts: GRIDS, writer: "caller" },
|
|
221
|
+
{ path: "presentation.fit", shape: "fit", layouts: GRIDS, writer: "caller" },
|
|
222
|
+
{ path: "presentation.freezeFirst", shape: "boolean", layouts: GRIDS, writer: "caller" },
|
|
223
|
+
{ path: "presentation.footer", shape: "footer", layouts: GRIDS, writer: "caller" },
|
|
224
|
+
{ path: "presentation.summaries", shape: "summaries", layouts: GRIDS, writer: "caller" },
|
|
225
|
+
{ path: "grid", shape: "grid", layouts: GRIDS, writer: "caller" },
|
|
226
|
+
{ path: "hidden_fields", shape: "input", layouts: HIDES, writer: "input" },
|
|
227
|
+
{ path: "table_id", shape: "server", layouts: ALL, writer: "server" },
|
|
228
|
+
{ path: "order", shape: "server", layouts: GRIDS, writer: "server" },
|
|
229
|
+
{ path: "moved_from", shape: "server", layouts: ALL, writer: "server" }
|
|
230
|
+
];
|
|
231
|
+
var STORE_KEPT_LAYOUTS = ["grid", "kanban", "calendar", "gallery", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list"];
|
|
232
|
+
var KINDS = STORE_KEPT_LAYOUTS;
|
|
233
|
+
function viewSettings(definition, rowFilters, codec = plainCodec()) {
|
|
234
|
+
const data = definition ?? {};
|
|
235
|
+
const text = (key) => {
|
|
236
|
+
const v = data[key];
|
|
237
|
+
return typeof v === "string" && v !== "" ? v : null;
|
|
238
|
+
};
|
|
239
|
+
const layout = String(data["layout"] ?? "grid");
|
|
240
|
+
const flat = rowFilters ?? (isObject(data["filters"]) ? data["filters"] : null);
|
|
241
|
+
const moved = data["moved_from"];
|
|
242
|
+
return {
|
|
243
|
+
layout: KINDS.includes(layout) ? layout : "grid",
|
|
244
|
+
filters: flat && Object.keys(flat).length > 0 ? flat : null,
|
|
245
|
+
where: isRule(data["where"]) ? data["where"] : null,
|
|
246
|
+
groupField: text("group_field"),
|
|
247
|
+
swimlaneField: text("swimlane_field"),
|
|
248
|
+
collapsedColumns: Array.isArray(data["collapsed_columns"]) ? data["collapsed_columns"].filter((v) => ["string", "number", "boolean"].includes(typeof v)).map(String) : [],
|
|
249
|
+
measure: text("measure"),
|
|
250
|
+
dateField: text("date_field"),
|
|
251
|
+
startField: text("start_field"),
|
|
252
|
+
endField: text("end_field"),
|
|
253
|
+
imageField: text("image_field"),
|
|
254
|
+
sorts: parseSorts(data["sorts"]),
|
|
255
|
+
ruleId: text("rule_id"),
|
|
256
|
+
isDefault: data["is_default"] === true || data["is_default"] === "true",
|
|
257
|
+
presentation: codec.parse(data["presentation"]),
|
|
258
|
+
movedFrom: isObject(moved) ? moved : null
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
function isObject(raw) {
|
|
262
|
+
return Boolean(raw) && typeof raw === "object" && !Array.isArray(raw);
|
|
263
|
+
}
|
|
264
|
+
function isRule(raw) {
|
|
265
|
+
if (!isObject(raw)) return false;
|
|
266
|
+
const node = raw;
|
|
267
|
+
return typeof node.op === "string" && Array.isArray(node.args);
|
|
268
|
+
}
|
|
269
|
+
function parseSorts(raw) {
|
|
270
|
+
let list = raw;
|
|
271
|
+
if (typeof raw === "string") {
|
|
272
|
+
try {
|
|
273
|
+
list = raw.trim() === "" ? [] : JSON.parse(raw);
|
|
274
|
+
} catch {
|
|
275
|
+
return [];
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (!Array.isArray(list)) return [];
|
|
279
|
+
return list.filter((s) => isObject(s) && typeof s.field === "string").map((s) => ({ field: s.field, direction: s.direction === "desc" ? "desc" : "asc" }));
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// src/views/views.ts
|
|
283
|
+
function plainCodec2() {
|
|
284
|
+
return plainPresentation;
|
|
285
|
+
}
|
|
286
|
+
var VIEW_LAYOUTS = ["grid", "kanban", "calendar", "gallery", "timeline", "list"];
|
|
287
|
+
var LAYOUT_LABEL = {
|
|
288
|
+
grid: "Grid",
|
|
289
|
+
kanban: "Kanban",
|
|
290
|
+
calendar: "Calendar",
|
|
291
|
+
gallery: "Gallery",
|
|
292
|
+
timeline: "Timeline",
|
|
293
|
+
list: "List"
|
|
294
|
+
};
|
|
295
|
+
function viewOrderOf(definition) {
|
|
296
|
+
const raw = definition?.["order"];
|
|
297
|
+
return raw === "manual" ? "manual" : raw === "sorted" ? "sorted" : null;
|
|
298
|
+
}
|
|
299
|
+
function defaultViewOf(views) {
|
|
300
|
+
return views.find((v) => v.isDefault);
|
|
301
|
+
}
|
|
302
|
+
var PAGE_VIEWS = [...VIEW_LAYOUTS, "dashboards", "archived"];
|
|
303
|
+
var PAGE_VIEW_LABEL = {
|
|
304
|
+
...LAYOUT_LABEL,
|
|
305
|
+
dashboards: "Dashboards",
|
|
306
|
+
archived: "Archived"
|
|
307
|
+
};
|
|
308
|
+
function viewFromRow(row, codec = plainCodec2()) {
|
|
309
|
+
const data = row.definition ?? {};
|
|
310
|
+
const k = viewSettings(data, row.filters && Object.keys(row.filters).length > 0 ? row.filters : null, codec);
|
|
311
|
+
const tableFromDefinition = typeof data["table_id"] === "string" && data["table_id"] !== "" ? data["table_id"] : null;
|
|
312
|
+
return {
|
|
313
|
+
id: row.view_id,
|
|
314
|
+
name: row.name || "Untitled view",
|
|
315
|
+
subject: row.table_id ?? tableFromDefinition ?? "",
|
|
316
|
+
layout: k.layout,
|
|
317
|
+
groupField: k.groupField,
|
|
318
|
+
swimlaneField: k.swimlaneField,
|
|
319
|
+
collapsedColumns: k.collapsedColumns,
|
|
320
|
+
measure: k.measure,
|
|
321
|
+
dateField: k.dateField,
|
|
322
|
+
startField: k.startField,
|
|
323
|
+
endField: k.endField,
|
|
324
|
+
imageField: k.imageField,
|
|
325
|
+
sorts: k.sorts,
|
|
326
|
+
order: viewOrderOf(data),
|
|
327
|
+
ruleId: k.ruleId,
|
|
328
|
+
...k.filters ? { filters: k.filters } : {},
|
|
329
|
+
where: k.where,
|
|
330
|
+
// The older table's own default view, carried in by the mover, IS this table's default —
|
|
331
|
+
// the mover wrote the row's column, which `custom.views` does not return. Read as anything
|
|
332
|
+
// else, the page would seed a second "All records" beside it and open on that.
|
|
333
|
+
isDefault: k.isDefault || k.movedFrom?.["kind"] === "default_view",
|
|
334
|
+
presentation: k.presentation,
|
|
335
|
+
movedFrom: k.movedFrom
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// src/views/look.ts
|
|
340
|
+
var plain = () => plainPresentation;
|
|
341
|
+
function lookFromDocument(doc, codec = plain()) {
|
|
342
|
+
const data = doc ?? {};
|
|
343
|
+
const read = viewSettings(data, void 0, codec);
|
|
344
|
+
const out = {};
|
|
345
|
+
const has = (key) => Object.prototype.hasOwnProperty.call(data, key);
|
|
346
|
+
if (has("layout") && VIEW_LAYOUTS.includes(String(data["layout"]))) {
|
|
347
|
+
out.layout = data["layout"];
|
|
348
|
+
}
|
|
349
|
+
if (has("group_field")) out.groupField = read.groupField;
|
|
350
|
+
if (has("swimlane_field")) out.swimlaneField = read.swimlaneField;
|
|
351
|
+
if (has("collapsed_columns")) out.collapsedColumns = read.collapsedColumns;
|
|
352
|
+
if (has("measure")) out.measure = read.measure;
|
|
353
|
+
if (has("date_field")) out.dateField = read.dateField;
|
|
354
|
+
if (has("start_field")) out.startField = read.startField;
|
|
355
|
+
if (has("end_field")) out.endField = read.endField;
|
|
356
|
+
if (has("image_field")) out.imageField = read.imageField;
|
|
357
|
+
if (has("sorts")) out.sorts = read.sorts;
|
|
358
|
+
if (has("where")) out.where = read.where;
|
|
359
|
+
if (has("presentation")) out.presentation = codec.parse(data["presentation"]);
|
|
360
|
+
return out;
|
|
361
|
+
}
|
|
362
|
+
function applyLook(view, look) {
|
|
363
|
+
if (!look) return view;
|
|
364
|
+
return { ...view, ...look };
|
|
365
|
+
}
|
|
366
|
+
async function readLooks(client, tableId, codec = plain()) {
|
|
367
|
+
const answered = await client.viewLookRead({ table_id: tableId });
|
|
368
|
+
if (!answered.ok) return answered;
|
|
369
|
+
const out = {};
|
|
370
|
+
for (const [viewId, row] of Object.entries(answered.data ?? {})) {
|
|
371
|
+
out[viewId] = lookFromDocument(row?.look ?? null, codec);
|
|
372
|
+
}
|
|
373
|
+
return { ok: true, data: out };
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// src/first-page/seed.ts
|
|
377
|
+
var TABLE_PAGE_SIZE = 100;
|
|
378
|
+
var EMBEDDED_PAGE_SIZE = 50;
|
|
379
|
+
function presentationFacts(presentation) {
|
|
380
|
+
const p = presentation && typeof presentation === "object" ? presentation : {};
|
|
381
|
+
const g = p["grouping"];
|
|
382
|
+
const grouping = g && typeof g === "object" && typeof g.field === "string" ? g : void 0;
|
|
383
|
+
const s = p["summaries"];
|
|
384
|
+
return { grouping, summaries: s && typeof s === "object" ? s : {} };
|
|
385
|
+
}
|
|
386
|
+
function firstGridPageArgs(input) {
|
|
387
|
+
const { shown, fields } = input;
|
|
388
|
+
if (!shown) return null;
|
|
389
|
+
if ((shown.layout ?? "grid") !== "grid") return null;
|
|
390
|
+
if (shown.ruleId) return null;
|
|
391
|
+
if (shown.order === "manual") return null;
|
|
392
|
+
const { grouping } = presentationFacts(shown.presentation);
|
|
393
|
+
if (grouping && !(input.merged && isPlainGrouping(grouping))) return null;
|
|
394
|
+
const first = (shown.sorts ?? [])[0];
|
|
395
|
+
const viewSort = first && fields.some((f) => f.key === first.field) ? { id: first.field, direction: first.direction } : null;
|
|
396
|
+
const opening = viewSort ?? defaultSortOf(input.table, fields);
|
|
397
|
+
return {
|
|
398
|
+
p_table_id: input.tableId,
|
|
399
|
+
p_filter: viewFilterOf(shown) ?? {},
|
|
400
|
+
p_search: null,
|
|
401
|
+
p_sort: groupedPageSort(fields, grouping?.field ?? null, pageSortFor(fields, opening)),
|
|
402
|
+
p_view_id: null,
|
|
403
|
+
p_limit: input.pageSize ?? TABLE_PAGE_SIZE,
|
|
404
|
+
p_offset: 0
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
async function firstGridPageRequest(client, tableId, options = {}) {
|
|
408
|
+
return (await firstGridOpening(client, tableId, options))?.args ?? null;
|
|
409
|
+
}
|
|
410
|
+
function shownFromSpec(spec, tableId) {
|
|
411
|
+
return { ...spec, subject: spec.subject ?? tableId, id: "", movedFrom: null };
|
|
412
|
+
}
|
|
413
|
+
async function firstGridOpening(client, tableId, options) {
|
|
414
|
+
const codec = options.codec ?? plainPresentation;
|
|
415
|
+
const explicit = options.view;
|
|
416
|
+
const [table, fields, views, looks] = await Promise.all([
|
|
417
|
+
client.tableRead({ table_id: tableId }),
|
|
418
|
+
client.fields({ table_id: tableId }),
|
|
419
|
+
explicit ? Promise.resolve(null) : client.views({ table_id: tableId }),
|
|
420
|
+
explicit ? Promise.resolve(null) : readLooks(client, tableId, codec)
|
|
421
|
+
]);
|
|
422
|
+
if (!table.ok || !fields.ok) return null;
|
|
423
|
+
let shown;
|
|
424
|
+
if (explicit) {
|
|
425
|
+
shown = shownFromSpec(explicit, tableId);
|
|
426
|
+
} else {
|
|
427
|
+
if (!views?.ok || !looks?.ok) return null;
|
|
428
|
+
const mine = views.data.map((row) => viewFromRow(row, codec)).filter((v) => v.subject === tableId);
|
|
429
|
+
const view = defaultViewOf(mine) ?? mine[0] ?? null;
|
|
430
|
+
shown = view ? applyLook(view, looks.data[view.id]) : shownFromSpec({ name: "All", subject: tableId, layout: "grid", isDefault: true }, tableId);
|
|
431
|
+
}
|
|
432
|
+
const args = firstGridPageArgs({
|
|
433
|
+
tableId,
|
|
434
|
+
table: table.data,
|
|
435
|
+
fields: fields.data,
|
|
436
|
+
shown,
|
|
437
|
+
...options.pageSize ? { pageSize: options.pageSize } : {},
|
|
438
|
+
...options.merged ? { merged: true } : {}
|
|
439
|
+
});
|
|
440
|
+
return args ? { args, shown, fields: fields.data } : null;
|
|
441
|
+
}
|
|
442
|
+
function serverRowsOf(seed) {
|
|
443
|
+
const found = seed?.answers.find((a) => a.door === "server_rows");
|
|
444
|
+
const data = found?.data;
|
|
445
|
+
if (!data || typeof data !== "object") return null;
|
|
446
|
+
return { on: data.on === true, capMs: typeof data.cap_ms === "number" && data.cap_ms > 0 ? data.cap_ms : null };
|
|
447
|
+
}
|
|
448
|
+
async function askTablePageSeed(input) {
|
|
449
|
+
const recording = recordingDataSource(asRecordsDataSource(input.dataSource));
|
|
450
|
+
const client = createRecordsClient({
|
|
451
|
+
dataSource: recording.source,
|
|
452
|
+
organizationId: input.organizationId,
|
|
453
|
+
actor: input.actor,
|
|
454
|
+
onError: () => {
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
const record = input.recordId ? Promise.resolve(
|
|
458
|
+
recording.source.rpc("record_page_bundle", { p_organization_id: input.organizationId, p_record_id: input.recordId }, { schema: "custom" })
|
|
459
|
+
).catch(() => null) : null;
|
|
460
|
+
try {
|
|
461
|
+
const pageSize = input.pageSize ?? (input.embedded ? EMBEDDED_PAGE_SIZE : TABLE_PAGE_SIZE);
|
|
462
|
+
const opening = await firstGridOpening(client, input.tableId, {
|
|
463
|
+
pageSize,
|
|
464
|
+
...input.merged ? { merged: true } : {},
|
|
465
|
+
...input.view ? { view: input.view } : {},
|
|
466
|
+
...input.codec ? { codec: input.codec } : {}
|
|
467
|
+
});
|
|
468
|
+
const wantRows = typeof input.rows === "function" ? input.rows(recording.seed()) : input.rows !== false;
|
|
469
|
+
if (opening && wantRows) {
|
|
470
|
+
const { args, shown, fields } = opening;
|
|
471
|
+
const page = await client.listPage({
|
|
472
|
+
table_id: args.p_table_id,
|
|
473
|
+
filter: args.p_filter,
|
|
474
|
+
search: args.p_search,
|
|
475
|
+
sort: args.p_sort,
|
|
476
|
+
view_id: args.p_view_id,
|
|
477
|
+
limit: args.p_limit,
|
|
478
|
+
offset: args.p_offset
|
|
479
|
+
});
|
|
480
|
+
if (page.ok) {
|
|
481
|
+
const { grouping, summaries: chosen } = presentationFacts(shown?.presentation);
|
|
482
|
+
const groupKey = grouping?.field ?? null;
|
|
483
|
+
const reads = [];
|
|
484
|
+
const filter = args.p_filter && Object.keys(args.p_filter).length > 0 ? args.p_filter : void 0;
|
|
485
|
+
if (groupKey) {
|
|
486
|
+
reads.push(client.recordAggregate({ table_id: input.tableId, groupBy: [groupKey], measures: groupFactMeasures(chosen), limit: 1e3, ...filter ? { filter } : {} }));
|
|
487
|
+
}
|
|
488
|
+
const bar = summaryBarMeasures(chosen);
|
|
489
|
+
if (bar.length > 0) reads.push(client.recordAggregate({ table_id: input.tableId, measures: bar, ...filter ? { filter } : {} }));
|
|
490
|
+
for (const field of fields) {
|
|
491
|
+
if (field.type !== "list" && field.type !== "relation") continue;
|
|
492
|
+
const ids = /* @__PURE__ */ new Set();
|
|
493
|
+
for (const row of page.data.rows) {
|
|
494
|
+
const value = row.document?.[field.key];
|
|
495
|
+
for (const id of Array.isArray(value) ? value.map(String) : typeof value === "string" ? [value] : []) if (isUuidShape2(id)) ids.add(id);
|
|
496
|
+
}
|
|
497
|
+
if (ids.size > 0) reads.push(client.relationWordsMany({ field_id: field.id, record_ids: [...ids] }));
|
|
498
|
+
}
|
|
499
|
+
if (input.merged) {
|
|
500
|
+
for (const key of choiceFieldKeys(fields)) {
|
|
501
|
+
reads.push(client.recordAggregate({ table_id: input.tableId, groupBy: [key], measures: [{ op: "count" }], limit: 500, ...filter ? { filter } : {} }));
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
const unversioned = page.data.rows.filter((row) => ownVersion(row) === null).map((row) => row.id);
|
|
505
|
+
if (unversioned.length > 0) reads.push(client.recordHeaders({ ids: unversioned }));
|
|
506
|
+
reads.push(
|
|
507
|
+
client.reverseColumns({ table_id: input.tableId }).then(async (columns) => {
|
|
508
|
+
if (!columns.ok || columns.data.length === 0) return null;
|
|
509
|
+
const record_ids = page.data.rows.map((row) => row.id);
|
|
510
|
+
const all = await client.reverseLinksFields({ table_id: input.tableId, source_field_ids: columns.data.map((c) => c.source_field_id), record_ids, limit: REVERSE_CELL_CHIPS });
|
|
511
|
+
if (all.ok || all.error.code !== "door_absent") return null;
|
|
512
|
+
return Promise.all(columns.data.map((c) => client.reverseLinksMany({ table_id: input.tableId, source_field_id: c.source_field_id, record_ids, limit: REVERSE_CELL_CHIPS })));
|
|
513
|
+
})
|
|
514
|
+
);
|
|
515
|
+
await Promise.all(reads.map((read) => read.catch(() => null)));
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
} catch {
|
|
519
|
+
}
|
|
520
|
+
if (record) await record;
|
|
521
|
+
return recording.seed();
|
|
522
|
+
}
|
|
523
|
+
function recordedClient(input) {
|
|
524
|
+
const recording = recordingDataSource(asRecordsDataSource(input.dataSource));
|
|
525
|
+
const client = createRecordsClient({ dataSource: recording.source, organizationId: input.organizationId, actor: input.actor, onError: () => {
|
|
526
|
+
} });
|
|
527
|
+
return { recording, client };
|
|
528
|
+
}
|
|
529
|
+
function entityTableQuery(options = {}) {
|
|
530
|
+
const search = (options.search ?? "").trim();
|
|
531
|
+
return { ...options.pageSize ? { pageSize: options.pageSize } : {}, ...search ? { search } : {} };
|
|
532
|
+
}
|
|
533
|
+
function entityChartQuestion(input) {
|
|
534
|
+
const m = input.measure ?? { op: "count" };
|
|
535
|
+
return {
|
|
536
|
+
...input.by ? { by: [input.by] } : {},
|
|
537
|
+
show: [m.op === "count" ? "count" : { op: m.op, of: m.of }],
|
|
538
|
+
...input.where ? { where: input.where } : {},
|
|
539
|
+
...input.organization ? { organization: input.organization } : {}
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
function mergeSeeds(...seeds) {
|
|
543
|
+
const held = seeds.filter((s) => Boolean(s));
|
|
544
|
+
const answers = /* @__PURE__ */ new Map();
|
|
545
|
+
for (const seed of held) for (const a of seed.answers) answers.set(`${a.door}|${JSON.stringify(a.args)}`, a);
|
|
546
|
+
return { at: held.length ? Math.min(...held.map((s) => s.at)) : Date.now(), answers: [...answers.values()] };
|
|
547
|
+
}
|
|
548
|
+
async function askEntityBlockSeed(input) {
|
|
549
|
+
const recording = recordingDataSource(asRecordsDataSource(input.dataSource));
|
|
550
|
+
const port = createSeedPort(recording.source);
|
|
551
|
+
try {
|
|
552
|
+
await Promise.all([port.describe(input.token), port.list(input.token, entityTableQuery(input.question ?? {}))]);
|
|
553
|
+
} catch {
|
|
554
|
+
}
|
|
555
|
+
return recording.seed();
|
|
556
|
+
}
|
|
557
|
+
async function askChartSeed(input) {
|
|
558
|
+
const { recording, client } = recordedClient(input);
|
|
559
|
+
try {
|
|
560
|
+
await client.drillAsk({ source: input.source, question: entityChartQuestion(input.question ?? {}) });
|
|
561
|
+
} catch {
|
|
562
|
+
}
|
|
563
|
+
return recording.seed();
|
|
564
|
+
}
|
|
565
|
+
async function askTileSeed(input) {
|
|
566
|
+
const { recording, client } = recordedClient(input);
|
|
567
|
+
const specs = Array.isArray(input.spec) ? input.spec : [input.spec];
|
|
568
|
+
await Promise.all(specs.map((spec) => client.recordAggregate({ table_id: input.tableId, ...spec }).catch(() => null)));
|
|
569
|
+
return recording.seed();
|
|
570
|
+
}
|
|
571
|
+
function bindFirstPageCodec(codec) {
|
|
572
|
+
return {
|
|
573
|
+
firstGridPageRequest: (client, tableId, options = {}) => firstGridPageRequest(client, tableId, { ...options, codec }),
|
|
574
|
+
askTablePageSeed: (input) => askTablePageSeed({ ...input, codec })
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
export {
|
|
578
|
+
EMBEDDED_PAGE_SIZE,
|
|
579
|
+
REVERSE_CELL_CHIPS,
|
|
580
|
+
SUMMARY_OPERATIONS,
|
|
581
|
+
TABLE_PAGE_SIZE,
|
|
582
|
+
askChartSeed,
|
|
583
|
+
askEntityBlockSeed,
|
|
584
|
+
askTablePageSeed,
|
|
585
|
+
askTileSeed,
|
|
586
|
+
bindFirstPageCodec,
|
|
587
|
+
choiceFieldKeys,
|
|
588
|
+
defaultSortOf,
|
|
589
|
+
entityChartQuestion,
|
|
590
|
+
entityTableQuery,
|
|
591
|
+
firstGridPageArgs,
|
|
592
|
+
firstGridPageRequest,
|
|
593
|
+
groupFactMeasures,
|
|
594
|
+
groupedPageSort,
|
|
595
|
+
holdsNumbers,
|
|
596
|
+
isPlainGrouping,
|
|
597
|
+
mergeSeeds,
|
|
598
|
+
pageSortFor,
|
|
599
|
+
serverRowsOf,
|
|
600
|
+
sortAsFor,
|
|
601
|
+
summaryBarMeasures,
|
|
602
|
+
viewFilterOf
|
|
603
|
+
};
|
|
604
|
+
//# sourceMappingURL=index.js.map
|