@lunora/server 1.0.0-alpha.61 → 1.0.0-alpha.63
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/data-model.d.mts +10 -10
- package/dist/data-model.d.ts +10 -10
- package/dist/index.d.mts +281 -293
- package/dist/index.d.ts +281 -293
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/{PRESENCE_DEFAULT_TTL_MS-DmnVChTY.mjs → PRESENCE_DEFAULT_TTL_MS-Dyb1szd2.mjs} +1 -1
- package/dist/packem_shared/buildRlsReadRegistry-CE5k6akj.mjs +1 -0
- package/dist/packem_shared/{composePluginMiddleware-B9NyOR1k.mjs → composePluginMiddleware-ByhCqIGt.mjs} +1 -1
- package/dist/packem_shared/{defineAggregateIndex-C3CMy5jn.mjs → defineAggregateIndex-BoiwhUKL.mjs} +1 -1
- package/dist/packem_shared/httpAction-BpEJYwzV.mjs +5 -0
- package/dist/packem_shared/initLunora-BadfSfpJ.mjs +1 -0
- package/dist/packem_shared/mask-Chnz8Z0H.mjs +1 -0
- package/dist/packem_shared/middleware-D9_39C5C.mjs +1 -0
- package/dist/packem_shared/plugin-184MITA3.mjs +1 -0
- package/dist/packem_shared/rls-CI2149Ve.mjs +1 -0
- package/dist/packem_shared/storageRules-6_G8JpCv.mjs +1 -0
- package/dist/packem_shared/{types.d-C4CMJK8x.d.mts → types.d-B-pIn8rE.d.mts} +2 -2
- package/dist/packem_shared/{types.d-DdYF8E18.d.ts → types.d-CdPDEjhz.d.ts} +2 -2
- package/dist/rls/testing.d.mts +1 -1
- package/dist/rls/testing.d.ts +1 -1
- package/dist/rls/testing.mjs +1 -1
- package/dist/types.d.mts +21 -21
- package/dist/types.d.ts +21 -21
- package/package.json +4 -4
- package/dist/packem_shared/buildRlsReadRegistry-CA-aUi7I.mjs +0 -1
- package/dist/packem_shared/httpAction-C14NuF3V.mjs +0 -4
- package/dist/packem_shared/initLunora-DXCOVntr.mjs +0 -1
- package/dist/packem_shared/mask-DF7mtxQe.mjs +0 -1
- package/dist/packem_shared/optional-writer-override-CXXO30sZ.mjs +0 -1
- package/dist/packem_shared/plugin-CDBMGCeQ.mjs +0 -1
- package/dist/packem_shared/rls-tRDkICWZ.mjs +0 -1
- package/dist/packem_shared/storageRules-BptPZbi8.mjs +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -6,8 +6,8 @@ import { LunoraError as LunoraError$1, LunoraErrorCode } from '@lunora/errors';
|
|
|
6
6
|
export type { LunoraErrorCode } from '@lunora/errors';
|
|
7
7
|
import { Context, Hono } from 'hono';
|
|
8
8
|
import { WhereOperators, QueryArgs as QueryArgs$2 } from "./data-model.mjs";
|
|
9
|
-
import {
|
|
10
|
-
export type { d as PolicyContext, e as PolicyDecision, f as PolicyDecisionOf, P as PolicyOperation } from "./packem_shared/types.d-
|
|
9
|
+
import { W as WhereInput, a as Policy, b as RlsOptions, c as Permission, R as Role, T as TypedDefinePolicyInput, D as DefinePolicyInput } from "./packem_shared/types.d-B-pIn8rE.mjs";
|
|
10
|
+
export type { d as PolicyContext, e as PolicyDecision, f as PolicyDecisionOf, P as PolicyOperation } from "./packem_shared/types.d-B-pIn8rE.mjs";
|
|
11
11
|
export { type CronJob, type CronJobsBuilder, type CronScheduleKind, type DailySchedule, type IntervalSchedule, type MonthlySchedule, type WeeklySchedule, cronJobs } from '@lunora/scheduler';
|
|
12
12
|
/**
|
|
13
13
|
* Make any resolved storage capability bucket-aware so `ctx.storage.bucket(name)`
|
|
@@ -51,7 +51,7 @@ type Middleware<ContextIn, ContextOut> = (options: {
|
|
|
51
51
|
ctx: ContextIn;
|
|
52
52
|
next: MiddlewareNext<ContextIn>;
|
|
53
53
|
}) => ContextOut | Promise<ContextOut>;
|
|
54
|
-
/** Options accepted by `initLunora.dataModel
|
|
54
|
+
/** Options accepted by `initLunora.dataModel<DM>().create(...)`. Reserved for transformer/error-formatter wiring. */
|
|
55
55
|
type CreateOptions = Record<never, never>;
|
|
56
56
|
/**
|
|
57
57
|
* `Output` carries the type declared by `.output(validator)`. It defaults to
|
|
@@ -66,7 +66,7 @@ interface QueryBuilder<Context, Args extends ArgsValidator, Output = undefined>
|
|
|
66
66
|
readonly __lunoraProcedure: "query";
|
|
67
67
|
/**
|
|
68
68
|
* Publish this query on the opt-in public REST surface (plan 167) — the
|
|
69
|
-
* runtime mints `GET /_lunora/rest
|
|
69
|
+
* runtime mints `GET /_lunora/rest/<namespace>/<fn>` (and `POST`), dispatching
|
|
70
70
|
* THROUGH the procedure so `ctx.auth` / RLS / validators are enforced, and the
|
|
71
71
|
* generated OpenAPI describes it. Default-closed: omit to keep it RPC-only.
|
|
72
72
|
*/
|
|
@@ -93,7 +93,7 @@ interface QueryBuilder<Context, Args extends ArgsValidator, Output = undefined>
|
|
|
93
93
|
}) => Output | Promise<Output>) => RegisteredQuery<Args, Output>;
|
|
94
94
|
/**
|
|
95
95
|
* Terminal: declare this procedure as a streaming query. The handler is an
|
|
96
|
-
* async generator (or any function returning an `AsyncIterable
|
|
96
|
+
* async generator (or any function returning an `AsyncIterable<R>`) that
|
|
97
97
|
* yields one chunk per server-pushed frame. The third `signal` argument is
|
|
98
98
|
* tripped when the client cancels — break out of the loop or check
|
|
99
99
|
* `signal.aborted` between yields. `.output()` does not apply: per-chunk
|
|
@@ -117,7 +117,7 @@ interface MutationBuilder<Context, Args extends ArgsValidator, Output = undefine
|
|
|
117
117
|
readonly __lunoraProcedure: "mutation";
|
|
118
118
|
/**
|
|
119
119
|
* Publish this mutation on the opt-in public REST surface (plan 167) — the
|
|
120
|
-
* runtime mints `POST /_lunora/rest
|
|
120
|
+
* runtime mints `POST /_lunora/rest/<namespace>/<fn>`, dispatching THROUGH the
|
|
121
121
|
* procedure so `ctx.auth` / RLS / validators are enforced, and the generated
|
|
122
122
|
* OpenAPI describes it. Default-closed: omit to keep it RPC-only.
|
|
123
123
|
*/
|
|
@@ -162,7 +162,7 @@ interface ActionBuilder<Context, Args extends ArgsValidator, Output = undefined>
|
|
|
162
162
|
}) => Output | Promise<Output>) => RegisteredAction<Args, Output>;
|
|
163
163
|
/**
|
|
164
164
|
* Publish this action on the opt-in public REST surface (plan 167) — the
|
|
165
|
-
* runtime mints `POST /_lunora/rest
|
|
165
|
+
* runtime mints `POST /_lunora/rest/<namespace>/<fn>`, dispatching THROUGH the
|
|
166
166
|
* procedure so `ctx.auth` / RLS / validators are enforced, and the generated
|
|
167
167
|
* OpenAPI describes it. Default-closed: omit to keep it RPC-only.
|
|
168
168
|
*/
|
|
@@ -291,7 +291,7 @@ interface DataModelInit<DataModel> {
|
|
|
291
291
|
create: (options?: CreateOptions) => LunoraBuilders;
|
|
292
292
|
}
|
|
293
293
|
/**
|
|
294
|
-
* Entry point for the procedure builder. `dataModel
|
|
294
|
+
* Entry point for the procedure builder. `dataModel<DM>()` binds the generated
|
|
295
295
|
* `DataModel` (phantom for now), and `.create()` yields the public root builders
|
|
296
296
|
* plus their `internal*` counterparts.
|
|
297
297
|
*/
|
|
@@ -482,7 +482,7 @@ interface FacadeEntry {
|
|
|
482
482
|
* Insert many documents into this table in one call. With
|
|
483
483
|
* `{ skipDuplicates: true }`, UNIQUE breaches resolve to `null` for that row
|
|
484
484
|
* instead of failing the batch. The typed facade narrows the return to
|
|
485
|
-
* `Id
|
|
485
|
+
* `Id<T>[]` when skipDuplicates is not requested.
|
|
486
486
|
*/
|
|
487
487
|
insertMany: (documents: ReadonlyArray<Record<string, unknown>>, options?: {
|
|
488
488
|
limit?: number;
|
|
@@ -556,7 +556,7 @@ interface UpsertManyArgs {
|
|
|
556
556
|
*
|
|
557
557
|
* The by-id accessors (`get`/`delete`/`patch`/`replace`) forward the bound
|
|
558
558
|
* `tableName` as `expectedTable` so the underlying writer scopes its id lookup
|
|
559
|
-
* to this table. Without it, a branded `Id
|
|
559
|
+
* to this table. Without it, a branded `Id<"posts">` carrying another table's
|
|
560
560
|
* id would resolve cross-table (the writer probes every table by id), letting
|
|
561
561
|
* `ctx.db.posts.get(foreignId)` read — or `.delete`/`.patch`/`.replace`
|
|
562
562
|
* mutate — a row in an unrelated table (IDOR). Writers that ignore the second
|
|
@@ -710,7 +710,7 @@ interface HttpRouteBuilder<SearchParams extends ArgsValidator, Body extends Args
|
|
|
710
710
|
/**
|
|
711
711
|
* Terminal: declare this route as a streaming Server-Sent Events endpoint.
|
|
712
712
|
* The handler is an async generator (or any function returning an
|
|
713
|
-
* `AsyncIterable
|
|
713
|
+
* `AsyncIterable<R>`) that yields one chunk per SSE `data:` frame; on
|
|
714
714
|
* iterator completion the route writes a final `event: complete` frame; on
|
|
715
715
|
* throw, an `event: error` frame is written with `{code, message}` before
|
|
716
716
|
* the stream closes. The chunks are JSON-encoded; `R` is inferred from the
|
|
@@ -957,7 +957,7 @@ interface ListArgsSpec<TDocument, F, O extends string> {
|
|
|
957
957
|
* `limit` clamped into `[1, maxLimit]`, `orderBy` reshaped from
|
|
958
958
|
* `{ field, direction }[]` into `ctx.db`'s `{ column: direction }[]`.
|
|
959
959
|
*
|
|
960
|
-
* Returns `QueryArgs
|
|
960
|
+
* Returns `QueryArgs<Doc>` — bound to the table, not free — so a mismatch
|
|
961
961
|
* between what this helper declares and what the table actually holds is a
|
|
962
962
|
* compile error at the `findMany` call site.
|
|
963
963
|
*/
|
|
@@ -967,10 +967,10 @@ interface ListArgsSpec<TDocument, F, O extends string> {
|
|
|
967
967
|
declare const clampLimit: (limit: number | undefined, fallback: number, maxLimit: number) => number;
|
|
968
968
|
/**
|
|
969
969
|
* Declare the filter / sort / page arguments for a list endpoint, plus the
|
|
970
|
-
* translation into `ctx.db
|
|
970
|
+
* translation into `ctx.db.<table>.findMany(...)` options. See the module docs
|
|
971
971
|
* for the shape and the reasoning behind it.
|
|
972
972
|
*
|
|
973
|
-
* Curried on the document type: `defineListArgs
|
|
973
|
+
* Curried on the document type: `defineListArgs<Doc<"messages">>()({ … })`. The
|
|
974
974
|
* extra `()` buys the thing that matters — with `Doc` bound, `filter` keys and
|
|
975
975
|
* `orderBy` entries are checked against the table's real columns, so a typo or a
|
|
976
976
|
* column renamed out from under the endpoint is a COMPILE error instead of a
|
|
@@ -1012,6 +1012,248 @@ interface ShardRankPageResultLike {
|
|
|
1012
1012
|
hasMore: boolean;
|
|
1013
1013
|
rows: ReadonlyArray<RankPageRowLike>;
|
|
1014
1014
|
}
|
|
1015
|
+
/**
|
|
1016
|
+
* Structural mirror of `@lunora/do`'s `QueryArgs` and `CountArgs`. The
|
|
1017
|
+
* runtime ORM in `@lunora/do`/`@lunora/d1` reads `baseWhere` /
|
|
1018
|
+
* `restrictsCounts` straight off these option objects, so as long as the
|
|
1019
|
+
* fields here stay name-compatible the wrapper is portable across the two
|
|
1020
|
+
* dialects without an inter-package dependency.
|
|
1021
|
+
*/
|
|
1022
|
+
interface QueryArgs$1 {
|
|
1023
|
+
baseWhere?: WhereInput;
|
|
1024
|
+
cursor?: null | string;
|
|
1025
|
+
limit?: number;
|
|
1026
|
+
orderBy?: ReadonlyArray<unknown>;
|
|
1027
|
+
/**
|
|
1028
|
+
* Per-target-table read filter the RLS wrapper attaches so a `with` relation
|
|
1029
|
+
* is policy-filtered on its own hop (see `@lunora/do`'s `QueryArgs`). Mirrors
|
|
1030
|
+
* the top-level read: `(table) => readBase(table).baseWhere`.
|
|
1031
|
+
*/
|
|
1032
|
+
relationBaseWhere?: (table: string) => undefined | WhereInput;
|
|
1033
|
+
restrictsCounts?: boolean;
|
|
1034
|
+
where?: WhereInput;
|
|
1035
|
+
with?: Record<string, unknown>;
|
|
1036
|
+
}
|
|
1037
|
+
interface CountArgs {
|
|
1038
|
+
baseWhere?: WhereInput;
|
|
1039
|
+
relationBaseWhere?: (table: string) => undefined | WhereInput;
|
|
1040
|
+
restrictsCounts?: boolean;
|
|
1041
|
+
where?: WhereInput;
|
|
1042
|
+
}
|
|
1043
|
+
/** Structural mirror of `@lunora/do`'s `AggregateOptions` — only the fields the wrapper touches. */
|
|
1044
|
+
interface AggregateArgs$1 {
|
|
1045
|
+
baseWhere?: WhereInput;
|
|
1046
|
+
field?: string;
|
|
1047
|
+
op: string;
|
|
1048
|
+
relationBaseWhere?: (table: string) => undefined | WhereInput;
|
|
1049
|
+
restrictsCounts?: boolean;
|
|
1050
|
+
where?: WhereInput;
|
|
1051
|
+
}
|
|
1052
|
+
/** Structural mirror of `@lunora/do`'s `GroupByOptions`. */
|
|
1053
|
+
interface GroupByArgs$1 {
|
|
1054
|
+
agg?: {
|
|
1055
|
+
field?: string;
|
|
1056
|
+
op: string;
|
|
1057
|
+
};
|
|
1058
|
+
baseWhere?: WhereInput;
|
|
1059
|
+
by: ReadonlyArray<string>;
|
|
1060
|
+
relationBaseWhere?: (table: string) => undefined | WhereInput;
|
|
1061
|
+
restrictsCounts?: boolean;
|
|
1062
|
+
where?: WhereInput;
|
|
1063
|
+
}
|
|
1064
|
+
/** Structural mirror of `@lunora/do`'s `RankOptions`. */
|
|
1065
|
+
interface RankArgs {
|
|
1066
|
+
baseWhere?: WhereInput;
|
|
1067
|
+
restrictsCounts?: boolean;
|
|
1068
|
+
row: Record<string, unknown> | string;
|
|
1069
|
+
where?: WhereInput;
|
|
1070
|
+
}
|
|
1071
|
+
/** Structural mirror of `@lunora/do`'s `RankBeforeOptions`. */
|
|
1072
|
+
interface RankBeforeArgs {
|
|
1073
|
+
partitionKey: string;
|
|
1074
|
+
restrictsCounts?: boolean;
|
|
1075
|
+
rowId: string;
|
|
1076
|
+
sortValues: ReadonlyArray<unknown>;
|
|
1077
|
+
}
|
|
1078
|
+
/** Structural mirror of `@lunora/do`'s `RankPageOptions`. */
|
|
1079
|
+
interface RankPageArgs {
|
|
1080
|
+
baseWhere?: WhereInput;
|
|
1081
|
+
cursor?: null | string;
|
|
1082
|
+
restrictsCounts?: boolean;
|
|
1083
|
+
take?: number;
|
|
1084
|
+
where?: WhereInput;
|
|
1085
|
+
}
|
|
1086
|
+
interface QueryPage$1 {
|
|
1087
|
+
continueCursor: null | string;
|
|
1088
|
+
isDone: boolean;
|
|
1089
|
+
page: Record<string, unknown>[];
|
|
1090
|
+
}
|
|
1091
|
+
interface TableReaderLike$1 {
|
|
1092
|
+
collect: () => Promise<Record<string, unknown>[]>;
|
|
1093
|
+
filter: (predicate: (document: Record<string, unknown>) => boolean) => TableReaderLike$1;
|
|
1094
|
+
first: () => Promise<Record<string, unknown> | null>;
|
|
1095
|
+
paginate: (options: {
|
|
1096
|
+
cursor?: null | string;
|
|
1097
|
+
numItems: number;
|
|
1098
|
+
}) => Promise<QueryPage$1>;
|
|
1099
|
+
take: (limit: number) => Promise<Record<string, unknown>[]>;
|
|
1100
|
+
withGeoIndex: (indexName: string, build: (q: unknown) => unknown) => TableReaderLike$1;
|
|
1101
|
+
withIndex: (indexName: string, range?: (q: unknown) => unknown) => TableReaderLike$1;
|
|
1102
|
+
withSearchIndex: (indexName: string, search: (q: unknown) => unknown) => TableReaderLike$1;
|
|
1103
|
+
}
|
|
1104
|
+
/**
|
|
1105
|
+
* Structural projection of the runtime ORM writer. The wrapper relies only
|
|
1106
|
+
* on these fields, so it's interchangeable between `@lunora/do`'s
|
|
1107
|
+
* `DatabaseWriterLike` and `@lunora/d1`'s `DatabaseWriterLike`.
|
|
1108
|
+
*/
|
|
1109
|
+
interface DatabaseWriterLike {
|
|
1110
|
+
/**
|
|
1111
|
+
* Reduce matching rows to a scalar. The RLS wrapper AND-merges the read
|
|
1112
|
+
* `baseWhere` into `options` so the reduction only sees policy-visible rows
|
|
1113
|
+
* (safe: an aggregate scoped to `where` never reveals a hidden row — see
|
|
1114
|
+
* `@lunora/do`'s `RestrictableQueryOptions`). Required: the only writer ever
|
|
1115
|
+
* wrapped is `@lunora/do`'s `createShardCtxDb`, which always implements it.
|
|
1116
|
+
*/
|
|
1117
|
+
aggregate: (tableName: string, options: AggregateArgs$1) => Promise<null | number>;
|
|
1118
|
+
count: (tableName: string, whereOrArgs?: CountArgs | WhereInput) => Promise<number>;
|
|
1119
|
+
delete: (id: string, expectedTable?: string, options?: {
|
|
1120
|
+
hard?: boolean;
|
|
1121
|
+
}) => Promise<void>;
|
|
1122
|
+
/** Uncapped, chunked erase of a whole table. The RLS wrapper gates each row like a single delete. */
|
|
1123
|
+
deleteAll?: (tableName: string, options?: {
|
|
1124
|
+
chunkSize?: number;
|
|
1125
|
+
hard?: boolean;
|
|
1126
|
+
}) => Promise<{
|
|
1127
|
+
deleted: number;
|
|
1128
|
+
}>;
|
|
1129
|
+
deleteMany: (ids: ReadonlyArray<string>, options?: {
|
|
1130
|
+
limit?: number;
|
|
1131
|
+
}, expectedTable?: string) => Promise<{
|
|
1132
|
+
deleted: number;
|
|
1133
|
+
}>;
|
|
1134
|
+
deleteWhere?: (tableName: string, where: WhereInput, options?: {
|
|
1135
|
+
limit?: number;
|
|
1136
|
+
}) => Promise<{
|
|
1137
|
+
deleted: number;
|
|
1138
|
+
}>;
|
|
1139
|
+
findFirst: (tableName: string, args?: QueryArgs$1) => Promise<Record<string, unknown> | null>;
|
|
1140
|
+
findFirstOrThrow: (tableName: string, args?: QueryArgs$1) => Promise<Record<string, unknown>>;
|
|
1141
|
+
findMany: (tableName: string, args?: QueryArgs$1) => Promise<QueryPage$1>;
|
|
1142
|
+
get: (id: string, expectedTable?: string) => Promise<Record<string, unknown> | null>;
|
|
1143
|
+
/**
|
|
1144
|
+
* Group + reduce. Same `baseWhere` injection as `aggregate`: the per-group
|
|
1145
|
+
* reduction is scoped to policy-visible rows, so a group count tallies only
|
|
1146
|
+
* rows the caller may read. Required for the same reason as `aggregate`.
|
|
1147
|
+
*/
|
|
1148
|
+
groupBy: (tableName: string, options: GroupByArgs$1) => Promise<ReadonlyArray<{
|
|
1149
|
+
key: Record<string, unknown>;
|
|
1150
|
+
value: null | number;
|
|
1151
|
+
}>>;
|
|
1152
|
+
insert: (tableName: string, document: Record<string, unknown>) => Promise<string>;
|
|
1153
|
+
insertMany: (tableName: string, documents: ReadonlyArray<Record<string, unknown>>, options?: {
|
|
1154
|
+
limit?: number;
|
|
1155
|
+
skipDuplicates?: boolean;
|
|
1156
|
+
}) => Promise<(string | null)[]>;
|
|
1157
|
+
insertManyUnsafe: (tableName: string, documents: ReadonlyArray<Record<string, unknown>>, options?: {
|
|
1158
|
+
allowExplicitId?: boolean;
|
|
1159
|
+
limit?: number;
|
|
1160
|
+
}) => Promise<string[]>;
|
|
1161
|
+
/**
|
|
1162
|
+
* Optional table-aware lookup. The underlying writer (e.g. `@lunora/do`)
|
|
1163
|
+
* already knows the owning table of an id internally, so it can return
|
|
1164
|
+
* `{ row, tableName }` in a single round-trip. When present, the RLS wrapper
|
|
1165
|
+
* uses it to collapse the per-call membership-probe fan-out (1 `get` + N
|
|
1166
|
+
* `findFirst` across every policy table) down to one lookup. Writers that
|
|
1167
|
+
* don't implement it fall back to the probe path.
|
|
1168
|
+
*/
|
|
1169
|
+
lookupById?: (id: string, expectedTable?: string) => Promise<null | {
|
|
1170
|
+
row: Record<string, unknown>;
|
|
1171
|
+
tableName: string;
|
|
1172
|
+
}>;
|
|
1173
|
+
patch: (id: string, patch: Record<string, unknown>, expectedTable?: string) => Promise<void>;
|
|
1174
|
+
patchMany: (patches: ReadonlyArray<{
|
|
1175
|
+
id: string;
|
|
1176
|
+
patch: Record<string, unknown>;
|
|
1177
|
+
}>, options?: {
|
|
1178
|
+
limit?: number;
|
|
1179
|
+
}, expectedTable?: string) => Promise<{
|
|
1180
|
+
patched: number;
|
|
1181
|
+
}>;
|
|
1182
|
+
patchWhere?: (tableName: string, args: {
|
|
1183
|
+
patch: Record<string, unknown>;
|
|
1184
|
+
where: WhereInput;
|
|
1185
|
+
}, options?: {
|
|
1186
|
+
limit?: number;
|
|
1187
|
+
}) => Promise<{
|
|
1188
|
+
patched: number;
|
|
1189
|
+
}>;
|
|
1190
|
+
query: (tableName: string) => TableReaderLike$1;
|
|
1191
|
+
/**
|
|
1192
|
+
* Rank a row within its partition. A position is a count-of-rows-before, so
|
|
1193
|
+
* — exactly like `count()` — it can't be trusted in an RLS-restricted
|
|
1194
|
+
* reader: the wrapper fails it closed with `COUNT_RLS_UNSUPPORTED`. Required
|
|
1195
|
+
* for the same reason as `aggregate`.
|
|
1196
|
+
*/
|
|
1197
|
+
rank: (tableName: string, indexName: string, options: RankArgs) => Promise<null | {
|
|
1198
|
+
position: number;
|
|
1199
|
+
total: number;
|
|
1200
|
+
}>;
|
|
1201
|
+
/** Cross-shard rank primitive — same count-of-before RLS hazard as `rank`; failed closed under a read policy. */
|
|
1202
|
+
rankBefore?: (tableName: string, indexName: string, options: RankBeforeArgs) => Promise<{
|
|
1203
|
+
before: number;
|
|
1204
|
+
total: number;
|
|
1205
|
+
}>;
|
|
1206
|
+
/**
|
|
1207
|
+
* Sorted pagination over a rank companion. The companion stores only the
|
|
1208
|
+
* partition + sort keys + id, so an arbitrary read `baseWhere` can't be
|
|
1209
|
+
* enforced against it (and re-filtering the fetched rows would break page
|
|
1210
|
+
* sizing). RLS therefore fails it closed rather than leak hidden rows.
|
|
1211
|
+
* Required for the same reason as `aggregate`.
|
|
1212
|
+
*/
|
|
1213
|
+
rankPage: (tableName: string, indexName: string, options?: RankPageArgs) => Promise<QueryPage$1>;
|
|
1214
|
+
/**
|
|
1215
|
+
* Cross-shard companion to `rankPage`: same ranked slice, but each row
|
|
1216
|
+
* keeps its rank-key tuple for the query coordinator's k-way merge. Same
|
|
1217
|
+
* count-of-partition RLS hazard as `rankPage` — failed closed under a read
|
|
1218
|
+
* policy for the identical reason (see `rankPage` above).
|
|
1219
|
+
*/
|
|
1220
|
+
rankPageRows?: (tableName: string, indexName: string, options?: RankPageArgs) => Promise<ShardRankPageResultLike>;
|
|
1221
|
+
replace: (id: string, document: Record<string, unknown>, expectedTable?: string) => Promise<void>;
|
|
1222
|
+
restore?: (id: string, expectedTable?: string) => Promise<void>;
|
|
1223
|
+
/**
|
|
1224
|
+
* Whole-shard erase. The RLS wrapper deliberately **fails this closed** rather
|
|
1225
|
+
* than wrapping it — see the wrapper's `wipeShard`.
|
|
1226
|
+
*/
|
|
1227
|
+
wipeShard?: (options?: {
|
|
1228
|
+
chunkSize?: number;
|
|
1229
|
+
exclude?: ReadonlyArray<string>;
|
|
1230
|
+
tables?: ReadonlyArray<string>;
|
|
1231
|
+
}) => Promise<{
|
|
1232
|
+
deleted: number;
|
|
1233
|
+
tables: Record<string, number>;
|
|
1234
|
+
}>;
|
|
1235
|
+
}
|
|
1236
|
+
/**
|
|
1237
|
+
* What a procedure's `ctx.db` must structurally satisfy for the middleware
|
|
1238
|
+
* to wrap it. We deliberately mirror `@lunora/do`'s `DatabaseWriterLike`
|
|
1239
|
+
* rather than `@lunora/server`'s nominal `DatabaseWriter`/`DatabaseReader`:
|
|
1240
|
+
* the runtime adapter that flows in is the `DatabaseWriterLike`-shaped one,
|
|
1241
|
+
* and structural matching keeps this module free of an `@lunora/do`-typed
|
|
1242
|
+
* `ctx`.
|
|
1243
|
+
*/
|
|
1244
|
+
type RlsDatabase = DatabaseWriterLike;
|
|
1245
|
+
/** Roles list source on the context. Tolerant of older auth states. */
|
|
1246
|
+
type AuthLike = {
|
|
1247
|
+
getIdentity?: () => Promise<Record<string, unknown> | null>;
|
|
1248
|
+
roles?: ReadonlyArray<string>;
|
|
1249
|
+
userId?: null | string;
|
|
1250
|
+
};
|
|
1251
|
+
/** Minimal shape the middleware needs on the incoming ctx. */
|
|
1252
|
+
interface RlsContextIn {
|
|
1253
|
+
auth?: AuthLike;
|
|
1254
|
+
db: RlsDatabase;
|
|
1255
|
+
}
|
|
1256
|
+
declare const rls: <Context extends RlsContextIn = RlsContextIn>(policies: ReadonlyArray<Policy<Context>>, options?: RlsOptions) => Middleware<Context, Context>;
|
|
1015
1257
|
/**
|
|
1016
1258
|
* The prefixed tables a single plugin `P` contributes, or an empty map when it
|
|
1017
1259
|
* ships no schema extension. Mirrors {@link PrefixedTables} at the plugin level
|
|
@@ -1030,7 +1272,7 @@ type ExtensionTablesOf<P> = P extends {
|
|
|
1030
1272
|
type InstalledTables<T extends Record<string, TableDefinition>, Plugins extends ReadonlyArray<unknown>> = Plugins extends readonly [infer Head, ...infer Rest] ? InstalledTables<ExtensionTablesOf<Head> & T, Rest> : T;
|
|
1031
1273
|
/**
|
|
1032
1274
|
* Union every plugin's `ContextOut` in a tuple — the type-level mirror of the
|
|
1033
|
-
* `ctx.api
|
|
1275
|
+
* `ctx.api.<key>` additions {@link composePluginMiddleware} accumulates as each
|
|
1034
1276
|
* plugin middleware runs. Independent of the incoming context, which the builder
|
|
1035
1277
|
* infers at the `.use(...)` site.
|
|
1036
1278
|
*/
|
|
@@ -1083,7 +1325,7 @@ interface Plugin<TExtension extends Record<string, TableDefinition> = Record<str
|
|
|
1083
1325
|
/**
|
|
1084
1326
|
* Optional middleware. Users attach with `c.query.use(plugin.middleware)`.
|
|
1085
1327
|
* The middleware can extend `ctx`; convention is to attach helpers under
|
|
1086
|
-
* `ctx.api
|
|
1328
|
+
* `ctx.api.<key>`, e.g.
|
|
1087
1329
|
*
|
|
1088
1330
|
* ```ts
|
|
1089
1331
|
* middleware: ({ ctx, next }) =>
|
|
@@ -1228,7 +1470,7 @@ declare const installPlugins: <T extends Record<string, TableDefinition>, const
|
|
|
1228
1470
|
* Compose every plugin's middleware into a single middleware you attach with one
|
|
1229
1471
|
* `.use(...)`. Plugins without middleware (schema-only) are skipped; the rest run
|
|
1230
1472
|
* in array order, each seeing the context the previous one widened, so the final
|
|
1231
|
-
* `next({ ctx })` the builder receives carries every plugin's `ctx.api
|
|
1473
|
+
* `next({ ctx })` the builder receives carries every plugin's `ctx.api.<key>`
|
|
1232
1474
|
* additions. Equivalent to `.use(a.middleware).use(b.middleware)…` but as one
|
|
1233
1475
|
* value, the middleware sibling of {@link installPlugins}.
|
|
1234
1476
|
*
|
|
@@ -1388,7 +1630,7 @@ interface TableBuilder<Shape extends Record<string, Validator> = Record<string,
|
|
|
1388
1630
|
shardBy: (field: keyof Shape & string) => TableBuilder<Shape>;
|
|
1389
1631
|
/**
|
|
1390
1632
|
* Turn on soft delete. Adds a nullable timestamp column (`options.field`,
|
|
1391
|
-
* default `deletedAt`) and changes `ctx.db
|
|
1633
|
+
* default `deletedAt`) and changes `ctx.db.<table>.delete()` to **set** it
|
|
1392
1634
|
* instead of removing the row; `onDelete: "cascade"` children are recursively
|
|
1393
1635
|
* soft-deleted too. **List reads** (`findMany`/`findFirst`/`query()`/`count`/
|
|
1394
1636
|
* `aggregate`/relation loads) then hide soft-deleted rows unless they pass
|
|
@@ -1677,12 +1919,12 @@ interface MaskOptions<Context = unknown> {
|
|
|
1677
1919
|
readonly indexFields?: IndexFieldsByTable;
|
|
1678
1920
|
readonly roles?: ReadonlyArray<Role>;
|
|
1679
1921
|
}
|
|
1680
|
-
interface QueryPage
|
|
1922
|
+
interface QueryPage {
|
|
1681
1923
|
continueCursor: null | string;
|
|
1682
1924
|
isDone: boolean;
|
|
1683
1925
|
page: Record<string, unknown>[];
|
|
1684
1926
|
}
|
|
1685
|
-
interface QueryArgs
|
|
1927
|
+
interface QueryArgs {
|
|
1686
1928
|
baseWhere?: unknown;
|
|
1687
1929
|
cursor?: null | string;
|
|
1688
1930
|
limit?: number;
|
|
@@ -1690,12 +1932,12 @@ interface QueryArgs$1 {
|
|
|
1690
1932
|
where?: unknown;
|
|
1691
1933
|
with?: Record<string, unknown>;
|
|
1692
1934
|
}
|
|
1693
|
-
interface AggregateArgs
|
|
1935
|
+
interface AggregateArgs {
|
|
1694
1936
|
field?: string;
|
|
1695
1937
|
op: string;
|
|
1696
1938
|
where?: unknown;
|
|
1697
1939
|
}
|
|
1698
|
-
interface GroupByArgs
|
|
1940
|
+
interface GroupByArgs {
|
|
1699
1941
|
agg?: {
|
|
1700
1942
|
field?: string;
|
|
1701
1943
|
op: string;
|
|
@@ -1717,22 +1959,22 @@ interface SearchScoredDocument {
|
|
|
1717
1959
|
document: Record<string, unknown>;
|
|
1718
1960
|
score: number;
|
|
1719
1961
|
}
|
|
1720
|
-
interface TableReaderLike
|
|
1962
|
+
interface TableReaderLike {
|
|
1721
1963
|
[Symbol.asyncIterator]: () => AsyncIterator<Record<string, unknown>>;
|
|
1722
1964
|
collect: () => Promise<Record<string, unknown>[]>;
|
|
1723
1965
|
collectWithScores: () => Promise<ScoredDocument[]>;
|
|
1724
|
-
filter: (predicate: (document: Record<string, unknown>) => boolean) => TableReaderLike
|
|
1966
|
+
filter: (predicate: (document: Record<string, unknown>) => boolean) => TableReaderLike;
|
|
1725
1967
|
first: () => Promise<Record<string, unknown> | null>;
|
|
1726
|
-
order: (direction: "asc" | "desc") => TableReaderLike
|
|
1968
|
+
order: (direction: "asc" | "desc") => TableReaderLike;
|
|
1727
1969
|
paginate: (options: {
|
|
1728
1970
|
cursor?: null | string;
|
|
1729
1971
|
numItems: number;
|
|
1730
|
-
}) => Promise<QueryPage
|
|
1972
|
+
}) => Promise<QueryPage>;
|
|
1731
1973
|
take: (limit: number) => Promise<Record<string, unknown>[]>;
|
|
1732
1974
|
unique: () => Promise<Record<string, unknown> | null>;
|
|
1733
|
-
withGeoIndex: (indexName: string, build: (q: unknown) => unknown) => TableReaderLike
|
|
1734
|
-
withIndex: (indexName: string, range?: (q: unknown) => unknown) => TableReaderLike
|
|
1735
|
-
withSearchIndex: (indexName: string, search: (q: unknown) => unknown) => TableReaderLike
|
|
1975
|
+
withGeoIndex: (indexName: string, build: (q: unknown) => unknown) => TableReaderLike;
|
|
1976
|
+
withIndex: (indexName: string, range?: (q: unknown) => unknown) => TableReaderLike;
|
|
1977
|
+
withSearchIndex: (indexName: string, search: (q: unknown) => unknown) => TableReaderLike;
|
|
1736
1978
|
}
|
|
1737
1979
|
/**
|
|
1738
1980
|
* Structural projection of the runtime ORM writer — the same subset
|
|
@@ -1741,7 +1983,7 @@ interface TableReaderLike$1 {
|
|
|
1741
1983
|
* inter-package dependency. `rankBefore` is optional (the D1 twin omits it).
|
|
1742
1984
|
*/
|
|
1743
1985
|
interface MaskDatabase {
|
|
1744
|
-
aggregate: (tableName: string, options: AggregateArgs
|
|
1986
|
+
aggregate: (tableName: string, options: AggregateArgs) => Promise<null | number>;
|
|
1745
1987
|
count: (tableName: string, whereOrArgs?: unknown) => Promise<number>;
|
|
1746
1988
|
delete: (id: string, expectedTable?: string) => Promise<void>;
|
|
1747
1989
|
deleteMany: (ids: ReadonlyArray<string>, options?: {
|
|
@@ -1754,11 +1996,11 @@ interface MaskDatabase {
|
|
|
1754
1996
|
}) => Promise<{
|
|
1755
1997
|
deleted: number;
|
|
1756
1998
|
}>;
|
|
1757
|
-
findFirst: (tableName: string, args?: QueryArgs
|
|
1758
|
-
findFirstOrThrow: (tableName: string, args?: QueryArgs
|
|
1759
|
-
findMany: (tableName: string, args?: QueryArgs
|
|
1999
|
+
findFirst: (tableName: string, args?: QueryArgs) => Promise<Record<string, unknown> | null>;
|
|
2000
|
+
findFirstOrThrow: (tableName: string, args?: QueryArgs) => Promise<Record<string, unknown>>;
|
|
2001
|
+
findMany: (tableName: string, args?: QueryArgs) => Promise<QueryPage>;
|
|
1760
2002
|
get: (id: string, expectedTable?: string) => Promise<Record<string, unknown> | null>;
|
|
1761
|
-
groupBy: (tableName: string, options: GroupByArgs
|
|
2003
|
+
groupBy: (tableName: string, options: GroupByArgs) => Promise<ReadonlyArray<{
|
|
1762
2004
|
key: Record<string, unknown>;
|
|
1763
2005
|
value: null | number;
|
|
1764
2006
|
}>>;
|
|
@@ -1788,7 +2030,7 @@ interface MaskDatabase {
|
|
|
1788
2030
|
}) => Promise<{
|
|
1789
2031
|
patched: number;
|
|
1790
2032
|
}>;
|
|
1791
|
-
query: (tableName: string) => TableReaderLike
|
|
2033
|
+
query: (tableName: string) => TableReaderLike;
|
|
1792
2034
|
rank: (tableName: string, indexName: string, options: unknown) => Promise<null | {
|
|
1793
2035
|
position: number;
|
|
1794
2036
|
total: number;
|
|
@@ -1797,19 +2039,13 @@ interface MaskDatabase {
|
|
|
1797
2039
|
before: number;
|
|
1798
2040
|
total: number;
|
|
1799
2041
|
}>;
|
|
1800
|
-
rankPage: (tableName: string, indexName: string, options?: unknown) => Promise<QueryPage
|
|
2042
|
+
rankPage: (tableName: string, indexName: string, options?: unknown) => Promise<QueryPage>;
|
|
1801
2043
|
/** Cross-shard companion to `rankPage`, gated the same way `rankPage` is masked below. */
|
|
1802
2044
|
rankPageRows?: (tableName: string, indexName: string, options?: unknown) => Promise<ShardRankPageResultLike>;
|
|
1803
2045
|
replace: (id: string, document: Record<string, unknown>, expectedTable?: string) => Promise<void>;
|
|
1804
2046
|
}
|
|
1805
|
-
/** Roles list source on the context. Tolerant of older auth states (mirrors RLS's `AuthLike`). */
|
|
1806
|
-
type AuthLike$1 = {
|
|
1807
|
-
getIdentity?: () => Promise<Record<string, unknown> | null>;
|
|
1808
|
-
roles?: ReadonlyArray<string>;
|
|
1809
|
-
userId?: null | string;
|
|
1810
|
-
};
|
|
1811
2047
|
interface MaskContextIn {
|
|
1812
|
-
auth?: AuthLike
|
|
2048
|
+
auth?: AuthLike;
|
|
1813
2049
|
db: MaskDatabase;
|
|
1814
2050
|
}
|
|
1815
2051
|
/**
|
|
@@ -2114,7 +2350,7 @@ declare const definePolicy: <Context = unknown>(input: DefinePolicyInput<Context
|
|
|
2114
2350
|
/**
|
|
2115
2351
|
* Build a project-bound, relation-aware `definePolicy` typed against the
|
|
2116
2352
|
* generated `DataModel` (`DM`) + `Relations` (`REL`) maps. Codegen emits a
|
|
2117
|
-
* `createPolicyDsl
|
|
2353
|
+
* `createPolicyDsl<DataModel, Relations>()` binding into `_generated/server.ts`,
|
|
2118
2354
|
* so importing `definePolicy` from the generated module constrains `table` to a
|
|
2119
2355
|
* real table name and type-checks the `when` predicate — including Prisma-style
|
|
2120
2356
|
* relation predicates (`is`/`some`/…) the `@lunora/do` pre-resolver now resolves
|
|
@@ -2148,248 +2384,6 @@ declare const definePermission: (name: string, options?: Omit<Permission, "name"
|
|
|
2148
2384
|
*/
|
|
2149
2385
|
declare const definePolicies: <Context = unknown>(policies: ReadonlyArray<Policy<Context>>) => ReadonlyArray<Policy<Context>>;
|
|
2150
2386
|
declare const defineRole: (name: string, options?: Omit<Role, "name">) => Role;
|
|
2151
|
-
/**
|
|
2152
|
-
* Structural mirror of `@lunora/do`'s `QueryArgs` and `CountArgs`. The
|
|
2153
|
-
* runtime ORM in `@lunora/do`/`@lunora/d1` reads `baseWhere` /
|
|
2154
|
-
* `restrictsCounts` straight off these option objects, so as long as the
|
|
2155
|
-
* fields here stay name-compatible the wrapper is portable across the two
|
|
2156
|
-
* dialects without an inter-package dependency.
|
|
2157
|
-
*/
|
|
2158
|
-
interface QueryArgs {
|
|
2159
|
-
baseWhere?: WhereInput;
|
|
2160
|
-
cursor?: null | string;
|
|
2161
|
-
limit?: number;
|
|
2162
|
-
orderBy?: ReadonlyArray<unknown>;
|
|
2163
|
-
/**
|
|
2164
|
-
* Per-target-table read filter the RLS wrapper attaches so a `with` relation
|
|
2165
|
-
* is policy-filtered on its own hop (see `@lunora/do`'s `QueryArgs`). Mirrors
|
|
2166
|
-
* the top-level read: `(table) => readBase(table).baseWhere`.
|
|
2167
|
-
*/
|
|
2168
|
-
relationBaseWhere?: (table: string) => undefined | WhereInput;
|
|
2169
|
-
restrictsCounts?: boolean;
|
|
2170
|
-
where?: WhereInput;
|
|
2171
|
-
with?: Record<string, unknown>;
|
|
2172
|
-
}
|
|
2173
|
-
interface CountArgs {
|
|
2174
|
-
baseWhere?: WhereInput;
|
|
2175
|
-
relationBaseWhere?: (table: string) => undefined | WhereInput;
|
|
2176
|
-
restrictsCounts?: boolean;
|
|
2177
|
-
where?: WhereInput;
|
|
2178
|
-
}
|
|
2179
|
-
/** Structural mirror of `@lunora/do`'s `AggregateOptions` — only the fields the wrapper touches. */
|
|
2180
|
-
interface AggregateArgs {
|
|
2181
|
-
baseWhere?: WhereInput;
|
|
2182
|
-
field?: string;
|
|
2183
|
-
op: string;
|
|
2184
|
-
relationBaseWhere?: (table: string) => undefined | WhereInput;
|
|
2185
|
-
restrictsCounts?: boolean;
|
|
2186
|
-
where?: WhereInput;
|
|
2187
|
-
}
|
|
2188
|
-
/** Structural mirror of `@lunora/do`'s `GroupByOptions`. */
|
|
2189
|
-
interface GroupByArgs {
|
|
2190
|
-
agg?: {
|
|
2191
|
-
field?: string;
|
|
2192
|
-
op: string;
|
|
2193
|
-
};
|
|
2194
|
-
baseWhere?: WhereInput;
|
|
2195
|
-
by: ReadonlyArray<string>;
|
|
2196
|
-
relationBaseWhere?: (table: string) => undefined | WhereInput;
|
|
2197
|
-
restrictsCounts?: boolean;
|
|
2198
|
-
where?: WhereInput;
|
|
2199
|
-
}
|
|
2200
|
-
/** Structural mirror of `@lunora/do`'s `RankOptions`. */
|
|
2201
|
-
interface RankArgs {
|
|
2202
|
-
baseWhere?: WhereInput;
|
|
2203
|
-
restrictsCounts?: boolean;
|
|
2204
|
-
row: Record<string, unknown> | string;
|
|
2205
|
-
where?: WhereInput;
|
|
2206
|
-
}
|
|
2207
|
-
/** Structural mirror of `@lunora/do`'s `RankBeforeOptions`. */
|
|
2208
|
-
interface RankBeforeArgs {
|
|
2209
|
-
partitionKey: string;
|
|
2210
|
-
restrictsCounts?: boolean;
|
|
2211
|
-
rowId: string;
|
|
2212
|
-
sortValues: ReadonlyArray<unknown>;
|
|
2213
|
-
}
|
|
2214
|
-
/** Structural mirror of `@lunora/do`'s `RankPageOptions`. */
|
|
2215
|
-
interface RankPageArgs {
|
|
2216
|
-
baseWhere?: WhereInput;
|
|
2217
|
-
cursor?: null | string;
|
|
2218
|
-
restrictsCounts?: boolean;
|
|
2219
|
-
take?: number;
|
|
2220
|
-
where?: WhereInput;
|
|
2221
|
-
}
|
|
2222
|
-
interface QueryPage {
|
|
2223
|
-
continueCursor: null | string;
|
|
2224
|
-
isDone: boolean;
|
|
2225
|
-
page: Record<string, unknown>[];
|
|
2226
|
-
}
|
|
2227
|
-
interface TableReaderLike {
|
|
2228
|
-
collect: () => Promise<Record<string, unknown>[]>;
|
|
2229
|
-
filter: (predicate: (document: Record<string, unknown>) => boolean) => TableReaderLike;
|
|
2230
|
-
first: () => Promise<Record<string, unknown> | null>;
|
|
2231
|
-
paginate: (options: {
|
|
2232
|
-
cursor?: null | string;
|
|
2233
|
-
numItems: number;
|
|
2234
|
-
}) => Promise<QueryPage>;
|
|
2235
|
-
take: (limit: number) => Promise<Record<string, unknown>[]>;
|
|
2236
|
-
withGeoIndex: (indexName: string, build: (q: unknown) => unknown) => TableReaderLike;
|
|
2237
|
-
withIndex: (indexName: string, range?: (q: unknown) => unknown) => TableReaderLike;
|
|
2238
|
-
withSearchIndex: (indexName: string, search: (q: unknown) => unknown) => TableReaderLike;
|
|
2239
|
-
}
|
|
2240
|
-
/**
|
|
2241
|
-
* Structural projection of the runtime ORM writer. The wrapper relies only
|
|
2242
|
-
* on these fields, so it's interchangeable between `@lunora/do`'s
|
|
2243
|
-
* `DatabaseWriterLike` and `@lunora/d1`'s `DatabaseWriterLike`.
|
|
2244
|
-
*/
|
|
2245
|
-
interface DatabaseWriterLike {
|
|
2246
|
-
/**
|
|
2247
|
-
* Reduce matching rows to a scalar. The RLS wrapper AND-merges the read
|
|
2248
|
-
* `baseWhere` into `options` so the reduction only sees policy-visible rows
|
|
2249
|
-
* (safe: an aggregate scoped to `where` never reveals a hidden row — see
|
|
2250
|
-
* `@lunora/do`'s `RestrictableQueryOptions`). Required: the only writer ever
|
|
2251
|
-
* wrapped is `@lunora/do`'s `createShardCtxDb`, which always implements it.
|
|
2252
|
-
*/
|
|
2253
|
-
aggregate: (tableName: string, options: AggregateArgs) => Promise<null | number>;
|
|
2254
|
-
count: (tableName: string, whereOrArgs?: CountArgs | WhereInput) => Promise<number>;
|
|
2255
|
-
delete: (id: string, expectedTable?: string, options?: {
|
|
2256
|
-
hard?: boolean;
|
|
2257
|
-
}) => Promise<void>;
|
|
2258
|
-
/** Uncapped, chunked erase of a whole table. The RLS wrapper gates each row like a single delete. */
|
|
2259
|
-
deleteAll?: (tableName: string, options?: {
|
|
2260
|
-
chunkSize?: number;
|
|
2261
|
-
hard?: boolean;
|
|
2262
|
-
}) => Promise<{
|
|
2263
|
-
deleted: number;
|
|
2264
|
-
}>;
|
|
2265
|
-
deleteMany: (ids: ReadonlyArray<string>, options?: {
|
|
2266
|
-
limit?: number;
|
|
2267
|
-
}, expectedTable?: string) => Promise<{
|
|
2268
|
-
deleted: number;
|
|
2269
|
-
}>;
|
|
2270
|
-
deleteWhere?: (tableName: string, where: WhereInput, options?: {
|
|
2271
|
-
limit?: number;
|
|
2272
|
-
}) => Promise<{
|
|
2273
|
-
deleted: number;
|
|
2274
|
-
}>;
|
|
2275
|
-
findFirst: (tableName: string, args?: QueryArgs) => Promise<Record<string, unknown> | null>;
|
|
2276
|
-
findFirstOrThrow: (tableName: string, args?: QueryArgs) => Promise<Record<string, unknown>>;
|
|
2277
|
-
findMany: (tableName: string, args?: QueryArgs) => Promise<QueryPage>;
|
|
2278
|
-
get: (id: string, expectedTable?: string) => Promise<Record<string, unknown> | null>;
|
|
2279
|
-
/**
|
|
2280
|
-
* Group + reduce. Same `baseWhere` injection as `aggregate`: the per-group
|
|
2281
|
-
* reduction is scoped to policy-visible rows, so a group count tallies only
|
|
2282
|
-
* rows the caller may read. Required for the same reason as `aggregate`.
|
|
2283
|
-
*/
|
|
2284
|
-
groupBy: (tableName: string, options: GroupByArgs) => Promise<ReadonlyArray<{
|
|
2285
|
-
key: Record<string, unknown>;
|
|
2286
|
-
value: null | number;
|
|
2287
|
-
}>>;
|
|
2288
|
-
insert: (tableName: string, document: Record<string, unknown>) => Promise<string>;
|
|
2289
|
-
insertMany: (tableName: string, documents: ReadonlyArray<Record<string, unknown>>, options?: {
|
|
2290
|
-
limit?: number;
|
|
2291
|
-
skipDuplicates?: boolean;
|
|
2292
|
-
}) => Promise<(string | null)[]>;
|
|
2293
|
-
insertManyUnsafe: (tableName: string, documents: ReadonlyArray<Record<string, unknown>>, options?: {
|
|
2294
|
-
allowExplicitId?: boolean;
|
|
2295
|
-
limit?: number;
|
|
2296
|
-
}) => Promise<string[]>;
|
|
2297
|
-
/**
|
|
2298
|
-
* Optional table-aware lookup. The underlying writer (e.g. `@lunora/do`)
|
|
2299
|
-
* already knows the owning table of an id internally, so it can return
|
|
2300
|
-
* `{ row, tableName }` in a single round-trip. When present, the RLS wrapper
|
|
2301
|
-
* uses it to collapse the per-call membership-probe fan-out (1 `get` + N
|
|
2302
|
-
* `findFirst` across every policy table) down to one lookup. Writers that
|
|
2303
|
-
* don't implement it fall back to the probe path.
|
|
2304
|
-
*/
|
|
2305
|
-
lookupById?: (id: string, expectedTable?: string) => Promise<null | {
|
|
2306
|
-
row: Record<string, unknown>;
|
|
2307
|
-
tableName: string;
|
|
2308
|
-
}>;
|
|
2309
|
-
patch: (id: string, patch: Record<string, unknown>, expectedTable?: string) => Promise<void>;
|
|
2310
|
-
patchMany: (patches: ReadonlyArray<{
|
|
2311
|
-
id: string;
|
|
2312
|
-
patch: Record<string, unknown>;
|
|
2313
|
-
}>, options?: {
|
|
2314
|
-
limit?: number;
|
|
2315
|
-
}, expectedTable?: string) => Promise<{
|
|
2316
|
-
patched: number;
|
|
2317
|
-
}>;
|
|
2318
|
-
patchWhere?: (tableName: string, args: {
|
|
2319
|
-
patch: Record<string, unknown>;
|
|
2320
|
-
where: WhereInput;
|
|
2321
|
-
}, options?: {
|
|
2322
|
-
limit?: number;
|
|
2323
|
-
}) => Promise<{
|
|
2324
|
-
patched: number;
|
|
2325
|
-
}>;
|
|
2326
|
-
query: (tableName: string) => TableReaderLike;
|
|
2327
|
-
/**
|
|
2328
|
-
* Rank a row within its partition. A position is a count-of-rows-before, so
|
|
2329
|
-
* — exactly like `count()` — it can't be trusted in an RLS-restricted
|
|
2330
|
-
* reader: the wrapper fails it closed with `COUNT_RLS_UNSUPPORTED`. Required
|
|
2331
|
-
* for the same reason as `aggregate`.
|
|
2332
|
-
*/
|
|
2333
|
-
rank: (tableName: string, indexName: string, options: RankArgs) => Promise<null | {
|
|
2334
|
-
position: number;
|
|
2335
|
-
total: number;
|
|
2336
|
-
}>;
|
|
2337
|
-
/** Cross-shard rank primitive — same count-of-before RLS hazard as `rank`; failed closed under a read policy. */
|
|
2338
|
-
rankBefore?: (tableName: string, indexName: string, options: RankBeforeArgs) => Promise<{
|
|
2339
|
-
before: number;
|
|
2340
|
-
total: number;
|
|
2341
|
-
}>;
|
|
2342
|
-
/**
|
|
2343
|
-
* Sorted pagination over a rank companion. The companion stores only the
|
|
2344
|
-
* partition + sort keys + id, so an arbitrary read `baseWhere` can't be
|
|
2345
|
-
* enforced against it (and re-filtering the fetched rows would break page
|
|
2346
|
-
* sizing). RLS therefore fails it closed rather than leak hidden rows.
|
|
2347
|
-
* Required for the same reason as `aggregate`.
|
|
2348
|
-
*/
|
|
2349
|
-
rankPage: (tableName: string, indexName: string, options?: RankPageArgs) => Promise<QueryPage>;
|
|
2350
|
-
/**
|
|
2351
|
-
* Cross-shard companion to `rankPage`: same ranked slice, but each row
|
|
2352
|
-
* keeps its rank-key tuple for the query coordinator's k-way merge. Same
|
|
2353
|
-
* count-of-partition RLS hazard as `rankPage` — failed closed under a read
|
|
2354
|
-
* policy for the identical reason (see `rankPage` above).
|
|
2355
|
-
*/
|
|
2356
|
-
rankPageRows?: (tableName: string, indexName: string, options?: RankPageArgs) => Promise<ShardRankPageResultLike>;
|
|
2357
|
-
replace: (id: string, document: Record<string, unknown>, expectedTable?: string) => Promise<void>;
|
|
2358
|
-
restore?: (id: string, expectedTable?: string) => Promise<void>;
|
|
2359
|
-
/**
|
|
2360
|
-
* Whole-shard erase. The RLS wrapper deliberately **fails this closed** rather
|
|
2361
|
-
* than wrapping it — see the wrapper's `wipeShard`.
|
|
2362
|
-
*/
|
|
2363
|
-
wipeShard?: (options?: {
|
|
2364
|
-
chunkSize?: number;
|
|
2365
|
-
exclude?: ReadonlyArray<string>;
|
|
2366
|
-
tables?: ReadonlyArray<string>;
|
|
2367
|
-
}) => Promise<{
|
|
2368
|
-
deleted: number;
|
|
2369
|
-
tables: Record<string, number>;
|
|
2370
|
-
}>;
|
|
2371
|
-
}
|
|
2372
|
-
/**
|
|
2373
|
-
* What a procedure's `ctx.db` must structurally satisfy for the middleware
|
|
2374
|
-
* to wrap it. We deliberately mirror `@lunora/do`'s `DatabaseWriterLike`
|
|
2375
|
-
* rather than `@lunora/server`'s nominal `DatabaseWriter`/`DatabaseReader`:
|
|
2376
|
-
* the runtime adapter that flows in is the `DatabaseWriterLike`-shaped one,
|
|
2377
|
-
* and structural matching keeps this module free of an `@lunora/do`-typed
|
|
2378
|
-
* `ctx`.
|
|
2379
|
-
*/
|
|
2380
|
-
type RlsDatabase = DatabaseWriterLike;
|
|
2381
|
-
/** Roles list source on the context. Tolerant of older auth states. */
|
|
2382
|
-
type AuthLike = {
|
|
2383
|
-
getIdentity?: () => Promise<Record<string, unknown> | null>;
|
|
2384
|
-
roles?: ReadonlyArray<string>;
|
|
2385
|
-
userId?: null | string;
|
|
2386
|
-
};
|
|
2387
|
-
/** Minimal shape the middleware needs on the incoming ctx. */
|
|
2388
|
-
interface RlsContextIn {
|
|
2389
|
-
auth?: AuthLike;
|
|
2390
|
-
db: RlsDatabase;
|
|
2391
|
-
}
|
|
2392
|
-
declare const rls: <Context extends RlsContextIn = RlsContextIn>(policies: ReadonlyArray<Policy<Context>>, options?: RlsOptions) => Middleware<Context, Context>;
|
|
2393
2387
|
/**
|
|
2394
2388
|
* A predicate matching **no** rows — the deny decision.
|
|
2395
2389
|
*
|
|
@@ -2623,14 +2617,8 @@ declare const defineStorageRule: <Context = unknown>(input: DefineStorageRuleInp
|
|
|
2623
2617
|
* immediately rather than as a silently double-evaluated predicate.
|
|
2624
2618
|
*/
|
|
2625
2619
|
declare const defineStorageRules: <Context = unknown>(rules: ReadonlyArray<StorageRule<Context>>) => ReadonlyArray<StorageRule<Context>>;
|
|
2626
|
-
/** The minimal `ctx.auth` shape the middleware reads — a structural subset that the full AuthState satisfies. Tolerant of older auth states (mirrors RLS's `AuthLike`). */
|
|
2627
|
-
type StorageAuthLike = {
|
|
2628
|
-
getIdentity?: () => Promise<Record<string, unknown> | null>;
|
|
2629
|
-
roles?: ReadonlyArray<string>;
|
|
2630
|
-
userId?: null | string;
|
|
2631
|
-
};
|
|
2632
2620
|
interface StorageContextIn {
|
|
2633
|
-
auth?:
|
|
2621
|
+
auth?: AuthLike;
|
|
2634
2622
|
storage?: unknown;
|
|
2635
2623
|
}
|
|
2636
2624
|
declare const storageRules: <Context extends StorageContextIn = StorageContextIn>(rules: ReadonlyArray<StorageRule<Context>>, options?: StorageRulesOptions) => Middleware<Context, Context>;
|