@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
|
@@ -239,6 +239,17 @@ interface ProviderCapabilities {
|
|
|
239
239
|
readonly actions?: boolean;
|
|
240
240
|
/** `comments` and `addComment` are served. */
|
|
241
241
|
readonly comments?: boolean;
|
|
242
|
+
/**
|
|
243
|
+
* The most rows one `getList` page may ask for. A request for more is
|
|
244
|
+
* refused (it is not cut short, which would shift later page boundaries),
|
|
245
|
+
* so a client that wants every row must page at this size or less.
|
|
246
|
+
*/
|
|
247
|
+
readonly maxPerPage?: number;
|
|
248
|
+
/**
|
|
249
|
+
* A delete moves the record to a recycle bin (it can be restored) instead
|
|
250
|
+
* of removing it. Asked per resource: `capabilities(resource)`.
|
|
251
|
+
*/
|
|
252
|
+
readonly softDelete?: boolean;
|
|
242
253
|
}
|
|
243
254
|
/** One audit record, as committed alongside the edit it describes. */
|
|
244
255
|
interface AuditEntry {
|
|
@@ -260,282 +271,4 @@ interface AuditEntry {
|
|
|
260
271
|
readonly after: DataRow | null;
|
|
261
272
|
}
|
|
262
273
|
|
|
263
|
-
|
|
264
|
-
type Identifier = string | number;
|
|
265
|
-
/** Base record type — all resources must have an id. */
|
|
266
|
-
type BaseRecord = {
|
|
267
|
-
id: Identifier;
|
|
268
|
-
[key: string]: unknown;
|
|
269
|
-
};
|
|
270
|
-
/** Pagination parameters (offset-based, with optional cursor for future use). */
|
|
271
|
-
interface PaginationParam {
|
|
272
|
-
page: number;
|
|
273
|
-
perPage: number;
|
|
274
|
-
cursor?: string;
|
|
275
|
-
}
|
|
276
|
-
/** Sort direction for a single field. */
|
|
277
|
-
interface SortParam {
|
|
278
|
-
field: string;
|
|
279
|
-
order: "asc" | "desc";
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* Filter expressions — discriminated union by operator.
|
|
283
|
-
* Filters are AND-ed together in queries.
|
|
284
|
-
*/
|
|
285
|
-
/** Operators that compare a field against a single scalar value. */
|
|
286
|
-
interface ScalarFilter {
|
|
287
|
-
field: string;
|
|
288
|
-
operator: "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "contains";
|
|
289
|
-
value: string | number | boolean;
|
|
290
|
-
}
|
|
291
|
-
/** Operator that checks field membership in a list. */
|
|
292
|
-
interface ArrayFilter {
|
|
293
|
-
field: string;
|
|
294
|
-
operator: "in";
|
|
295
|
-
value: (string | number | boolean)[];
|
|
296
|
-
}
|
|
297
|
-
/** Operator that checks field is within a range. */
|
|
298
|
-
interface RangeFilter {
|
|
299
|
-
field: string;
|
|
300
|
-
operator: "between";
|
|
301
|
-
value: [string | number, string | number];
|
|
302
|
-
}
|
|
303
|
-
/** Operators that check for null/non-null — no value needed. */
|
|
304
|
-
interface NullFilter {
|
|
305
|
-
field: string;
|
|
306
|
-
operator: "is_null" | "is_not_null";
|
|
307
|
-
}
|
|
308
|
-
type FilterParam = ScalarFilter | ArrayFilter | RangeFilter | NullFilter;
|
|
309
|
-
/** Parameters for `getList`. */
|
|
310
|
-
interface ListParams {
|
|
311
|
-
pagination?: PaginationParam;
|
|
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[];
|
|
318
|
-
filters?: FilterParam[];
|
|
319
|
-
/** Supabase select syntax, e.g. "*, author:profiles(name)". Mock provider ignores this. */
|
|
320
|
-
select?: string;
|
|
321
|
-
/** Multi-field text search (case-insensitive). */
|
|
322
|
-
search?: {
|
|
323
|
-
query: string;
|
|
324
|
-
fields: string[];
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
/** Result of `getList`. */
|
|
328
|
-
interface ListResult<T> {
|
|
329
|
-
data: T[];
|
|
330
|
-
total: number;
|
|
331
|
-
}
|
|
332
|
-
/** Parameters for `getOne`. */
|
|
333
|
-
interface GetOneParams {
|
|
334
|
-
id: Identifier;
|
|
335
|
-
/** Supabase select syntax, e.g. "*, author:profiles(name)". Defaults to "*". */
|
|
336
|
-
select?: string;
|
|
337
|
-
}
|
|
338
|
-
/** Result of `getOne`. */
|
|
339
|
-
interface GetOneResult<T> {
|
|
340
|
-
data: T;
|
|
341
|
-
}
|
|
342
|
-
/** Parameters for `getMany`. */
|
|
343
|
-
interface GetManyParams {
|
|
344
|
-
ids: Identifier[];
|
|
345
|
-
}
|
|
346
|
-
/** Result of `getMany`. */
|
|
347
|
-
interface GetManyResult<T> {
|
|
348
|
-
data: T[];
|
|
349
|
-
}
|
|
350
|
-
/** Parameters for `create`. */
|
|
351
|
-
interface CreateParams<T> {
|
|
352
|
-
data: Partial<T>;
|
|
353
|
-
}
|
|
354
|
-
/** Result of `create`. */
|
|
355
|
-
interface CreateResult<T> {
|
|
356
|
-
data: T;
|
|
357
|
-
/** The audit entry committed with the new row, from a provider that audits. */
|
|
358
|
-
audit?: AuditEntry;
|
|
359
|
-
}
|
|
360
|
-
/** Parameters for `update`. */
|
|
361
|
-
interface UpdateParams<T> {
|
|
362
|
-
/**
|
|
363
|
-
* The record's identifier. For a composite key, the canonical string from
|
|
364
|
-
* `encodeRecordKey` (`@marktiderman/genesis-core/schema`).
|
|
365
|
-
*/
|
|
366
|
-
id: Identifier;
|
|
367
|
-
data: Partial<T>;
|
|
368
|
-
/**
|
|
369
|
-
* The version token the caller read the row at. A provider that reports
|
|
370
|
-
* `versionedWrites` in its capabilities rejects the update with a
|
|
371
|
-
* `DataWriteError` (`conflict`) when the row has moved on since, instead of
|
|
372
|
-
* overwriting someone else's edit. Providers without versioned writes
|
|
373
|
-
* ignore it.
|
|
374
|
-
*/
|
|
375
|
-
expectedVersion?: string | null;
|
|
376
|
-
}
|
|
377
|
-
/** Result of `update`. */
|
|
378
|
-
interface UpdateResult<T> {
|
|
379
|
-
data: T;
|
|
380
|
-
/** The row's new version token, from a provider with versioned writes. */
|
|
381
|
-
version?: string | null;
|
|
382
|
-
/** The audit entry committed with the edit, from a provider that audits. */
|
|
383
|
-
audit?: AuditEntry;
|
|
384
|
-
}
|
|
385
|
-
/** Parameters for `deleteOne`. */
|
|
386
|
-
interface DeleteParams {
|
|
387
|
-
id: Identifier;
|
|
388
|
-
/** The version token the row was read at; see `UpdateParams.expectedVersion`. */
|
|
389
|
-
expectedVersion?: string | null;
|
|
390
|
-
}
|
|
391
|
-
/** Result of `deleteOne`. */
|
|
392
|
-
interface DeleteResult {
|
|
393
|
-
data: {
|
|
394
|
-
id: Identifier;
|
|
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;
|
|
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[];
|
|
449
|
-
interface DataProvider {
|
|
450
|
-
getList<T extends BaseRecord = BaseRecord>(resource: string, params: ListParams): Promise<ListResult<T>>;
|
|
451
|
-
getOne<T extends BaseRecord = BaseRecord>(resource: string, params: GetOneParams): Promise<GetOneResult<T>>;
|
|
452
|
-
getMany<T extends BaseRecord = BaseRecord>(resource: string, params: GetManyParams): Promise<GetManyResult<T>>;
|
|
453
|
-
create<T extends BaseRecord = BaseRecord>(resource: string, params: CreateParams<T>): Promise<CreateResult<T>>;
|
|
454
|
-
update<T extends BaseRecord = BaseRecord>(resource: string, params: UpdateParams<T>): Promise<UpdateResult<T>>;
|
|
455
|
-
deleteOne(resource: string, params: DeleteParams): Promise<DeleteResult>;
|
|
456
|
-
/**
|
|
457
|
-
* The resource's real shape for the CURRENT user: fields, key, version
|
|
458
|
-
* field, and per-field read and update rights. Fields the user may not read
|
|
459
|
-
* are omitted entirely.
|
|
460
|
-
*/
|
|
461
|
-
describe?(resource: string): Promise<ResourceSchema>;
|
|
462
|
-
/** Every resource this user may see, for a sidebar or a picker. */
|
|
463
|
-
listResources?(): Promise<ResourceSummary[]>;
|
|
464
|
-
/**
|
|
465
|
-
* What this provider can do, optionally for one resource. A UI hides the
|
|
466
|
-
* controls a provider cannot serve instead of letting them error.
|
|
467
|
-
*/
|
|
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[];
|
|
539
|
-
}
|
|
540
|
-
|
|
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 };
|
|
274
|
+
export type { AuditEntry as A, DataRow as D, FieldPermissions as F, ProviderCapabilities as P, RecordComment as R, StorageType as S, VersionField as V, FieldReference as a, FieldSchema as b, FilterOperator as c, ResourceAccess as d, ResourceContract as e, ResourceRelation as f, ResourceSchema as g, ResourceSummary as h, RowAction as i };
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { A as AuditEntry, g as ResourceSchema, h as ResourceSummary, P as ProviderCapabilities, R as RecordComment } from './types-C5bjsbxz.js';
|
|
2
|
+
|
|
3
|
+
/** Record identifier — supports both string UUIDs and numeric auto-increment IDs. */
|
|
4
|
+
type Identifier = string | number;
|
|
5
|
+
/** Base record type — all resources must have an id. */
|
|
6
|
+
type BaseRecord = {
|
|
7
|
+
id: Identifier;
|
|
8
|
+
[key: string]: unknown;
|
|
9
|
+
};
|
|
10
|
+
/** Pagination parameters (offset-based, with optional cursor for future use). */
|
|
11
|
+
interface PaginationParam {
|
|
12
|
+
page: number;
|
|
13
|
+
perPage: number;
|
|
14
|
+
cursor?: string;
|
|
15
|
+
}
|
|
16
|
+
/** Sort direction for a single field. */
|
|
17
|
+
interface SortParam {
|
|
18
|
+
field: string;
|
|
19
|
+
order: "asc" | "desc";
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Filter expressions — discriminated union by operator.
|
|
23
|
+
* Filters are AND-ed together in queries.
|
|
24
|
+
*/
|
|
25
|
+
/** Operators that compare a field against a single scalar value. */
|
|
26
|
+
interface ScalarFilter {
|
|
27
|
+
field: string;
|
|
28
|
+
operator: "eq" | "neq" | "gt" | "lt" | "gte" | "lte" | "contains";
|
|
29
|
+
value: string | number | boolean;
|
|
30
|
+
}
|
|
31
|
+
/** Operator that checks field membership in a list. */
|
|
32
|
+
interface ArrayFilter {
|
|
33
|
+
field: string;
|
|
34
|
+
operator: "in";
|
|
35
|
+
value: (string | number | boolean)[];
|
|
36
|
+
}
|
|
37
|
+
/** Operator that checks field is within a range. */
|
|
38
|
+
interface RangeFilter {
|
|
39
|
+
field: string;
|
|
40
|
+
operator: "between";
|
|
41
|
+
value: [string | number, string | number];
|
|
42
|
+
}
|
|
43
|
+
/** Operators that check for null/non-null — no value needed. */
|
|
44
|
+
interface NullFilter {
|
|
45
|
+
field: string;
|
|
46
|
+
operator: "is_null" | "is_not_null";
|
|
47
|
+
}
|
|
48
|
+
type FilterParam = ScalarFilter | ArrayFilter | RangeFilter | NullFilter;
|
|
49
|
+
/** Parameters for `getList`. */
|
|
50
|
+
interface ListParams {
|
|
51
|
+
pagination?: PaginationParam;
|
|
52
|
+
sort?: SortParam;
|
|
53
|
+
/**
|
|
54
|
+
* Sort by several fields, first one first. Wins over `sort` on a provider
|
|
55
|
+
* whose capabilities report `multiSort`; others use only `sort`.
|
|
56
|
+
*/
|
|
57
|
+
sorts?: SortParam[];
|
|
58
|
+
filters?: FilterParam[];
|
|
59
|
+
/** Supabase select syntax, e.g. "*, author:profiles(name)". Mock provider ignores this. */
|
|
60
|
+
select?: string;
|
|
61
|
+
/** Multi-field text search (case-insensitive). */
|
|
62
|
+
search?: {
|
|
63
|
+
query: string;
|
|
64
|
+
fields: string[];
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** Result of `getList`. */
|
|
68
|
+
interface ListResult<T> {
|
|
69
|
+
data: T[];
|
|
70
|
+
total: number;
|
|
71
|
+
}
|
|
72
|
+
/** Parameters for `getOne`. */
|
|
73
|
+
interface GetOneParams {
|
|
74
|
+
id: Identifier;
|
|
75
|
+
/** Supabase select syntax, e.g. "*, author:profiles(name)". Defaults to "*". */
|
|
76
|
+
select?: string;
|
|
77
|
+
}
|
|
78
|
+
/** Result of `getOne`. */
|
|
79
|
+
interface GetOneResult<T> {
|
|
80
|
+
data: T;
|
|
81
|
+
}
|
|
82
|
+
/** Parameters for `getMany`. */
|
|
83
|
+
interface GetManyParams {
|
|
84
|
+
ids: Identifier[];
|
|
85
|
+
}
|
|
86
|
+
/** Result of `getMany`. */
|
|
87
|
+
interface GetManyResult<T> {
|
|
88
|
+
data: T[];
|
|
89
|
+
}
|
|
90
|
+
/** Parameters for `create`. */
|
|
91
|
+
interface CreateParams<T> {
|
|
92
|
+
data: Partial<T>;
|
|
93
|
+
}
|
|
94
|
+
/** Result of `create`. */
|
|
95
|
+
interface CreateResult<T> {
|
|
96
|
+
data: T;
|
|
97
|
+
/** The audit entry committed with the new row, from a provider that audits. */
|
|
98
|
+
audit?: AuditEntry;
|
|
99
|
+
}
|
|
100
|
+
/** Parameters for `update`. */
|
|
101
|
+
interface UpdateParams<T> {
|
|
102
|
+
/**
|
|
103
|
+
* The record's identifier. For a composite key, the canonical string from
|
|
104
|
+
* `encodeRecordKey` (`@marktiderman/genesis-core/schema`).
|
|
105
|
+
*/
|
|
106
|
+
id: Identifier;
|
|
107
|
+
data: Partial<T>;
|
|
108
|
+
/**
|
|
109
|
+
* The version token the caller read the row at. A provider that reports
|
|
110
|
+
* `versionedWrites` in its capabilities rejects the update with a
|
|
111
|
+
* `DataWriteError` (`conflict`) when the row has moved on since, instead of
|
|
112
|
+
* overwriting someone else's edit. Providers without versioned writes
|
|
113
|
+
* ignore it.
|
|
114
|
+
*/
|
|
115
|
+
expectedVersion?: string | null;
|
|
116
|
+
}
|
|
117
|
+
/** Result of `update`. */
|
|
118
|
+
interface UpdateResult<T> {
|
|
119
|
+
data: T;
|
|
120
|
+
/** The row's new version token, from a provider with versioned writes. */
|
|
121
|
+
version?: string | null;
|
|
122
|
+
/** The audit entry committed with the edit, from a provider that audits. */
|
|
123
|
+
audit?: AuditEntry;
|
|
124
|
+
}
|
|
125
|
+
/** Parameters for `deleteOne`. */
|
|
126
|
+
interface DeleteParams {
|
|
127
|
+
id: Identifier;
|
|
128
|
+
/** The version token the row was read at; see `UpdateParams.expectedVersion`. */
|
|
129
|
+
expectedVersion?: string | null;
|
|
130
|
+
}
|
|
131
|
+
/** Result of `deleteOne`. */
|
|
132
|
+
interface DeleteResult {
|
|
133
|
+
data: {
|
|
134
|
+
id: Identifier;
|
|
135
|
+
};
|
|
136
|
+
/** The audit entry committed with the deletion, from a provider that audits. */
|
|
137
|
+
audit?: AuditEntry;
|
|
138
|
+
}
|
|
139
|
+
/** One row's change in a bulk update. */
|
|
140
|
+
interface BulkChange {
|
|
141
|
+
id: Identifier;
|
|
142
|
+
data: Record<string, unknown>;
|
|
143
|
+
/** The version token the row was read at. */
|
|
144
|
+
expectedVersion?: string | null;
|
|
145
|
+
}
|
|
146
|
+
/** Why one row of a bulk write or import didn't go through. */
|
|
147
|
+
interface RowFailure {
|
|
148
|
+
/** The row's position in the request, from 0. */
|
|
149
|
+
index: number;
|
|
150
|
+
id?: Identifier;
|
|
151
|
+
outcome: string;
|
|
152
|
+
message: string;
|
|
153
|
+
}
|
|
154
|
+
/** Result of a bulk write: every row changed, or none did. */
|
|
155
|
+
interface BulkResult {
|
|
156
|
+
/** Rows changed; always the number requested when `ok`. */
|
|
157
|
+
count: number;
|
|
158
|
+
ok: boolean;
|
|
159
|
+
/** Present when `ok` is false: every row that failed, so the caller can fix them all at once. */
|
|
160
|
+
failures?: RowFailure[];
|
|
161
|
+
/** One audit entry per row changed. */
|
|
162
|
+
audit?: AuditEntry[];
|
|
163
|
+
}
|
|
164
|
+
/** Parameters for `importRows`. */
|
|
165
|
+
interface ImportParams {
|
|
166
|
+
rows: Record<string, unknown>[];
|
|
167
|
+
/** Check every row against the database and change nothing. */
|
|
168
|
+
dryRun: boolean;
|
|
169
|
+
}
|
|
170
|
+
/** Parameters for `history`. */
|
|
171
|
+
interface HistoryParams {
|
|
172
|
+
id: Identifier;
|
|
173
|
+
/** Most recent first; default and maximum are the provider's. */
|
|
174
|
+
limit?: number;
|
|
175
|
+
}
|
|
176
|
+
/** A write that committed, as passed to a provider's `onWrite` and `invalidates`. */
|
|
177
|
+
interface WriteEvent {
|
|
178
|
+
resource: string;
|
|
179
|
+
kind: "create" | "update" | "delete";
|
|
180
|
+
id: Identifier;
|
|
181
|
+
/** The row as written, when the provider has it (not for a delete). */
|
|
182
|
+
record?: BaseRecord;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* A cache key to invalidate after a write. Shaped like a TanStack Query
|
|
186
|
+
* `QueryKey` (`readonly unknown[]`), matched by prefix.
|
|
187
|
+
*/
|
|
188
|
+
type InvalidationKey = readonly unknown[];
|
|
189
|
+
interface DataProvider {
|
|
190
|
+
getList<T extends BaseRecord = BaseRecord>(resource: string, params: ListParams): Promise<ListResult<T>>;
|
|
191
|
+
getOne<T extends BaseRecord = BaseRecord>(resource: string, params: GetOneParams): Promise<GetOneResult<T>>;
|
|
192
|
+
getMany<T extends BaseRecord = BaseRecord>(resource: string, params: GetManyParams): Promise<GetManyResult<T>>;
|
|
193
|
+
create<T extends BaseRecord = BaseRecord>(resource: string, params: CreateParams<T>): Promise<CreateResult<T>>;
|
|
194
|
+
update<T extends BaseRecord = BaseRecord>(resource: string, params: UpdateParams<T>): Promise<UpdateResult<T>>;
|
|
195
|
+
deleteOne(resource: string, params: DeleteParams): Promise<DeleteResult>;
|
|
196
|
+
/**
|
|
197
|
+
* The resource's real shape for the CURRENT user: fields, key, version
|
|
198
|
+
* field, and per-field read and update rights. Fields the user may not read
|
|
199
|
+
* are omitted entirely.
|
|
200
|
+
*/
|
|
201
|
+
describe?(resource: string): Promise<ResourceSchema>;
|
|
202
|
+
/** Every resource this user may see, for a sidebar or a picker. */
|
|
203
|
+
listResources?(): Promise<ResourceSummary[]>;
|
|
204
|
+
/**
|
|
205
|
+
* What this provider can do, optionally for one resource. A UI hides the
|
|
206
|
+
* controls a provider cannot serve instead of letting them error.
|
|
207
|
+
*/
|
|
208
|
+
capabilities?(resource?: string): Promise<ProviderCapabilities>;
|
|
209
|
+
/**
|
|
210
|
+
* A record's audit history, most recent first, limited to the fields this
|
|
211
|
+
* user may read.
|
|
212
|
+
*/
|
|
213
|
+
history?(resource: string, params: HistoryParams): Promise<AuditEntry[]>;
|
|
214
|
+
/**
|
|
215
|
+
* Update many rows in ONE transaction. All of them change or none do: a
|
|
216
|
+
* single conflict, refusal or invalid value rolls back the rest, and the
|
|
217
|
+
* result lists every row that failed.
|
|
218
|
+
*/
|
|
219
|
+
updateMany?(resource: string, params: {
|
|
220
|
+
changes: BulkChange[];
|
|
221
|
+
}): Promise<BulkResult>;
|
|
222
|
+
/** Delete many rows in one transaction, all or none, each at its version. */
|
|
223
|
+
deleteMany?(resource: string, params: {
|
|
224
|
+
items: {
|
|
225
|
+
id: Identifier;
|
|
226
|
+
expectedVersion?: string | null;
|
|
227
|
+
}[];
|
|
228
|
+
}): Promise<BulkResult>;
|
|
229
|
+
/**
|
|
230
|
+
* Add rows from an import. With `dryRun`, every row is tried against the
|
|
231
|
+
* database and nothing is kept, so the result lists every row that would
|
|
232
|
+
* fail; without it, all rows are added in one transaction or none are.
|
|
233
|
+
*/
|
|
234
|
+
importRows?(resource: string, params: ImportParams): Promise<BulkResult>;
|
|
235
|
+
/**
|
|
236
|
+
* Undo one audited change with a compensating write: put the changed
|
|
237
|
+
* fields back, remove an added row, or restore a deleted one. Refused when
|
|
238
|
+
* the row has changed since.
|
|
239
|
+
*/
|
|
240
|
+
undo?(resource: string, params: {
|
|
241
|
+
auditId: string;
|
|
242
|
+
}): Promise<{
|
|
243
|
+
audit?: AuditEntry;
|
|
244
|
+
}>;
|
|
245
|
+
/**
|
|
246
|
+
* Run one of the resource's row actions (`ResourceSchema.actions`) on a
|
|
247
|
+
* row, at the version it was read. The app's function does the work; the
|
|
248
|
+
* row's change is audited.
|
|
249
|
+
*/
|
|
250
|
+
runAction?(resource: string, params: {
|
|
251
|
+
id: Identifier;
|
|
252
|
+
action: string;
|
|
253
|
+
expectedVersion?: string | null;
|
|
254
|
+
}): Promise<{
|
|
255
|
+
data: Record<string, unknown> | null;
|
|
256
|
+
audit?: AuditEntry;
|
|
257
|
+
}>;
|
|
258
|
+
/** A record's comments, oldest first. */
|
|
259
|
+
comments?(resource: string, params: {
|
|
260
|
+
id: Identifier;
|
|
261
|
+
}): Promise<RecordComment[]>;
|
|
262
|
+
/** Add a comment to a record, as the signed-in user. */
|
|
263
|
+
addComment?(resource: string, params: {
|
|
264
|
+
id: Identifier;
|
|
265
|
+
body: string;
|
|
266
|
+
}): Promise<RecordComment>;
|
|
267
|
+
/**
|
|
268
|
+
* Maps a stored row to the values an edit form starts from, for a resource
|
|
269
|
+
* whose form shape differs from its table (the reverse of a write's
|
|
270
|
+
* `prepare`). `useResourceForm` applies it in edit mode.
|
|
271
|
+
*/
|
|
272
|
+
toFormValues?(resource: string, record: Record<string, unknown>): Record<string, unknown>;
|
|
273
|
+
/**
|
|
274
|
+
* Other cache keys a committed write makes stale, beyond the resource's
|
|
275
|
+
* own `[resource]` keys. `useResource` and `useResourceForm` invalidate
|
|
276
|
+
* them after their writes.
|
|
277
|
+
*/
|
|
278
|
+
invalidates?(event: WriteEvent): InvalidationKey[];
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export type { ArrayFilter as A, BaseRecord as B, CreateParams as C, DataProvider as D, FilterParam as F, GetManyParams as G, HistoryParams as H, Identifier as I, ListParams as L, NullFilter as N, PaginationParam as P, RangeFilter as R, ScalarFilter as S, UpdateParams as U, WriteEvent as W, BulkChange as a, BulkResult as b, CreateResult as c, DeleteParams as d, DeleteResult as e, GetManyResult as f, GetOneParams as g, GetOneResult as h, ImportParams as i, InvalidationKey as j, ListResult as k, RowFailure as l, SortParam as m, UpdateResult as n };
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schema/write-outcome.ts"],"names":[],"mappings":";AAgDO,IAAM,cAAA,GAAN,cAA6B,KAAA,CAAM;AAAA,EAC/B,OAAA;AAAA,EACA,OAAA;AAAA,EACA,cAAA;AAAA;AAAA,EAEA,IAAA;AAAA,EAET,WAAA,CAAY,OAAA,EAAuB,OAAA,EAAiB,OAAA,GAAiC,EAAC,EAAG;AACvF,IAAA,KAAA,CAAM,OAAA,EAAS,QAAQ,KAAA,KAAU,MAAA,GAAY,SAAY,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAO,CAAA;AACjF,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AACZ,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,IAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,OAAA;AACvB,IAAA,IAAA,CAAK,iBAAiB,OAAA,CAAQ,cAAA;AAC9B,IAAA,IAAI,OAAA,CAAQ,IAAA,KAAS,MAAA,EAAW,IAAA,CAAK,OAAO,OAAA,CAAQ,IAAA;AAAA,EACtD;AACF;AAMO,SAAS,iBAAiB,KAAA,EAAyC;AACxE,EAAA,OACE,iBAAiB,KAAA,IACjB,KAAA,CAAM,SAAS,gBAAA,IACf,OAAQ,MAAgC,OAAA,KAAY,QAAA;AAExD","file":"chunk-6MBACQYA.js","sourcesContent":["// ---------------------------------------------------------------------------\n// Why a write did not save (DATA-STUDIO.md \"Write safety\")\n//\n// A write that changes nothing is never reported as \"permission denied\" by\n// assumption. The provider re-reads the row and says what actually happened.\n// ---------------------------------------------------------------------------\n\nimport type { DataRow } from \"./types\";\n\n/**\n * - `conflict`: someone else changed the row since it was read. `current`\n * carries the row as it is now.\n * - `gone`: the row was deleted, or is no longer visible to this user. The\n * two cannot be told apart without a privileged look at the table, which\n * would show this user a fact about a row they cannot see.\n * - `forbidden`: the row is visible and unchanged, but the app or the\n * database does not let this user make this change. Only reported when\n * that is proven, never assumed from \"zero rows changed\".\n * - `invalid`: the store rejected the value (type, constraint, not-null).\n * - `audit_failed`: the audit entry could not be written, so the edit was\n * rolled back with it.\n * - `unauthenticated`: no signed-in user, or the session expired.\n * - `error`: anything else. The edit did not commit.\n */\nexport type WriteOutcome =\n | \"conflict\"\n | \"gone\"\n | \"forbidden\"\n | \"invalid\"\n | \"audit_failed\"\n | \"unauthenticated\"\n | \"error\";\n\nexport interface DataWriteErrorOptions {\n /** The row as it is now, for a `conflict`. Only fields the user may read. */\n current?: DataRow;\n /** The row's current version token, for a `conflict`. */\n currentVersion?: string | null;\n /**\n * The store's own error code, when it gave one (a Postgres SQLSTATE such as\n * `23505`, or a PostgREST code such as `PGRST301`).\n */\n code?: string;\n /** The underlying error, kept for logging. */\n cause?: unknown;\n}\n\n/** Thrown by a provider when a write did not commit. */\nexport class DataWriteError extends Error {\n readonly outcome: WriteOutcome;\n readonly current?: DataRow;\n readonly currentVersion?: string | null;\n /** The store's own error code, when it gave one. */\n readonly code?: string;\n\n constructor(outcome: WriteOutcome, message: string, options: DataWriteErrorOptions = {}) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.name = \"DataWriteError\";\n this.outcome = outcome;\n this.current = options.current;\n this.currentVersion = options.currentVersion;\n if (options.code !== undefined) this.code = options.code;\n }\n}\n\n/**\n * `instanceof` fails when two copies of this package are installed, so check\n * the shape instead.\n */\nexport function isDataWriteError(error: unknown): error is DataWriteError {\n return (\n error instanceof Error &&\n error.name === \"DataWriteError\" &&\n typeof (error as { outcome?: unknown }).outcome === \"string\"\n );\n}\n"]}
|
package/dist/chunk-EL7YGOTY.js
DELETED