@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/CHANGELOG.md +89 -0
- package/dist/index.cjs +28 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +46 -12
- package/dist/index.d.ts +46 -12
- package/dist/index.js +28 -5
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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
|
-
/**
|
|
525
|
-
|
|
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.
|
|
1041
|
-
*
|
|
1042
|
-
*
|
|
1043
|
-
*
|
|
1044
|
-
*
|
|
1045
|
-
*
|
|
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
|
-
*
|
|
1048
|
-
*
|
|
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,
|
|
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
|
-
/**
|
|
525
|
-
|
|
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.
|
|
1041
|
-
*
|
|
1042
|
-
*
|
|
1043
|
-
*
|
|
1044
|
-
*
|
|
1045
|
-
*
|
|
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
|
-
*
|
|
1048
|
-
*
|
|
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,
|
|
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,
|
|
5605
|
+
function recordsDataSource(client, fallbackSchema = "custom") {
|
|
5600
5606
|
const supabase = client;
|
|
5601
5607
|
return {
|
|
5602
|
-
rpc
|
|
5603
|
-
|
|
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
|
-
|
|
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(
|
|
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" }),
|