@marktiderman/genesis-core 1.4.0 → 1.5.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 +81 -0
- package/dist/{chunk-6MBACQYA.js → chunk-5NHR6ZXS.js} +10 -2
- package/dist/chunk-5NHR6ZXS.js.map +1 -0
- package/dist/chunk-BQOJX67X.js +31 -0
- package/dist/chunk-BQOJX67X.js.map +1 -0
- package/dist/{chunk-P4OIIRQS.js → chunk-DVW5GXWZ.js} +70 -26
- package/dist/chunk-DVW5GXWZ.js.map +1 -0
- package/dist/chunk-HT43MPKW.js +3 -0
- package/dist/{chunk-EL7YGOTY.js.map → chunk-HT43MPKW.js.map} +1 -1
- package/dist/chunk-HUNGCTRA.js +33 -0
- package/dist/chunk-HUNGCTRA.js.map +1 -0
- package/dist/{chunk-IHWWJUEN.js → chunk-IZT2O57C.js} +127 -39
- package/dist/chunk-IZT2O57C.js.map +1 -0
- package/dist/chunk-QH4P5MI2.js +278 -0
- package/dist/chunk-QH4P5MI2.js.map +1 -0
- package/dist/{chunk-NW26Z3LZ.js → chunk-RLY7TZUY.js} +178 -37
- package/dist/chunk-RLY7TZUY.js.map +1 -0
- package/dist/chunk-XQO4OH2N.js +32 -0
- package/dist/chunk-XQO4OH2N.js.map +1 -0
- package/dist/hooks/index.d.ts +5 -1
- package/dist/hooks/index.js +8 -4
- package/dist/hooks/mutation-mode.d.ts +109 -0
- package/dist/hooks/mutation-mode.js +3 -0
- package/dist/hooks/mutation-mode.js.map +1 -0
- package/dist/hooks/related-keys.d.ts +2 -1
- package/dist/hooks/use-capabilities.d.ts +21 -0
- package/dist/hooks/use-capabilities.js +5 -0
- package/dist/hooks/use-capabilities.js.map +1 -0
- package/dist/hooks/use-one.d.ts +2 -1
- package/dist/hooks/use-resource-form.d.ts +35 -2
- package/dist/hooks/use-resource-form.js +5 -2
- package/dist/hooks/use-resource.d.ts +29 -5
- package/dist/hooks/use-resource.js +2 -1
- package/dist/hooks/use-unsaved-changes-guard.d.ts +33 -0
- package/dist/hooks/use-unsaved-changes-guard.js +3 -0
- package/dist/hooks/use-unsaved-changes-guard.js.map +1 -0
- package/dist/index.d.ts +7 -3
- package/dist/index.js +10 -6
- package/dist/provider/index.d.ts +77 -5
- package/dist/provider/index.js +4 -2
- package/dist/read-outcome-BQkYcV4t.d.ts +88 -0
- package/dist/schema/index.d.ts +4 -3
- package/dist/schema/index.js +2 -1
- package/dist/{types-zILrlHuV.d.ts → types-C5bjsbxz.d.ts} +12 -279
- package/dist/types-Dsqqr9s7.d.ts +281 -0
- package/package.json +1 -1
- package/dist/chunk-6MBACQYA.js.map +0 -1
- package/dist/chunk-EL7YGOTY.js +0 -3
- package/dist/chunk-IHWWJUEN.js.map +0 -1
- package/dist/chunk-NW26Z3LZ.js.map +0 -1
- package/dist/chunk-P4OIIRQS.js.map +0 -1
- package/dist/write-outcome-BE3Tk6bA.d.ts +0 -47
package/dist/hooks/use-one.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { UseQueryResult } from '@tanstack/react-query';
|
|
2
|
-
import { B as BaseRecord, I as Identifier } from '../types-
|
|
2
|
+
import { B as BaseRecord, I as Identifier } from '../types-Dsqqr9s7.js';
|
|
3
|
+
import '../types-C5bjsbxz.js';
|
|
3
4
|
import '../form-types.js';
|
|
4
5
|
|
|
5
6
|
interface UseOneOptions {
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { UseFormReturn } from 'react-hook-form';
|
|
2
2
|
import { ResourceFormFieldDef } from '../form-types.js';
|
|
3
|
-
import {
|
|
3
|
+
import { j as InvalidationKey } from '../types-Dsqqr9s7.js';
|
|
4
|
+
import { MutationModeOptions } from './mutation-mode.js';
|
|
5
|
+
import '../types-C5bjsbxz.js';
|
|
6
|
+
import '@tanstack/react-query';
|
|
4
7
|
|
|
5
|
-
interface UseResourceFormOptions {
|
|
8
|
+
interface UseResourceFormOptions extends MutationModeOptions {
|
|
6
9
|
resource: string;
|
|
7
10
|
action: "create" | "edit";
|
|
8
11
|
id?: string;
|
|
@@ -10,8 +13,27 @@ interface UseResourceFormOptions {
|
|
|
10
13
|
fields?: ResourceFormFieldDef[];
|
|
11
14
|
/** Full dataset used to auto-detect select fields from unique values. */
|
|
12
15
|
listData?: Record<string, unknown>[];
|
|
16
|
+
/**
|
|
17
|
+
* The form is done. After the save in `pessimistic` mode (with the stored
|
|
18
|
+
* row); at once in `optimistic` and `undoable` modes (with the submitted
|
|
19
|
+
* values over the record, and no `id` for a create).
|
|
20
|
+
*/
|
|
13
21
|
onSuccess?: (data: Record<string, unknown>) => void;
|
|
22
|
+
/**
|
|
23
|
+
* The save failed. In `optimistic` and `undoable` modes the form may be
|
|
24
|
+
* gone by then, so show the error from here (genesis-ui's ResourceForm
|
|
25
|
+
* toasts it when no `onError` is given).
|
|
26
|
+
*/
|
|
14
27
|
onError?: (error: Error) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Warn before unsaved changes are lost. Default false. While the form is
|
|
30
|
+
* dirty, closing or reloading the tab shows the browser's prompt, and
|
|
31
|
+
* `confirmLeave()` asks before in-app navigation (wire it to a router
|
|
32
|
+
* blocker; see SKILL.md "Unsaved changes").
|
|
33
|
+
*/
|
|
34
|
+
warnWhenUnsaved?: boolean | {
|
|
35
|
+
message?: string;
|
|
36
|
+
};
|
|
15
37
|
/**
|
|
16
38
|
* Pre-fill create form defaults from URL query params: a param named like a
|
|
17
39
|
* field (`?status=draft`) becomes that field's starting value. Default true.
|
|
@@ -48,6 +70,17 @@ interface UseResourceFormReturn {
|
|
|
48
70
|
handleSave: (data: Record<string, unknown>) => Promise<void>;
|
|
49
71
|
isSaving: boolean;
|
|
50
72
|
isLoading: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* The form has changes that have not been saved. False again once a save
|
|
75
|
+
* succeeds (or, in optimistic / undoable modes, is handed off).
|
|
76
|
+
*/
|
|
77
|
+
isDirty: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* For in-app navigation: true when it is fine to leave (nothing unsaved,
|
|
80
|
+
* `warnWhenUnsaved` off, or the user confirmed). Asks with
|
|
81
|
+
* `window.confirm` otherwise.
|
|
82
|
+
*/
|
|
83
|
+
confirmLeave: () => boolean;
|
|
51
84
|
}
|
|
52
85
|
/** Build default values for a single array item from its sub-field definitions */
|
|
53
86
|
declare function buildArrayItemDefaults(arrayFields: ResourceFormFieldDef[]): Record<string, unknown>;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
export { buildArrayItemDefaults, useResourceForm } from '../chunk-
|
|
1
|
+
export { buildArrayItemDefaults, useResourceForm } from '../chunk-IZT2O57C.js';
|
|
2
|
+
import '../chunk-XQO4OH2N.js';
|
|
3
|
+
import '../chunk-5NHR6ZXS.js';
|
|
2
4
|
import '../chunk-RYEXWQFD.js';
|
|
3
|
-
import '../chunk-
|
|
5
|
+
import '../chunk-QH4P5MI2.js';
|
|
4
6
|
import '../chunk-7NUL32W7.js';
|
|
7
|
+
import '../chunk-ZK5C3OOT.js';
|
|
5
8
|
import '../chunk-GGSXSI6Z.js';
|
|
6
9
|
import '../chunk-ZYJUEJ4Z.js';
|
|
7
10
|
//# sourceMappingURL=use-resource-form.js.map
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { UseQueryResult, UseMutationResult } from '@tanstack/react-query';
|
|
2
|
-
import {
|
|
2
|
+
import { m as SortParam, F as FilterParam, j as InvalidationKey, k as ListResult, L as ListParams, I as Identifier, B as BaseRecord } from '../types-Dsqqr9s7.js';
|
|
3
|
+
import { MutationModeOptions } from './mutation-mode.js';
|
|
4
|
+
import '../types-C5bjsbxz.js';
|
|
3
5
|
import '../form-types.js';
|
|
4
6
|
|
|
5
|
-
interface UseResourceOptions<T> {
|
|
7
|
+
interface UseResourceOptions<T> extends MutationModeOptions {
|
|
6
8
|
defaultSort?: SortParam;
|
|
7
9
|
/**
|
|
8
10
|
* Re-synced whenever its value changes (deep-equal, order-independent),
|
|
@@ -15,6 +17,10 @@ interface UseResourceOptions<T> {
|
|
|
15
17
|
*/
|
|
16
18
|
defaultFilters?: FilterParam[];
|
|
17
19
|
defaultPerPage?: number;
|
|
20
|
+
/** The page to start on (from 1), e.g. restored from the URL. Default 1. */
|
|
21
|
+
defaultPage?: number;
|
|
22
|
+
/** The search to start with, e.g. restored from the URL. Default "". */
|
|
23
|
+
defaultSearch?: string;
|
|
18
24
|
/** Supabase select/join syntax, e.g. "*, author:profiles(name)". */
|
|
19
25
|
select?: string;
|
|
20
26
|
/** Fields to search across when setSearch is called. Required for server-side search. */
|
|
@@ -34,9 +40,19 @@ interface UseResourceOptions<T> {
|
|
|
34
40
|
* rather than flashing a skeleton. Default false.
|
|
35
41
|
*/
|
|
36
42
|
keepPreviousData?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* After the write commits, with the provider's row. In `optimistic` and
|
|
45
|
+
* `undoable` modes that is after `create` / `update` / `remove` have
|
|
46
|
+
* already resolved.
|
|
47
|
+
*/
|
|
37
48
|
onCreateSuccess?: (data: T) => void;
|
|
38
49
|
onUpdateSuccess?: (data: T) => void;
|
|
39
50
|
onDeleteSuccess?: () => void;
|
|
51
|
+
/**
|
|
52
|
+
* A write failed. In `optimistic` and `undoable` modes this is the only
|
|
53
|
+
* place a failure is reported (the cache has already been put back), so
|
|
54
|
+
* show it to the user here.
|
|
55
|
+
*/
|
|
40
56
|
onError?: (error: Error) => void;
|
|
41
57
|
}
|
|
42
58
|
interface UseResourceReturn<T> {
|
|
@@ -49,11 +65,19 @@ interface UseResourceReturn<T> {
|
|
|
49
65
|
setPage: (page: number) => void;
|
|
50
66
|
setPerPage: (perPage: number) => void;
|
|
51
67
|
setSearch: (query: string) => void;
|
|
52
|
-
/**
|
|
68
|
+
/**
|
|
69
|
+
* Create a new record. Returns the created item. In `optimistic` and
|
|
70
|
+
* `undoable` modes it resolves at once with the values given (no `id` yet;
|
|
71
|
+
* `onCreateSuccess` gets the stored row).
|
|
72
|
+
*/
|
|
53
73
|
create: (data: Partial<T>) => Promise<T>;
|
|
54
|
-
/**
|
|
74
|
+
/**
|
|
75
|
+
* Update an existing record by id. Returns the updated item. In
|
|
76
|
+
* `optimistic` and `undoable` modes it resolves at once with the cached
|
|
77
|
+
* row merged with `data`.
|
|
78
|
+
*/
|
|
55
79
|
update: (id: Identifier, data: Partial<T>) => Promise<T>;
|
|
56
|
-
/** Delete a record by id. */
|
|
80
|
+
/** Delete a record by id. Resolves at once in `optimistic` / `undoable` modes. */
|
|
57
81
|
remove: (id: Identifier) => Promise<void>;
|
|
58
82
|
/** True when any mutation is in-flight. */
|
|
59
83
|
isMutating: boolean;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
declare const DEFAULT_UNSAVED_CHANGES_MESSAGE = "You have unsaved changes. Leave without saving?";
|
|
2
|
+
interface UseUnsavedChangesGuardOptions {
|
|
3
|
+
/** Guard while this is true (e.g. a form is dirty). */
|
|
4
|
+
when: boolean;
|
|
5
|
+
/** The question `confirmLeave` asks. */
|
|
6
|
+
message?: string;
|
|
7
|
+
/**
|
|
8
|
+
* How to ask. Default `window.confirm`. Must answer synchronously, since
|
|
9
|
+
* router blockers and `beforeunload` cannot wait.
|
|
10
|
+
*/
|
|
11
|
+
confirm?: (message: string) => boolean;
|
|
12
|
+
}
|
|
13
|
+
interface UseUnsavedChangesGuardReturn {
|
|
14
|
+
/** True while leaving would lose changes. */
|
|
15
|
+
isBlocking: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Call before leaving in-app (closing a dialog, a router blocker). Returns
|
|
18
|
+
* true when it is fine to leave: nothing to lose, or the user said so.
|
|
19
|
+
*/
|
|
20
|
+
confirmLeave: () => boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Warns before unsaved changes are lost, without depending on a router.
|
|
24
|
+
*
|
|
25
|
+
* - While `when` is true, closing or reloading the tab shows the browser's
|
|
26
|
+
* own "Leave site?" prompt (`beforeunload`).
|
|
27
|
+
* - `confirmLeave()` is for in-app navigation: wire it to your router's
|
|
28
|
+
* blocker (React Router `useBlocker`, TanStack Router `useBlocker`), or call
|
|
29
|
+
* it before closing a dialog. See SKILL.md "Unsaved changes".
|
|
30
|
+
*/
|
|
31
|
+
declare function useUnsavedChangesGuard(options: UseUnsavedChangesGuardOptions): UseUnsavedChangesGuardReturn;
|
|
32
|
+
|
|
33
|
+
export { DEFAULT_UNSAVED_CHANGES_MESSAGE, type UseUnsavedChangesGuardOptions, type UseUnsavedChangesGuardReturn, useUnsavedChangesGuard };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"use-unsaved-changes-guard.js"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
export { A as ArrayFilter,
|
|
2
|
-
export { D as
|
|
3
|
-
export { DataProviderRoot, DataProviderRootProps, GenesisProvider, GenesisProviderProps, MockProviderOptions, SupabaseClient, SupabaseClientInput, SupabaseProviderOptions, SupabaseResourceConfig, SupabaseWriteContext, createMockProvider, createSupabaseProvider, toDataWriteError, useDataProvider, useStorage, writeOutcomeFromCode } from './provider/index.js';
|
|
1
|
+
export { A as ArrayFilter, B as BaseRecord, a as BulkChange, b as BulkResult, C as CreateParams, c as CreateResult, D as DataProvider, d as DeleteParams, e as DeleteResult, F as FilterParam, G as GetManyParams, f as GetManyResult, g as GetOneParams, h as GetOneResult, H as HistoryParams, I as Identifier, i as ImportParams, j as InvalidationKey, L as ListParams, k as ListResult, N as NullFilter, P as PaginationParam, R as RangeFilter, l as RowFailure, S as ScalarFilter, m as SortParam, U as UpdateParams, n as UpdateResult, W as WriteEvent } from './types-Dsqqr9s7.js';
|
|
2
|
+
export { D as DataReadError, a as DataReadErrorOptions, b as DataWriteError, c as DataWriteErrorOptions, R as ReadOutcome, W as WriteOutcome, i as isDataReadError, d as isDataWriteError, r as readFailureMessage } from './read-outcome-BQkYcV4t.js';
|
|
3
|
+
export { DataProviderRoot, DataProviderRootProps, GenesisProvider, GenesisProviderProps, MockProviderOptions, PostgrestFieldErrors, SupabaseClient, SupabaseClientInput, SupabaseProviderOptions, SupabaseResourceConfig, SupabaseWriteContext, createMockProvider, createSupabaseProvider, fieldErrorsFromPostgrest, readOutcomeFromCode, 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';
|
|
7
7
|
export { UseOneOptions, useOne } from './hooks/use-one.js';
|
|
8
|
+
export { useCapabilities } from './hooks/use-capabilities.js';
|
|
8
9
|
export { UseResourceFormOptions, UseResourceFormReturn, buildArrayItemDefaults, useResourceForm } from './hooks/use-resource-form.js';
|
|
9
10
|
export { UseWizardReturn, WizardStep, useWizard } from './hooks/use-wizard.js';
|
|
11
|
+
export { DEFAULT_UNDO_DELAY_MS, MutationMode, MutationModeOptions, UndoableWrite, pendingWriteCount } from './hooks/mutation-mode.js';
|
|
12
|
+
export { DEFAULT_UNSAVED_CHANGES_MESSAGE, UseUnsavedChangesGuardOptions, UseUnsavedChangesGuardReturn, useUnsavedChangesGuard } from './hooks/use-unsaved-changes-guard.js';
|
|
10
13
|
export { FieldType, ResourceFormFieldDef, SelectOption, FieldType as WidgetHint } from './form-types.js';
|
|
14
|
+
export { A as AuditEntry, D as DataRow, F as FieldPermissions, a as FieldReference, b as FieldSchema, c as FilterOperator, P as ProviderCapabilities, R as RecordComment, d as ResourceAccess, e as ResourceContract, f as ResourceRelation, g as ResourceSchema, h as ResourceSummary, i as RowAction, S as StorageType, V as VersionField } from './types-C5bjsbxz.js';
|
|
11
15
|
export { decodeRecordKey, encodeRecordKey, keyFields } from './schema/index.js';
|
|
12
16
|
export { titleCase } from './utils.js';
|
|
13
17
|
import 'react';
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
export { createSupabaseProvider, toDataWriteError, writeOutcomeFromCode } from './chunk-
|
|
1
|
+
export { createSupabaseProvider, fieldErrorsFromPostgrest, readOutcomeFromCode, toDataWriteError, writeOutcomeFromCode } from './chunk-RLY7TZUY.js';
|
|
2
2
|
export { decodeRecordKey, encodeRecordKey, keyFields } from './chunk-KV2HW4G4.js';
|
|
3
|
-
export {
|
|
3
|
+
export { DataReadError, isDataReadError, readFailureMessage } from './chunk-HUNGCTRA.js';
|
|
4
4
|
import './chunk-XCX2TRBL.js';
|
|
5
5
|
import './chunk-65SXNHWE.js';
|
|
6
|
-
import './chunk-
|
|
6
|
+
import './chunk-HT43MPKW.js';
|
|
7
|
+
export { buildArrayItemDefaults, useResourceForm } from './chunk-IZT2O57C.js';
|
|
8
|
+
export { useResource } from './chunk-DVW5GXWZ.js';
|
|
9
|
+
export { DEFAULT_UNSAVED_CHANGES_MESSAGE, useUnsavedChangesGuard } from './chunk-XQO4OH2N.js';
|
|
7
10
|
export { useWizard } from './chunk-7KOLYF27.js';
|
|
8
|
-
export {
|
|
11
|
+
export { DataWriteError, isDataWriteError } from './chunk-5NHR6ZXS.js';
|
|
9
12
|
export { titleCase } from './chunk-RYEXWQFD.js';
|
|
10
|
-
export {
|
|
11
|
-
export { useResource } from './chunk-P4OIIRQS.js';
|
|
13
|
+
export { DEFAULT_UNDO_DELAY_MS, pendingWriteCount } from './chunk-QH4P5MI2.js';
|
|
12
14
|
import './chunk-7NUL32W7.js';
|
|
15
|
+
export { useCapabilities } from './chunk-BQOJX67X.js';
|
|
16
|
+
export { useOne } from './chunk-ZK5C3OOT.js';
|
|
13
17
|
export { DataProviderRoot, GenesisProvider, createMockProvider, useDataProvider, useStorage } from './chunk-GGSXSI6Z.js';
|
|
14
18
|
export { createLocalStorageAdapter, createMemoryStorageAdapter, createNoopStorageAdapter } from './chunk-ZYJUEJ4Z.js';
|
|
15
19
|
//# sourceMappingURL=index.js.map
|
package/dist/provider/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { D as DataProvider, I as Identifier, B as BaseRecord,
|
|
2
|
-
export { A as ArrayFilter,
|
|
3
|
-
import { D as DataWriteError, W as WriteOutcome } from '../
|
|
4
|
-
export { a as DataWriteErrorOptions, i as isDataWriteError } from '../
|
|
1
|
+
import { D as DataProvider, I as Identifier, B as BaseRecord, j as InvalidationKey, W as WriteEvent } from '../types-Dsqqr9s7.js';
|
|
2
|
+
export { A as ArrayFilter, a as BulkChange, b as BulkResult, C as CreateParams, c as CreateResult, d as DeleteParams, e as DeleteResult, F as FilterParam, G as GetManyParams, f as GetManyResult, g as GetOneParams, h as GetOneResult, H as HistoryParams, i as ImportParams, L as ListParams, k as ListResult, N as NullFilter, P as PaginationParam, R as RangeFilter, l as RowFailure, S as ScalarFilter, m as SortParam, U as UpdateParams, n as UpdateResult } from '../types-Dsqqr9s7.js';
|
|
3
|
+
import { D as DataReadError, R as ReadOutcome, b as DataWriteError, W as WriteOutcome } from '../read-outcome-BQkYcV4t.js';
|
|
4
|
+
export { a as DataReadErrorOptions, c as DataWriteErrorOptions, i as isDataReadError, d as isDataWriteError, r as readFailureMessage } from '../read-outcome-BQkYcV4t.js';
|
|
5
5
|
import * as react from 'react';
|
|
6
6
|
import { ReactNode } from 'react';
|
|
7
7
|
import { QueryClient } from '@tanstack/react-query';
|
|
8
8
|
import { S as StorageAdapter } from '../types-DKcxHXxq.js';
|
|
9
|
+
import '../types-C5bjsbxz.js';
|
|
9
10
|
import '../form-types.js';
|
|
10
11
|
|
|
11
12
|
interface MockProviderOptions {
|
|
@@ -83,6 +84,23 @@ interface SupabaseWriteContext {
|
|
|
83
84
|
interface SupabaseResourceConfig {
|
|
84
85
|
/** Singular noun for failure messages, e.g. "project". Defaults to "record". */
|
|
85
86
|
noun?: string;
|
|
87
|
+
/** Plural for list messages, when it isn't `noun` + "s" ("categories"). */
|
|
88
|
+
nounPlural?: string;
|
|
89
|
+
/**
|
|
90
|
+
* The columns a search covers. `[]` means the resource can't be searched,
|
|
91
|
+
* and `capabilities(resource).search` reports false so a UI hides the box.
|
|
92
|
+
* Set, they replace the caller's `search.fields`; omitted, those are used
|
|
93
|
+
* as given.
|
|
94
|
+
*/
|
|
95
|
+
searchFields?: readonly string[];
|
|
96
|
+
/**
|
|
97
|
+
* The column a sorted list orders by last, so rows with equal sort values
|
|
98
|
+
* keep one order from page to page (none repeats, none is skipped).
|
|
99
|
+
* Default `"id"`; `false` for a table or view without one. With the
|
|
100
|
+
* default, a view that turns out to have no `id` column is read as before
|
|
101
|
+
* (without the key order) and a development warning suggests setting this.
|
|
102
|
+
*/
|
|
103
|
+
orderKey?: string | false;
|
|
86
104
|
/**
|
|
87
105
|
* `"bin"` for a table whose delete trigger moves the row to a recycle bin
|
|
88
106
|
* instead of removing it (see `SupabaseProviderOptions.binTables`).
|
|
@@ -140,6 +158,23 @@ interface SupabaseProviderOptions {
|
|
|
140
158
|
* failure is logged and never turns a committed write into a failed one.
|
|
141
159
|
*/
|
|
142
160
|
onWrite?: (event: WriteEvent) => void | Promise<void>;
|
|
161
|
+
/**
|
|
162
|
+
* The most rows one list page may ask for (PostgREST's `max-rows` caps
|
|
163
|
+
* reads anyway; default 1000). A larger request is refused with an
|
|
164
|
+
* `invalid` `DataReadError` (its `cause` says why) rather than cut short,
|
|
165
|
+
* so page boundaries never disagree with the caller's `perPage`.
|
|
166
|
+
* `capabilities().maxPerPage` reports it.
|
|
167
|
+
*/
|
|
168
|
+
maxPerPage?: number;
|
|
169
|
+
/**
|
|
170
|
+
* Called with every failed read, before it is thrown. The thrown
|
|
171
|
+
* `DataReadError` carries a plain message for users; the store's own
|
|
172
|
+
* error (its raw text and code) is its `cause`, for logging here.
|
|
173
|
+
*/
|
|
174
|
+
onReadError?: (error: DataReadError, context: {
|
|
175
|
+
resource: string;
|
|
176
|
+
operation: "getList" | "getOne" | "getMany";
|
|
177
|
+
}) => void | Promise<void>;
|
|
143
178
|
}
|
|
144
179
|
/**
|
|
145
180
|
* The Supabase data provider. Reads and writes go through the client you
|
|
@@ -160,6 +195,12 @@ interface SupabaseProviderOptions {
|
|
|
160
195
|
*/
|
|
161
196
|
declare function createSupabaseProvider(client: SupabaseClientInput, options?: SupabaseProviderOptions): DataProvider;
|
|
162
197
|
|
|
198
|
+
/**
|
|
199
|
+
* Maps a store error code to the read outcome it means: the write mapping,
|
|
200
|
+
* with `22***` and PostgREST request errors (`PGRST1**` other than PGRST116,
|
|
201
|
+
* `42703` unknown column, `42P01` unknown table) read as `invalid`.
|
|
202
|
+
*/
|
|
203
|
+
declare function readOutcomeFromCode(code: string | null | undefined): ReadOutcome;
|
|
163
204
|
/**
|
|
164
205
|
* Maps a Postgres SQLSTATE or PostgREST error code to the write outcome it
|
|
165
206
|
* means. Anything not listed is `error`: a code is only read as a refusal or
|
|
@@ -175,11 +216,42 @@ declare function createSupabaseProvider(client: SupabaseClientInput, options?: S
|
|
|
175
216
|
* - `PGRST116` (one row was asked for and none came back) → `gone`
|
|
176
217
|
*/
|
|
177
218
|
declare function writeOutcomeFromCode(code: string | null | undefined): WriteOutcome;
|
|
219
|
+
/** Field errors read from a store error, with the safe sentence that sums them up. */
|
|
220
|
+
interface PostgrestFieldErrors {
|
|
221
|
+
/** Column name → safe message for that input. */
|
|
222
|
+
fields: Record<string, string>;
|
|
223
|
+
/** One safe sentence for the whole error, to replace the store's raw text. */
|
|
224
|
+
message: string;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Reads which columns a Postgres constraint error is about, from PostgREST's
|
|
228
|
+
* `message` / `details`, and gives safe messages for them. Only plain column
|
|
229
|
+
* names are taken from the store's text; the values it echoes are never
|
|
230
|
+
* used. Returns `undefined` when nothing can be mapped safely.
|
|
231
|
+
*
|
|
232
|
+
* - `23505` unique violation, `Key (email)=(…) already exists.` → each
|
|
233
|
+
* column: "This value is already in use." (several columns: "This
|
|
234
|
+
* combination is already in use.")
|
|
235
|
+
* - `23502` not-null, `null value in column "title" …` → "This field is
|
|
236
|
+
* required."
|
|
237
|
+
* - `23503` foreign key on insert/update, `Key (owner_id)=(…) is not present
|
|
238
|
+
* in table …` → "The selected item doesn't exist."
|
|
239
|
+
*/
|
|
240
|
+
declare function fieldErrorsFromPostgrest(error: {
|
|
241
|
+
code?: unknown;
|
|
242
|
+
message?: unknown;
|
|
243
|
+
details?: unknown;
|
|
244
|
+
}): PostgrestFieldErrors | undefined;
|
|
178
245
|
/**
|
|
179
246
|
* Turns anything a write threw, or the `{ message, code }` error a Supabase
|
|
180
247
|
* client returned, into a `DataWriteError`. A `DataWriteError` passes through
|
|
181
248
|
* unchanged; anything else keeps its message and `code`, and is kept as the
|
|
182
249
|
* `cause`.
|
|
250
|
+
*
|
|
251
|
+
* When the error names the columns it is about (`fieldErrorsFromPostgrest`:
|
|
252
|
+
* unique, not-null and foreign-key violations), the result carries `fields`
|
|
253
|
+
* and its message is replaced with a safe sentence; the raw text stays on
|
|
254
|
+
* the `cause`.
|
|
183
255
|
*/
|
|
184
256
|
declare function toDataWriteError(error: unknown): DataWriteError;
|
|
185
257
|
|
|
@@ -234,4 +306,4 @@ type GenesisProviderProps = {
|
|
|
234
306
|
*/
|
|
235
307
|
declare function GenesisProvider({ children, provider, mock, storage, queryClient: queryClientProp, }: GenesisProviderProps): react.JSX.Element;
|
|
236
308
|
|
|
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 };
|
|
309
|
+
export { BaseRecord, DataProvider, DataProviderRoot, type DataProviderRootProps, DataReadError, DataWriteError, GenesisProvider, type GenesisProviderProps, Identifier, InvalidationKey, type MockProviderOptions, type PostgrestFieldErrors, ReadOutcome, type SupabaseClient, type SupabaseClientInput, type SupabaseProviderOptions, type SupabaseResourceConfig, type SupabaseWriteContext, WriteEvent, WriteOutcome, createMockProvider, createSupabaseProvider, fieldErrorsFromPostgrest, readOutcomeFromCode, toDataWriteError, useDataProvider, useStorage, writeOutcomeFromCode };
|
package/dist/provider/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
export { createSupabaseProvider, toDataWriteError, writeOutcomeFromCode } from '../chunk-
|
|
2
|
-
export {
|
|
1
|
+
export { createSupabaseProvider, fieldErrorsFromPostgrest, readOutcomeFromCode, toDataWriteError, writeOutcomeFromCode } from '../chunk-RLY7TZUY.js';
|
|
2
|
+
export { DataReadError, isDataReadError, readFailureMessage } from '../chunk-HUNGCTRA.js';
|
|
3
|
+
export { DataWriteError, isDataWriteError } from '../chunk-5NHR6ZXS.js';
|
|
4
|
+
import '../chunk-RYEXWQFD.js';
|
|
3
5
|
export { DataProviderRoot, GenesisProvider, createMockProvider, useDataProvider, useStorage } from '../chunk-GGSXSI6Z.js';
|
|
4
6
|
import '../chunk-ZYJUEJ4Z.js';
|
|
5
7
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { D as DataRow } from './types-C5bjsbxz.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* - `conflict`: someone else changed the row since it was read. `current`
|
|
5
|
+
* carries the row as it is now.
|
|
6
|
+
* - `gone`: the row was deleted, or is no longer visible to this user. The
|
|
7
|
+
* two cannot be told apart without a privileged look at the table, which
|
|
8
|
+
* would show this user a fact about a row they cannot see.
|
|
9
|
+
* - `forbidden`: the row is visible and unchanged, but the app or the
|
|
10
|
+
* database does not let this user make this change. Only reported when
|
|
11
|
+
* that is proven, never assumed from "zero rows changed".
|
|
12
|
+
* - `invalid`: the store rejected the value (type, constraint, not-null).
|
|
13
|
+
* - `audit_failed`: the audit entry could not be written, so the edit was
|
|
14
|
+
* rolled back with it.
|
|
15
|
+
* - `unauthenticated`: no signed-in user, or the session expired.
|
|
16
|
+
* - `error`: anything else. The edit did not commit.
|
|
17
|
+
*/
|
|
18
|
+
type WriteOutcome = "conflict" | "gone" | "forbidden" | "invalid" | "audit_failed" | "unauthenticated" | "error";
|
|
19
|
+
interface DataWriteErrorOptions {
|
|
20
|
+
/** The row as it is now, for a `conflict`. Only fields the user may read. */
|
|
21
|
+
current?: DataRow;
|
|
22
|
+
/** The row's current version token, for a `conflict`. */
|
|
23
|
+
currentVersion?: string | null;
|
|
24
|
+
/**
|
|
25
|
+
* The store's own error code, when it gave one (a Postgres SQLSTATE such as
|
|
26
|
+
* `23505`, or a PostgREST code such as `PGRST301`).
|
|
27
|
+
*/
|
|
28
|
+
code?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Per-field messages, keyed by field (column) name, for a write the store
|
|
31
|
+
* rejected because of particular values. Each message is safe to show next
|
|
32
|
+
* to its input: plain words, never the store's raw text or the value.
|
|
33
|
+
* `useResourceForm` puts each one on its field.
|
|
34
|
+
*/
|
|
35
|
+
fields?: Record<string, string>;
|
|
36
|
+
/** The underlying error, kept for logging. */
|
|
37
|
+
cause?: unknown;
|
|
38
|
+
}
|
|
39
|
+
/** Thrown by a provider when a write did not commit. */
|
|
40
|
+
declare class DataWriteError extends Error {
|
|
41
|
+
readonly outcome: WriteOutcome;
|
|
42
|
+
readonly current?: DataRow;
|
|
43
|
+
readonly currentVersion?: string | null;
|
|
44
|
+
/** The store's own error code, when it gave one. */
|
|
45
|
+
readonly code?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Per-field messages (field name → safe message), when the store said which
|
|
48
|
+
* values it rejected. See `DataWriteErrorOptions.fields`.
|
|
49
|
+
*/
|
|
50
|
+
readonly fields?: Readonly<Record<string, string>>;
|
|
51
|
+
constructor(outcome: WriteOutcome, message: string, options?: DataWriteErrorOptions);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* `instanceof` fails when two copies of this package are installed, so check
|
|
55
|
+
* the shape instead.
|
|
56
|
+
*/
|
|
57
|
+
declare function isDataWriteError(error: unknown): error is DataWriteError;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* - `unauthenticated`: no signed-in user, or the session expired.
|
|
61
|
+
* - `forbidden`: this user may not read these records.
|
|
62
|
+
* - `gone`: the one record asked for doesn't exist, or isn't visible.
|
|
63
|
+
* - `invalid`: the request itself was wrong (an unknown column, a bad value).
|
|
64
|
+
* - `error`: anything else.
|
|
65
|
+
*/
|
|
66
|
+
type ReadOutcome = "unauthenticated" | "forbidden" | "gone" | "invalid" | "error";
|
|
67
|
+
interface DataReadErrorOptions {
|
|
68
|
+
/** The store's own error code (a Postgres SQLSTATE or PostgREST code). */
|
|
69
|
+
code?: string;
|
|
70
|
+
/** The underlying error, with its raw text, kept for logging. */
|
|
71
|
+
cause?: unknown;
|
|
72
|
+
}
|
|
73
|
+
/** Thrown by a provider when a read failed. Its `message` is safe to show. */
|
|
74
|
+
declare class DataReadError extends Error {
|
|
75
|
+
readonly outcome: ReadOutcome;
|
|
76
|
+
/** The store's own error code, when it gave one. */
|
|
77
|
+
readonly code?: string;
|
|
78
|
+
constructor(outcome: ReadOutcome, message: string, options?: DataReadErrorOptions);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* `instanceof` fails when two copies of this package are installed, so check
|
|
82
|
+
* the shape instead.
|
|
83
|
+
*/
|
|
84
|
+
declare function isDataReadError(error: unknown): error is DataReadError;
|
|
85
|
+
/** The plain sentence for a failed read of `noun` records (one, or a list). */
|
|
86
|
+
declare function readFailureMessage(outcome: ReadOutcome, noun: string, one: boolean, plural?: string): string;
|
|
87
|
+
|
|
88
|
+
export { DataReadError as D, type ReadOutcome as R, type WriteOutcome as W, type DataReadErrorOptions as a, DataWriteError as b, type DataWriteErrorOptions as c, isDataWriteError as d, isDataReadError as i, readFailureMessage as r };
|
package/dist/schema/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
3
|
-
|
|
1
|
+
import { e as ResourceContract, D as DataRow } from '../types-C5bjsbxz.js';
|
|
2
|
+
export { A as AuditEntry, F as FieldPermissions, a as FieldReference, b as FieldSchema, c as FilterOperator, P as ProviderCapabilities, R as RecordComment, d as ResourceAccess, f as ResourceRelation, g as ResourceSchema, h as ResourceSummary, i as RowAction, S as StorageType, V as VersionField } from '../types-C5bjsbxz.js';
|
|
3
|
+
import { I as Identifier } from '../types-Dsqqr9s7.js';
|
|
4
|
+
export { D as DataReadError, a as DataReadErrorOptions, b as DataWriteError, c as DataWriteErrorOptions, R as ReadOutcome, W as WriteOutcome, i as isDataReadError, d as isDataWriteError, r as readFailureMessage } from '../read-outcome-BQkYcV4t.js';
|
|
4
5
|
export { FieldType as WidgetHint } from '../form-types.js';
|
|
5
6
|
|
|
6
7
|
/** The key of a contract as a list, whichever form `key` was declared in. */
|
package/dist/schema/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { decodeRecordKey, encodeRecordKey, keyFields } from '../chunk-KV2HW4G4.js';
|
|
2
|
-
export {
|
|
2
|
+
export { DataReadError, isDataReadError, readFailureMessage } from '../chunk-HUNGCTRA.js';
|
|
3
|
+
export { DataWriteError, isDataWriteError } from '../chunk-5NHR6ZXS.js';
|
|
3
4
|
//# sourceMappingURL=index.js.map
|
|
4
5
|
//# sourceMappingURL=index.js.map
|