@ai-matrx/records 0.77.2 → 0.78.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.
Files changed (70) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/app-table/index.cjs +94 -5
  3. package/dist/app-table/index.cjs.map +1 -1
  4. package/dist/app-table/index.d.cts +7 -7
  5. package/dist/app-table/index.d.ts +7 -7
  6. package/dist/app-table/index.js +94 -5
  7. package/dist/app-table/index.js.map +1 -1
  8. package/dist/{client-DZ3UcU4_.d.cts → client-BExNR0TK.d.cts} +5 -5
  9. package/dist/{client-ZIxyAOdh.d.ts → client-Byn_UthM.d.ts} +5 -5
  10. package/dist/core/index.cjs +98 -7
  11. package/dist/core/index.cjs.map +1 -1
  12. package/dist/core/index.d.cts +11 -11
  13. package/dist/core/index.d.ts +11 -11
  14. package/dist/core/index.js +98 -7
  15. package/dist/core/index.js.map +1 -1
  16. package/dist/data/index.cjs +90 -1
  17. package/dist/data/index.cjs.map +1 -1
  18. package/dist/data/index.d.cts +6 -6
  19. package/dist/data/index.d.ts +6 -6
  20. package/dist/data/index.js +90 -1
  21. package/dist/data/index.js.map +1 -1
  22. package/dist/{declareTable-BYZdFrt5.d.cts → declareTable-CgrEusy8.d.cts} +4 -4
  23. package/dist/{declareTable-DGSJMqGx.d.ts → declareTable-DWOh53eK.d.ts} +4 -4
  24. package/dist/{field-D7I9yck6.d.ts → field-B2bvpqcE.d.ts} +1 -1
  25. package/dist/{field-BTW7h7Wh.d.cts → field-t9aefszx.d.cts} +1 -1
  26. package/dist/index.cjs +6 -2
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +7 -7
  29. package/dist/index.d.ts +7 -7
  30. package/dist/index.js +6 -2
  31. package/dist/index.js.map +1 -1
  32. package/dist/memory/index.cjs +6 -1
  33. package/dist/memory/index.cjs.map +1 -1
  34. package/dist/memory/index.d.cts +6 -6
  35. package/dist/memory/index.d.ts +6 -6
  36. package/dist/memory/index.js +6 -1
  37. package/dist/memory/index.js.map +1 -1
  38. package/dist/{ports-CaYEF1dG.d.ts → ports-Ch4Ym0tj.d.ts} +7 -1
  39. package/dist/{ports-PpvsH1cQ.d.cts → ports-Cjl-IjFa.d.cts} +7 -1
  40. package/dist/react/index.cjs +98 -7
  41. package/dist/react/index.cjs.map +1 -1
  42. package/dist/react/index.d.cts +16 -0
  43. package/dist/react/index.d.ts +16 -0
  44. package/dist/react/index.js +98 -7
  45. package/dist/react/index.js.map +1 -1
  46. package/dist/realtime/index.d.cts +2 -2
  47. package/dist/realtime/index.d.ts +2 -2
  48. package/dist/{record-B7iwye2k.d.cts → record-Ba1F1CNS.d.cts} +10 -0
  49. package/dist/{record-B7iwye2k.d.ts → record-Ba1F1CNS.d.ts} +10 -0
  50. package/dist/{subscription-BWaRPLyo.d.ts → subscription-CccP6N93.d.ts} +1 -1
  51. package/dist/{subscription-Br30ZwIt.d.cts → subscription-DGCrwwSR.d.cts} +1 -1
  52. package/dist/{table-kind-Da21ZLdJ.d.ts → table-kind-BMWi8G37.d.ts} +3 -3
  53. package/dist/{table-kind-HAQ6WNxZ.d.cts → table-kind-BoelIMjr.d.cts} +3 -3
  54. package/dist/templates/index.cjs +6 -2
  55. package/dist/templates/index.cjs.map +1 -1
  56. package/dist/templates/index.d.cts +9 -9
  57. package/dist/templates/index.d.ts +9 -9
  58. package/dist/templates/index.js +6 -2
  59. package/dist/templates/index.js.map +1 -1
  60. package/dist/{types-DrJLOqVi.d.ts → types-CiHdoATO.d.ts} +2 -2
  61. package/dist/{types-DWZ5_3by.d.ts → types-CtyMwJvy.d.ts} +2 -2
  62. package/dist/{types-DYoWzHwJ.d.cts → types-D-Mhiodh.d.cts} +2 -2
  63. package/dist/{types-LvxsZ6Zv.d.cts → types-euaQwxnB.d.cts} +2 -2
  64. package/dist/use-cases/index.cjs.map +1 -1
  65. package/dist/use-cases/index.d.cts +5 -5
  66. package/dist/use-cases/index.d.ts +5 -5
  67. package/dist/use-cases/index.js.map +1 -1
  68. package/dist/{validate-j0WQoC3C.d.ts → validate-B-p3YPgA.d.ts} +1 -1
  69. package/dist/{validate-CRdXE73G.d.cts → validate-COvMcv8z.d.cts} +1 -1
  70. package/package.json +4 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog — @ai-matrx/records
