@ai-matrx/data 0.24.0 → 0.26.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/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;
@@ -896,13 +902,18 @@ interface QueryLike extends PromiseLike<Resp<any>> {
896
902
  interface SupabaseLike {
897
903
  schema(name: string): {
898
904
  from(table: string): QueryLike;
899
- rpc(fn: string, args?: Record<string, unknown>): PromiseLike<Resp<any>>;
905
+ rpc(fn: string, args?: Record<string, unknown>, opts?: {
906
+ count?: "exact" | "planned" | "estimated";
907
+ }): PromiseLike<Resp<any>>;
900
908
  };
901
909
  auth?: {
902
910
  getSession(): Promise<{
903
911
  data: {
904
912
  session: {
905
913
  access_token: string;
914
+ user?: {
915
+ id: string;
916
+ } | null;
906
917
  } | null;
907
918
  };
908
919
  }>;
@@ -1064,6 +1075,22 @@ declare function archive<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, id: u
1064
1075
  declare const restore: <R, I, U>(db: Db, table: TableDescriptor<R, I, U>, id: unknown, guard?: UpdateGuard) => Promise<WriteResult<R>>;
1065
1076
  /** Call a database function through its generated door (PostgREST chooses an overload by argument names). */
1066
1077
  declare function call<F extends FunctionDescriptor<any, any>>(db: Db, fn: F, args: ArgsOf<F>): Promise<ResultOf<F>>;
1078
+ /** One ordering column of a set-returning function's rows (PostgREST `order`). */
1079
+ type CallOrder = string | {
1080
+ column: string;
1081
+ ascending?: boolean;
1082
+ nullsFirst?: boolean;
1083
+ };
1084
+ /**
1085
+ * EVERY row a set-returning function answers, paged past the 1,000-row cap by
1086
+ * `range` over a stable `order` (name enough columns to make it total — end on a key);
1087
+ * throws a `DatabaseError` with the database's own error, or `IncompleteReadError` on a short read.
1088
+ */
1089
+ declare function callAll<F extends FunctionDescriptor<any, any>>(db: Db, fn: F, args: ArgsOf<F>, opts: {
1090
+ order: readonly CallOrder[];
1091
+ pageSize?: number;
1092
+ maxRows?: number;
1093
+ }): Promise<ResultOf<F> extends readonly (infer Row)[] ? Row[] : ResultOf<F>[]>;
1067
1094
  /** One schema's flags (`<schema>.flags.ts` from `matrx-data generate --flags-index`): "schema.table" → descriptor. */
1068
1095
  type FlagsIndex = Readonly<Record<string, TableDescriptor>>;
1069
1096
  /** Per-schema loaders (`flags-index.ts`): only the schema a runtime name names is loaded (pay-only). */
@@ -1078,4 +1105,4 @@ declare function changesOf(table: TableDescriptor<any, any, any>): {
1078
1105
  table: string;
1079
1106
  };
1080
1107
 
1081
- 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 };
1108
+ export { type ActiveOrgCookie, type ActiveOrgCookieOptions, type ActiveOrgSelection, type ArgsOf, type AuthRetryableResult, BulkWriteError, type CallOrder, 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, callAll, 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;
@@ -896,13 +902,18 @@ interface QueryLike extends PromiseLike<Resp<any>> {
896
902
  interface SupabaseLike {
897
903
  schema(name: string): {
898
904
  from(table: string): QueryLike;
899
- rpc(fn: string, args?: Record<string, unknown>): PromiseLike<Resp<any>>;
905
+ rpc(fn: string, args?: Record<string, unknown>, opts?: {
906
+ count?: "exact" | "planned" | "estimated";
907
+ }): PromiseLike<Resp<any>>;
900
908
  };
901
909
  auth?: {
902
910
  getSession(): Promise<{
903
911
  data: {
904
912
  session: {
905
913
  access_token: string;
914
+ user?: {
915
+ id: string;
916
+ } | null;
906
917
  } | null;
907
918
  };
908
919
  }>;
@@ -1064,6 +1075,22 @@ declare function archive<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, id: u
1064
1075
  declare const restore: <R, I, U>(db: Db, table: TableDescriptor<R, I, U>, id: unknown, guard?: UpdateGuard) => Promise<WriteResult<R>>;
1065
1076
  /** Call a database function through its generated door (PostgREST chooses an overload by argument names). */
1066
1077
  declare function call<F extends FunctionDescriptor<any, any>>(db: Db, fn: F, args: ArgsOf<F>): Promise<ResultOf<F>>;
1078
+ /** One ordering column of a set-returning function's rows (PostgREST `order`). */
1079
+ type CallOrder = string | {
1080
+ column: string;
1081
+ ascending?: boolean;
1082
+ nullsFirst?: boolean;
1083
+ };
1084
+ /**
1085
+ * EVERY row a set-returning function answers, paged past the 1,000-row cap by
1086
+ * `range` over a stable `order` (name enough columns to make it total — end on a key);
1087
+ * throws a `DatabaseError` with the database's own error, or `IncompleteReadError` on a short read.
1088
+ */
1089
+ declare function callAll<F extends FunctionDescriptor<any, any>>(db: Db, fn: F, args: ArgsOf<F>, opts: {
1090
+ order: readonly CallOrder[];
1091
+ pageSize?: number;
1092
+ maxRows?: number;
1093
+ }): Promise<ResultOf<F> extends readonly (infer Row)[] ? Row[] : ResultOf<F>[]>;
1067
1094
  /** One schema's flags (`<schema>.flags.ts` from `matrx-data generate --flags-index`): "schema.table" → descriptor. */
1068
1095
  type FlagsIndex = Readonly<Record<string, TableDescriptor>>;
1069
1096
  /** Per-schema loaders (`flags-index.ts`): only the schema a runtime name names is loaded (pay-only). */
@@ -1078,4 +1105,4 @@ declare function changesOf(table: TableDescriptor<any, any, any>): {
1078
1105
  table: string;
1079
1106
  };
1080
1107
 
1081
- 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 };
1108
+ export { type ActiveOrgCookie, type ActiveOrgCookieOptions, type ActiveOrgSelection, type ArgsOf, type AuthRetryableResult, BulkWriteError, type CallOrder, 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, callAll, 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
@@ -995,7 +995,10 @@ async function listAll(db, table, where, opts = {}) {
995
995
  ({ from: lo, to: hi }) => {
996
996
  let q = live(from(db, table).select(selectOf(opts.columns), { count: "exact" }), table, opts.includeDeleted);
997
997
  if (where) q = where(q);
998
- return ordered(q, table, opts.orderBy).range(lo, hi);
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
+ });
999
1002
  },
1000
1003
  {
1001
1004
  label: `listAll ${qualified(table)}`,
@@ -1041,7 +1044,12 @@ function withOrganization(db, table, values) {
1041
1044
  async function insert(db, table, values) {
1042
1045
  assertDoor(db, table, "insert");
1043
1046
  const many = Array.isArray(values);
1044
- const rows = (many ? values : [values]).map((v) => withOrganization(db, table, v));
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
+ }
1045
1053
  const res = await from(db, table).insert(rows).select("*");
1046
1054
  const stored = check(`insert ${qualified(table)}`, res);
1047
1055
  return many ? stored : stored[0];
@@ -1116,6 +1124,27 @@ async function call(db, fn, args) {
1116
1124
  }
1117
1125
  return check(door, await db.client.schema(fn.schema).rpc(fn.name, args));
1118
1126
  }
1127
+ async function callAll(db, fn, args, opts) {
1128
+ const door = `callAll ${fn.schema}.${fn.name}`;
1129
+ const role = db.role === "service" ? "service_role" : "authenticated";
1130
+ if (!fn.roles.includes(role) && !(role === "authenticated" && fn.roles.includes("anon"))) {
1131
+ throw new DoorRefusedError(door, `not executable by ${role} (executable by: ${fn.roles.join(", ") || "nobody"})`);
1132
+ }
1133
+ if (!opts.order.length) throw new DoorRefusedError(door, "a paged read needs an order (end on a key) \u2014 pages over no order can skip or repeat rows");
1134
+ return readAllRows(
1135
+ ({ from: lo, to: hi }) => {
1136
+ let q = db.client.schema(fn.schema).rpc(fn.name, args, { count: "exact" });
1137
+ for (const o of opts.order) {
1138
+ q = typeof o === "string" ? q.order(o) : q.order(o.column, { ascending: o.ascending ?? true, ...o.nullsFirst !== void 0 ? { nullsFirst: o.nullsFirst } : {} });
1139
+ }
1140
+ return Promise.resolve(q.range(lo, hi)).then((res) => {
1141
+ if (res.error) throw new DatabaseError(door, res.error);
1142
+ return res;
1143
+ });
1144
+ },
1145
+ { label: door, ...opts.pageSize !== void 0 ? { pageSize: opts.pageSize } : {}, ...opts.maxRows !== void 0 ? { maxRows: opts.maxRows } : {} }
1146
+ );
1147
+ }
1119
1148
  function tableByName(index, name) {
1120
1149
  const t = index[name];
1121
1150
  if (!t) throw new DoorRefusedError(`tableByName ${name}`, "no such table in the database description (schema-qualify it: schema.table)");
@@ -1148,6 +1177,7 @@ export {
1148
1177
  assertDoor,
1149
1178
  assertWriteLanded,
1150
1179
  call,
1180
+ callAll,
1151
1181
  changesOf,
1152
1182
  count,
1153
1183
  createActiveOrgCookie,