@ai-matrx/records-ui 0.3.1 → 0.4.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/dist/index.d.cts CHANGED
@@ -521,8 +521,16 @@ declare function ViewBar({ tableId, activeViewId, onActiveView, seed, className
521
521
  interface ProposedChange {
522
522
  id: string;
523
523
  act: "add" | "update" | "remove";
524
- /** The Table the change lands in. */
525
- table: Uuid;
524
+ /**
525
+ * The Table a NEW record lands in. Required for `add` and unused by `update`
526
+ * and `remove`, which name a record instead — and it is optional for exactly
527
+ * that reason: it used to be required for all three, so a proposer wanting to
528
+ * change an existing record had to supply the id of the kernel Table that
529
+ * record lives in, which is a fact the client has no door to ask for. A
530
+ * required field a caller cannot fill is a field that gets filled with
531
+ * something untrue.
532
+ */
533
+ table?: Uuid | undefined;
526
534
  /** The record it changes. Required for `update` and `remove`. */
527
535
  record?: Uuid | undefined;
528
536
  /** The document for `add`, or the patch for `update`. */
@@ -1037,17 +1045,36 @@ declare function personActor(userId: Uuid$1 | null | undefined): RecordsActor;
1037
1045
  *
1038
1046
  * `RecordsDataSource` is deliberately a small structural subset of
1039
1047
  * `SupabaseClient` — the package holds no key and opens no connection, the host
1040
- * hands it a client that already carries the person's session. Structurally the
1041
- * two agree. PROVING it does not fit in the type checker's budget: a generated
1042
- * `Database` type makes `schema().from().select()` enormous, and a host app
1043
- * that passes its client straight into `config` gets
1044
- * `TS2589: Type instantiation is excessively deep and possibly infinite` in its
1045
- * own build (matrx-frontend, 2026-09-18, on all three campaign routes at once).
1048
+ * hands it a client that already carries the person's session.
1049
+ *
1050
+ * IT IS NOT AN IDENTITY CAST, and it cost a live screen to learn why
1051
+ * (2026-09-19, /data-v2's first load): the port's `rpc(fn, args, { schema })`
1052
+ * says the schema OUT LOUD, because every door of this store is `custom.<name>`
1053
+ * and every door of the trust layer is `iam.<name>`. supabase-js's own
1054
+ * `rpc(fn, args, options)` has no `schema` option at all — its third argument is
1055
+ * `{ head, get, count }` — so a client passed straight through silently asked
1056
+ * its default PostgREST profile and the store answered, correctly and uselessly,
1057
+ * "Could not find the function public.table_kernel_id ... PGRST202". The schema
1058
+ * is chosen the one way supabase-js offers: `client.schema(name).rpc(...)`.
1059
+ *
1060
+ * `schema(name).from(table)` already agrees structurally and is passed through.
1046
1061
  *
1047
- * So the assertion is made HERE, once, where it is explained rather than as a
1048
- * cast copied into every route that mounts a screen.
1062
+ * `fallbackSchema` is the profile a call that says NOTHING is sent to. No caller
1063
+ * in `@ai-matrx/records` omits the option `callDoor` always says `custom` and
1064
+ * `trustDoor` always says `iam` — so it never fires today; it exists so that a
1065
+ * call which one day forgets lands on the store rather than silently on
1066
+ * `public`. It is a FALLBACK and not the answer: a version of this adapter that
1067
+ * sent EVERY door to one fixed schema would route the `iam` trust doors (the
1068
+ * external principal, the publish binding) into `custom` and get a PGRST202
1069
+ * naming the wrong schema.
1070
+ *
1071
+ * The cast itself stays HERE, once, where it is explained: a generated
1072
+ * `Database` type makes `schema().from().select()` enormous, and a host app that
1073
+ * passes its client straight into `config` gets `TS2589: Type instantiation is
1074
+ * excessively deep and possibly infinite` in its own build (matrx-frontend,
1075
+ * 2026-09-18, on all three campaign routes at once).
1049
1076
  */
1050
- declare function recordsDataSource(client: object, schema?: string): RecordsDataSource;
1077
+ declare function recordsDataSource(client: object, fallbackSchema?: string): RecordsDataSource;
1051
1078
 
1052
1079
  type TableLane = "mine" | "organization" | "system" | "community";
1053
1080
  /** The four lanes, in the order a person reads them. Never a flat list. */
@@ -1068,9 +1095,16 @@ interface TablePageProps {
1068
1095
  tableId: Uuid$1;
1069
1096
  /** Rows per page for every layout. */
1070
1097
  pageSize?: number | undefined;
1098
+ /**
1099
+ * The views this table should have. Each one whose NAME the table does not
1100
+ * hold yet is saved the first time the bar loads, and a name a person has
1101
+ * since tweaked is never overwritten. Left out, `DEFAULT_VIEW_NAME` below is
1102
+ * used — see why that default is not optional.
1103
+ */
1104
+ seedViews?: SavedViewSpec[] | undefined;
1071
1105
  className?: string | undefined;
1072
1106
  }
1073
- declare function TablePage({ tableId, pageSize, className }: TablePageProps): react.JSX.Element;
1107
+ declare function TablePage({ tableId, pageSize, seedViews, className }: TablePageProps): react.JSX.Element;
1074
1108
 
1075
1109
  /** One Field a person asked for, in the store's own behaviour words (FLD-1). */
1076
1110
  interface NewFieldSpec {
package/dist/index.d.ts CHANGED
@@ -521,8 +521,16 @@ declare function ViewBar({ tableId, activeViewId, onActiveView, seed, className
521
521
  interface ProposedChange {
522
522
  id: string;
523
523
  act: "add" | "update" | "remove";
524
- /** The Table the change lands in. */
525
- table: Uuid;
524
+ /**
525
+ * The Table a NEW record lands in. Required for `add` and unused by `update`
526
+ * and `remove`, which name a record instead — and it is optional for exactly
527
+ * that reason: it used to be required for all three, so a proposer wanting to
528
+ * change an existing record had to supply the id of the kernel Table that
529
+ * record lives in, which is a fact the client has no door to ask for. A
530
+ * required field a caller cannot fill is a field that gets filled with
531
+ * something untrue.
532
+ */
533
+ table?: Uuid | undefined;
526
534
  /** The record it changes. Required for `update` and `remove`. */
527
535
  record?: Uuid | undefined;
528
536
  /** The document for `add`, or the patch for `update`. */
@@ -1037,17 +1045,36 @@ declare function personActor(userId: Uuid$1 | null | undefined): RecordsActor;
1037
1045
  *
1038
1046
  * `RecordsDataSource` is deliberately a small structural subset of
1039
1047
  * `SupabaseClient` — the package holds no key and opens no connection, the host
1040
- * hands it a client that already carries the person's session. Structurally the
1041
- * two agree. PROVING it does not fit in the type checker's budget: a generated
1042
- * `Database` type makes `schema().from().select()` enormous, and a host app
1043
- * that passes its client straight into `config` gets
1044
- * `TS2589: Type instantiation is excessively deep and possibly infinite` in its
1045
- * own build (matrx-frontend, 2026-09-18, on all three campaign routes at once).
1048
+ * hands it a client that already carries the person's session.
1049
+ *
1050
+ * IT IS NOT AN IDENTITY CAST, and it cost a live screen to learn why
1051
+ * (2026-09-19, /data-v2's first load): the port's `rpc(fn, args, { schema })`
1052
+ * says the schema OUT LOUD, because every door of this store is `custom.<name>`
1053
+ * and every door of the trust layer is `iam.<name>`. supabase-js's own
1054
+ * `rpc(fn, args, options)` has no `schema` option at all — its third argument is
1055
+ * `{ head, get, count }` — so a client passed straight through silently asked
1056
+ * its default PostgREST profile and the store answered, correctly and uselessly,
1057
+ * "Could not find the function public.table_kernel_id ... PGRST202". The schema
1058
+ * is chosen the one way supabase-js offers: `client.schema(name).rpc(...)`.
1059
+ *
1060
+ * `schema(name).from(table)` already agrees structurally and is passed through.
1046
1061
  *
1047
- * So the assertion is made HERE, once, where it is explained rather than as a
1048
- * cast copied into every route that mounts a screen.
1062
+ * `fallbackSchema` is the profile a call that says NOTHING is sent to. No caller
1063
+ * in `@ai-matrx/records` omits the option `callDoor` always says `custom` and
1064
+ * `trustDoor` always says `iam` — so it never fires today; it exists so that a
1065
+ * call which one day forgets lands on the store rather than silently on
1066
+ * `public`. It is a FALLBACK and not the answer: a version of this adapter that
1067
+ * sent EVERY door to one fixed schema would route the `iam` trust doors (the
1068
+ * external principal, the publish binding) into `custom` and get a PGRST202
1069
+ * naming the wrong schema.
1070
+ *
1071
+ * The cast itself stays HERE, once, where it is explained: a generated
1072
+ * `Database` type makes `schema().from().select()` enormous, and a host app that
1073
+ * passes its client straight into `config` gets `TS2589: Type instantiation is
1074
+ * excessively deep and possibly infinite` in its own build (matrx-frontend,
1075
+ * 2026-09-18, on all three campaign routes at once).
1049
1076
  */
1050
- declare function recordsDataSource(client: object, schema?: string): RecordsDataSource;
1077
+ declare function recordsDataSource(client: object, fallbackSchema?: string): RecordsDataSource;
1051
1078
 
1052
1079
  type TableLane = "mine" | "organization" | "system" | "community";
1053
1080
  /** The four lanes, in the order a person reads them. Never a flat list. */
@@ -1068,9 +1095,16 @@ interface TablePageProps {
1068
1095
  tableId: Uuid$1;
1069
1096
  /** Rows per page for every layout. */
1070
1097
  pageSize?: number | undefined;
1098
+ /**
1099
+ * The views this table should have. Each one whose NAME the table does not
1100
+ * hold yet is saved the first time the bar loads, and a name a person has
1101
+ * since tweaked is never overwritten. Left out, `DEFAULT_VIEW_NAME` below is
1102
+ * used — see why that default is not optional.
1103
+ */
1104
+ seedViews?: SavedViewSpec[] | undefined;
1071
1105
  className?: string | undefined;
1072
1106
  }
1073
- declare function TablePage({ tableId, pageSize, className }: TablePageProps): react.JSX.Element;
1107
+ declare function TablePage({ tableId, pageSize, seedViews, className }: TablePageProps): react.JSX.Element;
1074
1108
 
1075
1109
  /** One Field a person asked for, in the store's own behaviour words (FLD-1). */
1076
1110
  interface NewFieldSpec {
package/dist/index.js CHANGED
@@ -2097,6 +2097,12 @@ function ProposalRow({
2097
2097
  const [confirming, setConfirming] = useState14(false);
2098
2098
  async function applyThroughTheStore() {
2099
2099
  if (change.act === "add") {
2100
+ if (!change.table) {
2101
+ return {
2102
+ settled: "refused",
2103
+ sentence: "This proposal asks to add a record but does not name the table it goes in, so nothing was written."
2104
+ };
2105
+ }
2100
2106
  const written = await client.recordWrite({ table_id: change.table, data: change.data ?? {} });
2101
2107
  return written.ok ? { settled: "accepted", sentence: "Written." } : { settled: "refused", sentence: written.error.message };
2102
2108
  }
@@ -5596,11 +5602,16 @@ function RecordsMount({
5596
5602
  function personActor(userId) {
5597
5603
  return userId ? { actor: "user", user_id: userId } : { actor: "user" };
5598
5604
  }
5599
- function recordsDataSource(client, schema = "custom") {
5605
+ function recordsDataSource(client, fallbackSchema = "custom") {
5600
5606
  const supabase = client;
5601
5607
  return {
5602
- rpc: (fn, args) => supabase.schema(schema).rpc(fn, args),
5603
- schema: (name) => supabase.schema(name)
5608
+ rpc(fn, args, options) {
5609
+ const on = supabase.schema(options?.schema ?? fallbackSchema);
5610
+ return on.rpc(fn, args);
5611
+ },
5612
+ schema(name) {
5613
+ return supabase.schema(name);
5614
+ }
5604
5615
  };
5605
5616
  }
5606
5617
 
@@ -5809,7 +5820,11 @@ import { useState as useState35 } from "react";
5809
5820
  import { useTable as useTable21 } from "@ai-matrx/records/react";
5810
5821
  import { Button as Button31, Separator as Separator7, Skeleton as Skeleton25, cn as cn36 } from "@ai-matrx/design-system";
5811
5822
  import { Fragment as Fragment8, jsx as jsx38, jsxs as jsxs35 } from "react/jsx-runtime";
5812
- function TablePage({ tableId, pageSize = 100, className }) {
5823
+ var DEFAULT_VIEW_NAME = "All records";
5824
+ function defaultView(tableId) {
5825
+ return { name: DEFAULT_VIEW_NAME, subject: tableId, layout: "grid", isDefault: true };
5826
+ }
5827
+ function TablePage({ tableId, pageSize = 100, seedViews, className }) {
5813
5828
  const table = useTable21(tableId);
5814
5829
  const rights = useTableRights(table.data);
5815
5830
  const [view, setView] = useState35(null);
@@ -5821,7 +5836,15 @@ function TablePage({ tableId, pageSize = 100, className }) {
5821
5836
  return /* @__PURE__ */ jsxs35("div", { className: cn36("flex min-h-0 gap-4", className), children: [
5822
5837
  /* @__PURE__ */ jsxs35("div", { className: "flex min-w-0 flex-1 flex-col gap-2", children: [
5823
5838
  /* @__PURE__ */ jsxs35("div", { className: "flex flex-wrap items-center gap-1.5", children: [
5824
- /* @__PURE__ */ jsx38(ViewBar, { tableId, onActiveView: setView, className: "min-w-0 flex-1" }),
5839
+ /* @__PURE__ */ jsx38(
5840
+ ViewBar,
5841
+ {
5842
+ tableId,
5843
+ onActiveView: setView,
5844
+ seed: seedViews ?? [defaultView(tableId)],
5845
+ className: "min-w-0 flex-1"
5846
+ }
5847
+ ),
5825
5848
  rights.write ? /* @__PURE__ */ jsx38(Button31, { size: "sm", onClick: () => show("new-record"), children: "New record" }) : null,
5826
5849
  rights.admin ? /* @__PURE__ */ jsxs35(Fragment8, { children: [
5827
5850
  /* @__PURE__ */ jsx38(Button31, { size: "sm", variant: "outline", onClick: () => show("field"), children: "Add field" }),