2
2
 
3
+ ## 0.78.0
4
+
5
+ PAGE-BUNDLE: a table page opens in one call. `custom.table_page_bundle` answers, in one round trip, the table row, fields, views, look, change actions, decorations, row actions, reverse columns, grid layout, the caller's level and recent imports. The client hands each part to the caller that asks that door with the same arguments (once, within 10 s), so every mapping, mask and refusal is unchanged; a refusing part, a missing door or a failed bundle is a miss and the door is asked itself.
6
+
7
+ - `RecordsDataSource.opensInOneCall` (optional): set by `supabaseDataSource`; a source without it (tests, replays) never asks the bundle.
8
+ - `store.generated.ts` regenerated from the live catalogue.
9
+
10
+ **Consumer action:** none. Measured on production as admin: 12 parts identical to their doors; ~0.2-0.6 s for the bundle against ~1.5-2.2 s for the doors one after another (`pnpm perf:bundle` in matrx-frontend).
11
+
12
+ ## 0.77.3
13
+
14
+ UUID checks in app-table graduation, landing outcomes and template validation use `@ai-matrx/kit/uuid` `isUuidShape`; table-kind slugs use `isLowercaseUuidShape` (the same lower-case contract the local regex had). Scripts' console lines format sizes, durations and cost through kit. Package-twins collapse.
15
+
16
+ Consumer action: none.
17
+
3
18
  ## 0.77.2
4
19
 
