@ai-matrx/data 0.23.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/README.md +34 -0
- package/bin/emit.mjs +32 -7
- package/bin/generate.mjs +38 -8
- package/bin/matrx-data.mjs +6 -4
- package/description/admin.json.gz +0 -0
- package/description/agent.json.gz +0 -0
- package/description/ai.json.gz +0 -0
- package/description/api.json.gz +0 -0
- package/description/app.json.gz +0 -0
- package/description/assignment.json.gz +0 -0
- package/description/audit.json.gz +0 -0
- package/description/batch.json.gz +0 -0
- package/description/billing.json.gz +0 -0
- package/description/browser.json.gz +0 -0
- package/description/canvas.json.gz +0 -0
- package/description/chat.json.gz +0 -0
- package/description/code.json.gz +0 -0
- package/description/commerce.json.gz +0 -0
- package/description/communication.json.gz +0 -0
- package/description/content.json.gz +0 -0
- package/description/content_ir.json.gz +0 -0
- package/description/context.json.gz +0 -0
- package/description/crm.json.gz +0 -0
- package/description/custom.json.gz +0 -0
- package/description/dictionary.json.gz +0 -0
- package/description/docproc.json.gz +0 -0
- package/description/education.json.gz +0 -0
- package/description/esign.json.gz +0 -0
- package/description/extend.json.gz +0 -0
- package/description/files.json.gz +0 -0
- package/description/growth.json.gz +0 -0
- package/description/hindsight.json.gz +0 -0
- package/description/history.json.gz +0 -0
- package/description/iam.json.gz +0 -0
- package/description/index.json.gz +0 -0
- package/description/interview.json.gz +0 -0
- package/description/knowledge.json.gz +0 -0
- package/description/legal.json.gz +0 -0
- package/description/mandate.json.gz +0 -0
- package/description/marketing.json.gz +0 -0
- package/description/media.json.gz +0 -0
- package/description/meta.json.gz +0 -0
- package/description/ops.json.gz +0 -0
- package/description/pdf.json.gz +0 -0
- package/description/plan.json.gz +0 -0
- package/description/platform.json.gz +0 -0
- package/description/podcast.json.gz +0 -0
- package/description/projects.json.gz +0 -0
- package/description/public.json.gz +0 -0
- package/description/rag.json.gz +0 -0
- package/description/research.json.gz +0 -0
- package/description/runtime.json.gz +0 -0
- package/description/scheduler.json.gz +0 -0
- package/description/scraper.json.gz +0 -0
- package/description/seo.json.gz +0 -0
- package/description/skill.json.gz +0 -0
- package/description/social.json.gz +0 -0
- package/description/tool.json.gz +0 -0
- package/description/transcripts.json.gz +0 -0
- package/description/ui.json.gz +0 -0
- package/description/users.json.gz +0 -0
- package/description/web.json.gz +0 -0
- package/description/work.json.gz +0 -0
- package/description/workbench.json.gz +0 -0
- package/description/workflow.json.gz +0 -0
- package/dist/db.cjs +71 -29
- package/dist/db.cjs.map +1 -1
- package/dist/db.d.cts +92 -33
- package/dist/db.d.ts +92 -33
- package/dist/db.js +71 -29
- package/dist/db.js.map +1 -1
- package/package.json +5 -4
package/dist/db.d.cts
CHANGED
|
@@ -842,6 +842,12 @@ interface TableDescriptor<Row = Record<string, unknown>, Insert = Record<string,
|
|
|
842
842
|
readonly readOnlyColumns: readonly string[];
|
|
843
843
|
readonly listScope: string | null;
|
|
844
844
|
readonly realtime: boolean;
|
|
845
|
+
/**
|
|
846
|
+
* The table has a `created_by` column. A signed-in insert that omits it is stamped with the
|
|
847
|
+
* session's person (row security on tables like `workbench.notes` refuses an insert whose
|
|
848
|
+
* `created_by` is not `auth.uid()`). Optional: descriptors generated before 0.25.0 lack it.
|
|
849
|
+
*/
|
|
850
|
+
readonly createdBy?: boolean;
|
|
845
851
|
readonly [ROW]?: {
|
|
846
852
|
row: Row;
|
|
847
853
|
insert: Insert;
|
|
@@ -884,6 +890,7 @@ interface QueryLike extends PromiseLike<Resp<any>> {
|
|
|
884
890
|
update(values: unknown): QueryLike;
|
|
885
891
|
delete(): QueryLike;
|
|
886
892
|
eq(column: string, value: unknown): QueryLike;
|
|
893
|
+
is(column: string, value: null | boolean): QueryLike;
|
|
887
894
|
order(column: string, opts?: {
|
|
888
895
|
ascending?: boolean;
|
|
889
896
|
}): QueryLike;
|
|
@@ -902,6 +909,9 @@ interface SupabaseLike {
|
|
|
902
909
|
data: {
|
|
903
910
|
session: {
|
|
904
911
|
access_token: string;
|
|
912
|
+
user?: {
|
|
913
|
+
id: string;
|
|
914
|
+
} | null;
|
|
905
915
|
} | null;
|
|
906
916
|
};
|
|
907
917
|
}>;
|
|
@@ -958,74 +968,123 @@ declare class DatabaseError extends Error {
|
|
|
958
968
|
type Op = "read" | "insert" | "update" | "remove" | "archive";
|
|
959
969
|
/** Refuse before the wire when the descriptor's rules do not open this door. */
|
|
960
970
|
declare function assertDoor(db: Db, table: TableDescriptor<any, any, any>, op: Op): void;
|
|
971
|
+
type Col<R> = Extract<keyof R, string>;
|
|
972
|
+
/** The typed filter a `Where` callback receives — column names and values checked against the row. */
|
|
973
|
+
interface Filter<R> {
|
|
974
|
+
eq<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;
|
|
975
|
+
neq<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;
|
|
976
|
+
gt<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;
|
|
977
|
+
gte<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;
|
|
978
|
+
lt<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;
|
|
979
|
+
lte<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;
|
|
980
|
+
like(column: Col<R>, pattern: string): Filter<R>;
|
|
981
|
+
ilike(column: Col<R>, pattern: string): Filter<R>;
|
|
982
|
+
in<K extends Col<R>>(column: K, values: readonly NonNullable<R[K]>[]): Filter<R>;
|
|
983
|
+
is(column: Col<R>, value: null | boolean): Filter<R>;
|
|
984
|
+
contains(column: Col<R>, value: unknown): Filter<R>;
|
|
985
|
+
overlaps(column: Col<R>, value: unknown): Filter<R>;
|
|
986
|
+
textSearch(column: Col<R>, query: string, opts?: {
|
|
987
|
+
type?: "plain" | "phrase" | "websearch";
|
|
988
|
+
config?: string;
|
|
989
|
+
}): Filter<R>;
|
|
990
|
+
/** PostgREST's raw `or` grammar (`"pinned.eq.true,starred.eq.true"`). */
|
|
991
|
+
or(filters: string, opts?: {
|
|
992
|
+
referencedTable?: string;
|
|
993
|
+
}): Filter<R>;
|
|
994
|
+
not(column: Col<R>, operator: string, value: unknown): Filter<R>;
|
|
995
|
+
}
|
|
996
|
+
/** A filter callback — the same builder `readAllRows` callers write today, typed to the row. */
|
|
997
|
+
type Where<R = any> = (q: Filter<R>) => Filter<R>;
|
|
998
|
+
interface ReadOptions<C> {
|
|
999
|
+
/** Only these columns (the result is typed to them). Default every column. */
|
|
1000
|
+
columns?: readonly C[];
|
|
1001
|
+
/** Include soft-deleted rows (default: excluded on tables with `deleted_at`). */
|
|
1002
|
+
includeDeleted?: boolean;
|
|
1003
|
+
}
|
|
961
1004
|
/** One row by primary key (a composite key takes `{ col: value }`), or null. */
|
|
962
|
-
declare function read<
|
|
963
|
-
/**
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
declare function listAll<T extends TableDescriptor<any, any, any>>(db: Db, table: T, where?: Where, opts?: {
|
|
967
|
-
columns?: string;
|
|
968
|
-
orderBy?: string;
|
|
1005
|
+
declare function read<R, I, U, C extends Col<R> = Col<R>>(db: Db, table: TableDescriptor<R, I, U>, id: unknown, opts?: ReadOptions<C>): Promise<Pick<R, C> | null>;
|
|
1006
|
+
/** EVERY matching row, paged past the 1,000-row cap (ordered by the full key); throws on a short read. */
|
|
1007
|
+
declare function listAll<R, I, U, C extends Col<R> = Col<R>>(db: Db, table: TableDescriptor<R, I, U>, where?: Where<R>, opts?: ReadOptions<C> & {
|
|
1008
|
+
orderBy?: Col<R>;
|
|
969
1009
|
pageSize?: number;
|
|
970
1010
|
maxRows?: number;
|
|
971
|
-
}): Promise<
|
|
1011
|
+
}): Promise<Pick<R, C>[]>;
|
|
972
1012
|
/** One explicit window (`from`..`to`, inclusive) plus the exact total. */
|
|
973
|
-
declare function page<
|
|
1013
|
+
declare function page<R, I, U, C extends Col<R> = Col<R>>(db: Db, table: TableDescriptor<R, I, U>, window: ReadOptions<C> & {
|
|
974
1014
|
from: number;
|
|
975
1015
|
to: number;
|
|
976
|
-
where?: Where
|
|
977
|
-
|
|
978
|
-
orderBy?: string;
|
|
1016
|
+
where?: Where<R>;
|
|
1017
|
+
orderBy?: Col<R>;
|
|
979
1018
|
ascending?: boolean;
|
|
980
1019
|
}): Promise<{
|
|
981
|
-
rows:
|
|
1020
|
+
rows: Pick<R, C>[];
|
|
982
1021
|
total: number | null;
|
|
983
1022
|
}>;
|
|
984
1023
|
/** The exact count of matching rows (no rows transferred). */
|
|
985
|
-
declare function count<
|
|
1024
|
+
declare function count<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, where?: Where<R>, opts?: {
|
|
1025
|
+
includeDeleted?: boolean;
|
|
1026
|
+
}): Promise<number>;
|
|
986
1027
|
/** Insert one row (or many) and return what the database stored. */
|
|
987
|
-
declare function insert<
|
|
988
|
-
declare function insert<
|
|
1028
|
+
declare function insert<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, values: I): Promise<R>;
|
|
1029
|
+
declare function insert<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, values: readonly I[]): Promise<R[]>;
|
|
1030
|
+
/** Every write on a versioned table is explicit: `{ expectedVersion }` (guarded) or `{ overwrite: true }`. */
|
|
989
1031
|
type UpdateGuard = {
|
|
990
1032
|
expectedVersion: number;
|
|
991
1033
|
} | {
|
|
992
1034
|
overwrite: true;
|
|
993
1035
|
};
|
|
1036
|
+
type WriteResult<R> = {
|
|
1037
|
+
status: "saved";
|
|
1038
|
+
row: R;
|
|
1039
|
+
rebasedFrom?: {
|
|
1040
|
+
expectedVersion: number;
|
|
1041
|
+
currentVersion: number;
|
|
1042
|
+
};
|
|
1043
|
+
} | {
|
|
1044
|
+
status: "conflict";
|
|
1045
|
+
currentRow: R;
|
|
1046
|
+
currentVersion: number;
|
|
1047
|
+
} | {
|
|
1048
|
+
status: "not_found";
|
|
1049
|
+
};
|
|
994
1050
|
/**
|
|
995
1051
|
* Update one row by primary key. On a versioned table the guard is required:
|
|
996
1052
|
* `{ expectedVersion }` (a conflict comes back, never a silent overwrite) or
|
|
997
|
-
* `{ overwrite: true }
|
|
1053
|
+
* `{ overwrite: true }`; on an unversioned table `expectedVersion` is refused.
|
|
998
1054
|
*/
|
|
999
|
-
declare function update<
|
|
1000
|
-
version: number;
|
|
1001
|
-
}> | {
|
|
1002
|
-
status: "saved";
|
|
1003
|
-
row: RowOf<T>;
|
|
1004
|
-
} | {
|
|
1005
|
-
status: "not_found";
|
|
1006
|
-
}>;
|
|
1055
|
+
declare function update<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, id: unknown, patch: U, guard?: UpdateGuard): Promise<WriteResult<R>>;
|
|
1007
1056
|
/**
|
|
1008
1057
|
* Remove one row the way the table removes: soft delete (`deleted_at`) where it
|
|
1009
1058
|
* has one; an archive-only table refuses (use `archive`); a hard delete only where
|
|
1010
|
-
* the table has neither.
|
|
1059
|
+
* the table has neither. Guarded like `update` on a versioned table.
|
|
1011
1060
|
*/
|
|
1012
|
-
declare function remove<
|
|
1013
|
-
|
|
1014
|
-
|
|
1061
|
+
declare function remove<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, id: unknown, guard?: UpdateGuard): Promise<{
|
|
1062
|
+
status: "soft_deleted" | "deleted" | "not_found";
|
|
1063
|
+
} | {
|
|
1064
|
+
status: "conflict";
|
|
1065
|
+
currentVersion: number;
|
|
1066
|
+
}>;
|
|
1067
|
+
/** Archive (or, with `restore`, bring back) one row by the table's archive column. Guarded like `update`. */
|
|
1068
|
+
declare function archive<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, id: unknown, opts?: {
|
|
1015
1069
|
restore?: boolean;
|
|
1016
|
-
|
|
1070
|
+
guard?: UpdateGuard;
|
|
1071
|
+
}): Promise<WriteResult<R>>;
|
|
1017
1072
|
/** Bring back an archived or soft-deleted row. */
|
|
1018
|
-
declare const restore: <
|
|
1073
|
+
declare const restore: <R, I, U>(db: Db, table: TableDescriptor<R, I, U>, id: unknown, guard?: UpdateGuard) => Promise<WriteResult<R>>;
|
|
1019
1074
|
/** Call a database function through its generated door (PostgREST chooses an overload by argument names). */
|
|
1020
1075
|
declare function call<F extends FunctionDescriptor<any, any>>(db: Db, fn: F, args: ArgsOf<F>): Promise<ResultOf<F>>;
|
|
1021
|
-
/**
|
|
1076
|
+
/** One schema's flags (`<schema>.flags.ts` from `matrx-data generate --flags-index`): "schema.table" → descriptor. */
|
|
1022
1077
|
type FlagsIndex = Readonly<Record<string, TableDescriptor>>;
|
|
1078
|
+
/** Per-schema loaders (`flags-index.ts`): only the schema a runtime name names is loaded (pay-only). */
|
|
1079
|
+
type FlagLoaders = Readonly<Record<string, () => Promise<FlagsIndex>>>;
|
|
1023
1080
|
/** The door for a table whose name arrives at runtime — loosely typed, the same rules. */
|
|
1024
1081
|
declare function tableByName(index: FlagsIndex, name: string): TableDescriptor;
|
|
1082
|
+
/** `tableByName` over per-schema loaders: loads only the named schema's flags. */
|
|
1083
|
+
declare function loadTableByName(loaders: FlagLoaders, name: string): Promise<TableDescriptor>;
|
|
1025
1084
|
/** The `postgres_changes` filter for a table — only published tables have one (an unpublished table delivers nothing). */
|
|
1026
1085
|
declare function changesOf(table: TableDescriptor<any, any, any>): {
|
|
1027
1086
|
schema: string;
|
|
1028
1087
|
table: string;
|
|
1029
1088
|
};
|
|
1030
1089
|
|
|
1031
|
-
export { type ActiveOrgCookie, type ActiveOrgCookieOptions, type ActiveOrgSelection, type ArgsOf, type AuthRetryableResult, BulkWriteError, type CreateActiveOrgCookieArgs, type CreateDbOptions, type CreateOAuthRefreshFetchArgs, type CreateSessionRetryOptions, DEFAULT_ACTIVE_ORG_COOKIE_MAX_AGE, DEFAULT_ACTIVE_ORG_COOKIE_NAME, DatabaseError, type Db, DoorRefusedError, type FlagsIndex, type FunctionDescriptor, type GuardedUpdateArgs, type GuardedUpdateResult, IncompleteReadError, type InsertOf, type JsonObject, type MergeJsonColumnArgs, type MergeJsonColumnResult, type OAuthRefreshStorage, type OrgRule, type PagedReadQuery, type PagedReadResult, type QueryLike, type ReadAllRowsOptions, type ReadAllRowsRestOptions, RecordUnavailableError, type RecordUnavailableReason, type RecordUnavailableResolution, type ResultOf, type RowOf, type SessionSource, SessionUnavailableError, type SupabaseLike, type TableDescriptor, type TableType, type TryWriteOneResult, type UpdateGuard, type UpdateOf, type UserCredentialsPort, type VersionedRow, type Where, WriteDidNotLandError, type WriteDidNotLandReason, type WriteFailureWords, type WriteOneAction, type WriteOneOptions, type WriteOneRowResult, WriteRefusedError, archive, asJsonObject, assertDoor, assertWriteLanded, call, changesOf, count, createActiveOrgCookie, createDb, createOAuthRefreshFetch, createServiceDb, createSessionRetry, decodeActiveOrgSelection, decodeOAuthRefreshClaims, describeWriteFailure, encodeActiveOrgSelection, guardedUpdate, insert, isMissingSessionError, isRecordUnavailableError, listAll, mergeJsonColumn, page, personSentence, read, readAllRows, readAllRowsRest, recordUnavailableMessage, remove, restore, serverMessageFromBody, tableByName, tryReadAllRows, tryReadAllRowsRest, tryWriteOne, update, writeFailureStatus, writeOne, writeOneRow };
|
|
1090
|
+
export { type ActiveOrgCookie, type ActiveOrgCookieOptions, type ActiveOrgSelection, type ArgsOf, type AuthRetryableResult, BulkWriteError, type CreateActiveOrgCookieArgs, type CreateDbOptions, type CreateOAuthRefreshFetchArgs, type CreateSessionRetryOptions, DEFAULT_ACTIVE_ORG_COOKIE_MAX_AGE, DEFAULT_ACTIVE_ORG_COOKIE_NAME, DatabaseError, type Db, DoorRefusedError, type Filter, type FlagLoaders, type FlagsIndex, type FunctionDescriptor, type GuardedUpdateArgs, type GuardedUpdateResult, IncompleteReadError, type InsertOf, type JsonObject, type MergeJsonColumnArgs, type MergeJsonColumnResult, type OAuthRefreshStorage, type OrgRule, type PagedReadQuery, type PagedReadResult, type QueryLike, type ReadAllRowsOptions, type ReadAllRowsRestOptions, type ReadOptions, RecordUnavailableError, type RecordUnavailableReason, type RecordUnavailableResolution, type ResultOf, type RowOf, type SessionSource, SessionUnavailableError, type SupabaseLike, type TableDescriptor, type TableType, type TryWriteOneResult, type UpdateGuard, type UpdateOf, type UserCredentialsPort, type VersionedRow, type Where, WriteDidNotLandError, type WriteDidNotLandReason, type WriteFailureWords, type WriteOneAction, type WriteOneOptions, type WriteOneRowResult, WriteRefusedError, type WriteResult, archive, asJsonObject, assertDoor, assertWriteLanded, call, changesOf, count, createActiveOrgCookie, createDb, createOAuthRefreshFetch, createServiceDb, createSessionRetry, decodeActiveOrgSelection, decodeOAuthRefreshClaims, describeWriteFailure, encodeActiveOrgSelection, guardedUpdate, insert, isMissingSessionError, isRecordUnavailableError, listAll, loadTableByName, mergeJsonColumn, page, personSentence, read, readAllRows, readAllRowsRest, recordUnavailableMessage, remove, restore, serverMessageFromBody, tableByName, tryReadAllRows, tryReadAllRowsRest, tryWriteOne, update, writeFailureStatus, writeOne, writeOneRow };
|
package/dist/db.d.ts
CHANGED
|
@@ -842,6 +842,12 @@ interface TableDescriptor<Row = Record<string, unknown>, Insert = Record<string,
|
|
|
842
842
|
readonly readOnlyColumns: readonly string[];
|
|
843
843
|
readonly listScope: string | null;
|
|
844
844
|
readonly realtime: boolean;
|
|
845
|
+
/**
|
|
846
|
+
* The table has a `created_by` column. A signed-in insert that omits it is stamped with the
|
|
847
|
+
* session's person (row security on tables like `workbench.notes` refuses an insert whose
|
|
848
|
+
* `created_by` is not `auth.uid()`). Optional: descriptors generated before 0.25.0 lack it.
|
|
849
|
+
*/
|
|
850
|
+
readonly createdBy?: boolean;
|
|
845
851
|
readonly [ROW]?: {
|
|
846
852
|
row: Row;
|
|
847
853
|
insert: Insert;
|
|
@@ -884,6 +890,7 @@ interface QueryLike extends PromiseLike<Resp<any>> {
|
|
|
884
890
|
update(values: unknown): QueryLike;
|
|
885
891
|
delete(): QueryLike;
|
|
886
892
|
eq(column: string, value: unknown): QueryLike;
|
|
893
|
+
is(column: string, value: null | boolean): QueryLike;
|
|
887
894
|
order(column: string, opts?: {
|
|
888
895
|
ascending?: boolean;
|
|
889
896
|
}): QueryLike;
|
|
@@ -902,6 +909,9 @@ interface SupabaseLike {
|
|
|
902
909
|
data: {
|
|
903
910
|
session: {
|
|
904
911
|
access_token: string;
|
|
912
|
+
user?: {
|
|
913
|
+
id: string;
|
|
914
|
+
} | null;
|
|
905
915
|
} | null;
|
|
906
916
|
};
|
|
907
917
|
}>;
|
|
@@ -958,74 +968,123 @@ declare class DatabaseError extends Error {
|
|
|
958
968
|
type Op = "read" | "insert" | "update" | "remove" | "archive";
|
|
959
969
|
/** Refuse before the wire when the descriptor's rules do not open this door. */
|
|
960
970
|
declare function assertDoor(db: Db, table: TableDescriptor<any, any, any>, op: Op): void;
|
|
971
|
+
type Col<R> = Extract<keyof R, string>;
|
|
972
|
+
/** The typed filter a `Where` callback receives — column names and values checked against the row. */
|
|
973
|
+
interface Filter<R> {
|
|
974
|
+
eq<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;
|
|
975
|
+
neq<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;
|
|
976
|
+
gt<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;
|
|
977
|
+
gte<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;
|
|
978
|
+
lt<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;
|
|
979
|
+
lte<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;
|
|
980
|
+
like(column: Col<R>, pattern: string): Filter<R>;
|
|
981
|
+
ilike(column: Col<R>, pattern: string): Filter<R>;
|
|
982
|
+
in<K extends Col<R>>(column: K, values: readonly NonNullable<R[K]>[]): Filter<R>;
|
|
983
|
+
is(column: Col<R>, value: null | boolean): Filter<R>;
|
|
984
|
+
contains(column: Col<R>, value: unknown): Filter<R>;
|
|
985
|
+
overlaps(column: Col<R>, value: unknown): Filter<R>;
|
|
986
|
+
textSearch(column: Col<R>, query: string, opts?: {
|
|
987
|
+
type?: "plain" | "phrase" | "websearch";
|
|
988
|
+
config?: string;
|
|
989
|
+
}): Filter<R>;
|
|
990
|
+
/** PostgREST's raw `or` grammar (`"pinned.eq.true,starred.eq.true"`). */
|
|
991
|
+
or(filters: string, opts?: {
|
|
992
|
+
referencedTable?: string;
|
|
993
|
+
}): Filter<R>;
|
|
994
|
+
not(column: Col<R>, operator: string, value: unknown): Filter<R>;
|
|
995
|
+
}
|
|
996
|
+
/** A filter callback — the same builder `readAllRows` callers write today, typed to the row. */
|
|
997
|
+
type Where<R = any> = (q: Filter<R>) => Filter<R>;
|
|
998
|
+
interface ReadOptions<C> {
|
|
999
|
+
/** Only these columns (the result is typed to them). Default every column. */
|
|
1000
|
+
columns?: readonly C[];
|
|
1001
|
+
/** Include soft-deleted rows (default: excluded on tables with `deleted_at`). */
|
|
1002
|
+
includeDeleted?: boolean;
|
|
1003
|
+
}
|
|
961
1004
|
/** One row by primary key (a composite key takes `{ col: value }`), or null. */
|
|
962
|
-
declare function read<
|
|
963
|
-
/**
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
declare function listAll<T extends TableDescriptor<any, any, any>>(db: Db, table: T, where?: Where, opts?: {
|
|
967
|
-
columns?: string;
|
|
968
|
-
orderBy?: string;
|
|
1005
|
+
declare function read<R, I, U, C extends Col<R> = Col<R>>(db: Db, table: TableDescriptor<R, I, U>, id: unknown, opts?: ReadOptions<C>): Promise<Pick<R, C> | null>;
|
|
1006
|
+
/** EVERY matching row, paged past the 1,000-row cap (ordered by the full key); throws on a short read. */
|
|
1007
|
+
declare function listAll<R, I, U, C extends Col<R> = Col<R>>(db: Db, table: TableDescriptor<R, I, U>, where?: Where<R>, opts?: ReadOptions<C> & {
|
|
1008
|
+
orderBy?: Col<R>;
|
|
969
1009
|
pageSize?: number;
|
|
970
1010
|
maxRows?: number;
|
|
971
|
-
}): Promise<
|
|
1011
|
+
}): Promise<Pick<R, C>[]>;
|
|
972
1012
|
/** One explicit window (`from`..`to`, inclusive) plus the exact total. */
|
|
973
|
-
declare function page<
|
|
1013
|
+
declare function page<R, I, U, C extends Col<R> = Col<R>>(db: Db, table: TableDescriptor<R, I, U>, window: ReadOptions<C> & {
|
|
974
1014
|
from: number;
|
|
975
1015
|
to: number;
|
|
976
|
-
where?: Where
|
|
977
|
-
|
|
978
|
-
orderBy?: string;
|
|
1016
|
+
where?: Where<R>;
|
|
1017
|
+
orderBy?: Col<R>;
|
|
979
1018
|
ascending?: boolean;
|
|
980
1019
|
}): Promise<{
|
|
981
|
-
rows:
|
|
1020
|
+
rows: Pick<R, C>[];
|
|
982
1021
|
total: number | null;
|
|
983
1022
|
}>;
|
|
984
1023
|
/** The exact count of matching rows (no rows transferred). */
|
|
985
|
-
declare function count<
|
|
1024
|
+
declare function count<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, where?: Where<R>, opts?: {
|
|
1025
|
+
includeDeleted?: boolean;
|
|
1026
|
+
}): Promise<number>;
|
|
986
1027
|
/** Insert one row (or many) and return what the database stored. */
|
|
987
|
-
declare function insert<
|
|
988
|
-
declare function insert<
|
|
1028
|
+
declare function insert<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, values: I): Promise<R>;
|
|
1029
|
+
declare function insert<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, values: readonly I[]): Promise<R[]>;
|
|
1030
|
+
/** Every write on a versioned table is explicit: `{ expectedVersion }` (guarded) or `{ overwrite: true }`. */
|
|
989
1031
|
type UpdateGuard = {
|
|
990
1032
|
expectedVersion: number;
|
|
991
1033
|
} | {
|
|
992
1034
|
overwrite: true;
|
|
993
1035
|
};
|
|
1036
|
+
type WriteResult<R> = {
|
|
1037
|
+
status: "saved";
|
|
1038
|
+
row: R;
|
|
1039
|
+
rebasedFrom?: {
|
|
1040
|
+
expectedVersion: number;
|
|
1041
|
+
currentVersion: number;
|
|
1042
|
+
};
|
|
1043
|
+
} | {
|
|
1044
|
+
status: "conflict";
|
|
1045
|
+
currentRow: R;
|
|
1046
|
+
currentVersion: number;
|
|
1047
|
+
} | {
|
|
1048
|
+
status: "not_found";
|
|
1049
|
+
};
|
|
994
1050
|
/**
|
|
995
1051
|
* Update one row by primary key. On a versioned table the guard is required:
|
|
996
1052
|
* `{ expectedVersion }` (a conflict comes back, never a silent overwrite) or
|
|
997
|
-
* `{ overwrite: true }
|
|
1053
|
+
* `{ overwrite: true }`; on an unversioned table `expectedVersion` is refused.
|
|
998
1054
|
*/
|
|
999
|
-
declare function update<
|
|
1000
|
-
version: number;
|
|
1001
|
-
}> | {
|
|
1002
|
-
status: "saved";
|
|
1003
|
-
row: RowOf<T>;
|
|
1004
|
-
} | {
|
|
1005
|
-
status: "not_found";
|
|
1006
|
-
}>;
|
|
1055
|
+
declare function update<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, id: unknown, patch: U, guard?: UpdateGuard): Promise<WriteResult<R>>;
|
|
1007
1056
|
/**
|
|
1008
1057
|
* Remove one row the way the table removes: soft delete (`deleted_at`) where it
|
|
1009
1058
|
* has one; an archive-only table refuses (use `archive`); a hard delete only where
|
|
1010
|
-
* the table has neither.
|
|
1059
|
+
* the table has neither. Guarded like `update` on a versioned table.
|
|
1011
1060
|
*/
|
|
1012
|
-
declare function remove<
|
|
1013
|
-
|
|
1014
|
-
|
|
1061
|
+
declare function remove<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, id: unknown, guard?: UpdateGuard): Promise<{
|
|
1062
|
+
status: "soft_deleted" | "deleted" | "not_found";
|
|
1063
|
+
} | {
|
|
1064
|
+
status: "conflict";
|
|
1065
|
+
currentVersion: number;
|
|
1066
|
+
}>;
|
|
1067
|
+
/** Archive (or, with `restore`, bring back) one row by the table's archive column. Guarded like `update`. */
|
|
1068
|
+
declare function archive<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, id: unknown, opts?: {
|
|
1015
1069
|
restore?: boolean;
|
|
1016
|
-
|
|
1070
|
+
guard?: UpdateGuard;
|
|
1071
|
+
}): Promise<WriteResult<R>>;
|
|
1017
1072
|
/** Bring back an archived or soft-deleted row. */
|
|
1018
|
-
declare const restore: <
|
|
1073
|
+
declare const restore: <R, I, U>(db: Db, table: TableDescriptor<R, I, U>, id: unknown, guard?: UpdateGuard) => Promise<WriteResult<R>>;
|
|
1019
1074
|
/** Call a database function through its generated door (PostgREST chooses an overload by argument names). */
|
|
1020
1075
|
declare function call<F extends FunctionDescriptor<any, any>>(db: Db, fn: F, args: ArgsOf<F>): Promise<ResultOf<F>>;
|
|
1021
|
-
/**
|
|
1076
|
+
/** One schema's flags (`<schema>.flags.ts` from `matrx-data generate --flags-index`): "schema.table" → descriptor. */
|
|
1022
1077
|
type FlagsIndex = Readonly<Record<string, TableDescriptor>>;
|
|
1078
|
+
/** Per-schema loaders (`flags-index.ts`): only the schema a runtime name names is loaded (pay-only). */
|
|
1079
|
+
type FlagLoaders = Readonly<Record<string, () => Promise<FlagsIndex>>>;
|
|
1023
1080
|
/** The door for a table whose name arrives at runtime — loosely typed, the same rules. */
|
|
1024
1081
|
declare function tableByName(index: FlagsIndex, name: string): TableDescriptor;
|
|
1082
|
+
/** `tableByName` over per-schema loaders: loads only the named schema's flags. */
|
|
1083
|
+
declare function loadTableByName(loaders: FlagLoaders, name: string): Promise<TableDescriptor>;
|
|
1025
1084
|
/** The `postgres_changes` filter for a table — only published tables have one (an unpublished table delivers nothing). */
|
|
1026
1085
|
declare function changesOf(table: TableDescriptor<any, any, any>): {
|
|
1027
1086
|
schema: string;
|
|
1028
1087
|
table: string;
|
|
1029
1088
|
};
|
|
1030
1089
|
|
|
1031
|
-
export { type ActiveOrgCookie, type ActiveOrgCookieOptions, type ActiveOrgSelection, type ArgsOf, type AuthRetryableResult, BulkWriteError, type CreateActiveOrgCookieArgs, type CreateDbOptions, type CreateOAuthRefreshFetchArgs, type CreateSessionRetryOptions, DEFAULT_ACTIVE_ORG_COOKIE_MAX_AGE, DEFAULT_ACTIVE_ORG_COOKIE_NAME, DatabaseError, type Db, DoorRefusedError, type FlagsIndex, type FunctionDescriptor, type GuardedUpdateArgs, type GuardedUpdateResult, IncompleteReadError, type InsertOf, type JsonObject, type MergeJsonColumnArgs, type MergeJsonColumnResult, type OAuthRefreshStorage, type OrgRule, type PagedReadQuery, type PagedReadResult, type QueryLike, type ReadAllRowsOptions, type ReadAllRowsRestOptions, RecordUnavailableError, type RecordUnavailableReason, type RecordUnavailableResolution, type ResultOf, type RowOf, type SessionSource, SessionUnavailableError, type SupabaseLike, type TableDescriptor, type TableType, type TryWriteOneResult, type UpdateGuard, type UpdateOf, type UserCredentialsPort, type VersionedRow, type Where, WriteDidNotLandError, type WriteDidNotLandReason, type WriteFailureWords, type WriteOneAction, type WriteOneOptions, type WriteOneRowResult, WriteRefusedError, archive, asJsonObject, assertDoor, assertWriteLanded, call, changesOf, count, createActiveOrgCookie, createDb, createOAuthRefreshFetch, createServiceDb, createSessionRetry, decodeActiveOrgSelection, decodeOAuthRefreshClaims, describeWriteFailure, encodeActiveOrgSelection, guardedUpdate, insert, isMissingSessionError, isRecordUnavailableError, listAll, mergeJsonColumn, page, personSentence, read, readAllRows, readAllRowsRest, recordUnavailableMessage, remove, restore, serverMessageFromBody, tableByName, tryReadAllRows, tryReadAllRowsRest, tryWriteOne, update, writeFailureStatus, writeOne, writeOneRow };
|
|
1090
|
+
export { type ActiveOrgCookie, type ActiveOrgCookieOptions, type ActiveOrgSelection, type ArgsOf, type AuthRetryableResult, BulkWriteError, type CreateActiveOrgCookieArgs, type CreateDbOptions, type CreateOAuthRefreshFetchArgs, type CreateSessionRetryOptions, DEFAULT_ACTIVE_ORG_COOKIE_MAX_AGE, DEFAULT_ACTIVE_ORG_COOKIE_NAME, DatabaseError, type Db, DoorRefusedError, type Filter, type FlagLoaders, type FlagsIndex, type FunctionDescriptor, type GuardedUpdateArgs, type GuardedUpdateResult, IncompleteReadError, type InsertOf, type JsonObject, type MergeJsonColumnArgs, type MergeJsonColumnResult, type OAuthRefreshStorage, type OrgRule, type PagedReadQuery, type PagedReadResult, type QueryLike, type ReadAllRowsOptions, type ReadAllRowsRestOptions, type ReadOptions, RecordUnavailableError, type RecordUnavailableReason, type RecordUnavailableResolution, type ResultOf, type RowOf, type SessionSource, SessionUnavailableError, type SupabaseLike, type TableDescriptor, type TableType, type TryWriteOneResult, type UpdateGuard, type UpdateOf, type UserCredentialsPort, type VersionedRow, type Where, WriteDidNotLandError, type WriteDidNotLandReason, type WriteFailureWords, type WriteOneAction, type WriteOneOptions, type WriteOneRowResult, WriteRefusedError, type WriteResult, archive, asJsonObject, assertDoor, assertWriteLanded, call, changesOf, count, createActiveOrgCookie, createDb, createOAuthRefreshFetch, createServiceDb, createSessionRetry, decodeActiveOrgSelection, decodeOAuthRefreshClaims, describeWriteFailure, encodeActiveOrgSelection, guardedUpdate, insert, isMissingSessionError, isRecordUnavailableError, listAll, loadTableByName, mergeJsonColumn, page, personSentence, read, readAllRows, readAllRowsRest, recordUnavailableMessage, remove, restore, serverMessageFromBody, tableByName, tryReadAllRows, tryReadAllRowsRest, tryWriteOne, update, writeFailureStatus, writeOne, writeOneRow };
|
package/dist/db.js
CHANGED
|
@@ -976,18 +976,29 @@ function byPk(q, t, id) {
|
|
|
976
976
|
const key = id;
|
|
977
977
|
return t.pk.reduce((acc, col) => acc.eq(col, key[col]), q);
|
|
978
978
|
}
|
|
979
|
-
|
|
979
|
+
var selectOf = (columns) => columns && columns.length ? columns.join(",") : "*";
|
|
980
|
+
function live(q, table, includeDeleted) {
|
|
981
|
+
return table.softDelete && !includeDeleted ? q.is("deleted_at", null) : q;
|
|
982
|
+
}
|
|
983
|
+
function ordered(q, table, orderBy, ascending = true) {
|
|
984
|
+
const cols = orderBy ? [orderBy, ...table.pk.filter((c) => c !== orderBy)] : table.pk.length ? table.pk : ["id"];
|
|
985
|
+
return cols.reduce((acc, c) => acc.order(c, { ascending }), q);
|
|
986
|
+
}
|
|
987
|
+
async function read(db, table, id, opts = {}) {
|
|
980
988
|
assertDoor(db, table, "read");
|
|
981
|
-
|
|
989
|
+
const q = live(byPk(from(db, table).select(selectOf(opts.columns)), table, id), table, opts.includeDeleted);
|
|
990
|
+
return check(`read ${qualified(table)}`, await q.maybeSingle());
|
|
982
991
|
}
|
|
983
992
|
async function listAll(db, table, where, opts = {}) {
|
|
984
993
|
assertDoor(db, table, "read");
|
|
985
|
-
const order = opts.orderBy ?? table.pk[0] ?? "id";
|
|
986
994
|
return readAllRows(
|
|
987
995
|
({ from: lo, to: hi }) => {
|
|
988
|
-
let q = from(db, table).select(opts.columns
|
|
996
|
+
let q = live(from(db, table).select(selectOf(opts.columns), { count: "exact" }), table, opts.includeDeleted);
|
|
989
997
|
if (where) q = where(q);
|
|
990
|
-
return
|
|
998
|
+
return Promise.resolve(ordered(q, table, opts.orderBy).range(lo, hi)).then((res) => {
|
|
999
|
+
if (res.error) throw new DatabaseError(`listAll ${qualified(table)}`, res.error);
|
|
1000
|
+
return res;
|
|
1001
|
+
});
|
|
991
1002
|
},
|
|
992
1003
|
{
|
|
993
1004
|
label: `listAll ${qualified(table)}`,
|
|
@@ -998,14 +1009,14 @@ async function listAll(db, table, where, opts = {}) {
|
|
|
998
1009
|
}
|
|
999
1010
|
async function page(db, table, window2) {
|
|
1000
1011
|
assertDoor(db, table, "read");
|
|
1001
|
-
let q = from(db, table).select(window2.columns
|
|
1012
|
+
let q = live(from(db, table).select(selectOf(window2.columns), { count: "exact" }), table, window2.includeDeleted);
|
|
1002
1013
|
if (window2.where) q = window2.where(q);
|
|
1003
|
-
const res = await q
|
|
1014
|
+
const res = await ordered(q, table, window2.orderBy, window2.ascending ?? true).range(window2.from, window2.to);
|
|
1004
1015
|
return { rows: check(`page ${qualified(table)}`, res) ?? [], total: res.count ?? null };
|
|
1005
1016
|
}
|
|
1006
|
-
async function count(db, table, where) {
|
|
1017
|
+
async function count(db, table, where, opts = {}) {
|
|
1007
1018
|
assertDoor(db, table, "read");
|
|
1008
|
-
let q = from(db, table).select("*", { count: "exact", head: true });
|
|
1019
|
+
let q = live(from(db, table).select("*", { count: "exact", head: true }), table, opts.includeDeleted);
|
|
1009
1020
|
if (where) q = where(q);
|
|
1010
1021
|
const res = await q;
|
|
1011
1022
|
check(`count ${qualified(table)}`, res);
|
|
@@ -1033,11 +1044,34 @@ function withOrganization(db, table, values) {
|
|
|
1033
1044
|
async function insert(db, table, values) {
|
|
1034
1045
|
assertDoor(db, table, "insert");
|
|
1035
1046
|
const many = Array.isArray(values);
|
|
1036
|
-
|
|
1047
|
+
let rows = (many ? values : [values]).map((v) => withOrganization(db, table, v));
|
|
1048
|
+
if (table.createdBy && db.role === "user" && rows.some((r) => r.created_by == null) && db.client.auth) {
|
|
1049
|
+
const { data } = await db.client.auth.getSession();
|
|
1050
|
+
const person = data.session?.user?.id;
|
|
1051
|
+
if (person) rows = rows.map((r) => r.created_by == null ? { ...r, created_by: person } : r);
|
|
1052
|
+
}
|
|
1037
1053
|
const res = await from(db, table).insert(rows).select("*");
|
|
1038
1054
|
const stored = check(`insert ${qualified(table)}`, res);
|
|
1039
1055
|
return many ? stored : stored[0];
|
|
1040
1056
|
}
|
|
1057
|
+
async function writeRow(db, table, id, values, door, guard) {
|
|
1058
|
+
const expected = guard && "expectedVersion" in guard ? guard.expectedVersion : void 0;
|
|
1059
|
+
if (expected !== void 0 && !table.versioned) {
|
|
1060
|
+
throw new DoorRefusedError(door, "expectedVersion on a table that is not versioned \u2014 nothing would guard it; pass no guard");
|
|
1061
|
+
}
|
|
1062
|
+
if (table.versioned && expected === void 0 && !(guard && "overwrite" in guard && guard.overwrite)) {
|
|
1063
|
+
throw new DoorRefusedError(door, "a versioned table takes { expectedVersion } or { overwrite: true }");
|
|
1064
|
+
}
|
|
1065
|
+
if (expected !== void 0) {
|
|
1066
|
+
return await guardedUpdate({
|
|
1067
|
+
expectedVersion: expected,
|
|
1068
|
+
applyUpdate: ({ expectedVersion, nextVersion }) => byPk(from(db, table).update({ ...values, version: nextVersion }), table, id).eq("version", expectedVersion).select("*").maybeSingle(),
|
|
1069
|
+
fetchCurrent: () => byPk(from(db, table).select("*"), table, id).maybeSingle()
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
const row = check(door, await byPk(from(db, table).update(values), table, id).select("*").maybeSingle());
|
|
1073
|
+
return row ? { status: "saved", row } : { status: "not_found" };
|
|
1074
|
+
}
|
|
1041
1075
|
async function update(db, table, id, patch, guard) {
|
|
1042
1076
|
assertDoor(db, table, "update");
|
|
1043
1077
|
const door = `update ${qualified(table)}`;
|
|
@@ -1046,29 +1080,30 @@ async function update(db, table, id, patch, guard) {
|
|
|
1046
1080
|
const blocked = table.readOnlyColumns.filter((c) => c in values);
|
|
1047
1081
|
if (blocked.length) throw new DoorRefusedError(door, `read-only to clients: ${blocked.join(", ")}`);
|
|
1048
1082
|
}
|
|
1049
|
-
|
|
1050
|
-
return guardedUpdate({
|
|
1051
|
-
expectedVersion: guard.expectedVersion,
|
|
1052
|
-
applyUpdate: ({ expectedVersion, nextVersion }) => byPk(from(db, table).update({ ...values, version: nextVersion }), table, id).eq("version", expectedVersion).select("*").maybeSingle(),
|
|
1053
|
-
fetchCurrent: () => byPk(from(db, table).select("*"), table, id).maybeSingle()
|
|
1054
|
-
});
|
|
1055
|
-
}
|
|
1056
|
-
if (table.versioned && !(guard && "overwrite" in guard && guard.overwrite)) {
|
|
1057
|
-
throw new DoorRefusedError(door, "a versioned table takes { expectedVersion } or { overwrite: true }");
|
|
1058
|
-
}
|
|
1059
|
-
const row = check(door, await byPk(from(db, table).update(values), table, id).select("*").maybeSingle());
|
|
1060
|
-
return row ? { status: "saved", row } : { status: "not_found" };
|
|
1083
|
+
return writeRow(db, table, id, values, door, guard);
|
|
1061
1084
|
}
|
|
1062
|
-
async function remove(db, table, id) {
|
|
1085
|
+
async function remove(db, table, id, guard) {
|
|
1063
1086
|
assertDoor(db, table, "remove");
|
|
1064
1087
|
const door = `remove ${qualified(table)}`;
|
|
1065
1088
|
if (table.softDelete) {
|
|
1066
|
-
const
|
|
1067
|
-
return
|
|
1089
|
+
const res = await writeRow(db, table, id, { deleted_at: (/* @__PURE__ */ new Date()).toISOString() }, door, guard);
|
|
1090
|
+
return res.status === "saved" ? { status: "soft_deleted" } : res.status === "conflict" ? { status: "conflict", currentVersion: res.currentVersion } : res;
|
|
1068
1091
|
}
|
|
1069
1092
|
if (table.archive) throw new DoorRefusedError(door, "this table archives instead of deleting \u2014 use archive()");
|
|
1070
|
-
const
|
|
1071
|
-
|
|
1093
|
+
const expected = guard && "expectedVersion" in guard ? guard.expectedVersion : void 0;
|
|
1094
|
+
if (expected !== void 0 && !table.versioned) throw new DoorRefusedError(door, "expectedVersion on a table that is not versioned");
|
|
1095
|
+
if (table.versioned && expected === void 0 && !(guard && "overwrite" in guard)) {
|
|
1096
|
+
throw new DoorRefusedError(door, "a versioned table takes { expectedVersion } or { overwrite: true }");
|
|
1097
|
+
}
|
|
1098
|
+
let q = byPk(from(db, table).delete(), table, id);
|
|
1099
|
+
if (expected !== void 0) q = q.eq("version", expected);
|
|
1100
|
+
const rows = check(door, await q.select("*"));
|
|
1101
|
+
if (rows && rows.length) return { status: "deleted" };
|
|
1102
|
+
if (expected !== void 0) {
|
|
1103
|
+
const current = check(door, await byPk(from(db, table).select("version"), table, id).maybeSingle());
|
|
1104
|
+
if (current) return { status: "conflict", currentVersion: current.version };
|
|
1105
|
+
}
|
|
1106
|
+
return { status: "not_found" };
|
|
1072
1107
|
}
|
|
1073
1108
|
async function archive(db, table, id, opts = {}) {
|
|
1074
1109
|
assertDoor(db, table, "archive");
|
|
@@ -1078,9 +1113,9 @@ async function archive(db, table, id, opts = {}) {
|
|
|
1078
1113
|
else if (table.archive === "is_archived") values = { is_archived: !opts.restore };
|
|
1079
1114
|
else if (table.softDelete && opts.restore) values = { deleted_at: null };
|
|
1080
1115
|
else throw new DoorRefusedError(door, "the table has no archive column");
|
|
1081
|
-
return
|
|
1116
|
+
return writeRow(db, table, id, values, door, opts.guard);
|
|
1082
1117
|
}
|
|
1083
|
-
var restore = (db, table, id) => archive(db, table, id, { restore: true });
|
|
1118
|
+
var restore = (db, table, id, guard) => archive(db, table, id, guard ? { restore: true, guard } : { restore: true });
|
|
1084
1119
|
async function call(db, fn, args) {
|
|
1085
1120
|
const door = `call ${fn.schema}.${fn.name}`;
|
|
1086
1121
|
const role = db.role === "service" ? "service_role" : "authenticated";
|
|
@@ -1094,6 +1129,12 @@ function tableByName(index, name) {
|
|
|
1094
1129
|
if (!t) throw new DoorRefusedError(`tableByName ${name}`, "no such table in the database description (schema-qualify it: schema.table)");
|
|
1095
1130
|
return t;
|
|
1096
1131
|
}
|
|
1132
|
+
async function loadTableByName(loaders, name) {
|
|
1133
|
+
const schema = name.slice(0, name.indexOf("."));
|
|
1134
|
+
const load = schema ? loaders[schema] : void 0;
|
|
1135
|
+
if (!load) throw new DoorRefusedError(`tableByName ${name}`, "no such schema in the database description (schema-qualify it: schema.table)");
|
|
1136
|
+
return tableByName(await load(), name);
|
|
1137
|
+
}
|
|
1097
1138
|
function changesOf(table) {
|
|
1098
1139
|
if (!table.realtime) throw new DoorRefusedError(`changesOf ${qualified(table)}`, "the table is not in the supabase_realtime publication");
|
|
1099
1140
|
return { schema: table.schema, table: table.name };
|
|
@@ -1132,6 +1173,7 @@ export {
|
|
|
1132
1173
|
isMissingSessionError,
|
|
1133
1174
|
isRecordUnavailableError,
|
|
1134
1175
|
listAll,
|
|
1176
|
+
loadTableByName,
|
|
1135
1177
|
mergeJsonColumn,
|
|
1136
1178
|
page,
|
|
1137
1179
|
parseCookieHeader,
|