@marktiderman/genesis-core 1.2.0 → 1.4.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/README.md +142 -0
- package/dist/{chunk-4W4W7F4I.js → chunk-6MBACQYA.js} +6 -3
- package/dist/chunk-6MBACQYA.js.map +1 -0
- package/dist/chunk-7NUL32W7.js +14 -0
- package/dist/chunk-7NUL32W7.js.map +1 -0
- package/dist/{chunk-6V2TIN3G.js → chunk-GGSXSI6Z.js} +6 -5
- package/dist/chunk-GGSXSI6Z.js.map +1 -0
- package/dist/{chunk-5FTUB2M6.js → chunk-IHWWJUEN.js} +47 -15
- package/dist/chunk-IHWWJUEN.js.map +1 -0
- package/dist/chunk-NW26Z3LZ.js +303 -0
- package/dist/chunk-NW26Z3LZ.js.map +1 -0
- package/dist/{chunk-QFTMHOEH.js → chunk-P4OIIRQS.js} +22 -13
- package/dist/chunk-P4OIIRQS.js.map +1 -0
- package/dist/{chunk-3P4PHPMJ.js → chunk-ZK5C3OOT.js} +3 -3
- package/dist/{chunk-3P4PHPMJ.js.map → chunk-ZK5C3OOT.js.map} +1 -1
- package/dist/form-types.d.ts +6 -0
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.js +6 -5
- package/dist/hooks/related-keys.d.ts +11 -0
- package/dist/hooks/related-keys.js +3 -0
- package/dist/hooks/related-keys.js.map +1 -0
- package/dist/hooks/use-one.d.ts +1 -1
- package/dist/hooks/use-one.js +2 -2
- package/dist/hooks/use-resource-form.d.ts +19 -1
- package/dist/hooks/use-resource-form.js +4 -3
- package/dist/hooks/use-resource.d.ts +14 -1
- package/dist/hooks/use-resource.js +3 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +8 -7
- package/dist/provider/index.d.ts +140 -6
- package/dist/provider/index.js +3 -3
- package/dist/schema/index.d.ts +3 -3
- package/dist/schema/index.js +1 -1
- package/dist/{types-C7UVaF87.d.ts → types-zILrlHuV.d.ts} +226 -4
- package/dist/{write-outcome-D8kjoQ1A.d.ts → write-outcome-BE3Tk6bA.d.ts} +10 -1
- package/package.json +2 -2
- package/dist/chunk-4W4W7F4I.js.map +0 -1
- package/dist/chunk-5FTUB2M6.js.map +0 -1
- package/dist/chunk-6AA4ISUA.js +0 -125
- package/dist/chunk-6AA4ISUA.js.map +0 -1
- package/dist/chunk-6V2TIN3G.js.map +0 -1
- package/dist/chunk-QFTMHOEH.js.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { UseFormReturn } from 'react-hook-form';
|
|
2
2
|
import { ResourceFormFieldDef } from '../form-types.js';
|
|
3
|
+
import { p as InvalidationKey } from '../types-zILrlHuV.js';
|
|
3
4
|
|
|
4
5
|
interface UseResourceFormOptions {
|
|
5
6
|
resource: string;
|
|
@@ -11,14 +12,31 @@ interface UseResourceFormOptions {
|
|
|
11
12
|
listData?: Record<string, unknown>[];
|
|
12
13
|
onSuccess?: (data: Record<string, unknown>) => void;
|
|
13
14
|
onError?: (error: Error) => void;
|
|
14
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Pre-fill create form defaults from URL query params: a param named like a
|
|
17
|
+
* field (`?status=draft`) becomes that field's starting value. Default true.
|
|
18
|
+
* Pass false for a form that should not read the page's URL, e.g. one
|
|
19
|
+
* opened from a list whose own filters live in the query string.
|
|
20
|
+
*/
|
|
15
21
|
prefillFromUrl?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Generate a placeholder ("Enter name", "name@example.com") for a field
|
|
24
|
+
* whose `placeholder` is unset. Default true. A placeholder that only
|
|
25
|
+
* repeats the label adds noise without information, so `ResourceForm`
|
|
26
|
+
* turns this off unless asked.
|
|
27
|
+
*/
|
|
28
|
+
autoPlaceholder?: boolean;
|
|
16
29
|
/** Validation trigger mode. Default "onBlur". */
|
|
17
30
|
validationMode?: "onBlur" | "onChange" | "onSubmit";
|
|
18
31
|
/** Enable autosave drafts to localStorage for create mode. */
|
|
19
32
|
autosave?: boolean | {
|
|
20
33
|
debounceMs?: number;
|
|
21
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* Other query keys to invalidate after a save, on top of `[resource]` and
|
|
37
|
+
* the provider's own `invalidates`.
|
|
38
|
+
*/
|
|
39
|
+
invalidates?: InvalidationKey[];
|
|
22
40
|
}
|
|
23
41
|
interface UseResourceFormReturn {
|
|
24
42
|
form: UseFormReturn<Record<string, unknown>>;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
export { buildArrayItemDefaults, useResourceForm } from '../chunk-
|
|
1
|
+
export { buildArrayItemDefaults, useResourceForm } from '../chunk-IHWWJUEN.js';
|
|
2
2
|
import '../chunk-RYEXWQFD.js';
|
|
3
|
-
import '../chunk-
|
|
4
|
-
import '../chunk-
|
|
3
|
+
import '../chunk-ZK5C3OOT.js';
|
|
4
|
+
import '../chunk-7NUL32W7.js';
|
|
5
|
+
import '../chunk-GGSXSI6Z.js';
|
|
5
6
|
import '../chunk-ZYJUEJ4Z.js';
|
|
6
7
|
//# sourceMappingURL=use-resource-form.js.map
|
|
7
8
|
//# sourceMappingURL=use-resource-form.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UseQueryResult, UseMutationResult } from '@tanstack/react-query';
|
|
2
|
-
import {
|
|
2
|
+
import { E as SortParam, k as FilterParam, p as InvalidationKey, q as ListResult, L as ListParams, I as Identifier, B as BaseRecord } from '../types-zILrlHuV.js';
|
|
3
3
|
import '../form-types.js';
|
|
4
4
|
|
|
5
5
|
interface UseResourceOptions<T> {
|
|
@@ -21,6 +21,19 @@ interface UseResourceOptions<T> {
|
|
|
21
21
|
searchFields?: string[];
|
|
22
22
|
/** Disable auto-fetching. */
|
|
23
23
|
enabled?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Other query keys to invalidate after a create, update or delete, on top
|
|
26
|
+
* of `[resource]` and the provider's own `invalidates` (e.g. `[["me"]]`
|
|
27
|
+
* when a write changes the signed-in user's roles).
|
|
28
|
+
*/
|
|
29
|
+
invalidates?: InvalidationKey[];
|
|
30
|
+
/**
|
|
31
|
+
* While the next page / sort / search is loading, keep returning the
|
|
32
|
+
* previous result (`list.isPlaceholderData` is true meanwhile) instead of
|
|
33
|
+
* dropping to `undefined`. A paged list then stays on screen between pages
|
|
34
|
+
* rather than flashing a skeleton. Default false.
|
|
35
|
+
*/
|
|
36
|
+
keepPreviousData?: boolean;
|
|
24
37
|
onCreateSuccess?: (data: T) => void;
|
|
25
38
|
onUpdateSuccess?: (data: T) => void;
|
|
26
39
|
onDeleteSuccess?: () => void;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export { useResource } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
1
|
+
export { useResource } from '../chunk-P4OIIRQS.js';
|
|
2
|
+
import '../chunk-7NUL32W7.js';
|
|
3
|
+
import '../chunk-GGSXSI6Z.js';
|
|
3
4
|
import '../chunk-ZYJUEJ4Z.js';
|
|
4
5
|
//# sourceMappingURL=use-resource.js.map
|
|
5
6
|
//# sourceMappingURL=use-resource.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { A as ArrayFilter, a as AuditEntry, B as BaseRecord, C as CreateParams,
|
|
2
|
-
export { D as DataWriteError, a as DataWriteErrorOptions, W as WriteOutcome, i as isDataWriteError } from './write-outcome-
|
|
3
|
-
export { DataProviderRoot, DataProviderRootProps, GenesisProvider, GenesisProviderProps, MockProviderOptions, SupabaseClient, SupabaseClientInput, createMockProvider, createSupabaseProvider, useDataProvider, useStorage } from './provider/index.js';
|
|
1
|
+
export { A as ArrayFilter, a as AuditEntry, B as BaseRecord, b as BulkChange, c as BulkResult, C as CreateParams, d as CreateResult, D as DataProvider, e as DataRow, f as DeleteParams, g as DeleteResult, F as FieldPermissions, h as FieldReference, i as FieldSchema, j as FilterOperator, k as FilterParam, G as GetManyParams, l as GetManyResult, m as GetOneParams, n as GetOneResult, H as HistoryParams, I as Identifier, o as ImportParams, p as InvalidationKey, L as ListParams, q as ListResult, N as NullFilter, P as PaginationParam, r as ProviderCapabilities, R as RangeFilter, s as RecordComment, t as ResourceAccess, u as ResourceContract, v as ResourceRelation, w as ResourceSchema, x as ResourceSummary, y as RowAction, z as RowFailure, S as ScalarFilter, E as SortParam, J as StorageType, U as UpdateParams, K as UpdateResult, V as VersionField, W as WriteEvent } from './types-zILrlHuV.js';
|
|
2
|
+
export { D as DataWriteError, a as DataWriteErrorOptions, W as WriteOutcome, i as isDataWriteError } from './write-outcome-BE3Tk6bA.js';
|
|
3
|
+
export { DataProviderRoot, DataProviderRootProps, GenesisProvider, GenesisProviderProps, MockProviderOptions, SupabaseClient, SupabaseClientInput, SupabaseProviderOptions, SupabaseResourceConfig, SupabaseWriteContext, createMockProvider, createSupabaseProvider, toDataWriteError, useDataProvider, useStorage, writeOutcomeFromCode } from './provider/index.js';
|
|
4
4
|
export { S as StorageAdapter } from './types-DKcxHXxq.js';
|
|
5
5
|
export { createLocalStorageAdapter, createMemoryStorageAdapter, createNoopStorageAdapter } from './storage/index.js';
|
|
6
6
|
export { UseResourceOptions, UseResourceReturn, useResource } from './hooks/use-resource.js';
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
export { createSupabaseProvider } from './chunk-
|
|
1
|
+
export { createSupabaseProvider, toDataWriteError, writeOutcomeFromCode } from './chunk-NW26Z3LZ.js';
|
|
2
2
|
export { decodeRecordKey, encodeRecordKey, keyFields } from './chunk-KV2HW4G4.js';
|
|
3
|
-
export { DataWriteError, isDataWriteError } from './chunk-
|
|
3
|
+
export { DataWriteError, isDataWriteError } from './chunk-6MBACQYA.js';
|
|
4
4
|
import './chunk-XCX2TRBL.js';
|
|
5
5
|
import './chunk-65SXNHWE.js';
|
|
6
6
|
import './chunk-EL7YGOTY.js';
|
|
7
|
-
export {
|
|
7
|
+
export { useWizard } from './chunk-7KOLYF27.js';
|
|
8
|
+
export { buildArrayItemDefaults, useResourceForm } from './chunk-IHWWJUEN.js';
|
|
8
9
|
export { titleCase } from './chunk-RYEXWQFD.js';
|
|
9
|
-
export { useOne } from './chunk-
|
|
10
|
-
export { useResource } from './chunk-
|
|
11
|
-
|
|
10
|
+
export { useOne } from './chunk-ZK5C3OOT.js';
|
|
11
|
+
export { useResource } from './chunk-P4OIIRQS.js';
|
|
12
|
+
import './chunk-7NUL32W7.js';
|
|
13
|
+
export { DataProviderRoot, GenesisProvider, createMockProvider, useDataProvider, useStorage } from './chunk-GGSXSI6Z.js';
|
|
12
14
|
export { createLocalStorageAdapter, createMemoryStorageAdapter, createNoopStorageAdapter } from './chunk-ZYJUEJ4Z.js';
|
|
13
|
-
export { useWizard } from './chunk-7KOLYF27.js';
|
|
14
15
|
//# sourceMappingURL=index.js.map
|
|
15
16
|
//# sourceMappingURL=index.js.map
|
package/dist/provider/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { D as DataProvider } from '../types-
|
|
2
|
-
export { A as ArrayFilter,
|
|
3
|
-
|
|
1
|
+
import { D as DataProvider, I as Identifier, B as BaseRecord, p as InvalidationKey, W as WriteEvent } from '../types-zILrlHuV.js';
|
|
2
|
+
export { A as ArrayFilter, b as BulkChange, c as BulkResult, C as CreateParams, d as CreateResult, f as DeleteParams, g as DeleteResult, k as FilterParam, G as GetManyParams, l as GetManyResult, m as GetOneParams, n as GetOneResult, H as HistoryParams, o as ImportParams, L as ListParams, q as ListResult, N as NullFilter, P as PaginationParam, R as RangeFilter, z as RowFailure, S as ScalarFilter, E as SortParam, U as UpdateParams, K as UpdateResult } from '../types-zILrlHuV.js';
|
|
3
|
+
import { D as DataWriteError, W as WriteOutcome } from '../write-outcome-BE3Tk6bA.js';
|
|
4
|
+
export { a as DataWriteErrorOptions, i as isDataWriteError } from '../write-outcome-BE3Tk6bA.js';
|
|
4
5
|
import * as react from 'react';
|
|
5
6
|
import { ReactNode } from 'react';
|
|
7
|
+
import { QueryClient } from '@tanstack/react-query';
|
|
6
8
|
import { S as StorageAdapter } from '../types-DKcxHXxq.js';
|
|
7
9
|
import '../form-types.js';
|
|
8
10
|
|
|
@@ -70,8 +72,124 @@ interface SupabaseClient {
|
|
|
70
72
|
interface SupabaseClientInput {
|
|
71
73
|
from(table: string): unknown;
|
|
72
74
|
}
|
|
73
|
-
|
|
75
|
+
/** What a write hook is told about the write it is part of. */
|
|
76
|
+
interface SupabaseWriteContext {
|
|
77
|
+
resource: string;
|
|
78
|
+
action: "create" | "update";
|
|
79
|
+
/** The row's id, for an update. */
|
|
80
|
+
id?: Identifier;
|
|
81
|
+
}
|
|
82
|
+
/** Per-resource rules for `createSupabaseProvider`. Every field is optional. */
|
|
83
|
+
interface SupabaseResourceConfig {
|
|
84
|
+
/** Singular noun for failure messages, e.g. "project". Defaults to "record". */
|
|
85
|
+
noun?: string;
|
|
86
|
+
/**
|
|
87
|
+
* `"bin"` for a table whose delete trigger moves the row to a recycle bin
|
|
88
|
+
* instead of removing it (see `SupabaseProviderOptions.binTables`).
|
|
89
|
+
* `"hard"` forces a plain delete even when `binTables` lists the table.
|
|
90
|
+
*/
|
|
91
|
+
deleteMode?: "hard" | "bin";
|
|
92
|
+
/**
|
|
93
|
+
* Turns submitted values into the row to write: trim, drop read-only keys,
|
|
94
|
+
* validate. Runs before every create and update, including the `create`
|
|
95
|
+
* and `update` overrides. Throw (ideally `DataWriteError("invalid", ...)`)
|
|
96
|
+
* to refuse the write; nothing is sent.
|
|
97
|
+
*/
|
|
98
|
+
prepare?: (values: Record<string, unknown>, context: SupabaseWriteContext) => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
99
|
+
/**
|
|
100
|
+
* Creates the row some other way than an insert, e.g. a security-definer
|
|
101
|
+
* RPC. Return the new row, or its id and the provider reads the row back
|
|
102
|
+
* (if the read-back fails, the create is still reported as saved, with
|
|
103
|
+
* just the id, so the user does not retry and make a second one). Throw to
|
|
104
|
+
* fail; a Supabase `{ message, code }` error is mapped like any other.
|
|
105
|
+
*/
|
|
106
|
+
create?: (row: Record<string, unknown>) => Promise<BaseRecord | Identifier>;
|
|
107
|
+
/**
|
|
108
|
+
* Updates the row some other way than an update, e.g. an RPC. Return the
|
|
109
|
+
* updated row, or its id (or `true`) and the provider reads it back.
|
|
110
|
+
* Returning nothing (`undefined`/`null`/`false`) means no row changed: the provider then reads the
|
|
111
|
+
* row to say why (`forbidden` or `gone`), exactly as for a plain update,
|
|
112
|
+
* so a function that silently skips a row never reports a save.
|
|
113
|
+
*/
|
|
114
|
+
update?: (id: Identifier, row: Record<string, unknown>) => Promise<BaseRecord | Identifier | boolean | null | undefined | void>;
|
|
115
|
+
/** Maps a stored row to edit-form values; see `DataProvider.toFormValues`. */
|
|
116
|
+
toFormValues?: (record: Record<string, unknown>) => Record<string, unknown>;
|
|
117
|
+
/**
|
|
118
|
+
* Other cache keys a committed write to this resource makes stale, e.g.
|
|
119
|
+
* `[["staff"], ["me"]]`. Served through `DataProvider.invalidates`, which
|
|
120
|
+
* `useResource` and `useResourceForm` invalidate after their writes.
|
|
121
|
+
*/
|
|
122
|
+
invalidates?: InvalidationKey[] | ((event: WriteEvent) => InvalidationKey[]);
|
|
123
|
+
}
|
|
124
|
+
/** Options for `createSupabaseProvider`. All optional; none changes reads. */
|
|
125
|
+
interface SupabaseProviderOptions {
|
|
126
|
+
/**
|
|
127
|
+
* Recycle-bin tables: their delete trigger turns a delete into a "binned"
|
|
128
|
+
* mark and the binned row drops out of the caller's view (RLS or a view
|
|
129
|
+
* filter). The database reports such a delete as zero rows, so for these
|
|
130
|
+
* the provider checks the row is visible, deletes it, and reads it back:
|
|
131
|
+
* gone from view is success, still visible is `forbidden`. A row that was
|
|
132
|
+
* not visible beforehand is `gone`.
|
|
133
|
+
*/
|
|
134
|
+
binTables?: readonly string[] | ((resource: string) => boolean);
|
|
135
|
+
/** Per-resource rules, keyed by resource (table) name. */
|
|
136
|
+
resources?: Record<string, SupabaseResourceConfig>;
|
|
137
|
+
/**
|
|
138
|
+
* Called after every committed create, update and delete, e.g. to
|
|
139
|
+
* invalidate caches the Genesis hooks don't know about. Awaited, but a
|
|
140
|
+
* failure is logged and never turns a committed write into a failed one.
|
|
141
|
+
*/
|
|
142
|
+
onWrite?: (event: WriteEvent) => void | Promise<void>;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* The Supabase data provider. Reads and writes go through the client you
|
|
146
|
+
* pass, under that client's session and RLS.
|
|
147
|
+
*
|
|
148
|
+
* Writes never report a save that did not happen:
|
|
149
|
+
* - `update` and `deleteOne` ask for the affected rows. Zero rows is a
|
|
150
|
+
* `DataWriteError`: the row is read back, and still visible means
|
|
151
|
+
* `forbidden` (RLS or a trigger refused the change), no longer visible
|
|
152
|
+
* means `gone`.
|
|
153
|
+
* - Database errors on writes are thrown as `DataWriteError` with the
|
|
154
|
+
* outcome their code means (`writeOutcomeFromCode`) and the code kept on
|
|
155
|
+
* `error.code`.
|
|
156
|
+
* - Recycle-bin tables (`binTables`) succeed when the row leaves the
|
|
157
|
+
* caller's view.
|
|
158
|
+
*
|
|
159
|
+
* Reads are unchanged: errors are thrown as an `Error` carrying `code`.
|
|
160
|
+
*/
|
|
161
|
+
declare function createSupabaseProvider(client: SupabaseClientInput, options?: SupabaseProviderOptions): DataProvider;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Maps a Postgres SQLSTATE or PostgREST error code to the write outcome it
|
|
165
|
+
* means. Anything not listed is `error`: a code is only read as a refusal or
|
|
166
|
+
* a bad value when it says so.
|
|
167
|
+
*
|
|
168
|
+
* - `42501` (insufficient privilege, including "new row violates row-level
|
|
169
|
+
* security policy") → `forbidden`
|
|
170
|
+
* - `22***` (data exception: bad type, out of range) and `23***` (integrity
|
|
171
|
+
* constraint: `23505` unique, `23503` foreign key, `23502` not null,
|
|
172
|
+
* `23514` check) → `invalid`
|
|
173
|
+
* - `PGRST301`–`PGRST303` (JWT missing, expired or rejected), `28000`,
|
|
174
|
+
* `28P01` → `unauthenticated`
|
|
175
|
+
* - `PGRST116` (one row was asked for and none came back) → `gone`
|
|
176
|
+
*/
|
|
177
|
+
declare function writeOutcomeFromCode(code: string | null | undefined): WriteOutcome;
|
|
178
|
+
/**
|
|
179
|
+
* Turns anything a write threw, or the `{ message, code }` error a Supabase
|
|
180
|
+
* client returned, into a `DataWriteError`. A `DataWriteError` passes through
|
|
181
|
+
* unchanged; anything else keeps its message and `code`, and is kept as the
|
|
182
|
+
* `cause`.
|
|
183
|
+
*/
|
|
184
|
+
declare function toDataWriteError(error: unknown): DataWriteError;
|
|
74
185
|
|
|
186
|
+
/**
|
|
187
|
+
* Puts a `DataProvider` in context, and nothing else. Mount it inside your
|
|
188
|
+
* app's own `QueryClientProvider` and the Genesis hooks share that cache:
|
|
189
|
+
* the same query keys (`[resource, "list", params]`,
|
|
190
|
+
* `[resource, "detail", id, select]`), so invalidating `[resource]` from app
|
|
191
|
+
* code refreshes Genesis lists too, and vice versa.
|
|
192
|
+
*/
|
|
75
193
|
interface DataProviderRootProps {
|
|
76
194
|
provider: DataProvider;
|
|
77
195
|
children: ReactNode;
|
|
@@ -87,6 +205,14 @@ type GenesisProviderProps = {
|
|
|
87
205
|
mock?: never;
|
|
88
206
|
/** Platform-specific storage adapter. Defaults to localStorage (SSR-safe). */
|
|
89
207
|
storage?: StorageAdapter;
|
|
208
|
+
/**
|
|
209
|
+
* The TanStack Query client to use. Without it, GenesisProvider creates
|
|
210
|
+
* its OWN client — a second cache beside any the app already has, so app
|
|
211
|
+
* queries and Genesis queries would not see each other's invalidations.
|
|
212
|
+
* An app with a `QueryClientProvider` should pass its client here, or
|
|
213
|
+
* use `DataProviderRoot` inside that provider instead.
|
|
214
|
+
*/
|
|
215
|
+
queryClient?: QueryClient;
|
|
90
216
|
} | {
|
|
91
217
|
children: ReactNode;
|
|
92
218
|
provider?: never;
|
|
@@ -97,7 +223,15 @@ type GenesisProviderProps = {
|
|
|
97
223
|
};
|
|
98
224
|
/** Platform-specific storage adapter. Defaults to localStorage (SSR-safe). */
|
|
99
225
|
storage?: StorageAdapter;
|
|
226
|
+
/** See the `provider` variant. */
|
|
227
|
+
queryClient?: QueryClient;
|
|
100
228
|
};
|
|
101
|
-
|
|
229
|
+
/**
|
|
230
|
+
* Convenience root: a `QueryClientProvider`, storage, and a data provider
|
|
231
|
+
* (yours, or a mock built from datasets). It creates its own `QueryClient`
|
|
232
|
+
* unless you pass `queryClient`; an app that already has one should pass it,
|
|
233
|
+
* or mount `DataProviderRoot` inside its existing `QueryClientProvider`.
|
|
234
|
+
*/
|
|
235
|
+
declare function GenesisProvider({ children, provider, mock, storage, queryClient: queryClientProp, }: GenesisProviderProps): react.JSX.Element;
|
|
102
236
|
|
|
103
|
-
export { DataProvider, DataProviderRoot, type DataProviderRootProps, GenesisProvider, type GenesisProviderProps, type MockProviderOptions, type SupabaseClient, type SupabaseClientInput, createMockProvider, createSupabaseProvider, useDataProvider, useStorage };
|
|
237
|
+
export { BaseRecord, DataProvider, DataProviderRoot, type DataProviderRootProps, DataWriteError, GenesisProvider, type GenesisProviderProps, Identifier, InvalidationKey, type MockProviderOptions, type SupabaseClient, type SupabaseClientInput, type SupabaseProviderOptions, type SupabaseResourceConfig, type SupabaseWriteContext, WriteEvent, WriteOutcome, createMockProvider, createSupabaseProvider, toDataWriteError, useDataProvider, useStorage, writeOutcomeFromCode };
|
package/dist/provider/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { createSupabaseProvider } from '../chunk-
|
|
2
|
-
export { DataWriteError, isDataWriteError } from '../chunk-
|
|
3
|
-
export { DataProviderRoot, GenesisProvider, createMockProvider, useDataProvider, useStorage } from '../chunk-
|
|
1
|
+
export { createSupabaseProvider, toDataWriteError, writeOutcomeFromCode } from '../chunk-NW26Z3LZ.js';
|
|
2
|
+
export { DataWriteError, isDataWriteError } from '../chunk-6MBACQYA.js';
|
|
3
|
+
export { DataProviderRoot, GenesisProvider, createMockProvider, useDataProvider, useStorage } from '../chunk-GGSXSI6Z.js';
|
|
4
4
|
import '../chunk-ZYJUEJ4Z.js';
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
package/dist/schema/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { a as AuditEntry, F as FieldPermissions,
|
|
3
|
-
export { D as DataWriteError, a as DataWriteErrorOptions, W as WriteOutcome, i as isDataWriteError } from '../write-outcome-
|
|
1
|
+
import { u as ResourceContract, I as Identifier, e as DataRow } from '../types-zILrlHuV.js';
|
|
2
|
+
export { a as AuditEntry, F as FieldPermissions, h as FieldReference, i as FieldSchema, j as FilterOperator, r as ProviderCapabilities, s as RecordComment, t as ResourceAccess, v as ResourceRelation, w as ResourceSchema, x as ResourceSummary, y as RowAction, J as StorageType, V as VersionField } from '../types-zILrlHuV.js';
|
|
3
|
+
export { D as DataWriteError, a as DataWriteErrorOptions, W as WriteOutcome, i as isDataWriteError } from '../write-outcome-BE3Tk6bA.js';
|
|
4
4
|
export { FieldType as WidgetHint } from '../form-types.js';
|
|
5
5
|
|
|
6
6
|
/** The key of a contract as a list, whichever form `key` was declared in. */
|
package/dist/schema/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { decodeRecordKey, encodeRecordKey, keyFields } from '../chunk-KV2HW4G4.js';
|
|
2
|
-
export { DataWriteError, isDataWriteError } from '../chunk-
|
|
2
|
+
export { DataWriteError, isDataWriteError } from '../chunk-6MBACQYA.js';
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
|
@@ -47,6 +47,8 @@ interface FieldSchema {
|
|
|
47
47
|
readonly array?: boolean;
|
|
48
48
|
/** Human note (surfaces in describe()/drift reports). */
|
|
49
49
|
readonly description?: string;
|
|
50
|
+
/** Human label, e.g. "Date of birth". Absent means a UI derives one from `name`. */
|
|
51
|
+
readonly label?: string;
|
|
50
52
|
/** The store's exact type, e.g. `timestamp with time zone` or `public.status`. */
|
|
51
53
|
readonly dbType?: string;
|
|
52
54
|
/** Which control fits this field. A hint: a UI may still choose another. */
|
|
@@ -68,7 +70,7 @@ interface FieldSchema {
|
|
|
68
70
|
* One declaration of a resource: its fields and its identity.
|
|
69
71
|
*
|
|
70
72
|
* `key` names the identity field, or several for a composite key (a junction
|
|
71
|
-
* table keyed on `(
|
|
73
|
+
* table keyed on `(team_id, user_id)`). Use {@link keyFields} to read it as
|
|
72
74
|
* a list without caring which form it took.
|
|
73
75
|
*/
|
|
74
76
|
interface ResourceContract<Row extends DataRow = DataRow> {
|
|
@@ -97,6 +99,46 @@ interface ResourceAccess {
|
|
|
97
99
|
readonly update: boolean;
|
|
98
100
|
/** Why `update` (or `read`) is false, in one human sentence. */
|
|
99
101
|
readonly reason?: string;
|
|
102
|
+
/** True when this user may add rows. Absent means the provider doesn't say. */
|
|
103
|
+
readonly create?: boolean;
|
|
104
|
+
/** True when this user may delete rows they can see. */
|
|
105
|
+
readonly delete?: boolean;
|
|
106
|
+
/** True when this user may read a row's audit history. */
|
|
107
|
+
readonly history?: boolean;
|
|
108
|
+
/** True when this user may read and add comments on rows they can see. */
|
|
109
|
+
readonly comment?: boolean;
|
|
110
|
+
/** Why `create`, `delete`, `history` or `comment` is false, in one human sentence each. */
|
|
111
|
+
readonly reasons?: {
|
|
112
|
+
readonly create?: string;
|
|
113
|
+
readonly delete?: string;
|
|
114
|
+
readonly history?: string;
|
|
115
|
+
readonly comment?: string;
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* How another resource relates to this one, from the store's foreign keys.
|
|
120
|
+
*
|
|
121
|
+
* - `one`: a field on THIS resource points at one row of `resource`.
|
|
122
|
+
* - `many`: rows of `resource` point at this row through their `field`.
|
|
123
|
+
* - `through`: many rows of `resource`, linked by the junction resource in
|
|
124
|
+
* `through` (a table whose key is two foreign keys).
|
|
125
|
+
*/
|
|
126
|
+
interface ResourceRelation {
|
|
127
|
+
readonly kind: "one" | "many" | "through";
|
|
128
|
+
/** The related resource. */
|
|
129
|
+
readonly resource: string;
|
|
130
|
+
/**
|
|
131
|
+
* `one`: the field on this resource. `many`: the field on `resource` that
|
|
132
|
+
* holds this row's key. `through`: the junction's field holding this row's key.
|
|
133
|
+
*/
|
|
134
|
+
readonly field: string;
|
|
135
|
+
/** For `through`: the junction resource, and its field pointing at `resource`. */
|
|
136
|
+
readonly through?: {
|
|
137
|
+
readonly resource: string;
|
|
138
|
+
readonly otherField: string;
|
|
139
|
+
};
|
|
140
|
+
/** True when at most one related row can exist (a unique foreign key). */
|
|
141
|
+
readonly unique?: boolean;
|
|
100
142
|
}
|
|
101
143
|
/**
|
|
102
144
|
* The column a provider checks on every update so an edit never silently
|
|
@@ -111,7 +153,12 @@ interface VersionField {
|
|
|
111
153
|
* `expectedVersion` echoes `String(row[field])` back unchanged.
|
|
112
154
|
*/
|
|
113
155
|
readonly field: string;
|
|
114
|
-
|
|
156
|
+
/**
|
|
157
|
+
* `row`: no column tracks versions, so the token is a fingerprint of the
|
|
158
|
+
* row's values, and `field` is a name the provider adds to each record
|
|
159
|
+
* (it is not one of the resource's fields).
|
|
160
|
+
*/
|
|
161
|
+
readonly kind: "integer" | "timestamp" | "row";
|
|
115
162
|
}
|
|
116
163
|
/**
|
|
117
164
|
* A resource as `describe()` reports it for the CURRENT user: the contract,
|
|
@@ -124,6 +171,32 @@ interface ResourceSchema<Row extends DataRow = DataRow> extends ResourceContract
|
|
|
124
171
|
readonly access: ResourceAccess;
|
|
125
172
|
/** Present only when writes can be version-checked. */
|
|
126
173
|
readonly version?: VersionField;
|
|
174
|
+
/** The field that best names a row to a person (a name or title), for links and pickers. */
|
|
175
|
+
readonly labelField?: string;
|
|
176
|
+
/** Resources this one links to or is linked from. Only ones this user may see. */
|
|
177
|
+
readonly relations?: readonly ResourceRelation[];
|
|
178
|
+
/** Fields the user may set when creating a row. Absent when creating isn't allowed. */
|
|
179
|
+
readonly createFields?: readonly string[];
|
|
180
|
+
/** Row actions this user may run: each calls the app's own function on one row. */
|
|
181
|
+
readonly actions?: readonly RowAction[];
|
|
182
|
+
}
|
|
183
|
+
/** A named operation on one row, carried out by the app's own database function. */
|
|
184
|
+
interface RowAction {
|
|
185
|
+
readonly name: string;
|
|
186
|
+
readonly label: string;
|
|
187
|
+
/** Ask before running, with this question. */
|
|
188
|
+
readonly confirm?: string;
|
|
189
|
+
/** One sentence on what it does. */
|
|
190
|
+
readonly description?: string;
|
|
191
|
+
}
|
|
192
|
+
/** A comment on a record. */
|
|
193
|
+
interface RecordComment {
|
|
194
|
+
readonly id: string;
|
|
195
|
+
/** The signed-in user who wrote it (the token's `sub`). */
|
|
196
|
+
readonly author: string;
|
|
197
|
+
readonly body: string;
|
|
198
|
+
/** ISO 8601, as the store recorded it. */
|
|
199
|
+
readonly createdAt: string;
|
|
127
200
|
}
|
|
128
201
|
/** One entry of `listResources()`: enough to draw a sidebar. */
|
|
129
202
|
interface ResourceSummary {
|
|
@@ -151,6 +224,21 @@ interface ProviderCapabilities {
|
|
|
151
224
|
readonly versionedWrites: boolean;
|
|
152
225
|
/** Records may be keyed by more than one field. */
|
|
153
226
|
readonly compositeKeys: boolean;
|
|
227
|
+
/** Server-side sort by several fields at once (`ListParams.sorts`). */
|
|
228
|
+
readonly multiSort?: boolean;
|
|
229
|
+
/** `create` and `deleteOne` are served, subject to each resource's access. */
|
|
230
|
+
readonly create?: boolean;
|
|
231
|
+
readonly delete?: boolean;
|
|
232
|
+
/** `history` is served, subject to each resource's access. */
|
|
233
|
+
readonly history?: boolean;
|
|
234
|
+
/** `importRows` is served, with a dry run. */
|
|
235
|
+
readonly import?: boolean;
|
|
236
|
+
/** `undo` is served. */
|
|
237
|
+
readonly undo?: boolean;
|
|
238
|
+
/** `runAction` is served. */
|
|
239
|
+
readonly actions?: boolean;
|
|
240
|
+
/** `comments` and `addComment` are served. */
|
|
241
|
+
readonly comments?: boolean;
|
|
154
242
|
}
|
|
155
243
|
/** One audit record, as committed alongside the edit it describes. */
|
|
156
244
|
interface AuditEntry {
|
|
@@ -162,7 +250,10 @@ interface AuditEntry {
|
|
|
162
250
|
readonly resource: string;
|
|
163
251
|
/** The record's key, field name → value. */
|
|
164
252
|
readonly key: DataRow;
|
|
165
|
-
|
|
253
|
+
/** `run` is a row action; `rowAction` names it. */
|
|
254
|
+
readonly action: "create" | "update" | "delete" | "run";
|
|
255
|
+
/** For `run`: which row action. */
|
|
256
|
+
readonly rowAction?: string;
|
|
166
257
|
/** Values of the changed fields before the edit. */
|
|
167
258
|
readonly before: DataRow | null;
|
|
168
259
|
/** Values of the changed fields after the edit. */
|
|
@@ -219,6 +310,11 @@ type FilterParam = ScalarFilter | ArrayFilter | RangeFilter | NullFilter;
|
|
|
219
310
|
interface ListParams {
|
|
220
311
|
pagination?: PaginationParam;
|
|
221
312
|
sort?: SortParam;
|
|
313
|
+
/**
|
|
314
|
+
* Sort by several fields, first one first. Wins over `sort` on a provider
|
|
315
|
+
* whose capabilities report `multiSort`; others use only `sort`.
|
|
316
|
+
*/
|
|
317
|
+
sorts?: SortParam[];
|
|
222
318
|
filters?: FilterParam[];
|
|
223
319
|
/** Supabase select syntax, e.g. "*, author:profiles(name)". Mock provider ignores this. */
|
|
224
320
|
select?: string;
|
|
@@ -258,6 +354,8 @@ interface CreateParams<T> {
|
|
|
258
354
|
/** Result of `create`. */
|
|
259
355
|
interface CreateResult<T> {
|
|
260
356
|
data: T;
|
|
357
|
+
/** The audit entry committed with the new row, from a provider that audits. */
|
|
358
|
+
audit?: AuditEntry;
|
|
261
359
|
}
|
|
262
360
|
/** Parameters for `update`. */
|
|
263
361
|
interface UpdateParams<T> {
|
|
@@ -287,13 +385,67 @@ interface UpdateResult<T> {
|
|
|
287
385
|
/** Parameters for `deleteOne`. */
|
|
288
386
|
interface DeleteParams {
|
|
289
387
|
id: Identifier;
|
|
388
|
+
/** The version token the row was read at; see `UpdateParams.expectedVersion`. */
|
|
389
|
+
expectedVersion?: string | null;
|
|
290
390
|
}
|
|
291
391
|
/** Result of `deleteOne`. */
|
|
292
392
|
interface DeleteResult {
|
|
293
393
|
data: {
|
|
294
394
|
id: Identifier;
|
|
295
395
|
};
|
|
396
|
+
/** The audit entry committed with the deletion, from a provider that audits. */
|
|
397
|
+
audit?: AuditEntry;
|
|
398
|
+
}
|
|
399
|
+
/** One row's change in a bulk update. */
|
|
400
|
+
interface BulkChange {
|
|
401
|
+
id: Identifier;
|
|
402
|
+
data: Record<string, unknown>;
|
|
403
|
+
/** The version token the row was read at. */
|
|
404
|
+
expectedVersion?: string | null;
|
|
296
405
|
}
|
|
406
|
+
/** Why one row of a bulk write or import didn't go through. */
|
|
407
|
+
interface RowFailure {
|
|
408
|
+
/** The row's position in the request, from 0. */
|
|
409
|
+
index: number;
|
|
410
|
+
id?: Identifier;
|
|
411
|
+
outcome: string;
|
|
412
|
+
message: string;
|
|
413
|
+
}
|
|
414
|
+
/** Result of a bulk write: every row changed, or none did. */
|
|
415
|
+
interface BulkResult {
|
|
416
|
+
/** Rows changed; always the number requested when `ok`. */
|
|
417
|
+
count: number;
|
|
418
|
+
ok: boolean;
|
|
419
|
+
/** Present when `ok` is false: every row that failed, so the caller can fix them all at once. */
|
|
420
|
+
failures?: RowFailure[];
|
|
421
|
+
/** One audit entry per row changed. */
|
|
422
|
+
audit?: AuditEntry[];
|
|
423
|
+
}
|
|
424
|
+
/** Parameters for `importRows`. */
|
|
425
|
+
interface ImportParams {
|
|
426
|
+
rows: Record<string, unknown>[];
|
|
427
|
+
/** Check every row against the database and change nothing. */
|
|
428
|
+
dryRun: boolean;
|
|
429
|
+
}
|
|
430
|
+
/** Parameters for `history`. */
|
|
431
|
+
interface HistoryParams {
|
|
432
|
+
id: Identifier;
|
|
433
|
+
/** Most recent first; default and maximum are the provider's. */
|
|
434
|
+
limit?: number;
|
|
435
|
+
}
|
|
436
|
+
/** A write that committed, as passed to a provider's `onWrite` and `invalidates`. */
|
|
437
|
+
interface WriteEvent {
|
|
438
|
+
resource: string;
|
|
439
|
+
kind: "create" | "update" | "delete";
|
|
440
|
+
id: Identifier;
|
|
441
|
+
/** The row as written, when the provider has it (not for a delete). */
|
|
442
|
+
record?: BaseRecord;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* A cache key to invalidate after a write. Shaped like a TanStack Query
|
|
446
|
+
* `QueryKey` (`readonly unknown[]`), matched by prefix.
|
|
447
|
+
*/
|
|
448
|
+
type InvalidationKey = readonly unknown[];
|
|
297
449
|
interface DataProvider {
|
|
298
450
|
getList<T extends BaseRecord = BaseRecord>(resource: string, params: ListParams): Promise<ListResult<T>>;
|
|
299
451
|
getOne<T extends BaseRecord = BaseRecord>(resource: string, params: GetOneParams): Promise<GetOneResult<T>>;
|
|
@@ -314,6 +466,76 @@ interface DataProvider {
|
|
|
314
466
|
* controls a provider cannot serve instead of letting them error.
|
|
315
467
|
*/
|
|
316
468
|
capabilities?(resource?: string): Promise<ProviderCapabilities>;
|
|
469
|
+
/**
|
|
470
|
+
* A record's audit history, most recent first, limited to the fields this
|
|
471
|
+
* user may read.
|
|
472
|
+
*/
|
|
473
|
+
history?(resource: string, params: HistoryParams): Promise<AuditEntry[]>;
|
|
474
|
+
/**
|
|
475
|
+
* Update many rows in ONE transaction. All of them change or none do: a
|
|
476
|
+
* single conflict, refusal or invalid value rolls back the rest, and the
|
|
477
|
+
* result lists every row that failed.
|
|
478
|
+
*/
|
|
479
|
+
updateMany?(resource: string, params: {
|
|
480
|
+
changes: BulkChange[];
|
|
481
|
+
}): Promise<BulkResult>;
|
|
482
|
+
/** Delete many rows in one transaction, all or none, each at its version. */
|
|
483
|
+
deleteMany?(resource: string, params: {
|
|
484
|
+
items: {
|
|
485
|
+
id: Identifier;
|
|
486
|
+
expectedVersion?: string | null;
|
|
487
|
+
}[];
|
|
488
|
+
}): Promise<BulkResult>;
|
|
489
|
+
/**
|
|
490
|
+
* Add rows from an import. With `dryRun`, every row is tried against the
|
|
491
|
+
* database and nothing is kept, so the result lists every row that would
|
|
492
|
+
* fail; without it, all rows are added in one transaction or none are.
|
|
493
|
+
*/
|
|
494
|
+
importRows?(resource: string, params: ImportParams): Promise<BulkResult>;
|
|
495
|
+
/**
|
|
496
|
+
* Undo one audited change with a compensating write: put the changed
|
|
497
|
+
* fields back, remove an added row, or restore a deleted one. Refused when
|
|
498
|
+
* the row has changed since.
|
|
499
|
+
*/
|
|
500
|
+
undo?(resource: string, params: {
|
|
501
|
+
auditId: string;
|
|
502
|
+
}): Promise<{
|
|
503
|
+
audit?: AuditEntry;
|
|
504
|
+
}>;
|
|
505
|
+
/**
|
|
506
|
+
* Run one of the resource's row actions (`ResourceSchema.actions`) on a
|
|
507
|
+
* row, at the version it was read. The app's function does the work; the
|
|
508
|
+
* row's change is audited.
|
|
509
|
+
*/
|
|
510
|
+
runAction?(resource: string, params: {
|
|
511
|
+
id: Identifier;
|
|
512
|
+
action: string;
|
|
513
|
+
expectedVersion?: string | null;
|
|
514
|
+
}): Promise<{
|
|
515
|
+
data: Record<string, unknown> | null;
|
|
516
|
+
audit?: AuditEntry;
|
|
517
|
+
}>;
|
|
518
|
+
/** A record's comments, oldest first. */
|
|
519
|
+
comments?(resource: string, params: {
|
|
520
|
+
id: Identifier;
|
|
521
|
+
}): Promise<RecordComment[]>;
|
|
522
|
+
/** Add a comment to a record, as the signed-in user. */
|
|
523
|
+
addComment?(resource: string, params: {
|
|
524
|
+
id: Identifier;
|
|
525
|
+
body: string;
|
|
526
|
+
}): Promise<RecordComment>;
|
|
527
|
+
/**
|
|
528
|
+
* Maps a stored row to the values an edit form starts from, for a resource
|
|
529
|
+
* whose form shape differs from its table (the reverse of a write's
|
|
530
|
+
* `prepare`). `useResourceForm` applies it in edit mode.
|
|
531
|
+
*/
|
|
532
|
+
toFormValues?(resource: string, record: Record<string, unknown>): Record<string, unknown>;
|
|
533
|
+
/**
|
|
534
|
+
* Other cache keys a committed write makes stale, beyond the resource's
|
|
535
|
+
* own `[resource]` keys. `useResource` and `useResourceForm` invalidate
|
|
536
|
+
* them after their writes.
|
|
537
|
+
*/
|
|
538
|
+
invalidates?(event: WriteEvent): InvalidationKey[];
|
|
317
539
|
}
|
|
318
540
|
|
|
319
|
-
export type { ArrayFilter as A, BaseRecord as B, CreateParams as C, DataProvider as D, FieldPermissions as F, GetManyParams as G, Identifier as I, ListParams as L, NullFilter as N, PaginationParam as P, RangeFilter as R, ScalarFilter as S, UpdateParams as U, VersionField as V, AuditEntry as a,
|
|
541
|
+
export type { ArrayFilter as A, BaseRecord as B, CreateParams as C, DataProvider as D, SortParam as E, FieldPermissions as F, GetManyParams as G, HistoryParams as H, Identifier as I, StorageType as J, UpdateResult as K, ListParams as L, NullFilter as N, PaginationParam as P, RangeFilter as R, ScalarFilter as S, UpdateParams as U, VersionField as V, WriteEvent as W, AuditEntry as a, BulkChange as b, BulkResult as c, CreateResult as d, DataRow as e, DeleteParams as f, DeleteResult as g, FieldReference as h, FieldSchema as i, FilterOperator as j, FilterParam as k, GetManyResult as l, GetOneParams as m, GetOneResult as n, ImportParams as o, InvalidationKey as p, ListResult as q, ProviderCapabilities as r, RecordComment as s, ResourceAccess as t, ResourceContract as u, ResourceRelation as v, ResourceSchema as w, ResourceSummary as x, RowAction as y, RowFailure as z };
|