@ai-matrx/records 0.72.23 → 0.73.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/CHANGELOG.md +10 -0
- package/dist/list/index.cjs +221 -0
- package/dist/list/index.cjs.map +1 -0
- package/dist/list/index.d.cts +395 -0
- package/dist/list/index.d.ts +395 -0
- package/dist/list/index.js +198 -0
- package/dist/list/index.js.map +1 -0
- package/dist/memory/index.cjs +235 -4
- package/dist/memory/index.cjs.map +1 -1
- package/dist/memory/index.js +235 -4
- package/dist/memory/index.js.map +1 -1
- package/package.json +12 -1
package/dist/memory/index.cjs
CHANGED
|
@@ -2424,6 +2424,146 @@ function matching(world, table, args) {
|
|
|
2424
2424
|
if (search) ids = ids.filter((id) => JSON.stringify(readDocument(world, table, id)).toLowerCase().includes(search));
|
|
2425
2425
|
return sortRows(world, table, ids, args["p_sort"]);
|
|
2426
2426
|
}
|
|
2427
|
+
var DAY_MS = 864e5;
|
|
2428
|
+
function bucketOf(value, by) {
|
|
2429
|
+
if (typeof value !== "string" || value.length < 10) return null;
|
|
2430
|
+
const [y, m, d] = value.slice(0, 10).split("-").map(Number);
|
|
2431
|
+
let at = new Date(Date.UTC(y, m - 1, d));
|
|
2432
|
+
if (by === "week") at = new Date(at.getTime() - (at.getUTCDay() + 6) % 7 * DAY_MS);
|
|
2433
|
+
else if (by === "month") at = new Date(Date.UTC(y, m - 1, 1));
|
|
2434
|
+
else if (by === "quarter") at = new Date(Date.UTC(y, Math.floor((m - 1) / 3) * 3, 1));
|
|
2435
|
+
else if (by === "year") at = new Date(Date.UTC(y, 0, 1));
|
|
2436
|
+
return `${at.toISOString().slice(0, 10)}T00:00:00+00:00`;
|
|
2437
|
+
}
|
|
2438
|
+
function groupValues(doc, stored, key) {
|
|
2439
|
+
const shown = doc[key];
|
|
2440
|
+
const raw = stored[key];
|
|
2441
|
+
const pick = typeof raw === "string" && raw === shown ? raw : shown ?? raw;
|
|
2442
|
+
const list = Array.isArray(pick) ? pick : [pick];
|
|
2443
|
+
const out = list.map((v) => v === void 0 || v === null || v === "" ? null : String(v));
|
|
2444
|
+
return out.length ? out : [null];
|
|
2445
|
+
}
|
|
2446
|
+
function runBlock(world, subject, raw, canvas, index) {
|
|
2447
|
+
const table = world.tableById.get(String(raw["table_id"] ?? subject));
|
|
2448
|
+
const title = String(raw["title"] ?? `Block ${index + 1}`);
|
|
2449
|
+
const base = { ...raw, title, table_id: table?.id ?? subject, ms: 0 };
|
|
2450
|
+
if (!table) return { ...base, rows: [], refused: "This block's table is not in this template." };
|
|
2451
|
+
if (raw["kind"] === "stuck") return { ...base, rows: [] };
|
|
2452
|
+
const measures = (raw["measures"] ?? [{ op: "count" }]).map((m) => ({ op: String(m["op"] ?? "count"), key: m["key"] }));
|
|
2453
|
+
const groupBy = (raw["group_by"] ?? []).slice();
|
|
2454
|
+
const bucket = raw["bucket"] ?? null;
|
|
2455
|
+
const ids = table.order.filter((id) => admits(world, table, id, raw["filter"]) && admits(world, table, id, canvas));
|
|
2456
|
+
const groups = /* @__PURE__ */ new Map();
|
|
2457
|
+
for (const id of ids) {
|
|
2458
|
+
const doc = readDocument(world, table, id);
|
|
2459
|
+
const stored = table.rows.get(id) ?? {};
|
|
2460
|
+
let combos = [{}];
|
|
2461
|
+
for (const key of groupBy) {
|
|
2462
|
+
const values = groupValues(doc, stored, key);
|
|
2463
|
+
combos = combos.flatMap((c) => values.map((v) => ({ ...c, [key]: v })));
|
|
2464
|
+
}
|
|
2465
|
+
if (bucket?.key) {
|
|
2466
|
+
const at = bucketOf(doc[bucket.key] ?? stored[bucket.key], bucket.by ?? "month");
|
|
2467
|
+
if (at === null) continue;
|
|
2468
|
+
combos = combos.map((c) => ({ ...c, [`${bucket.key}_${bucket.by ?? "month"}`]: at }));
|
|
2469
|
+
}
|
|
2470
|
+
for (const c of combos) {
|
|
2471
|
+
const k = JSON.stringify(c);
|
|
2472
|
+
const g = groups.get(k) ?? { groups: c, ids: [] };
|
|
2473
|
+
g.ids.push(id);
|
|
2474
|
+
groups.set(k, g);
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
if (!groupBy.length && !bucket?.key && !groups.size) groups.set("{}", { groups: {}, ids: [] });
|
|
2478
|
+
const measureName = (m) => m.op === "count" ? "count" : `${m.op}_${m.key ?? ""}`;
|
|
2479
|
+
let rows = [...groups.values()].map((g) => {
|
|
2480
|
+
const out = {};
|
|
2481
|
+
for (const m of measures) {
|
|
2482
|
+
if (m.op === "count") {
|
|
2483
|
+
out["count"] = g.ids.length;
|
|
2484
|
+
continue;
|
|
2485
|
+
}
|
|
2486
|
+
const nums = g.ids.map((id) => readDocument(world, table, id)[m.key ?? ""]).filter((v) => typeof v === "number");
|
|
2487
|
+
const sum = nums.reduce((a, b) => a + b, 0);
|
|
2488
|
+
out[measureName(m)] = m.op === "sum" ? sum : !nums.length ? null : m.op === "avg" ? sum / nums.length : m.op === "min" ? Math.min(...nums) : m.op === "max" ? Math.max(...nums) : null;
|
|
2489
|
+
}
|
|
2490
|
+
return { groups: g.groups, measures: out, row_count: g.ids.length };
|
|
2491
|
+
});
|
|
2492
|
+
const primary = measures[0] ? measureName(measures[0]) : "count";
|
|
2493
|
+
if (bucket?.key) {
|
|
2494
|
+
const k = `${bucket.key}_${bucket.by ?? "month"}`;
|
|
2495
|
+
rows.sort((a, b) => String(a.groups[k]).localeCompare(String(b.groups[k])));
|
|
2496
|
+
} else rows.sort((a, b) => (b.measures[primary] ?? 0) - (a.measures[primary] ?? 0));
|
|
2497
|
+
const limit = Number(raw["limit"] ?? 0);
|
|
2498
|
+
if (limit > 0) rows = rows.slice(0, limit);
|
|
2499
|
+
return { ...base, measures, group_by: groupBy, rows };
|
|
2500
|
+
}
|
|
2501
|
+
function bookingAvailability(world, raw) {
|
|
2502
|
+
const num = (k, fallback) => typeof raw[k] === "number" ? raw[k] : fallback;
|
|
2503
|
+
return {
|
|
2504
|
+
timezone: String(raw["timezone"] ?? world.timezone),
|
|
2505
|
+
slot_minutes: num("slot_minutes", 30),
|
|
2506
|
+
buffer_minutes: num("buffer_minutes", 0),
|
|
2507
|
+
lead_minutes: num("lead_minutes", 0),
|
|
2508
|
+
max_per_day: num("max_per_day", 0),
|
|
2509
|
+
days: num("days", 14),
|
|
2510
|
+
windows: (raw["windows"] ?? []).map((w) => ({
|
|
2511
|
+
weekday: Number(w["weekday"] ?? 1),
|
|
2512
|
+
from: String(w["from"] ?? "09:00"),
|
|
2513
|
+
to: String(w["to"] ?? "17:00"),
|
|
2514
|
+
member_user_id: null
|
|
2515
|
+
}))
|
|
2516
|
+
};
|
|
2517
|
+
}
|
|
2518
|
+
function zoneOffset2(zone, at) {
|
|
2519
|
+
const parts = new Intl.DateTimeFormat("en-US", { timeZone: zone, hourCycle: "h23", year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" }).formatToParts(new Date(at)).reduce((acc, p) => p.type === "literal" ? acc : { ...acc, [p.type]: Number(p.value) }, {});
|
|
2520
|
+
return (Date.UTC(parts["year"], parts["month"] - 1, parts["day"], parts["hour"], parts["minute"]) - at) / 6e4;
|
|
2521
|
+
}
|
|
2522
|
+
function zonedInstant(zone, day, minutes) {
|
|
2523
|
+
const guess = day + minutes * 6e4;
|
|
2524
|
+
return guess - zoneOffset2(zone, guess - zoneOffset2(zone, guess) * 6e4) * 6e4;
|
|
2525
|
+
}
|
|
2526
|
+
function bookingSlots(world, table, a, days) {
|
|
2527
|
+
const zone = (() => {
|
|
2528
|
+
try {
|
|
2529
|
+
new Intl.DateTimeFormat("en-US", { timeZone: a.timezone });
|
|
2530
|
+
return a.timezone;
|
|
2531
|
+
} catch {
|
|
2532
|
+
return "UTC";
|
|
2533
|
+
}
|
|
2534
|
+
})();
|
|
2535
|
+
const taken = /* @__PURE__ */ new Set();
|
|
2536
|
+
for (const id of table.order) {
|
|
2537
|
+
for (const v of Object.values(table.rows.get(id) ?? {})) {
|
|
2538
|
+
if (typeof v === "string" && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/.test(v)) taken.add(new Date(v).getTime());
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
const toMin = (hhmm) => {
|
|
2542
|
+
const [h, m2] = hhmm.split(":").map(Number);
|
|
2543
|
+
return (h ?? 0) * 60 + (m2 ?? 0);
|
|
2544
|
+
};
|
|
2545
|
+
const [y, m, d] = world.today.split("-").map(Number);
|
|
2546
|
+
const start = Date.UTC(y, m - 1, d);
|
|
2547
|
+
const earliest = zonedInstant(zone, start, 9 * 60) + a.lead_minutes * 6e4;
|
|
2548
|
+
const step = Math.max(5, a.slot_minutes + a.buffer_minutes);
|
|
2549
|
+
const slots = [];
|
|
2550
|
+
for (let i = 0; i < Math.max(1, days); i += 1) {
|
|
2551
|
+
const day = start + i * DAY_MS;
|
|
2552
|
+
const weekday = new Date(day).getUTCDay();
|
|
2553
|
+
let today = 0;
|
|
2554
|
+
for (const w of a.windows.filter((x) => x.weekday === weekday)) {
|
|
2555
|
+
for (let t = toMin(w.from); t + a.slot_minutes <= toMin(w.to); t += step) {
|
|
2556
|
+
if (a.max_per_day > 0 && today >= a.max_per_day) break;
|
|
2557
|
+
const at = zonedInstant(zone, day, t);
|
|
2558
|
+
if (at < earliest) continue;
|
|
2559
|
+
today += 1;
|
|
2560
|
+
const iso = new Date(at).toISOString();
|
|
2561
|
+
slots.push({ key: iso, at: iso, taken: taken.has(at), member_user_id: null });
|
|
2562
|
+
}
|
|
2563
|
+
}
|
|
2564
|
+
}
|
|
2565
|
+
return slots;
|
|
2566
|
+
}
|
|
2427
2567
|
var VIEWER = "viewer";
|
|
2428
2568
|
function memoryDataSource(world) {
|
|
2429
2569
|
const looks = /* @__PURE__ */ new Map();
|
|
@@ -2632,15 +2772,106 @@ function memoryDataSource(world) {
|
|
|
2632
2772
|
record_stage_pending: () => ok([]),
|
|
2633
2773
|
io_imports: () => ok([]),
|
|
2634
2774
|
relation_words: (args) => ok(nameOf(String(args["p_value"] ?? ""))),
|
|
2775
|
+
// The read doors a form, a booking page and a dashboard are drawn from (lane CHAIR-GALLERY-3).
|
|
2635
2776
|
forms: (args) => ok(
|
|
2636
|
-
world.forms.filter((f) => !f.booking && (!args["p_table_id"] || f.table_id === args["p_table_id"])).map((f) => ({
|
|
2777
|
+
world.forms.filter((f) => !f.booking && (!args["p_table_id"] || f.table_id === args["p_table_id"])).map((f) => ({
|
|
2778
|
+
form_id: f.form_id,
|
|
2779
|
+
table_id: f.table_id,
|
|
2780
|
+
title: f.title,
|
|
2781
|
+
slug: f.token,
|
|
2782
|
+
published_at: `${world.today}T09:00:00Z`,
|
|
2783
|
+
closed_at: null,
|
|
2784
|
+
submission_cap: null,
|
|
2785
|
+
responses: 0,
|
|
2786
|
+
in_table: 0,
|
|
2787
|
+
held: 0,
|
|
2788
|
+
rejected: 0,
|
|
2789
|
+
state: "open",
|
|
2790
|
+
quarantine_rule_id: null,
|
|
2791
|
+
notify_rule_id: null,
|
|
2792
|
+
questions: f.questions,
|
|
2793
|
+
presentation: { ...f.presentation, questions: f.presentation["questions"] ?? f.questions }
|
|
2794
|
+
}))
|
|
2637
2795
|
),
|
|
2796
|
+
form_preview_asks: (args) => {
|
|
2797
|
+
const t = tableOf(args);
|
|
2798
|
+
const values = args["p_values"] ?? {};
|
|
2799
|
+
return ok(
|
|
2800
|
+
(args["p_questions"] ?? []).map((q) => {
|
|
2801
|
+
const when = q["show_if"] ?? q["showIf"] ?? null;
|
|
2802
|
+
const asked = !when || !t ? true : rule(t, values, values, when) !== false;
|
|
2803
|
+
return { field_key: String(q["field"] ?? q["key"] ?? ""), asked, decided: true, said: null };
|
|
2804
|
+
})
|
|
2805
|
+
);
|
|
2806
|
+
},
|
|
2638
2807
|
bookings: (args) => ok(
|
|
2639
|
-
world.forms.filter((f) => f.booking && (!args["p_table_id"] || f.table_id === args["p_table_id"])).map((f) => ({
|
|
2808
|
+
world.forms.filter((f) => f.booking && (!args["p_table_id"] || f.table_id === args["p_table_id"])).map((f) => ({
|
|
2809
|
+
form_id: f.form_id,
|
|
2810
|
+
table_id: f.table_id,
|
|
2811
|
+
title: f.title,
|
|
2812
|
+
slug: f.token,
|
|
2813
|
+
published_at: `${world.today}T09:00:00Z`,
|
|
2814
|
+
closed_at: null,
|
|
2815
|
+
slot_minutes: Number(f.booking["slot_minutes"] ?? 30),
|
|
2816
|
+
timezone: String(f.booking["timezone"] ?? world.timezone),
|
|
2817
|
+
slot_table_id: null,
|
|
2818
|
+
booked: 0,
|
|
2819
|
+
cancelled: 0,
|
|
2820
|
+
upcoming: 0,
|
|
2821
|
+
held: 0,
|
|
2822
|
+
next_at: null,
|
|
2823
|
+
state: "open"
|
|
2824
|
+
}))
|
|
2640
2825
|
),
|
|
2826
|
+
booking_public: (args) => {
|
|
2827
|
+
const f = world.forms.find((x) => x.form_id === args["p_form_id"] && x.booking);
|
|
2828
|
+
const t = f ? world.tableById.get(f.table_id) : void 0;
|
|
2829
|
+
if (!f || !t) return refuse("That booking page is not in this template.", "P0002");
|
|
2830
|
+
const availability = bookingAvailability(world, f.booking);
|
|
2831
|
+
return ok({
|
|
2832
|
+
form_id: f.form_id,
|
|
2833
|
+
organization_id: world.organization_id,
|
|
2834
|
+
table_id: t.id,
|
|
2835
|
+
title: f.title,
|
|
2836
|
+
presentation: { ...f.presentation, questions: f.questions },
|
|
2837
|
+
fields: t.fields.map((x) => ({ id: x.id, ...x.data })),
|
|
2838
|
+
honeypot_key: null,
|
|
2839
|
+
availability,
|
|
2840
|
+
slots: bookingSlots(world, t, availability, Number(args["p_days"] ?? availability.days)),
|
|
2841
|
+
state: "open",
|
|
2842
|
+
message: null
|
|
2843
|
+
});
|
|
2844
|
+
},
|
|
2641
2845
|
dashboards: (args) => ok(
|
|
2642
|
-
world.dashboards.filter((d) => !args["p_table_id"] || d.table_id === args["p_table_id"]).map((d) => ({
|
|
2643
|
-
|
|
2846
|
+
world.dashboards.filter((d) => !args["p_table_id"] || d.table_id === args["p_table_id"]).map((d) => ({
|
|
2847
|
+
dashboard_id: d.dashboard_id,
|
|
2848
|
+
table_id: d.table_id,
|
|
2849
|
+
name: d.name,
|
|
2850
|
+
blocks: d.blocks,
|
|
2851
|
+
presentation: {},
|
|
2852
|
+
block_count: d.blocks.length,
|
|
2853
|
+
version: 1,
|
|
2854
|
+
created_at: `${world.today}T09:00:00Z`,
|
|
2855
|
+
updated_at: `${world.today}T09:00:00Z`
|
|
2856
|
+
}))
|
|
2857
|
+
),
|
|
2858
|
+
dashboard_run: (args) => {
|
|
2859
|
+
const d = world.dashboards.find((x) => x.dashboard_id === args["p_dashboard_id"]);
|
|
2860
|
+
if (!d) return refuse("That dashboard is not in this template.", "P0002");
|
|
2861
|
+
const canvas = args["p_filter"] ?? {};
|
|
2862
|
+
return ok({
|
|
2863
|
+
dashboard_id: d.dashboard_id,
|
|
2864
|
+
name: d.name,
|
|
2865
|
+
subject_table_id: d.table_id,
|
|
2866
|
+
presentation: {},
|
|
2867
|
+
filter: canvas,
|
|
2868
|
+
grain: null,
|
|
2869
|
+
compare: null,
|
|
2870
|
+
calendar: { time_zone: world.timezone, week_start: "monday" },
|
|
2871
|
+
blocks: d.blocks.map((b, i) => runBlock(world, d.table_id, b, canvas, i))
|
|
2872
|
+
});
|
|
2873
|
+
},
|
|
2874
|
+
dashboard_stuck: () => ok([])
|
|
2644
2875
|
};
|
|
2645
2876
|
const source = {
|
|
2646
2877
|
world,
|