5
20
  Automatic changed-only republish (docs/metadata drift since the last tag — see
@@ -56,6 +56,7 @@ __export(app_table_exports, {
56
56
  module.exports = __toCommonJS(app_table_exports);
57
57
 
58
58
  // src/app-table/graduate.ts
59
+ var import_uuid = require("@ai-matrx/kit/uuid");
59
60
  var TO_CUSTOM_FIELDS = "custom_fields";
60
61
  var TO_ASSOCIATION = "association";
61
62
  var GRADUATION_BASE_COLUMNS = [
@@ -115,10 +116,9 @@ function graduationProblems(fields, graduation) {
115
116
  }
116
117
  return problems;
117
118
  }
118
- var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
119
119
  function idsOf(value) {
120
120
  const list = Array.isArray(value) ? value : value === null || value === void 0 ? [] : [value];
121
- return list.filter((v) => typeof v === "string" && UUID.test(v));
121
+ return list.filter((v) => typeof v === "string" && (0, import_uuid.isUuidShape)(v));
122
122
  }
123
123
  function graduatedRow(fields, graduation, snapshot) {
124
124
  const row = {
@@ -649,7 +649,7 @@ function mapPgError(error, where) {
649
649
  }
650
650
 
651
651
  // src/relation.ts
652
- var import_uuid = require("@ai-matrx/kit/uuid");
652
+ var import_uuid2 = require("@ai-matrx/kit/uuid");
653
653
  var REVERSE_LINKS_RECORDS_PER_CALL = 200;
654
654
  function sourceArchivedOf(value) {
655
655
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
@@ -692,7 +692,7 @@ function mintOpId() {
692
692
  }
693
693
 
694
694
  // src/choice.ts
695
- var import_uuid2 = require("@ai-matrx/kit/uuid");
695
+ var import_uuid3 = require("@ai-matrx/kit/uuid");
696
696
  var CHOICE_NUDGES = ["ask", "always_add", "never_add"];
697
697
  function asChoiceNudge(value) {
698
698
  return typeof value === "string" && CHOICE_NUDGES.includes(value) ? value : "ask";
@@ -1131,6 +1131,7 @@ var STORE_DOORS = [
1131
1131
  { name: "data_home", args: "p_organization_id uuid DEFAULT NULL::uuid, p_search text DEFAULT NULL::text, p_include_app_tables boolean DEFAULT false", returns: "jsonb", security: "definer" },
1132
1132
  { name: "data_home_changed_by", args: "p_asks jsonb", returns: "TABLE(organization_id uuid, id uuid, at timestamp with time zone, who text)", security: "definer" },
1133
1133
  { name: "data_home_items", args: "p_organization_id uuid DEFAULT NULL::uuid", returns: "TABLE(kind text, organization_id uuid, organization_name text, item_id uuid, table_id uuid, table_name text, item_row jsonb)", security: "definer" },
1134
+ { name: "data_home_slim", args: "p_organization_id uuid DEFAULT NULL::uuid, p_search text DEFAULT NULL::text, p_include_app_tables boolean DEFAULT false", returns: "jsonb", security: "invoker" },
1134
1135
  { name: "data_home_tables", args: "p_organization_id uuid DEFAULT NULL::uuid", returns: "TABLE(table_id uuid, table_name text, organization_id uuid, organization_name text, member boolean, visibility text, updated_at timestamp with time zone, mine boolean, shared_with_me boolean, kept_by_the_app boolean, kind text, team boolean, system boolean, created_by uuid)", security: "definer" },
1135
1136
  { name: "data_home_tables", args: "p_organization_id uuid, p_include_app_tables boolean", returns: "TABLE(table_id uuid, table_name text, organization_id uuid, organization_name text, member boolean, visibility text, updated_at timestamp with time zone, mine boolean, shared_with_me boolean, kept_by_the_app boolean, kind text, team boolean, system boolean, created_by uuid)", security: "invoker" },
1136
1137
  { name: "declared_conversation", args: "", returns: "uuid", security: "invoker" },
@@ -1711,6 +1712,7 @@ var STORE_DOORS = [
1711
1712
  { name: "table_list_everywhere", args: "p_organization_id uuid DEFAULT NULL::uuid", returns: "jsonb", security: "definer" },
1712
1713
  { name: "table_list_everywhere", args: "p_organization_id uuid, p_include_app_tables boolean", returns: "jsonb", security: "invoker" },
1713
1714
  { name: "table_move", args: "p_table_id uuid, p_to_organization_id uuid, p_expected_version integer DEFAULT NULL::integer", returns: "jsonb", security: "definer" },
1715
+ { name: "table_page_bundle", args: "p_organization_id uuid, p_table_id uuid, p_view_id uuid DEFAULT NULL::uuid", returns: "jsonb", security: "invoker" },
1714
1716
  { name: "table_placement", args: "p_organization_id uuid, p_table_id uuid, p_data jsonb, p_is_kernel boolean DEFAULT false", returns: "jsonb", security: "invoker" },
1715
1717
  { name: "table_record_ceiling", args: "", returns: "integer", security: "invoker" },
1716
1718
  { name: "table_record_ceiling", args: "p_organization_id uuid", returns: "integer", security: "invoker" },
@@ -2571,6 +2573,8 @@ function supabaseDataSource(client) {
2571
2573
  const supabase = client;
2572
2574
  const hasSchema = typeof supabase.schema === "function";
2573
2575
  const bound = {
2576
+ // PAGE-BUNDLE: the real adapter opens a table page with one `custom.table_page_bundle` call.
2577
+ opensInOneCall: true,
2574
2578
  rpc(fn, args, options) {
2575
2579
  if (!hasSchema) {
2576
2580
  return Promise.resolve(
@@ -2693,6 +2697,12 @@ function intersectIds(sets) {
2693
2697
 
2694
2698
  // src/core/client.ts
2695
2699
  var DEFAULT_SCHEMA = "custom";
2700
+ function canonicalArgs(value) {
2701
+ return JSON.stringify(
2702
+ value,
2703
+ (_key, held) => held && typeof held === "object" && !Array.isArray(held) ? Object.fromEntries(Object.keys(held).sort().map((k) => [k, held[k]])) : held
2704
+ );
2705
+ }
2696
2706
  var A_PERSONS_REFUSAL = /* @__PURE__ */ new Set([
2697
2707
  "refused_by_rule",
2698
2708
  "stale_write",
@@ -2721,7 +2731,83 @@ function createRecordsClient(given) {
2721
2731
  const schema = config.schema ?? DEFAULT_SCHEMA;
2722
2732
  const org = config.organizationId;
2723
2733
  const scream = sink(config);
2734
+ const BUNDLE_TTL_MS = 1e4;
2735
+ const BUNDLE_OPENERS = /* @__PURE__ */ new Set(["applicable_fields", "views", "view_look_read", "table_decorations", "row_actions", "reverse_columns", "record_change_actions", "grid_layout", "io_imports"]);
2736
+ const bundleParts = /* @__PURE__ */ new Map();
2737
+ const bundleFlights = /* @__PURE__ */ new Map();
2738
+ const bundleAsked = /* @__PURE__ */ new Map();
2739
+ let bundleKernel = null;
2740
+ const bundleKey = (door, args) => `${door}|${canonicalArgs(args)}`;
2741
+ function bundleTableOf(door, args) {
2742
+ const t = args["p_table_id"];
2743
+ if (door === "read_records_by_ids") {
2744
+ const ids = args["p_record_ids"];
2745
+ return typeof t === "string" && t === bundleKernel && Array.isArray(ids) && ids.length === 1 && typeof ids[0] === "string" ? ids[0] : null;
2746
+ }
2747
+ if (door === "my_levels") {
2748
+ const ids = args["p_ids"];
2749
+ return args["p_type"] === "record" && Array.isArray(ids) && ids.length === 1 && typeof ids[0] === "string" ? ids[0] : null;
2750
+ }
2751
+ return typeof t === "string" ? t : null;
2752
+ }
2753
+ async function fillBundle(tableId, viewId) {
2754
+ try {
2755
+ const response = await config.dataSource.rpc(
2756
+ "table_page_bundle",
2757
+ { p_organization_id: org, p_table_id: tableId, p_view_id: typeof viewId === "string" ? viewId : null },
2758
+ { schema }
2759
+ );
2760
+ const answer = response.data;
2761
+ if (response.error || !answer || !Array.isArray(answer.parts)) return;
2762
+ const now = Date.now();
2763
+ for (const part of answer.parts) {
2764
+ if (part.error !== void 0 || part.data === void 0) continue;
2765
+ if (part.door === "table_kernel_id" && typeof part.data === "string") bundleKernel = part.data;
2766
+ bundleParts.set(bundleKey(part.door, part.args), { data: part.data, at: now });
2767
+ }
2768
+ } catch {
2769
+ }
2770
+ }
2771
+ async function fromBundle(door, args) {
2772
+ if (!config.dataSource.opensInOneCall || !doorReady(config, "table_page_bundle")) return null;
2773
+ const tableId = bundleTableOf(door, args);
2774
+ if (tableId) {
2775
+ const asked = bundleAsked.get(tableId);
2776
+ const fresh = asked !== void 0 && Date.now() - asked < BUNDLE_TTL_MS;
2777
+ if (!fresh && BUNDLE_OPENERS.has(door)) {
2778
+ bundleAsked.set(tableId, Date.now());
2779
+ const flight2 = fillBundle(tableId, door === "grid_layout" ? args["p_view_id"] : null).finally(() => bundleFlights.delete(tableId));
2780
+ bundleFlights.set(tableId, flight2);
2781
+ }
2782
+ const flight = bundleFlights.get(tableId);
2783
+ if (flight) await flight;
2784
+ } else if (door === "table_kernel_id") {
2785
+ if (bundleKernel === null) {
2786
+ await new Promise((resolve) => setTimeout(resolve, 0));
2787
+ await Promise.all([...bundleFlights.values()]);
2788
+ }
2789
+ return bundleKernel === null ? null : { data: bundleKernel };
2790
+ } else {
2791
+ return null;
2792
+ }
2793
+ const key = bundleKey(door, args);
2794
+ const held = bundleParts.get(key);
2795
+ if (!held) return null;
2796
+ bundleParts.delete(key);
2797
+ return Date.now() - held.at < BUNDLE_TTL_MS ? { data: held.data } : null;
2798
+ }
2799
+ function bundleDrop(tableId) {
2800
+ if (tableId === null) {
2801
+ bundleParts.clear();
2802
+ bundleAsked.clear();
2803
+ return;
2804
+ }
2805
+ bundleAsked.delete(tableId);
2806
+ for (const key of [...bundleParts.keys()]) if (key.includes(tableId)) bundleParts.delete(key);
2807
+ }
2724
2808
  async function callDoor(door, args, where) {
2809
+ const bundled = await fromBundle(door, args);
2810
+ if (bundled) return ok(bundled.data);
2725
2811
  if (!doorReady(config, door)) {
2726
2812
  const refusal2 = doorAbsent(door);
2727
2813
  scream({ code: refusal2.code, message: refusal2.message, ...refusal2.hint ? { hint: refusal2.hint } : {}, where });
@@ -2736,7 +2822,10 @@ function createRecordsClient(given) {
2736
2822
  return ok(response.data);
2737
2823
  }
2738
2824
  function structureMoved(tableId, result) {
2739
- if (result.ok) announceTableStructureChanged(tableId);
2825
+ if (result.ok) {
2826
+ bundleDrop(tableId);
2827
+ announceTableStructureChanged(tableId);
2828
+ }
2740
2829
  return result;
2741
2830
  }
2742
2831
  async function owedDoor(door, args, where) {