@ai-matrx/records 0.87.32 → 0.92.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 +92 -0
- package/README.md +115 -0
- package/dist/{client-E0VQ0NPO.d.ts → client-DE9Mq6YX.d.cts} +8 -5
- package/dist/{client-C3ZZNfGH.d.cts → client-vJAb7g9r.d.ts} +8 -5
- package/dist/core/index.cjs +25 -7
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +23 -12
- package/dist/core/index.d.ts +23 -12
- package/dist/core/index.js +25 -7
- package/dist/core/index.js.map +1 -1
- package/dist/data/index.cjs +19 -7
- package/dist/data/index.cjs.map +1 -1
- package/dist/data/index.d.cts +12 -142
- package/dist/data/index.d.ts +12 -142
- package/dist/data/index.js +19 -7
- package/dist/data/index.js.map +1 -1
- package/dist/{declareTable-BK3zufr7.d.cts → declareTable-Btg5bql1.d.cts} +4 -4
- package/dist/{declareTable-B12XybRp.d.ts → declareTable-JKt2q34d.d.ts} +4 -4
- package/dist/entity/index.cjs +984 -0
- package/dist/entity/index.cjs.map +1 -0
- package/dist/entity/index.d.cts +36 -0
- package/dist/entity/index.d.ts +36 -0
- package/dist/entity/index.js +964 -0
- package/dist/entity/index.js.map +1 -0
- package/dist/entity/react.cjs +1024 -0
- package/dist/entity/react.cjs.map +1 -0
- package/dist/entity/react.d.cts +511 -0
- package/dist/entity/react.d.ts +511 -0
- package/dist/entity/react.js +1015 -0
- package/dist/entity/react.js.map +1 -0
- package/dist/{field-BanTVGK2.d.cts → field-BJBnTyJ0.d.cts} +1 -1
- package/dist/{field-BPABOJ2Y.d.ts → field-Ti5iAxFr.d.ts} +1 -1
- package/dist/forms/index.cjs +984 -0
- package/dist/forms/index.cjs.map +1 -0
- package/dist/forms/index.d.cts +333 -0
- package/dist/forms/index.d.ts +333 -0
- package/dist/forms/index.js +961 -0
- package/dist/forms/index.js.map +1 -0
- package/dist/index.cjs +10 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -8
- package/dist/index.d.ts +11 -8
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/memory/index.d.cts +7 -6
- package/dist/memory/index.d.ts +7 -6
- package/dist/port-CPVBfDxS.d.cts +301 -0
- package/dist/port-D2i2o7Lg.d.ts +301 -0
- package/dist/portal-Db4CYyHe.d.ts +331 -0
- package/dist/portal-DfeY2Boy.d.cts +331 -0
- package/dist/{ports-TMWX-t9l.d.ts → ports-BWtxAnXh.d.ts} +2 -2
- package/dist/{ports-D8-iuY1P.d.cts → ports-DSU2RsR6.d.cts} +2 -2
- package/dist/react/index.cjs +55 -523
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +14 -1
- package/dist/react/index.d.ts +14 -1
- package/dist/react/index.js +52 -527
- package/dist/react/index.js.map +1 -1
- package/dist/realtime/index.d.cts +2 -2
- package/dist/realtime/index.d.ts +2 -2
- package/dist/{record-DpB2QgAZ.d.cts → record-BQi92d4-.d.cts} +7 -1
- package/dist/{record-DpB2QgAZ.d.ts → record-BQi92d4-.d.ts} +7 -1
- package/dist/relation-DMwkmzgN.d.cts +230 -0
- package/dist/relation-DlcqV_W5.d.ts +230 -0
- package/dist/rule-B8kR0l01.d.ts +250 -0
- package/dist/rule-BMViCLmW.d.cts +250 -0
- package/dist/search/index.cjs +283 -0
- package/dist/search/index.cjs.map +1 -0
- package/dist/search/index.d.cts +44 -0
- package/dist/search/index.d.ts +44 -0
- package/dist/search/index.js +260 -0
- package/dist/search/index.js.map +1 -0
- package/dist/setup/index.cjs +6854 -0
- package/dist/setup/index.cjs.map +1 -0
- package/dist/setup/index.d.cts +87 -0
- package/dist/setup/index.d.ts +87 -0
- package/dist/setup/index.js +6829 -0
- package/dist/setup/index.js.map +1 -0
- package/dist/{subscription-D7KQBHXN.d.ts → subscription-5CLN3Jug.d.ts} +3 -249
- package/dist/{subscription-BD9DnJxX.d.cts → subscription-D-VEzvyy.d.cts} +3 -249
- package/dist/{table-kind-BZu8mtND.d.cts → table-kind-CVp43g6h.d.ts} +3 -558
- package/dist/{table-kind-xKxTHtrV.d.ts → table-kind-Cm6PXkWx.d.cts} +3 -558
- package/dist/templates/index.d.cts +10 -9
- package/dist/templates/index.d.ts +10 -9
- package/dist/typed-table/index.cjs +19 -7
- package/dist/typed-table/index.cjs.map +1 -1
- package/dist/typed-table/index.d.cts +10 -7
- package/dist/typed-table/index.d.ts +10 -7
- package/dist/typed-table/index.js +19 -7
- package/dist/typed-table/index.js.map +1 -1
- package/dist/{types-CLP5H4Wk.d.cts → types-9Q5SHRDJ.d.cts} +2 -2
- package/dist/{types-DmPkWQic.d.ts → types-CfYy-vdV.d.ts} +2 -2
- package/dist/{types-C2uspRtf.d.cts → types-Cs2MyE3u.d.cts} +2 -2
- package/dist/{types-Dv61jStB.d.ts → types-DF-dxB_l.d.ts} +2 -2
- package/dist/types-DTEGaxso.d.cts +139 -0
- package/dist/types-Dji5SpFS.d.ts +139 -0
- package/dist/use-cases/index.d.cts +5 -5
- package/dist/use-cases/index.d.ts +5 -5
- package/dist/{validate-CWVToe1T.d.ts → validate-BydKd-Le.d.ts} +1 -1
- package/dist/{validate-DEB_mn4Y.d.cts → validate-CqJakTKk.d.cts} +1 -1
- package/dist/versions/index.cjs +375 -0
- package/dist/versions/index.cjs.map +1 -0
- package/dist/versions/index.d.cts +160 -0
- package/dist/versions/index.d.ts +160 -0
- package/dist/versions/index.js +353 -0
- package/dist/versions/index.js.map +1 -0
- package/package.json +62 -2
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
// src/core/supabase.ts
|
|
2
|
+
function refuse(code, message, hint) {
|
|
3
|
+
return { data: null, error: { code, message, hint, details: "" } };
|
|
4
|
+
}
|
|
5
|
+
function supabaseDataSource(client) {
|
|
6
|
+
if (isBound(client)) return client;
|
|
7
|
+
const supabase = client;
|
|
8
|
+
const hasSchema = typeof supabase.schema === "function";
|
|
9
|
+
const bound = {
|
|
10
|
+
// PAGE-BUNDLE: the real adapter opens a table page with one `custom.table_page_bundle` call.
|
|
11
|
+
opensInOneCall: true,
|
|
12
|
+
rpc(fn, args, options) {
|
|
13
|
+
if (!hasSchema) {
|
|
14
|
+
return Promise.resolve(
|
|
15
|
+
refuse(
|
|
16
|
+
"data_source_unbound",
|
|
17
|
+
`The records client was given something that is not a supabase client: it has no schema() method, so the door ${fn} cannot be called in the schema it lives in.`,
|
|
18
|
+
"Pass a supabase-js v2 client (createClient(...)) to supabaseDataSource()."
|
|
19
|
+
)
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
const name = options?.schema;
|
|
23
|
+
if (!name) {
|
|
24
|
+
return Promise.resolve(
|
|
25
|
+
refuse(
|
|
26
|
+
"schema_unsaid",
|
|
27
|
+
`The door ${fn} was called without saying which schema it lives in. Every door of this store is custom.${fn} and every trust door is iam.${fn}; an unqualified call reaches PostgREST's default profile (public) and is refused there.`,
|
|
28
|
+
"This is a bug in the caller, not in your data: /core says the schema on every call."
|
|
29
|
+
)
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
return supabase.schema(name).rpc(fn, args);
|
|
33
|
+
},
|
|
34
|
+
schema(name) {
|
|
35
|
+
return supabase.schema(name);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(bound, BOUND, { value: true, enumerable: false });
|
|
39
|
+
return bound;
|
|
40
|
+
}
|
|
41
|
+
var BOUND = /* @__PURE__ */ Symbol.for("@ai-matrx/records/supabaseDataSource");
|
|
42
|
+
function isBound(source) {
|
|
43
|
+
return source[BOUND] === true;
|
|
44
|
+
}
|
|
45
|
+
function asRecordsDataSource(source) {
|
|
46
|
+
if (source === null || typeof source !== "object") return supabaseDataSource({});
|
|
47
|
+
if (isBound(source)) return source;
|
|
48
|
+
const candidate = source;
|
|
49
|
+
const looksLikeSupabaseJs = typeof candidate.schema === "function" && typeof candidate.from === "function" && candidate.auth !== null && typeof candidate.auth === "object";
|
|
50
|
+
if (looksLikeSupabaseJs || typeof candidate.rpc !== "function") return supabaseDataSource(source);
|
|
51
|
+
return source;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// src/core/pgError.ts
|
|
55
|
+
var BY_SQLSTATE = {
|
|
56
|
+
PT409: "stale_write",
|
|
57
|
+
"42501": "door",
|
|
58
|
+
"23514": "refused_by_rule",
|
|
59
|
+
"22004": "invalid_argument",
|
|
60
|
+
"22023": "invalid_argument",
|
|
61
|
+
// MX005 — a value the store cannot take as asked: since 2026-10-06 (AP-3 U3) a word that names more than one
|
|
62
|
+
// choice or linked record raises it (it used to borrow PT409 and read as somebody else's write winning).
|
|
63
|
+
MX005: "invalid_argument",
|
|
64
|
+
// MXD01 — the held-change door tried the proposed values before filing an
|
|
65
|
+
// approval request and the store refused them. Nothing is waiting for a
|
|
66
|
+
// person to decide; correct the value before asking again, which is the same
|
|
67
|
+
// caller-side condition as the other invalid-argument refusals.
|
|
68
|
+
MXD01: "invalid_argument",
|
|
69
|
+
// 22P02 — a value does not fit the type the store holds for it. The class is
|
|
70
|
+
// real and was hit live: an organization whose copy of a package table grew
|
|
71
|
+
// `status` as a uuid-valued Field was sent the text "open", and the store
|
|
72
|
+
// answered `invalid input syntax for type uuid: "open"`. It is the CALL that
|
|
73
|
+
// is wrong for the shape the store holds, which is what `invalid_argument`
|
|
74
|
+
// already means — the store's own sentence names the value and the type.
|
|
75
|
+
"22P02": "invalid_argument",
|
|
76
|
+
// 42703 — a column that is not there. The store raises it from
|
|
77
|
+
// `custom.entity_table`, which is asked for a column by NAME, so the class is
|
|
78
|
+
// exactly "the call named something the shape does not have": the same thing
|
|
79
|
+
// `invalid_argument` already means, and the store's own sentence names the
|
|
80
|
+
// column. Added 2026-09-20 (lane FORMS) because the package's live-door suite
|
|
81
|
+
// caught it raised by a door this package did not know about — which is the
|
|
82
|
+
// suite working, and is why the map is a census rather than a guess.
|
|
83
|
+
"42703": "invalid_argument",
|
|
84
|
+
// 22007 — a date or a time the store could not read as one. It is raised by
|
|
85
|
+
// `custom.dashboard_window_sql`, which is handed a window a caller wrote
|
|
86
|
+
// ("last 30 days", a literal date), so the class is again "the call named
|
|
87
|
+
// something the shape does not accept" and the store's own sentence names the
|
|
88
|
+
// text it could not read. Added 2026-09-20 (lane SCREEN-BREAK) after the
|
|
89
|
+
// live-door census caught it — the same way 42703 arrived, which is the
|
|
90
|
+
// census working rather than a guess.
|
|
91
|
+
"22007": "invalid_argument",
|
|
92
|
+
// 22003 — a number the store could not hold at the size it was handed. It is
|
|
93
|
+
// raised by `custom.context_resolve`, which is given a window or a depth a
|
|
94
|
+
// caller wrote, so the class is the same one 22P02, 42703 and 22007 already
|
|
95
|
+
// are: the CALL named a value the shape does not accept, and the store's own
|
|
96
|
+
// sentence names the number and the range. Added 2026-09-20 (lane GRID-TWO)
|
|
97
|
+
// when the live-door census caught the release gate red on it — which is the
|
|
98
|
+
// census working, and the fourth time it has been the thing that found a new
|
|
99
|
+
// refusal class rather than a person guessing one.
|
|
100
|
+
"22003": "invalid_argument",
|
|
101
|
+
// 42883 — `custom._template_call` (the template family, 2026-10-03) was handed a step that
|
|
102
|
+
// names a door the store does not have, or an argument that door does not take. The TEMPLATE
|
|
103
|
+
// named something the shape does not have — the same class 42703 is — and the store's own
|
|
104
|
+
// sentence names the door or the argument. Caught by the live-door census on records 0.68.1's
|
|
105
|
+
// tag, the eighth time the census found a class before a person did. (A bare 42883 on a door
|
|
106
|
+
// this package itself asks for is still `door_absent`, mapped before this funnel in
|
|
107
|
+
// `owedDoor`.)
|
|
108
|
+
"42883": "invalid_argument",
|
|
109
|
+
"02000": "not_found",
|
|
110
|
+
// P0002 — `custom.inbox_snooze` / `custom.inbox_clear` (lane S5-PRIME-2, 2026-09-24): "There is
|
|
111
|
+
// nothing in your inbox with that id". An invented id, another person's item and another
|
|
112
|
+
// organization's all answer it alike, so it reads exactly as 02000 does: not found.
|
|
113
|
+
"P0002": "not_found",
|
|
114
|
+
"23503": "missing_reference",
|
|
115
|
+
"23505": "already_exists",
|
|
116
|
+
"0A000": "not_supported",
|
|
117
|
+
"53400": "store_limit",
|
|
118
|
+
"22012": "store_limit",
|
|
119
|
+
// 54001 — `custom.record_delete` stops a cascade that nests past sixty-four
|
|
120
|
+
// levels of containment, because that is a loop somebody built rather than a
|
|
121
|
+
// hierarchy, and saying so beats recursing until the server runs out of
|
|
122
|
+
// stack. It is a LIMIT of the store, and the store's own sentence names what
|
|
123
|
+
// to do about it, so it reads as one.
|
|
124
|
+
"54001": "store_limit",
|
|
125
|
+
// 54000 — the grid primitives' organization ceilings (GRID-PRIMITIVES, 2026-09-23):
|
|
126
|
+
// `custom.action_run` on a selection past its knob, `custom.table_decorate` past the
|
|
127
|
+
// rule count, `custom.table_from_example` past `custom/example_rows_max`,
|
|
128
|
+
// `custom.table_webhook_declare` past `custom/table_webhooks_max`, and
|
|
129
|
+
// `custom.hub_changed_by`. Each names its knob in the hint and writes nothing, so it
|
|
130
|
+
// reads exactly like 54001: a limit of the store, in the store's own sentence.
|
|
131
|
+
"54000": "store_limit",
|
|
132
|
+
// VIS: `custom.has_visibility_at` refuses to answer from a snapshot older
|
|
133
|
+
// than a write this reader has already seen, rather than returning something
|
|
134
|
+
// they just lost access to. It is retryable on a fresher connection, which is
|
|
135
|
+
// a different instruction from every other refusal here.
|
|
136
|
+
// 55000 — `custom.table_move` (SC-1', 2026-09-24) refuses a move the table's present state
|
|
137
|
+
// does not allow: a destination that cannot take it, a table something else holds, contents
|
|
138
|
+
// that point at themselves in a circle. The store's own sentence names the reason and nothing
|
|
139
|
+
// moves, so it reads as a refusal on the merits. Caught by the live-door census on records
|
|
140
|
+
// 0.58.3's tag, the seventh time the census found a class before a person did.
|
|
141
|
+
"55000": "refused_by_rule",
|
|
142
|
+
// 42P17 — a worked-out column that would read itself round a circle (STORE-TAILS-3,
|
|
143
|
+
// 2026-09-25): `custom._field_reads_what_it_reads` refuses the declaration or edit that would
|
|
144
|
+
// close the circle, naming every column in it, and `custom.far_value` refuses a circle stored
|
|
145
|
+
// before that rule when a lookup or rollup is worked out. Refused on its merits, in the store's
|
|
146
|
+
// own sentence, nothing written — so it reads as 55000 does.
|
|
147
|
+
"42P17": "refused_by_rule",
|
|
148
|
+
// P0001 — `custom.context_scope_write` (2026-10-03) refuses a scope whose parent breaks the
|
|
149
|
+
// parent rule in the old trigger's own class and words (manager ruling H6). Refused on its
|
|
150
|
+
// merits, nothing written. Caught by the live-door census on records 0.65.0's tag.
|
|
151
|
+
P0001: "refused_by_rule",
|
|
152
|
+
"40001": "stale_read",
|
|
153
|
+
// 57014 — the store cancelled the statement at its own timeout. Like
|
|
154
|
+
// `stale_read` and unlike every other refusal here, the call was never
|
|
155
|
+
// refused on its merits: the same call on a smaller page, or once the
|
|
156
|
+
// organization's kernel is not being rewritten, can succeed. It gets its own
|
|
157
|
+
// code so a screen can offer "try again" honestly instead of showing a
|
|
158
|
+
// failure sentence the caller cannot act on.
|
|
159
|
+
"57014": "timed_out",
|
|
160
|
+
// PostgREST's own two: the store is not being SERVED, which is a different
|
|
161
|
+
// thing from the store refusing. `custom` absent from `pgrst.db_schemas`, or
|
|
162
|
+
// the grants not copied, land here.
|
|
163
|
+
PGRST202: "store_not_served",
|
|
164
|
+
PGRST205: "store_not_served",
|
|
165
|
+
PGRST301: "door",
|
|
166
|
+
// PT428 — NOT A FAILURE, and the release gate's live census is what found it
|
|
167
|
+
// missing: the store raises it and this package answered `internal`, which is
|
|
168
|
+
// the one classification that tells a screen nothing. A stage gate whose
|
|
169
|
+
// `on_fail` is `require_approval` files the request and leaves the record
|
|
170
|
+
// where it was; the transaction is rolled back to the pipeline's own block, so
|
|
171
|
+
// "nothing was written" is a fact rather than a promise. Landed by lane
|
|
172
|
+
// STAGE-RULES; mapped here by STAGE-RULES-2 the day after, when the census
|
|
173
|
+
// caught it — the sixth time that census has been the thing that found a
|
|
174
|
+
// refusal class rather than a person guessing one.
|
|
175
|
+
PT428: "needs_approval"
|
|
176
|
+
};
|
|
177
|
+
var MAPPED_SQLSTATES = Object.keys(BY_SQLSTATE);
|
|
178
|
+
function parseDetail(details) {
|
|
179
|
+
if (!details) return void 0;
|
|
180
|
+
const trimmed = details.trim();
|
|
181
|
+
if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return details;
|
|
182
|
+
try {
|
|
183
|
+
return JSON.parse(trimmed);
|
|
184
|
+
} catch {
|
|
185
|
+
return details;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function isNotASqlstate(code) {
|
|
189
|
+
if (!code) return true;
|
|
190
|
+
return /^[0-9]{3}$/.test(code);
|
|
191
|
+
}
|
|
192
|
+
function mapPgError(error, where) {
|
|
193
|
+
const raw = error.code ?? void 0;
|
|
194
|
+
const sqlstate = raw && raw !== "" ? raw : void 0;
|
|
195
|
+
const mapped = {
|
|
196
|
+
code: "internal",
|
|
197
|
+
message: error.message,
|
|
198
|
+
...error.hint ? { hint: error.hint } : {},
|
|
199
|
+
...sqlstate ? { sqlstate } : {}
|
|
200
|
+
};
|
|
201
|
+
if (isNotASqlstate(sqlstate)) {
|
|
202
|
+
mapped.code = "unreachable";
|
|
203
|
+
} else {
|
|
204
|
+
mapped.code = BY_SQLSTATE[sqlstate] ?? "internal";
|
|
205
|
+
}
|
|
206
|
+
const detail = parseDetail(error.details);
|
|
207
|
+
if (detail !== void 0) mapped.detail = detail;
|
|
208
|
+
if (mapped.code === "internal") {
|
|
209
|
+
mapped.unmapped = true;
|
|
210
|
+
mapped.diagnostic = `@ai-matrx/records did not recognise SQLSTATE ${sqlstate ?? "(none)"} from ${where}; the store's own message is the thing to act on.`;
|
|
211
|
+
} else if (mapped.code === "unreachable") {
|
|
212
|
+
mapped.unmapped = true;
|
|
213
|
+
mapped.diagnostic = `@ai-matrx/records never reached the store from ${where}: ${raw ? `the transport answered ${raw}` : "no response"} \u2014 ${error.message}`;
|
|
214
|
+
mapped.message = "We could not reach your data.";
|
|
215
|
+
delete mapped.hint;
|
|
216
|
+
}
|
|
217
|
+
return mapped;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// src/search/index.ts
|
|
221
|
+
var STORE_RECORD_SEARCH_MIN_CHARS = 2;
|
|
222
|
+
async function searchRecords(dataSource, request = {}) {
|
|
223
|
+
const search = request.search?.trim() ?? "";
|
|
224
|
+
if (search.length > 0 && search.length < STORE_RECORD_SEARCH_MIN_CHARS) return { ok: true, data: [] };
|
|
225
|
+
const args = { p_search: search, p_limit: request.limit ?? 25, p_offset: request.offset ?? 0 };
|
|
226
|
+
if (request.tableIds && request.tableIds.length > 0) args["p_table_ids"] = [...request.tableIds];
|
|
227
|
+
if (request.organizationIds && request.organizationIds.length > 0) args["p_organization_ids"] = [...request.organizationIds];
|
|
228
|
+
try {
|
|
229
|
+
const answer = await asRecordsDataSource(dataSource).rpc("records_search", args, { schema: "custom" });
|
|
230
|
+
if (answer.error) return { ok: false, error: mapPgError(answer.error, "custom.records_search") };
|
|
231
|
+
const rows = answer.data ?? [];
|
|
232
|
+
return {
|
|
233
|
+
ok: true,
|
|
234
|
+
data: rows.map((row) => ({
|
|
235
|
+
recordId: row.record_id,
|
|
236
|
+
tableId: row.table_id,
|
|
237
|
+
tableName: row.table_name,
|
|
238
|
+
name: row.name,
|
|
239
|
+
organizationId: row.organization_id,
|
|
240
|
+
updatedAt: row.updated_at
|
|
241
|
+
}))
|
|
242
|
+
};
|
|
243
|
+
} catch (thrown) {
|
|
244
|
+
return { ok: false, error: mapPgError({ code: "", message: thrown instanceof Error ? thrown.message : String(thrown) }, "custom.records_search") };
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
async function listStoreRecordCandidates(dataSource, args) {
|
|
248
|
+
const found = await searchRecords(dataSource, { ...args.search !== void 0 ? { search: args.search } : {}, limit: args.limit ?? 25 });
|
|
249
|
+
if (!found.ok) {
|
|
250
|
+
console.error("[listStoreRecordCandidates] failed", found.error);
|
|
251
|
+
return { ok: false, error: found.error.message || "Could not search records" };
|
|
252
|
+
}
|
|
253
|
+
return { ok: true, data: found.data.map((hit) => ({ id: hit.recordId, title: hit.name ? `${hit.name} \xB7 ${hit.tableName}` : hit.tableName })) };
|
|
254
|
+
}
|
|
255
|
+
export {
|
|
256
|
+
STORE_RECORD_SEARCH_MIN_CHARS,
|
|
257
|
+
listStoreRecordCandidates,
|
|
258
|
+
searchRecords
|
|
259
|
+
};
|
|
260
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/supabase.ts","../../src/core/pgError.ts","../../src/search/index.ts"],"sourcesContent":["// src/core/supabase.ts — @ai-matrx/records (HEADLESS)\n//\n// THE ONE ADAPTER FROM A SUPABASE CLIENT TO THIS PACKAGE'S DATA SEAM.\n//\n// Why it exists, and what it cost to learn (2026-09-19, the independent verdict\n// on /data): `RecordsDataSource.rpc(fn, args, { schema })` says the schema\n// out loud, because every door of this store is `custom.<name>` and every door\n// of the trust layer is `iam.<name>`. supabase-js's own\n// `rpc(fn, args, options)` HAS NO `schema` OPTION — its third argument is\n// `{ head, get, count }`, and an unknown key is dropped in silence. So a\n// supabase client handed straight to `config.dataSource` as a structural cast\n// asked its default PostgREST profile, `public`, for every door, and the store\n// answered correctly and uselessly:\n//\n// PGRST202 — Could not find the function public.table_kernel_id(...) in the\n// schema cache\n//\n// Every screen in the record store was dead from a browser because of it, while\n// the desktop app and the browser extension each grew their own way of asking.\n// The class fix is ONE adapter, here, in the headless core, that every host\n// inherits — never three hosts remembering the same thing.\n//\n// The schema is chosen the ONE way supabase-js offers: `client.schema(name)`\n// returns a client bound to that PostgREST profile (it sets the\n// `Accept-Profile` / `Content-Profile` headers), and `.rpc()` on THAT is the\n// call. There is no per-call option that does it.\n//\n// This file holds no key and opens no connection: the host hands in a client\n// that already carries the operating person's session, which is what makes\n// DOOR-5 and AGT-N-4 true — the store sees the person, not us.\n\nimport type { PgError } from \"../results\";\nimport type { RecordsDataSource } from \"../ports\";\n\n/**\n * The structural shape of the supabase client this adapter needs. Deliberately\n * NOT `SupabaseClient<Database>`: a generated `Database` type makes\n * `schema().from().select()` enormous, and a host app that passed its typed\n * client in got `TS2589: Type instantiation is excessively deep and possibly\n * infinite` in its own build (matrx-frontend, 2026-09-18, on all three campaign\n * routes at once). The cast lives here, once, where it is explained.\n */\nexport interface SupabaseLike {\n schema(name: string): {\n rpc(\n fn: string,\n args?: Record<string, unknown>,\n ): PromiseLike<{ data: unknown; error: PgError | null }>;\n from(table: string): unknown;\n };\n}\n\n/** The refusal a caller sees rather than a silent call to the wrong schema. */\nfunction refuse(code: string, message: string, hint: string): { data: null; error: PgError } {\n return { data: null, error: { code, message, hint, details: \"\" } as unknown as PgError };\n}\n\n/**\n * Bind a supabase-js client (or anything with the same `schema(name).rpc()`\n * shape) as this package's data seam.\n *\n * Two things never happen here, both of them loudly:\n *\n * - A call with NO schema is never sent. It is refused by name, because\n * sending it would reach `public` and get the store's PGRST202 several\n * layers away from the mistake.\n * - A client with no `.schema()` is never used. supabase-js has had it since\n * v2.0; a host that binds something else is told exactly what is missing\n * instead of throwing `undefined is not a function` inside a render.\n */\nexport function supabaseDataSource(client: object): RecordsDataSource {\n if (isBound(client)) return client;\n const supabase = client as unknown as Partial<SupabaseLike>;\n const hasSchema = typeof supabase.schema === \"function\";\n\n const bound: RecordsDataSource = {\n // PAGE-BUNDLE: the real adapter opens a table page with one `custom.table_page_bundle` call.\n opensInOneCall: true,\n rpc(fn, args, options) {\n if (!hasSchema) {\n return Promise.resolve(\n refuse(\n \"data_source_unbound\",\n `The records client was given something that is not a supabase client: it has no schema() ` +\n `method, so the door ${fn} cannot be called in the schema it lives in.`,\n \"Pass a supabase-js v2 client (createClient(...)) to supabaseDataSource().\",\n ),\n );\n }\n const name = options?.schema;\n if (!name) {\n return Promise.resolve(\n refuse(\n \"schema_unsaid\",\n `The door ${fn} was called without saying which schema it lives in. ` +\n `Every door of this store is custom.${fn} and every trust door is iam.${fn}; ` +\n `an unqualified call reaches PostgREST's default profile (public) and is refused there.`,\n \"This is a bug in the caller, not in your data: /core says the schema on every call.\",\n ),\n );\n }\n return (supabase as SupabaseLike).schema(name).rpc(fn, args) as ReturnType<\n RecordsDataSource[\"rpc\"]\n >;\n },\n schema(name) {\n return (supabase as SupabaseLike).schema(name) as ReturnType<RecordsDataSource[\"schema\"]>;\n },\n };\n Object.defineProperty(bound, BOUND, { value: true, enumerable: false });\n return bound;\n}\n\n/** Marks a data source this adapter made, so binding it twice is a no-op, never a double wrap. */\nconst BOUND = Symbol.for(\"@ai-matrx/records/supabaseDataSource\");\n\nfunction isBound(source: object): source is RecordsDataSource {\n return (source as Record<symbol, unknown>)[BOUND] === true;\n}\n\n/**\n * WHAT `createRecordsClient` DOES WITH WHATEVER IT IS HANDED (lane PLATFORM-APP-DATA, 2026-10-02).\n *\n * The README has always shown `dataSource: supabase` — a PLAIN supabase-js client — and that\n * exact line answered every call \"Could not find the function public.table_kernel_id\" (PGRST202),\n * because supabase-js's own `rpc()` drops the `{ schema }` option in silence (see the header).\n * Measured on the clone as admin@admin.com, 2026-10-02. The example is now true:\n *\n * - Already bound by `supabaseDataSource` → used as it is.\n * - A supabase-js client (it has `schema()`, `from()` and an `auth` client) → bound here, once.\n * - Nothing callable at all (no `rpc()`) → bound here too, so every call is REFUSED by name with\n * the remedy (`data_source_unbound`) instead of throwing `rpc is not a function` in a render.\n * - Anything else that has its own `rpc(fn, args, { schema })` — a host's adapter, a test\n * double — is the host's own data seam and is used as it is: it promised to honour `schema`.\n */\nexport function asRecordsDataSource(source: unknown): RecordsDataSource {\n if (source === null || typeof source !== \"object\") return supabaseDataSource({});\n if (isBound(source)) return source;\n const candidate = source as Partial<SupabaseLike> & { rpc?: unknown; from?: unknown; auth?: unknown };\n const looksLikeSupabaseJs =\n typeof candidate.schema === \"function\" &&\n typeof candidate.from === \"function\" &&\n candidate.auth !== null &&\n typeof candidate.auth === \"object\";\n if (looksLikeSupabaseJs || typeof candidate.rpc !== \"function\") return supabaseDataSource(source);\n return source as RecordsDataSource;\n}\n","// src/core/pgError.ts — @ai-matrx/records\n//\n// THE ONE FUNNEL from what the database said to what a caller reads. Every\n// method in this package's client goes through it, and it does exactly three\n// things: it classifies the SQLSTATE, it carries the store's message and hint\n// VERBATIM, and it parses the DETAIL when the store put json there.\n//\n// It never writes a sentence of its own about a refusal the store already\n// explained. The store's messages were written to be read by the person who hit\n// them — \"Someone else changed this record while you were working on it\" is the\n// screen's text, not a code the screen has to translate.\n\nimport type { PgError, RecordsError, RecordsErrorCode, StaleWriteDetail } from \"../results\";\n\n/**\n * SQLSTATE -> code. Every entry here answers one of the codes\n * `STORE_REFUSAL_CODES` reports the store raising; the real-door suite asserts\n * that this map covers all of them, so a new refusal class in the store shows\n * up as a red test rather than an `internal` in somebody's console.\n */\nconst BY_SQLSTATE: Record<string, RecordsErrorCode> = {\n PT409: \"stale_write\",\n \"42501\": \"door\",\n \"23514\": \"refused_by_rule\",\n \"22004\": \"invalid_argument\",\n \"22023\": \"invalid_argument\",\n // MX005 — a value the store cannot take as asked: since 2026-10-06 (AP-3 U3) a word that names more than one\n // choice or linked record raises it (it used to borrow PT409 and read as somebody else's write winning).\n MX005: \"invalid_argument\",\n // MXD01 — the held-change door tried the proposed values before filing an\n // approval request and the store refused them. Nothing is waiting for a\n // person to decide; correct the value before asking again, which is the same\n // caller-side condition as the other invalid-argument refusals.\n MXD01: \"invalid_argument\",\n // 22P02 — a value does not fit the type the store holds for it. The class is\n // real and was hit live: an organization whose copy of a package table grew\n // `status` as a uuid-valued Field was sent the text \"open\", and the store\n // answered `invalid input syntax for type uuid: \"open\"`. It is the CALL that\n // is wrong for the shape the store holds, which is what `invalid_argument`\n // already means — the store's own sentence names the value and the type.\n \"22P02\": \"invalid_argument\",\n // 42703 — a column that is not there. The store raises it from\n // `custom.entity_table`, which is asked for a column by NAME, so the class is\n // exactly \"the call named something the shape does not have\": the same thing\n // `invalid_argument` already means, and the store's own sentence names the\n // column. Added 2026-09-20 (lane FORMS) because the package's live-door suite\n // caught it raised by a door this package did not know about — which is the\n // suite working, and is why the map is a census rather than a guess.\n \"42703\": \"invalid_argument\",\n // 22007 — a date or a time the store could not read as one. It is raised by\n // `custom.dashboard_window_sql`, which is handed a window a caller wrote\n // (\"last 30 days\", a literal date), so the class is again \"the call named\n // something the shape does not accept\" and the store's own sentence names the\n // text it could not read. Added 2026-09-20 (lane SCREEN-BREAK) after the\n // live-door census caught it — the same way 42703 arrived, which is the\n // census working rather than a guess.\n \"22007\": \"invalid_argument\",\n // 22003 — a number the store could not hold at the size it was handed. It is\n // raised by `custom.context_resolve`, which is given a window or a depth a\n // caller wrote, so the class is the same one 22P02, 42703 and 22007 already\n // are: the CALL named a value the shape does not accept, and the store's own\n // sentence names the number and the range. Added 2026-09-20 (lane GRID-TWO)\n // when the live-door census caught the release gate red on it — which is the\n // census working, and the fourth time it has been the thing that found a new\n // refusal class rather than a person guessing one.\n \"22003\": \"invalid_argument\",\n // 42883 — `custom._template_call` (the template family, 2026-10-03) was handed a step that\n // names a door the store does not have, or an argument that door does not take. The TEMPLATE\n // named something the shape does not have — the same class 42703 is — and the store's own\n // sentence names the door or the argument. Caught by the live-door census on records 0.68.1's\n // tag, the eighth time the census found a class before a person did. (A bare 42883 on a door\n // this package itself asks for is still `door_absent`, mapped before this funnel in\n // `owedDoor`.)\n \"42883\": \"invalid_argument\",\n \"02000\": \"not_found\",\n // P0002 — `custom.inbox_snooze` / `custom.inbox_clear` (lane S5-PRIME-2, 2026-09-24): \"There is\n // nothing in your inbox with that id\". An invented id, another person's item and another\n // organization's all answer it alike, so it reads exactly as 02000 does: not found.\n \"P0002\": \"not_found\",\n \"23503\": \"missing_reference\",\n \"23505\": \"already_exists\",\n \"0A000\": \"not_supported\",\n \"53400\": \"store_limit\",\n \"22012\": \"store_limit\",\n // 54001 — `custom.record_delete` stops a cascade that nests past sixty-four\n // levels of containment, because that is a loop somebody built rather than a\n // hierarchy, and saying so beats recursing until the server runs out of\n // stack. It is a LIMIT of the store, and the store's own sentence names what\n // to do about it, so it reads as one.\n \"54001\": \"store_limit\",\n // 54000 — the grid primitives' organization ceilings (GRID-PRIMITIVES, 2026-09-23):\n // `custom.action_run` on a selection past its knob, `custom.table_decorate` past the\n // rule count, `custom.table_from_example` past `custom/example_rows_max`,\n // `custom.table_webhook_declare` past `custom/table_webhooks_max`, and\n // `custom.hub_changed_by`. Each names its knob in the hint and writes nothing, so it\n // reads exactly like 54001: a limit of the store, in the store's own sentence.\n \"54000\": \"store_limit\",\n // VIS: `custom.has_visibility_at` refuses to answer from a snapshot older\n // than a write this reader has already seen, rather than returning something\n // they just lost access to. It is retryable on a fresher connection, which is\n // a different instruction from every other refusal here.\n // 55000 — `custom.table_move` (SC-1', 2026-09-24) refuses a move the table's present state\n // does not allow: a destination that cannot take it, a table something else holds, contents\n // that point at themselves in a circle. The store's own sentence names the reason and nothing\n // moves, so it reads as a refusal on the merits. Caught by the live-door census on records\n // 0.58.3's tag, the seventh time the census found a class before a person did.\n \"55000\": \"refused_by_rule\",\n // 42P17 — a worked-out column that would read itself round a circle (STORE-TAILS-3,\n // 2026-09-25): `custom._field_reads_what_it_reads` refuses the declaration or edit that would\n // close the circle, naming every column in it, and `custom.far_value` refuses a circle stored\n // before that rule when a lookup or rollup is worked out. Refused on its merits, in the store's\n // own sentence, nothing written — so it reads as 55000 does.\n \"42P17\": \"refused_by_rule\",\n // P0001 — `custom.context_scope_write` (2026-10-03) refuses a scope whose parent breaks the\n // parent rule in the old trigger's own class and words (manager ruling H6). Refused on its\n // merits, nothing written. Caught by the live-door census on records 0.65.0's tag.\n P0001: \"refused_by_rule\",\n \"40001\": \"stale_read\",\n // 57014 — the store cancelled the statement at its own timeout. Like\n // `stale_read` and unlike every other refusal here, the call was never\n // refused on its merits: the same call on a smaller page, or once the\n // organization's kernel is not being rewritten, can succeed. It gets its own\n // code so a screen can offer \"try again\" honestly instead of showing a\n // failure sentence the caller cannot act on.\n \"57014\": \"timed_out\",\n // PostgREST's own two: the store is not being SERVED, which is a different\n // thing from the store refusing. `custom` absent from `pgrst.db_schemas`, or\n // the grants not copied, land here.\n PGRST202: \"store_not_served\",\n PGRST205: \"store_not_served\",\n PGRST301: \"door\",\n // PT428 — NOT A FAILURE, and the release gate's live census is what found it\n // missing: the store raises it and this package answered `internal`, which is\n // the one classification that tells a screen nothing. A stage gate whose\n // `on_fail` is `require_approval` files the request and leaves the record\n // where it was; the transaction is rolled back to the pipeline's own block, so\n // \"nothing was written\" is a fact rather than a promise. Landed by lane\n // STAGE-RULES; mapped here by STAGE-RULES-2 the day after, when the census\n // caught it — the sixth time that census has been the thing that found a\n // refusal class rather than a person guessing one.\n PT428: \"needs_approval\",\n};\n\n/** The SQLSTATEs this package claims to understand. Exported for the guard. */\nexport const MAPPED_SQLSTATES = Object.keys(BY_SQLSTATE);\n\nfunction parseDetail(details: string | null | undefined): unknown {\n if (!details) return undefined;\n const trimmed = details.trim();\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\")) return details;\n try {\n return JSON.parse(trimmed) as unknown;\n } catch {\n return details;\n }\n}\n\n/**\n * A CODE THAT IS NOT A SQLSTATE AT ALL — so it is not read as one.\n *\n * A SQLSTATE is five characters. supabase-js puts something else in `code` in\n * exactly two situations, and BOTH of them mean the call never reached the\n * store rather than the store refusing it:\n *\n * `\"\"` a `FetchError` — no network, a cancelled request, CORS.\n * `\"404\"`… an HTTP status, when the gateway answered with no JSON body.\n *\n * Lane TAILS-6 (2026-09-22) found both landing in `internal`, which is the one\n * classification that tells a screen nothing: a person on the Checklists tab of\n * a plumbing company's jobs table was shown \"Something went wrong at our end\"\n * with nothing to do about it, over a sentence naming this package. They are\n * `unreachable`, which a screen can honestly offer \"try again\" for.\n */\nfunction isNotASqlstate(code: string | undefined): boolean {\n if (!code) return true;\n return /^[0-9]{3}$/.test(code);\n}\n\n/** Map a PostgREST/supabase-js failure into the package's refusal shape. */\nexport function mapPgError(error: PgError, where: string): RecordsError {\n // `code: \"\"` is supabase-js's own value for a transport failure, and `\"\"` is\n // not nullish — so it has to be emptied deliberately or it becomes a SQLSTATE\n // nobody can look up.\n const raw = error.code ?? undefined;\n const sqlstate = raw && raw !== \"\" ? raw : undefined;\n const mapped: RecordsError = {\n code: \"internal\",\n message: error.message,\n ...(error.hint ? { hint: error.hint } : {}),\n ...(sqlstate ? { sqlstate } : {}),\n };\n if (isNotASqlstate(sqlstate)) {\n mapped.code = \"unreachable\";\n } else {\n mapped.code = BY_SQLSTATE[sqlstate!] ?? \"internal\";\n }\n const detail = parseDetail(error.details);\n if (detail !== undefined) mapped.detail = detail;\n if (mapped.code === \"internal\") {\n // 🚨 THE NOTE GOES IN ITS OWN FIELD, NEVER ONTO `hint` (lane TAILS-6).\n // `hint` is THE REMEDY — the sentence screens hand a person to act on — so\n // a note this package writes about ITSELF being surprised belonged nowhere\n // near it. It is still said out loud, so nobody reads the silence as\n // \"handled\"; it is said to whoever debugs this and to nobody else.\n mapped.unmapped = true;\n mapped.diagnostic =\n `@ai-matrx/records did not recognise SQLSTATE ${sqlstate ?? \"(none)\"} from ${where}; ` +\n `the store's own message is the thing to act on.`;\n } else if (mapped.code === \"unreachable\") {\n mapped.unmapped = true;\n mapped.diagnostic =\n `@ai-matrx/records never reached the store from ${where}: ` +\n `${raw ? `the transport answered ${raw}` : \"no response\"} — ${error.message}`;\n // 🚨 THE ONE PLACE THIS PACKAGE WRITES A MESSAGE OF ITS OWN, and it is the\n // one place where there is no store message to carry: the store never\n // answered. `TypeError: Failed to fetch` is the browser talking to itself,\n // not a sentence anybody should read, so it goes to the engineer's line\n // above and the person gets what actually happened.\n mapped.message = \"We could not reach your data.\";\n // Whatever the transport said was never a remedy either.\n delete mapped.hint;\n }\n return mapped;\n}\n\n/** Pull the conflict out of a `stale_write`, when the store sent one. */\nexport function staleWriteDetail(error: RecordsError): StaleWriteDetail | null {\n if (error.code !== \"stale_write\") return null;\n const detail = error.detail as Partial<StaleWriteDetail> | undefined;\n if (\n !detail ||\n typeof detail.expected_version !== \"number\" ||\n typeof detail.current_version !== \"number\"\n ) {\n return null;\n }\n return {\n expected_version: detail.expected_version,\n current_version: detail.current_version,\n contested_fields: detail.contested_fields ?? {},\n };\n}\n\n/**\n * HONEST-REFUSALS 1 — a member of an ARCHIVED organization is refused with the store's own sentence\n * (\"This organization is archived, …\") and DETAIL `organization_archived:<organization id>`. The sentence\n * and the restore hint ride `message` and `hint` verbatim like every refusal; this reads the organization out\n * so a screen can offer \"Restore\" (the owner's `iam.organization_restore` door) instead of a dead end.\n * Null for every other refusal, including the non-member's \"You are not a member of that organization\".\n */\nexport function archivedOrganizationId(error: RecordsError): string | null {\n if (error.code !== \"door\" || typeof error.detail !== \"string\") return null;\n const m = /^organization_archived:([0-9a-f-]{36})$/i.exec(error.detail.trim());\n return m ? m[1]! : null;\n}\n","// @ai-matrx/records/search — search across every table a person can see (moved from the website's\n// `features/unified-data/storeRecordCandidates.ts`, 2026-10-08; the body is the same, the client is\n// the host's data source instead of the website's).\n//\n// The store's own search door, `custom.records_search`, answers across EVERY organization the person\n// belongs to — the active organization is never passed (access-ladder: it is not a list filter) —\n// and names each record by its table's title field. Narrowing to tables or organizations is the\n// caller's visible choice (`tableIds`, `organizationIds`).\n//\n// The door costs ~200–450 ms, so a single typed character is not sent: a picker already waits for a\n// pause, and this answers a one-character search with nothing rather than a slow broad read.\n\nimport { asRecordsDataSource } from \"../core/supabase\";\nimport { mapPgError } from \"../core/pgError\";\nimport type { Uuid } from \"../record\";\nimport type { PgError, RecordsResult } from \"../results\";\n\nexport const STORE_RECORD_SEARCH_MIN_CHARS = 2;\n\n/** One record the search door found. */\nexport interface RecordSearchHit {\n recordId: Uuid;\n tableId: Uuid;\n tableName: string;\n /** The record's title-field value; null when the record has none yet. */\n name: string | null;\n organizationId: Uuid;\n updatedAt: string;\n}\n\nexport interface RecordSearchRequest {\n search?: string;\n limit?: number;\n offset?: number;\n /** Only these tables (a visible filter the person chose). */\n tableIds?: readonly Uuid[];\n /** Only these organizations (a visible filter the person chose; never the active one by default). */\n organizationIds?: readonly Uuid[];\n}\n\ninterface SearchRow {\n record_id: Uuid;\n table_id: Uuid;\n table_name: string;\n name: string | null;\n organization_id: Uuid;\n updated_at: string;\n}\n\n/** Records across every table the person can see whose name matches `search`. */\nexport async function searchRecords(dataSource: unknown, request: RecordSearchRequest = {}): Promise<RecordsResult<RecordSearchHit[]>> {\n const search = request.search?.trim() ?? \"\";\n if (search.length > 0 && search.length < STORE_RECORD_SEARCH_MIN_CHARS) return { ok: true, data: [] };\n const args: Record<string, unknown> = { p_search: search, p_limit: request.limit ?? 25, p_offset: request.offset ?? 0 };\n if (request.tableIds && request.tableIds.length > 0) args[\"p_table_ids\"] = [...request.tableIds];\n if (request.organizationIds && request.organizationIds.length > 0) args[\"p_organization_ids\"] = [...request.organizationIds];\n try {\n const answer = await asRecordsDataSource(dataSource).rpc(\"records_search\", args, { schema: \"custom\" });\n if (answer.error) return { ok: false, error: mapPgError(answer.error as PgError, \"custom.records_search\") };\n const rows = (answer.data ?? []) as SearchRow[];\n return {\n ok: true,\n data: rows.map((row) => ({\n recordId: row.record_id,\n tableId: row.table_id,\n tableName: row.table_name,\n name: row.name,\n organizationId: row.organization_id,\n updatedAt: row.updated_at,\n })),\n };\n } catch (thrown) {\n return { ok: false, error: mapPgError({ code: \"\", message: thrown instanceof Error ? thrown.message : String(thrown) } as PgError, \"custom.records_search\") };\n }\n}\n\n/**\n * Candidates for the `record` entity token in a record picker (\"Link a record…\"). Two tables often\n * hold a record of the same name (\"UnitedHealthcare\" in two choice lists), so each candidate says\n * which table it is in; the same words label the link.\n */\nexport async function listStoreRecordCandidates(\n dataSource: unknown,\n args: { search?: string; limit?: number },\n): Promise<{ ok: true; data: { id: string; title: string }[] } | { ok: false; error: string }> {\n const found = await searchRecords(dataSource, { ...(args.search !== undefined ? { search: args.search } : {}), limit: args.limit ?? 25 });\n if (!found.ok) {\n console.error(\"[listStoreRecordCandidates] failed\", found.error);\n return { ok: false, error: found.error.message || \"Could not search records\" };\n }\n return { ok: true, data: found.data.map((hit) => ({ id: hit.recordId, title: hit.name ? `${hit.name} · ${hit.tableName}` : hit.tableName })) };\n}\n"],"mappings":"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","names":[]}
|