@ai-matrx/records 0.99.30 → 0.99.32
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 +20 -1
- package/dist/{client-Dthx26hr.d.ts → client-CrwedBYU.d.ts} +8 -8
- package/dist/{client-B7KEs9hi.d.cts → client-D1EwyWfh.d.cts} +8 -8
- package/dist/core/index.cjs +64 -0
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +203 -35
- package/dist/core/index.d.ts +203 -35
- package/dist/core/index.js +64 -0
- package/dist/core/index.js.map +1 -1
- package/dist/data/index.d.cts +11 -11
- package/dist/data/index.d.ts +11 -11
- package/dist/{declareTable-enQs2N0E.d.cts → declareTable-BIIt0Wqt.d.cts} +3 -3
- package/dist/{declareTable-CvBu5dTJ.d.ts → declareTable-CC5rTTIA.d.ts} +3 -3
- package/dist/{doors-KbjyhBW-.d.cts → doors-D1yAs0a0.d.cts} +1 -1
- package/dist/{doors-C2-sFvAk.d.ts → doors-D2z3kH2i.d.ts} +1 -1
- package/dist/entity/index.d.cts +7 -7
- package/dist/entity/index.d.ts +7 -7
- package/dist/{field-ppX29ddi.d.cts → field-B8loYt-A.d.cts} +1 -1
- package/dist/{field-BHlhq24W.d.ts → field-DaE90BZ7.d.ts} +1 -1
- package/dist/forms/index.d.cts +3 -3
- package/dist/forms/index.d.ts +3 -3
- package/dist/index.d.cts +13 -13
- package/dist/index.d.ts +13 -13
- package/dist/memory/index.d.cts +7 -7
- package/dist/memory/index.d.ts +7 -7
- package/dist/{objectOrganization-DtR3lWG2.d.ts → objectOrganization-D1ox3gUx.d.ts} +1 -1
- package/dist/{objectOrganization-Cu73SBxH.d.cts → objectOrganization-DazBoDAq.d.cts} +1 -1
- package/dist/{port-Bk7TG0aE.d.ts → port-D6wepPvr.d.ts} +3 -3
- package/dist/{port-rqQEGhew.d.cts → port-O-UdH1HS.d.cts} +3 -3
- package/dist/{portal-DmxuUr2f.d.ts → portal-CAssJHRZ.d.ts} +1 -1
- package/dist/{portal-ffH13fsE.d.cts → portal-L_mN8l9P.d.cts} +1 -1
- package/dist/{ports-BCNNghmf.d.ts → ports-CmmvR8OI.d.ts} +2 -2
- package/dist/{ports-iATV-A2v.d.cts → ports-alv3bgKY.d.cts} +2 -2
- package/dist/questions/index.d.cts +9 -9
- package/dist/questions/index.d.ts +9 -9
- package/dist/realtime/index.d.cts +3 -3
- package/dist/realtime/index.d.ts +3 -3
- package/dist/{record-C8q21jjB.d.cts → record-CTgSgWe3.d.cts} +1 -1
- package/dist/{record-C8q21jjB.d.ts → record-CTgSgWe3.d.ts} +1 -1
- package/dist/{relation-Bwp8iuei.d.cts → relation-BjjjXyqn.d.cts} +2 -2
- package/dist/{relation-Bsjwkn6N.d.ts → relation-T4biacnz.d.ts} +2 -2
- package/dist/results/index.cjs +245 -0
- package/dist/results/index.cjs.map +1 -0
- package/dist/results/index.d.cts +24 -0
- package/dist/results/index.d.ts +24 -0
- package/dist/results/index.js +222 -0
- package/dist/results/index.js.map +1 -0
- package/dist/{rule-BQwUtKk5.d.cts → rule-49jO7lN-.d.cts} +1 -1
- package/dist/{rule-cGqclk_0.d.ts → rule-DzNj0QvN.d.ts} +1 -1
- package/dist/scopes/index.d.cts +3 -3
- package/dist/scopes/index.d.ts +3 -3
- package/dist/search/index.d.cts +1 -1
- package/dist/search/index.d.ts +1 -1
- package/dist/setup/index.d.cts +12 -12
- package/dist/setup/index.d.ts +12 -12
- package/dist/{subscription-eNzL9scc.d.ts → subscription-Bp1RSb6p.d.ts} +2 -2
- package/dist/{subscription-Ba8RKtPA.d.cts → subscription-CuaGi3lC.d.cts} +2 -2
- package/dist/templates/index.d.cts +10 -10
- package/dist/templates/index.d.ts +10 -10
- package/dist/typed-table/index.d.cts +10 -10
- package/dist/typed-table/index.d.ts +10 -10
- package/dist/{types-C4XCuv8O.d.cts → types-B54BeQzf.d.cts} +2 -2
- package/dist/{types-BlzdL4Vd.d.cts → types-BWfL38XJ.d.cts} +2 -2
- package/dist/{types-BBR2NGqj.d.ts → types-BZcYXFK3.d.ts} +2 -2
- package/dist/{types-EKwXJfxY.d.cts → types-Bztv0-pH.d.cts} +2 -2
- package/dist/{types-CmkHpvll.d.ts → types-CjGuR5ks.d.ts} +2 -2
- package/dist/{types-CrkzINrb.d.ts → types-bN7dG2ji.d.ts} +2 -2
- package/dist/use-cases/index.d.cts +5 -5
- package/dist/use-cases/index.d.ts +5 -5
- package/dist/{validate-BKeBAVSi.d.cts → validate-8VBa2xIU.d.cts} +1 -1
- package/dist/{validate-BB6DWgCP.d.ts → validate-xBnply7J.d.ts} +1 -1
- package/dist/views/index.d.cts +9 -9
- package/dist/views/index.d.ts +9 -9
- package/package.json +14 -4
|
@@ -6708,4 +6708,4 @@ interface RecordRead {
|
|
|
6708
6708
|
version?: number | null;
|
|
6709
6709
|
}
|
|
6710
6710
|
|
|
6711
|
-
export { type
|
|
6711
|
+
export { type MergeFieldSource as $, type Actor as A, type EntityToken as B, type ComputeOn as C, type DeclarableFieldKind as D, ENTITY_TOKENS as E, type FieldSource as F, FIELD_SENSITIVITIES as G, type HiddenFieldNotice as H, FIELD_SOURCES as I, FORMULA_NODE_RESULTS as J, FRESHNESS as K, type ForbiddenEnvelopeWord as L, type Freshness as M, KERNEL_TABLES as N, type OnDelete as O, type PgError as P, type KernelTableName as Q, type RecordsResult as R, type StorageMode as S, type TableType as T, type Uuid as U, type KeysetRow as V, MERGE_FIELD_MODIFIERS as W, MERGE_FIELD_SEMANTIC_TYPES as X, MERGE_FIELD_SOURCES as Y, type MergeFieldModifier as Z, type MergeFieldSemanticType as _, type RecordsError as a, ON_DELETE as a0, OVERRIDE_POLICIES as a1, type OverridePolicy as a2, PARITY_FIELD_TYPES as a3, PER_VALUE_ACCESS_WORDS as a4, type PerValueAccessWord as a5, type ProvenancePointer as a6, RELATION_BINDINGS as a7, RELATION_CARDINALITIES as a8, RELATION_FLAVORS as a9, type ValueAlternateKey as aA, type ValueEnvelope as aB, type ValueEnvelopeKey as aC, type ValueSource as aD, type WriteConflict as aE, err as aF, isLockedStub as aG, isRecordsErr as aH, ok as aI, splitLockedRows as aJ, unwrapRecords as aK, RETIRED_ACTOR_WORDS as aa, RULE_NODE_KINDS as ab, RULE_USES as ac, type RecordChange as ad, type RecordChangeResult as ae, type RecordGraphWritten as af, type RecordKeysetPage as ag, type RecordPage as ah, type RecordRead as ai, type RecordRevision as aj, type RetiredActorWord as ak, STORAGE_MODES as al, STORE_DOORS as am, STORE_KNOBS as an, STORE_REFUSAL_CODES as ao, type StaleWriteDetail as ap, type StoreDoorName as aq, type StoreRefusalCode as ar, type StoredRecord as as, TABLE_DISPLAYS as at, TABLE_ORIGINS as au, TABLE_TYPES as av, type TableOrigin as aw, VALUE_ALTERNATE_KEYS as ax, VALUE_ENVELOPE_KEYS as ay, type ValueAlternate as az, type TableDisplay as b, type FieldSensitivity as c, type ContextPolicy as d, type RelationFlavor as e, type RelationCardinality as f, type RelationBinding as g, type Timestamp as h, type RuleNodeKind as i, type RuleUse as j, type RecordPageSort as k, type ReadRow as l, type RecordsErrorCode as m, type RecordDocument as n, type FieldBehavior as o, type ParityFieldType as p, type PredictedRefusal as q, type ReadValue as r, ABSENCE_REASONS as s, ACTOR_VOCABULARY as t, type AbsenceReason as u, COMPUTE_ON as v, CONTEXT_POLICIES as w, DECLARABLE_FIELD_KINDS as x, DELIVERIES as y, type Delivery as z };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { U as Uuid, e as RelationFlavor, O as OnDelete, g as RelationBinding, f as RelationCardinality, h as Timestamp, R as RecordsResult } from './record-
|
|
2
|
-
import { d as RecordsDataSource } from './ports-
|
|
1
|
+
import { U as Uuid, e as RelationFlavor, O as OnDelete, g as RelationBinding, f as RelationCardinality, h as Timestamp, R as RecordsResult } from './record-CTgSgWe3.cjs';
|
|
2
|
+
import { d as RecordsDataSource } from './ports-alv3bgKY.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* REL-6. Whether Visibility flows along this relation and the MAXIMUM access
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { U as Uuid, e as RelationFlavor, O as OnDelete, g as RelationBinding, f as RelationCardinality, h as Timestamp, R as RecordsResult } from './record-
|
|
2
|
-
import { d as RecordsDataSource } from './ports-
|
|
1
|
+
import { U as Uuid, e as RelationFlavor, O as OnDelete, g as RelationBinding, f as RelationCardinality, h as Timestamp, R as RecordsResult } from './record-CTgSgWe3.js';
|
|
2
|
+
import { d as RecordsDataSource } from './ports-CmmvR8OI.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* REL-6. Whether Visibility flows along this relation and the MAXIMUM access
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/results-light.ts
|
|
21
|
+
var results_light_exports = {};
|
|
22
|
+
__export(results_light_exports, {
|
|
23
|
+
MAPPED_SQLSTATES: () => MAPPED_SQLSTATES,
|
|
24
|
+
archivedOrganizationId: () => archivedOrganizationId,
|
|
25
|
+
err: () => err,
|
|
26
|
+
isRecordsErr: () => isRecordsErr,
|
|
27
|
+
mapPgError: () => mapPgError,
|
|
28
|
+
mapThrownError: () => mapThrownError,
|
|
29
|
+
ok: () => ok,
|
|
30
|
+
staleWriteDetail: () => staleWriteDetail,
|
|
31
|
+
unwrapRecords: () => unwrapRecords
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(results_light_exports);
|
|
34
|
+
|
|
35
|
+
// src/results.ts
|
|
36
|
+
function isRecordsErr(result) {
|
|
37
|
+
return result.ok === false;
|
|
38
|
+
}
|
|
39
|
+
function unwrapRecords(result) {
|
|
40
|
+
if (result.ok) return result.data;
|
|
41
|
+
throw new Error(result.error.message);
|
|
42
|
+
}
|
|
43
|
+
var ok = (data) => ({ ok: true, data });
|
|
44
|
+
var err = (error) => ({ ok: false, error });
|
|
45
|
+
|
|
46
|
+
// src/core/pgError.ts
|
|
47
|
+
var BY_SQLSTATE = {
|
|
48
|
+
PT409: "stale_write",
|
|
49
|
+
"42501": "door",
|
|
50
|
+
"23514": "refused_by_rule",
|
|
51
|
+
"22004": "invalid_argument",
|
|
52
|
+
"22023": "invalid_argument",
|
|
53
|
+
// MX005 — a value the store cannot take as asked: since 2026-10-06 (AP-3 U3) a word that names more than one
|
|
54
|
+
// choice or linked record raises it (it used to borrow PT409 and read as somebody else's write winning).
|
|
55
|
+
MX005: "invalid_argument",
|
|
56
|
+
// MXD01 — the held-change door tried the proposed values before filing an
|
|
57
|
+
// approval request and the store refused them. Nothing is waiting for a
|
|
58
|
+
// person to decide; correct the value before asking again, which is the same
|
|
59
|
+
// caller-side condition as the other invalid-argument refusals.
|
|
60
|
+
MXD01: "invalid_argument",
|
|
61
|
+
// 22P02 — a value does not fit the type the store holds for it. The class is
|
|
62
|
+
// real and was hit live: an organization whose copy of a package table grew
|
|
63
|
+
// `status` as a uuid-valued Field was sent the text "open", and the store
|
|
64
|
+
// answered `invalid input syntax for type uuid: "open"`. It is the CALL that
|
|
65
|
+
// is wrong for the shape the store holds, which is what `invalid_argument`
|
|
66
|
+
// already means — the store's own sentence names the value and the type.
|
|
67
|
+
"22P02": "invalid_argument",
|
|
68
|
+
// 42703 — a column that is not there. The store raises it from
|
|
69
|
+
// `custom.entity_table`, which is asked for a column by NAME, so the class is
|
|
70
|
+
// exactly "the call named something the shape does not have": the same thing
|
|
71
|
+
// `invalid_argument` already means, and the store's own sentence names the
|
|
72
|
+
// column. Added 2026-09-20 (lane FORMS) because the package's live-door suite
|
|
73
|
+
// caught it raised by a door this package did not know about — which is the
|
|
74
|
+
// suite working, and is why the map is a census rather than a guess.
|
|
75
|
+
"42703": "invalid_argument",
|
|
76
|
+
// 22007 — a date or a time the store could not read as one. It is raised by
|
|
77
|
+
// `custom.dashboard_window_sql`, which is handed a window a caller wrote
|
|
78
|
+
// ("last 30 days", a literal date), so the class is again "the call named
|
|
79
|
+
// something the shape does not accept" and the store's own sentence names the
|
|
80
|
+
// text it could not read. Added 2026-09-20 (lane SCREEN-BREAK) after the
|
|
81
|
+
// live-door census caught it — the same way 42703 arrived, which is the
|
|
82
|
+
// census working rather than a guess.
|
|
83
|
+
"22007": "invalid_argument",
|
|
84
|
+
// 22003 — a number the store could not hold at the size it was handed. It is
|
|
85
|
+
// raised by `custom.context_resolve`, which is given a window or a depth a
|
|
86
|
+
// caller wrote, so the class is the same one 22P02, 42703 and 22007 already
|
|
87
|
+
// are: the CALL named a value the shape does not accept, and the store's own
|
|
88
|
+
// sentence names the number and the range. Added 2026-09-20 (lane GRID-TWO)
|
|
89
|
+
// when the live-door census caught the release gate red on it — which is the
|
|
90
|
+
// census working, and the fourth time it has been the thing that found a new
|
|
91
|
+
// refusal class rather than a person guessing one.
|
|
92
|
+
"22003": "invalid_argument",
|
|
93
|
+
// 42883 — `custom._template_call` (the template family, 2026-10-03) was handed a step that
|
|
94
|
+
// names a door the store does not have, or an argument that door does not take. The TEMPLATE
|
|
95
|
+
// named something the shape does not have — the same class 42703 is — and the store's own
|
|
96
|
+
// sentence names the door or the argument. Caught by the live-door census on records 0.68.1's
|
|
97
|
+
// tag, the eighth time the census found a class before a person did. (A bare 42883 on a door
|
|
98
|
+
// this package itself asks for is still `door_absent`, mapped before this funnel in
|
|
99
|
+
// `owedDoor`.)
|
|
100
|
+
"42883": "invalid_argument",
|
|
101
|
+
"02000": "not_found",
|
|
102
|
+
// P0002 — `custom.inbox_snooze` / `custom.inbox_clear` (lane S5-PRIME-2, 2026-09-24): "There is
|
|
103
|
+
// nothing in your inbox with that id". An invented id, another person's item and another
|
|
104
|
+
// organization's all answer it alike, so it reads exactly as 02000 does: not found.
|
|
105
|
+
"P0002": "not_found",
|
|
106
|
+
"23503": "missing_reference",
|
|
107
|
+
"23505": "already_exists",
|
|
108
|
+
"0A000": "not_supported",
|
|
109
|
+
"53400": "store_limit",
|
|
110
|
+
"22012": "store_limit",
|
|
111
|
+
// 54001 — `custom.record_delete` stops a cascade that nests past sixty-four
|
|
112
|
+
// levels of containment, because that is a loop somebody built rather than a
|
|
113
|
+
// hierarchy, and saying so beats recursing until the server runs out of
|
|
114
|
+
// stack. It is a LIMIT of the store, and the store's own sentence names what
|
|
115
|
+
// to do about it, so it reads as one.
|
|
116
|
+
"54001": "store_limit",
|
|
117
|
+
// 54000 — the grid primitives' organization ceilings (GRID-PRIMITIVES, 2026-09-23):
|
|
118
|
+
// `custom.action_run` on a selection past its knob, `custom.table_decorate` past the
|
|
119
|
+
// rule count, `custom.table_from_example` past `custom/example_rows_max`,
|
|
120
|
+
// `custom.table_webhook_declare` past `custom/table_webhooks_max`, and
|
|
121
|
+
// `custom.hub_changed_by`. Each names its knob in the hint and writes nothing, so it
|
|
122
|
+
// reads exactly like 54001: a limit of the store, in the store's own sentence.
|
|
123
|
+
"54000": "store_limit",
|
|
124
|
+
// VIS: `custom.has_visibility_at` refuses to answer from a snapshot older
|
|
125
|
+
// than a write this reader has already seen, rather than returning something
|
|
126
|
+
// they just lost access to. It is retryable on a fresher connection, which is
|
|
127
|
+
// a different instruction from every other refusal here.
|
|
128
|
+
// 55000 — `custom.table_move` (SC-1', 2026-09-24) refuses a move the table's present state
|
|
129
|
+
// does not allow: a destination that cannot take it, a table something else holds, contents
|
|
130
|
+
// that point at themselves in a circle. The store's own sentence names the reason and nothing
|
|
131
|
+
// moves, so it reads as a refusal on the merits. Caught by the live-door census on records
|
|
132
|
+
// 0.58.3's tag, the seventh time the census found a class before a person did.
|
|
133
|
+
"55000": "refused_by_rule",
|
|
134
|
+
// 42P17 — a worked-out column that would read itself round a circle (STORE-TAILS-3,
|
|
135
|
+
// 2026-09-25): `custom._field_reads_what_it_reads` refuses the declaration or edit that would
|
|
136
|
+
// close the circle, naming every column in it, and `custom.far_value` refuses a circle stored
|
|
137
|
+
// before that rule when a lookup or rollup is worked out. Refused on its merits, in the store's
|
|
138
|
+
// own sentence, nothing written — so it reads as 55000 does.
|
|
139
|
+
"42P17": "refused_by_rule",
|
|
140
|
+
// P0001 — `custom.context_scope_write` (2026-10-03) refuses a scope whose parent breaks the
|
|
141
|
+
// parent rule in the old trigger's own class and words (manager ruling H6). Refused on its
|
|
142
|
+
// merits, nothing written. Caught by the live-door census on records 0.65.0's tag.
|
|
143
|
+
P0001: "refused_by_rule",
|
|
144
|
+
"40001": "stale_read",
|
|
145
|
+
// 57014 — the store cancelled the statement at its own timeout. Like
|
|
146
|
+
// `stale_read` and unlike every other refusal here, the call was never
|
|
147
|
+
// refused on its merits: the same call on a smaller page, or once the
|
|
148
|
+
// organization's kernel is not being rewritten, can succeed. It gets its own
|
|
149
|
+
// code so a screen can offer "try again" honestly instead of showing a
|
|
150
|
+
// failure sentence the caller cannot act on.
|
|
151
|
+
"57014": "timed_out",
|
|
152
|
+
// PostgREST's own two: the store is not being SERVED, which is a different
|
|
153
|
+
// thing from the store refusing. `custom` absent from `pgrst.db_schemas`, or
|
|
154
|
+
// the grants not copied, land here.
|
|
155
|
+
PGRST202: "store_not_served",
|
|
156
|
+
PGRST205: "store_not_served",
|
|
157
|
+
PGRST301: "door",
|
|
158
|
+
// PT428 — NOT A FAILURE, and the release gate's live census is what found it
|
|
159
|
+
// missing: the store raises it and this package answered `internal`, which is
|
|
160
|
+
// the one classification that tells a screen nothing. A stage gate whose
|
|
161
|
+
// `on_fail` is `require_approval` files the request and leaves the record
|
|
162
|
+
// where it was; the transaction is rolled back to the pipeline's own block, so
|
|
163
|
+
// "nothing was written" is a fact rather than a promise. Landed by lane
|
|
164
|
+
// STAGE-RULES; mapped here by STAGE-RULES-2 the day after, when the census
|
|
165
|
+
// caught it — the sixth time that census has been the thing that found a
|
|
166
|
+
// refusal class rather than a person guessing one.
|
|
167
|
+
PT428: "needs_approval"
|
|
168
|
+
};
|
|
169
|
+
var MAPPED_SQLSTATES = Object.keys(BY_SQLSTATE);
|
|
170
|
+
function parseDetail(details) {
|
|
171
|
+
if (!details) return void 0;
|
|
172
|
+
const trimmed = details.trim();
|
|
173
|
+
if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return details;
|
|
174
|
+
try {
|
|
175
|
+
return JSON.parse(trimmed);
|
|
176
|
+
} catch {
|
|
177
|
+
return details;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function isNotASqlstate(code) {
|
|
181
|
+
if (!code) return true;
|
|
182
|
+
return /^[0-9]{3}$/.test(code);
|
|
183
|
+
}
|
|
184
|
+
function mapPgError(error, where) {
|
|
185
|
+
const raw = error.code ?? void 0;
|
|
186
|
+
const sqlstate = raw && raw !== "" ? raw : void 0;
|
|
187
|
+
const mapped = {
|
|
188
|
+
code: "internal",
|
|
189
|
+
message: error.message,
|
|
190
|
+
...error.hint ? { hint: error.hint } : {},
|
|
191
|
+
...sqlstate ? { sqlstate } : {}
|
|
192
|
+
};
|
|
193
|
+
if (isNotASqlstate(sqlstate)) {
|
|
194
|
+
mapped.code = "unreachable";
|
|
195
|
+
} else {
|
|
196
|
+
mapped.code = BY_SQLSTATE[sqlstate] ?? "internal";
|
|
197
|
+
}
|
|
198
|
+
const detail = parseDetail(error.details);
|
|
199
|
+
if (detail !== void 0) mapped.detail = detail;
|
|
200
|
+
if (mapped.code === "internal") {
|
|
201
|
+
mapped.unmapped = true;
|
|
202
|
+
mapped.diagnostic = `@ai-matrx/records did not recognise SQLSTATE ${sqlstate ?? "(none)"} from ${where}; the store's own message is the thing to act on.`;
|
|
203
|
+
} else if (mapped.code === "unreachable") {
|
|
204
|
+
mapped.unmapped = true;
|
|
205
|
+
mapped.diagnostic = `@ai-matrx/records never reached the store from ${where}: ${raw ? `the transport answered ${raw}` : "no response"} \u2014 ${error.message}`;
|
|
206
|
+
mapped.message = "We could not reach your data.";
|
|
207
|
+
delete mapped.hint;
|
|
208
|
+
}
|
|
209
|
+
return mapped;
|
|
210
|
+
}
|
|
211
|
+
function mapThrownError(thrown, where) {
|
|
212
|
+
const o = thrown && typeof thrown === "object" ? thrown : {};
|
|
213
|
+
const message = typeof o.message === "string" && o.message ? o.message : thrown == null ? "Unknown error" : String(thrown);
|
|
214
|
+
const code = typeof o.code === "string" ? o.code : null;
|
|
215
|
+
if (code !== null || thrown instanceof TypeError && /fetch|network/i.test(message)) {
|
|
216
|
+
return mapPgError(
|
|
217
|
+
{ code, message, details: typeof o.details === "string" ? o.details : null, hint: typeof o.hint === "string" ? o.hint : null },
|
|
218
|
+
where
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
code: "internal",
|
|
223
|
+
message,
|
|
224
|
+
unmapped: true,
|
|
225
|
+
diagnostic: `@ai-matrx/records: ${where} threw outside the store.`
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function staleWriteDetail(error) {
|
|
229
|
+
if (error.code !== "stale_write") return null;
|
|
230
|
+
const detail = error.detail;
|
|
231
|
+
if (!detail || typeof detail.expected_version !== "number" || typeof detail.current_version !== "number") {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
expected_version: detail.expected_version,
|
|
236
|
+
current_version: detail.current_version,
|
|
237
|
+
contested_fields: detail.contested_fields ?? {}
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
function archivedOrganizationId(error) {
|
|
241
|
+
if (error.code !== "door" || typeof error.detail !== "string") return null;
|
|
242
|
+
const m = /^organization_archived:([0-9a-f-]{36})$/i.exec(error.detail.trim());
|
|
243
|
+
return m ? m[1] : null;
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/results-light.ts","../../src/results.ts","../../src/core/pgError.ts"],"sourcesContent":["// THE RESULT ENVELOPE ALONE (`@ai-matrx/records/results`) — the never-throw envelope and the refusal\n// mappers, with nothing behind them. A host service that only narrows a `RecordsResult`\n// (`isRecordsErr`) or maps a thrown supabase error (`mapThrownError`) imports this, never the root or\n// `/core`, so a module the shell reaches does not carry the whole store client into every first load.\nexport * from \"./results\";\nexport { MAPPED_SQLSTATES, mapPgError, mapThrownError, staleWriteDetail, archivedOrganizationId } from \"./core/pgError\";\n","// src/results.ts — @ai-matrx/records\n//\n// THE NEVER-THROW RESULT ENVELOPE, and the refusal vocabulary behind it.\n//\n// This package's whole posture toward the store is in one sentence: THE CLIENT\n// MIRRORS THE STORE'S CONTRACT AND NEVER RE-IMPLEMENTS A RULE THE STORE\n// ENFORCES. When the store refuses, the client hands back the store's OWN\n// message, the store's OWN hint and the store's OWN SQLSTATE, under a code a\n// screen can branch on. It never rewrites the sentence, never swallows it, and\n// never invents a friendlier one — the store's refusals were written to be read\n// by a person, and a client that paraphrases them is lying about what happened.\n\nimport type { PerValueAccessWord } from \"./vocabulary\";\nimport type { Uuid } from \"./record\";\n\n/**\n * What KIND of refusal it was. The mapping from SQLSTATE to code lives in\n * `/core`, and it is checked against `STORE_REFUSAL_CODES` — the list of every\n * SQLSTATE the store's own bodies raise, generated from the live catalogue. A\n * code the store can raise and this union cannot name is a hole, and the\n * real-door suite fails on it.\n */\nexport type RecordsErrorCode =\n /** `PT409` — somebody else's write won. The record clock moved under you. */\n | \"stale_write\"\n /**\n * The call needs an organization and none was carried (the platform's `organization_required`; the entity\n * doors' MX002). Never resolved by guessing one: the person is shown their memberships and picks.\n */\n | \"organization_required\"\n /** `42501` — a door. Either the schema is revoked, or the store is switched off, or this principal may not pass. */\n | \"door\"\n /** `23514` — a Rule, a shape guard, or a validation the store enforces refused it. */\n | \"refused_by_rule\"\n /**\n * `22004` / `22023` / `22P02` — the call itself was malformed: a missing id, a\n * patch that is not an object, or a value that does not fit the type the\n * store holds for that Field. The store's own message names the value and the\n * type it could not be read as.\n */\n | \"invalid_argument\"\n /** `02000` — the record is not here (deleted, never existed, or another organization's). */\n | \"not_found\"\n /** `23503` — something it points at is not there. */\n | \"missing_reference\"\n /** `23505` — that thing is already here. */\n | \"already_exists\"\n /** `0A000` — the store does not do this yet, and says which part. */\n | \"not_supported\"\n /** `53400` / `22012` — the store ran out of something, or the arithmetic could not be done. */\n | \"store_limit\"\n /**\n * `40001` — the read-access snapshot this connection carries is older than a\n * write the reader has already observed, so the store refused to answer at\n * all rather than hand back something they just lost. Retry on a fresh\n * connection; it is the one refusal in this list that is worth repeating.\n */\n | \"stale_read\"\n /**\n * `57014` — the store cancelled the statement at its own timeout. Nothing was\n * refused on its merits and nothing was written; the same call can succeed on\n * a smaller page or a quieter moment. With `stale_read`, one of the only two\n * refusals in this list worth repeating.\n */\n | \"timed_out\"\n /**\n * THE DOOR THAT DOES NOT EXIST YET. Not an error condition in the database —\n * this package asked for a door that is not in the live catalogue, so it\n * refused to guess. `door_absent` always names the door and the lane that\n * owns it; it is never a silent no-op and never an empty list.\n */\n | \"door_absent\"\n /**\n * `PGRST202` / `PGRST205` — PostgREST could not find the function or the\n * schema. The database this client is pointed at is not serving the record\n * store: the schema is not exposed, or the grants are not there.\n */\n | \"store_not_served\"\n /**\n * `PT428` — the move was not refused and it did not happen: a stage gate whose\n * `on_fail` is `require_approval` filed a request with the people who can\n * answer it, and left the record exactly where it was. The store's own\n * sentence is the gate's own sentence, and the DETAIL carries the approval.\n *\n * It is the one code in this list that is not a failure. A screen that drew it\n * as one would tell somebody their work was rejected when it is being\n * considered; a screen that drew it as success would move the card while\n * somebody is still deciding. `custom.pipeline_move` answers an object on this\n * path rather than raising, so a caller only meets PT428 when the move went\n * through the ORDINARY write door — which is most of them.\n */\n | \"needs_approval\"\n /**\n * THE CALL NEVER REACHED THE STORE. Not a refusal — a transport failure: the\n * browser lost the network, the gateway answered with an HTTP status and no\n * body, the request was cancelled. supabase-js hands these back with an EMPTY\n * `code` (a `FetchError`) or with the HTTP status in it (`\"404\"`, `\"502\"`),\n * neither of which is a SQLSTATE, and until 2026-09-22 they all landed in\n * `internal` — which is the one classification that tells a screen nothing,\n * and which made the package print a sentence about ITSELF to the person\n * (lane TAILS-6). Nothing was written, and the same call can simply be made\n * again, which is what separates it from `internal`.\n */\n | \"unreachable\"\n /** Anything the mapper could not place. It still carries the store's own words. */\n | \"internal\";\n\n/** A refusal, in the store's own words. */\nexport interface RecordsError {\n code: RecordsErrorCode;\n /** THE STORE'S message, verbatim. Never paraphrased. */\n message: string;\n /** THE STORE'S hint, verbatim — this is where the remedy is written. */\n hint?: string;\n /** The SQLSTATE, so a caller can be exact when a code is not exact enough. */\n sqlstate?: string;\n /** Whatever the store put in DETAIL, parsed when it was json. */\n detail?: unknown;\n /**\n * TRUE when this package did not recognise the class it was handed, so a\n * caller can say so instead of reading the silence as \"handled\".\n *\n * 🚨 IT IS A FLAG AND A SEPARATE SENTENCE, NEVER AN APPENDIX TO `hint`\n * (lane TAILS-6, 2026-09-22). `mapPgError` used to append \"@ai-matrx/records\n * did not recognise SQLSTATE … from checklistTemplates\" ONTO `hint`, and\n * `hint` is the field every screen treats as THE REMEDY — the sentence a\n * person is told to act on. So a dropped connection on the Checklists tab\n * showed a plumbing company \"Something went wrong at our end\" over a line\n * about a TypeScript package and a SQLSTATE. A note this package writes about\n * ITSELF is for whoever debugs it and belongs nowhere a person reads.\n */\n unmapped?: boolean;\n /**\n * THIS PACKAGE'S OWN NOTE, for an engineer. Never the store's words and never\n * a person's: screens render it out of sight (a `title` attribute, a\n * screen-reader line) or not at all.\n */\n diagnostic?: string;\n}\n\nexport type RecordsResult<T> = { ok: true; data: T } | { ok: false; error: RecordsError };\n\n/** Narrowing helper for hosts compiled without `strictNullChecks`. */\nexport function isRecordsErr<T>(\n result: RecordsResult<T>,\n): result is { ok: false; error: RecordsError } {\n return result.ok === false;\n}\n\n/**\n * A result's data, or THROW its refusal as an `Error` carrying the store's sentence — for the places\n * a throw is the contract (a `createAsyncThunk` body, a loader whose caller catches and shows it).\n */\nexport function unwrapRecords<T>(result: RecordsResult<T>): T {\n if (result.ok) return result.data;\n throw new Error(result.error.message);\n}\n\nexport const ok = <T>(data: T): RecordsResult<T> => ({ ok: true, data });\nexport const err = <T>(error: RecordsError): RecordsResult<T> => ({ ok: false, error });\n\n/**\n * A `stale_write` carries everything the screen needs to show the conflict\n * rather than a toast: which version you wrote against, which one won, and the\n * value of every field you touched as it stands now. The store builds this and\n * this type is its shape — nothing is reconstructed on the client.\n */\nexport interface StaleWriteDetail {\n expected_version: number;\n current_version: number;\n contested_fields: Record<string, unknown>;\n}\n\n/** The parsed form of a `stale_write`, for `useRecordMutation`'s conflict state. */\nexport interface WriteConflict extends StaleWriteDetail {\n record_id: Uuid;\n /** The store's own sentence — what the screen shows. */\n message: string;\n /** The store's own remedy. */\n hint: string;\n}\n\n/**\n * The structural shape of a PostgREST failure as supabase-js resolves it: a\n * PLAIN OBJECT parsed from the response body, NOT an `Error`. Reading\n * `.message` off `instanceof Error` discards the real database message on every\n * genuine failure.\n */\nexport interface PgError {\n code?: string | null;\n message: string;\n details?: string | null;\n hint?: string | null;\n}\n\n/** What the validation mirror answers: the same sentence the trigger would raise. */\nexport interface PredictedRefusal {\n /** The field key the store would name, when it names one. */\n field_key?: string;\n /** The message the store's own body would raise, word for word. */\n message: string;\n hint?: string;\n /** The store's structured detail, when its refusal carries one (e.g. `{ example }`). */\n detail?: Record<string, unknown>;\n sqlstate: string;\n /**\n * Which of the store's bodies would raise it, so a reader can go and check\n * that this mirror still tells the truth.\n */\n predicted_by: string;\n}\n\n/** VAL-5 / VAL-6, named so a caller can say which word was the problem. */\nexport interface ForbiddenEnvelopeWord {\n field_key: string;\n word: PerValueAccessWord;\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/**\n * Anything a host caught (a supabase-js error object, a thrown `Error`, a string) as the package's\n * refusal, through `mapPgError` — so a host service's `catch` speaks the same words as its doors.\n */\nexport function mapThrownError(thrown: unknown, where: string): RecordsError {\n const o = thrown && typeof thrown === \"object\" ? (thrown as { code?: unknown; message?: unknown; details?: unknown; hint?: unknown }) : {};\n const message = typeof o.message === \"string\" && o.message ? o.message : thrown == null ? \"Unknown error\" : String(thrown);\n const code = typeof o.code === \"string\" ? o.code : null;\n // A supabase-js answer (it carries a code) and a transport failure are the store's / the\n // network's; anything else a host threw is its own sentence and is kept as said.\n if (code !== null || (thrown instanceof TypeError && /fetch|network/i.test(message))) {\n return mapPgError(\n { code, message, details: typeof o.details === \"string\" ? o.details : null, hint: typeof o.hint === \"string\" ? o.hint : null },\n where,\n );\n }\n return {\n code: \"internal\",\n message,\n unmapped: true,\n diagnostic: `@ai-matrx/records: ${where} threw outside the store.`,\n };\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"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { a as RecordsError, P as PgError, ap as StaleWriteDetail } from '../record-CTgSgWe3.cjs';
|
|
2
|
+
export { L as ForbiddenEnvelopeWord, q as PredictedRefusal, m as RecordsErrorCode, R as RecordsResult, aE as WriteConflict, aF as err, aH as isRecordsErr, aI as ok, aK as unwrapRecords } from '../record-CTgSgWe3.cjs';
|
|
3
|
+
|
|
4
|
+
/** The SQLSTATEs this package claims to understand. Exported for the guard. */
|
|
5
|
+
declare const MAPPED_SQLSTATES: string[];
|
|
6
|
+
/** Map a PostgREST/supabase-js failure into the package's refusal shape. */
|
|
7
|
+
declare function mapPgError(error: PgError, where: string): RecordsError;
|
|
8
|
+
/**
|
|
9
|
+
* Anything a host caught (a supabase-js error object, a thrown `Error`, a string) as the package's
|
|
10
|
+
* refusal, through `mapPgError` — so a host service's `catch` speaks the same words as its doors.
|
|
11
|
+
*/
|
|
12
|
+
declare function mapThrownError(thrown: unknown, where: string): RecordsError;
|
|
13
|
+
/** Pull the conflict out of a `stale_write`, when the store sent one. */
|
|
14
|
+
declare function staleWriteDetail(error: RecordsError): StaleWriteDetail | null;
|
|
15
|
+
/**
|
|
16
|
+
* HONEST-REFUSALS 1 — a member of an ARCHIVED organization is refused with the store's own sentence
|
|
17
|
+
* ("This organization is archived, …") and DETAIL `organization_archived:<organization id>`. The sentence
|
|
18
|
+
* and the restore hint ride `message` and `hint` verbatim like every refusal; this reads the organization out
|
|
19
|
+
* so a screen can offer "Restore" (the owner's `iam.organization_restore` door) instead of a dead end.
|
|
20
|
+
* Null for every other refusal, including the non-member's "You are not a member of that organization".
|
|
21
|
+
*/
|
|
22
|
+
declare function archivedOrganizationId(error: RecordsError): string | null;
|
|
23
|
+
|
|
24
|
+
export { MAPPED_SQLSTATES, PgError, RecordsError, StaleWriteDetail, archivedOrganizationId, mapPgError, mapThrownError, staleWriteDetail };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { a as RecordsError, P as PgError, ap as StaleWriteDetail } from '../record-CTgSgWe3.js';
|
|
2
|
+
export { L as ForbiddenEnvelopeWord, q as PredictedRefusal, m as RecordsErrorCode, R as RecordsResult, aE as WriteConflict, aF as err, aH as isRecordsErr, aI as ok, aK as unwrapRecords } from '../record-CTgSgWe3.js';
|
|
3
|
+
|
|
4
|
+
/** The SQLSTATEs this package claims to understand. Exported for the guard. */
|
|
5
|
+
declare const MAPPED_SQLSTATES: string[];
|
|
6
|
+
/** Map a PostgREST/supabase-js failure into the package's refusal shape. */
|
|
7
|
+
declare function mapPgError(error: PgError, where: string): RecordsError;
|
|
8
|
+
/**
|
|
9
|
+
* Anything a host caught (a supabase-js error object, a thrown `Error`, a string) as the package's
|
|
10
|
+
* refusal, through `mapPgError` — so a host service's `catch` speaks the same words as its doors.
|
|
11
|
+
*/
|
|
12
|
+
declare function mapThrownError(thrown: unknown, where: string): RecordsError;
|
|
13
|
+
/** Pull the conflict out of a `stale_write`, when the store sent one. */
|
|
14
|
+
declare function staleWriteDetail(error: RecordsError): StaleWriteDetail | null;
|
|
15
|
+
/**
|
|
16
|
+
* HONEST-REFUSALS 1 — a member of an ARCHIVED organization is refused with the store's own sentence
|
|
17
|
+
* ("This organization is archived, …") and DETAIL `organization_archived:<organization id>`. The sentence
|
|
18
|
+
* and the restore hint ride `message` and `hint` verbatim like every refusal; this reads the organization out
|
|
19
|
+
* so a screen can offer "Restore" (the owner's `iam.organization_restore` door) instead of a dead end.
|
|
20
|
+
* Null for every other refusal, including the non-member's "You are not a member of that organization".
|
|
21
|
+
*/
|
|
22
|
+
declare function archivedOrganizationId(error: RecordsError): string | null;
|
|
23
|
+
|
|
24
|
+
export { MAPPED_SQLSTATES, PgError, RecordsError, StaleWriteDetail, archivedOrganizationId, mapPgError, mapThrownError, staleWriteDetail };
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
// src/results.ts
|
|
2
|
+
function isRecordsErr(result) {
|
|
3
|
+
return result.ok === false;
|
|
4
|
+
}
|
|
5
|
+
function unwrapRecords(result) {
|
|
6
|
+
if (result.ok) return result.data;
|
|
7
|
+
throw new Error(result.error.message);
|
|
8
|
+
}
|
|
9
|
+
var ok = (data) => ({ ok: true, data });
|
|
10
|
+
var err = (error) => ({ ok: false, error });
|
|
11
|
+
|
|
12
|
+
// src/core/pgError.ts
|
|
13
|
+
var BY_SQLSTATE = {
|
|
14
|
+
PT409: "stale_write",
|
|
15
|
+
"42501": "door",
|
|
16
|
+
"23514": "refused_by_rule",
|
|
17
|
+
"22004": "invalid_argument",
|
|
18
|
+
"22023": "invalid_argument",
|
|
19
|
+
// MX005 — a value the store cannot take as asked: since 2026-10-06 (AP-3 U3) a word that names more than one
|
|
20
|
+
// choice or linked record raises it (it used to borrow PT409 and read as somebody else's write winning).
|
|
21
|
+
MX005: "invalid_argument",
|
|
22
|
+
// MXD01 — the held-change door tried the proposed values before filing an
|
|
23
|
+
// approval request and the store refused them. Nothing is waiting for a
|
|
24
|
+
// person to decide; correct the value before asking again, which is the same
|
|
25
|
+
// caller-side condition as the other invalid-argument refusals.
|
|
26
|
+
MXD01: "invalid_argument",
|
|
27
|
+
// 22P02 — a value does not fit the type the store holds for it. The class is
|
|
28
|
+
// real and was hit live: an organization whose copy of a package table grew
|
|
29
|
+
// `status` as a uuid-valued Field was sent the text "open", and the store
|
|
30
|
+
// answered `invalid input syntax for type uuid: "open"`. It is the CALL that
|
|
31
|
+
// is wrong for the shape the store holds, which is what `invalid_argument`
|
|
32
|
+
// already means — the store's own sentence names the value and the type.
|
|
33
|
+
"22P02": "invalid_argument",
|
|
34
|
+
// 42703 — a column that is not there. The store raises it from
|
|
35
|
+
// `custom.entity_table`, which is asked for a column by NAME, so the class is
|
|
36
|
+
// exactly "the call named something the shape does not have": the same thing
|
|
37
|
+
// `invalid_argument` already means, and the store's own sentence names the
|
|
38
|
+
// column. Added 2026-09-20 (lane FORMS) because the package's live-door suite
|
|
39
|
+
// caught it raised by a door this package did not know about — which is the
|
|
40
|
+
// suite working, and is why the map is a census rather than a guess.
|
|
41
|
+
"42703": "invalid_argument",
|
|
42
|
+
// 22007 — a date or a time the store could not read as one. It is raised by
|
|
43
|
+
// `custom.dashboard_window_sql`, which is handed a window a caller wrote
|
|
44
|
+
// ("last 30 days", a literal date), so the class is again "the call named
|
|
45
|
+
// something the shape does not accept" and the store's own sentence names the
|
|
46
|
+
// text it could not read. Added 2026-09-20 (lane SCREEN-BREAK) after the
|
|
47
|
+
// live-door census caught it — the same way 42703 arrived, which is the
|
|
48
|
+
// census working rather than a guess.
|
|
49
|
+
"22007": "invalid_argument",
|
|
50
|
+
// 22003 — a number the store could not hold at the size it was handed. It is
|
|
51
|
+
// raised by `custom.context_resolve`, which is given a window or a depth a
|
|
52
|
+
// caller wrote, so the class is the same one 22P02, 42703 and 22007 already
|
|
53
|
+
// are: the CALL named a value the shape does not accept, and the store's own
|
|
54
|
+
// sentence names the number and the range. Added 2026-09-20 (lane GRID-TWO)
|
|
55
|
+
// when the live-door census caught the release gate red on it — which is the
|
|
56
|
+
// census working, and the fourth time it has been the thing that found a new
|
|
57
|
+
// refusal class rather than a person guessing one.
|
|
58
|
+
"22003": "invalid_argument",
|
|
59
|
+
// 42883 — `custom._template_call` (the template family, 2026-10-03) was handed a step that
|
|
60
|
+
// names a door the store does not have, or an argument that door does not take. The TEMPLATE
|
|
61
|
+
// named something the shape does not have — the same class 42703 is — and the store's own
|
|
62
|
+
// sentence names the door or the argument. Caught by the live-door census on records 0.68.1's
|
|
63
|
+
// tag, the eighth time the census found a class before a person did. (A bare 42883 on a door
|
|
64
|
+
// this package itself asks for is still `door_absent`, mapped before this funnel in
|
|
65
|
+
// `owedDoor`.)
|
|
66
|
+
"42883": "invalid_argument",
|
|
67
|
+
"02000": "not_found",
|
|
68
|
+
// P0002 — `custom.inbox_snooze` / `custom.inbox_clear` (lane S5-PRIME-2, 2026-09-24): "There is
|
|
69
|
+
// nothing in your inbox with that id". An invented id, another person's item and another
|
|
70
|
+
// organization's all answer it alike, so it reads exactly as 02000 does: not found.
|
|
71
|
+
"P0002": "not_found",
|
|
72
|
+
"23503": "missing_reference",
|
|
73
|
+
"23505": "already_exists",
|
|
74
|
+
"0A000": "not_supported",
|
|
75
|
+
"53400": "store_limit",
|
|
76
|
+
"22012": "store_limit",
|
|
77
|
+
// 54001 — `custom.record_delete` stops a cascade that nests past sixty-four
|
|
78
|
+
// levels of containment, because that is a loop somebody built rather than a
|
|
79
|
+
// hierarchy, and saying so beats recursing until the server runs out of
|
|
80
|
+
// stack. It is a LIMIT of the store, and the store's own sentence names what
|
|
81
|
+
// to do about it, so it reads as one.
|
|
82
|
+
"54001": "store_limit",
|
|
83
|
+
// 54000 — the grid primitives' organization ceilings (GRID-PRIMITIVES, 2026-09-23):
|
|
84
|
+
// `custom.action_run` on a selection past its knob, `custom.table_decorate` past the
|
|
85
|
+
// rule count, `custom.table_from_example` past `custom/example_rows_max`,
|
|
86
|
+
// `custom.table_webhook_declare` past `custom/table_webhooks_max`, and
|
|
87
|
+
// `custom.hub_changed_by`. Each names its knob in the hint and writes nothing, so it
|
|
88
|
+
// reads exactly like 54001: a limit of the store, in the store's own sentence.
|
|
89
|
+
"54000": "store_limit",
|
|
90
|
+
// VIS: `custom.has_visibility_at` refuses to answer from a snapshot older
|
|
91
|
+
// than a write this reader has already seen, rather than returning something
|
|
92
|
+
// they just lost access to. It is retryable on a fresher connection, which is
|
|
93
|
+
// a different instruction from every other refusal here.
|
|
94
|
+
// 55000 — `custom.table_move` (SC-1', 2026-09-24) refuses a move the table's present state
|
|
95
|
+
// does not allow: a destination that cannot take it, a table something else holds, contents
|
|
96
|
+
// that point at themselves in a circle. The store's own sentence names the reason and nothing
|
|
97
|
+
// moves, so it reads as a refusal on the merits. Caught by the live-door census on records
|
|
98
|
+
// 0.58.3's tag, the seventh time the census found a class before a person did.
|
|
99
|
+
"55000": "refused_by_rule",
|
|
100
|
+
// 42P17 — a worked-out column that would read itself round a circle (STORE-TAILS-3,
|
|
101
|
+
// 2026-09-25): `custom._field_reads_what_it_reads` refuses the declaration or edit that would
|
|
102
|
+
// close the circle, naming every column in it, and `custom.far_value` refuses a circle stored
|
|
103
|
+
// before that rule when a lookup or rollup is worked out. Refused on its merits, in the store's
|
|
104
|
+
// own sentence, nothing written — so it reads as 55000 does.
|
|
105
|
+
"42P17": "refused_by_rule",
|
|
106
|
+
// P0001 — `custom.context_scope_write` (2026-10-03) refuses a scope whose parent breaks the
|
|
107
|
+
// parent rule in the old trigger's own class and words (manager ruling H6). Refused on its
|
|
108
|
+
// merits, nothing written. Caught by the live-door census on records 0.65.0's tag.
|
|
109
|
+
P0001: "refused_by_rule",
|
|
110
|
+
"40001": "stale_read",
|
|
111
|
+
// 57014 — the store cancelled the statement at its own timeout. Like
|
|
112
|
+
// `stale_read` and unlike every other refusal here, the call was never
|
|
113
|
+
// refused on its merits: the same call on a smaller page, or once the
|
|
114
|
+
// organization's kernel is not being rewritten, can succeed. It gets its own
|
|
115
|
+
// code so a screen can offer "try again" honestly instead of showing a
|
|
116
|
+
// failure sentence the caller cannot act on.
|
|
117
|
+
"57014": "timed_out",
|
|
118
|
+
// PostgREST's own two: the store is not being SERVED, which is a different
|
|
119
|
+
// thing from the store refusing. `custom` absent from `pgrst.db_schemas`, or
|
|
120
|
+
// the grants not copied, land here.
|
|
121
|
+
PGRST202: "store_not_served",
|
|
122
|
+
PGRST205: "store_not_served",
|
|
123
|
+
PGRST301: "door",
|
|
124
|
+
// PT428 — NOT A FAILURE, and the release gate's live census is what found it
|
|
125
|
+
// missing: the store raises it and this package answered `internal`, which is
|
|
126
|
+
// the one classification that tells a screen nothing. A stage gate whose
|
|
127
|
+
// `on_fail` is `require_approval` files the request and leaves the record
|
|
128
|
+
// where it was; the transaction is rolled back to the pipeline's own block, so
|
|
129
|
+
// "nothing was written" is a fact rather than a promise. Landed by lane
|
|
130
|
+
// STAGE-RULES; mapped here by STAGE-RULES-2 the day after, when the census
|
|
131
|
+
// caught it — the sixth time that census has been the thing that found a
|
|
132
|
+
// refusal class rather than a person guessing one.
|
|
133
|
+
PT428: "needs_approval"
|
|
134
|
+
};
|
|
135
|
+
var MAPPED_SQLSTATES = Object.keys(BY_SQLSTATE);
|
|
136
|
+
function parseDetail(details) {
|
|
137
|
+
if (!details) return void 0;
|
|
138
|
+
const trimmed = details.trim();
|
|
139
|
+
if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return details;
|
|
140
|
+
try {
|
|
141
|
+
return JSON.parse(trimmed);
|
|
142
|
+
} catch {
|
|
143
|
+
return details;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function isNotASqlstate(code) {
|
|
147
|
+
if (!code) return true;
|
|
148
|
+
return /^[0-9]{3}$/.test(code);
|
|
149
|
+
}
|
|
150
|
+
function mapPgError(error, where) {
|
|
151
|
+
const raw = error.code ?? void 0;
|
|
152
|
+
const sqlstate = raw && raw !== "" ? raw : void 0;
|
|
153
|
+
const mapped = {
|
|
154
|
+
code: "internal",
|
|
155
|
+
message: error.message,
|
|
156
|
+
...error.hint ? { hint: error.hint } : {},
|
|
157
|
+
...sqlstate ? { sqlstate } : {}
|
|
158
|
+
};
|
|
159
|
+
if (isNotASqlstate(sqlstate)) {
|
|
160
|
+
mapped.code = "unreachable";
|
|
161
|
+
} else {
|
|
162
|
+
mapped.code = BY_SQLSTATE[sqlstate] ?? "internal";
|
|
163
|
+
}
|
|
164
|
+
const detail = parseDetail(error.details);
|
|
165
|
+
if (detail !== void 0) mapped.detail = detail;
|
|
166
|
+
if (mapped.code === "internal") {
|
|
167
|
+
mapped.unmapped = true;
|
|
168
|
+
mapped.diagnostic = `@ai-matrx/records did not recognise SQLSTATE ${sqlstate ?? "(none)"} from ${where}; the store's own message is the thing to act on.`;
|
|
169
|
+
} else if (mapped.code === "unreachable") {
|
|
170
|
+
mapped.unmapped = true;
|
|
171
|
+
mapped.diagnostic = `@ai-matrx/records never reached the store from ${where}: ${raw ? `the transport answered ${raw}` : "no response"} \u2014 ${error.message}`;
|
|
172
|
+
mapped.message = "We could not reach your data.";
|
|
173
|
+
delete mapped.hint;
|
|
174
|
+
}
|
|
175
|
+
return mapped;
|
|
176
|
+
}
|
|
177
|
+
function mapThrownError(thrown, where) {
|
|
178
|
+
const o = thrown && typeof thrown === "object" ? thrown : {};
|
|
179
|
+
const message = typeof o.message === "string" && o.message ? o.message : thrown == null ? "Unknown error" : String(thrown);
|
|
180
|
+
const code = typeof o.code === "string" ? o.code : null;
|
|
181
|
+
if (code !== null || thrown instanceof TypeError && /fetch|network/i.test(message)) {
|
|
182
|
+
return mapPgError(
|
|
183
|
+
{ code, message, details: typeof o.details === "string" ? o.details : null, hint: typeof o.hint === "string" ? o.hint : null },
|
|
184
|
+
where
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
code: "internal",
|
|
189
|
+
message,
|
|
190
|
+
unmapped: true,
|
|
191
|
+
diagnostic: `@ai-matrx/records: ${where} threw outside the store.`
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function staleWriteDetail(error) {
|
|
195
|
+
if (error.code !== "stale_write") return null;
|
|
196
|
+
const detail = error.detail;
|
|
197
|
+
if (!detail || typeof detail.expected_version !== "number" || typeof detail.current_version !== "number") {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
expected_version: detail.expected_version,
|
|
202
|
+
current_version: detail.current_version,
|
|
203
|
+
contested_fields: detail.contested_fields ?? {}
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function archivedOrganizationId(error) {
|
|
207
|
+
if (error.code !== "door" || typeof error.detail !== "string") return null;
|
|
208
|
+
const m = /^organization_archived:([0-9a-f-]{36})$/i.exec(error.detail.trim());
|
|
209
|
+
return m ? m[1] : null;
|
|
210
|
+
}
|
|
211
|
+
export {
|
|
212
|
+
MAPPED_SQLSTATES,
|
|
213
|
+
archivedOrganizationId,
|
|
214
|
+
err,
|
|
215
|
+
isRecordsErr,
|
|
216
|
+
mapPgError,
|
|
217
|
+
mapThrownError,
|
|
218
|
+
ok,
|
|
219
|
+
staleWriteDetail,
|
|
220
|
+
unwrapRecords
|
|
221
|
+
};
|
|
222
|
+
//# sourceMappingURL=index.js.map
|