@lunora/server 1.0.0-alpha.2 → 1.0.0-alpha.4

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.
@@ -49,6 +49,13 @@ interface QueryArgs<TDocument> {
49
49
  cursor?: null | string;
50
50
  limit?: number;
51
51
  orderBy?: OrderBy<TDocument>[];
52
+ /**
53
+ * Project each returned row down to these columns (plus the system fields
54
+ * `_id`/`_creationTime`, always retained). Trims wire payload for wide rows;
55
+ * relations requested via `with` are still attached. Reactivity is unaffected —
56
+ * the engine still reads the whole row to track dependencies.
57
+ */
58
+ select?: ReadonlyArray<keyof TDocument & string>;
52
59
  where?: Where<TDocument>;
53
60
  }
54
61
  /**
@@ -97,6 +104,12 @@ type WhereOf<DM, REL extends Record<keyof DM, object>, T extends keyof DM> = Rel
97
104
  /** {@link QueryArgs} with the relation-aware {@link WhereOf} `where` typing. */
98
105
  interface QueryArgsOf<DM, REL extends Record<keyof DM, object>, T extends keyof DM> {
99
106
  cursor?: null | string;
107
+ /**
108
+ * Include soft-deleted rows (`.softDelete()` tables only). Default hides them;
109
+ * `true` returns deleted rows alongside live ones. No effect on a table
110
+ * without `.softDelete()`.
111
+ */
112
+ includeDeleted?: boolean;
100
113
  limit?: number;
101
114
  orderBy?: OrderBy<DM[T]>[];
102
115
  where?: WhereOf<DM, REL, T>;
@@ -110,11 +123,15 @@ interface QueryPage<TDocument> {
110
123
  type NestedWithArgument<WK> = WK extends {
111
124
  with: infer NW;
112
125
  } ? NW : {};
126
+ /** The nested `select` tuple inside a relation's with-value, or `undefined` (no projection). */
127
+ type NestedSelectArgument<WK> = WK extends {
128
+ select: infer S;
129
+ } ? S : undefined;
113
130
  /**
114
131
  * The `with` argument for table `T`: each relation can be `true` (load with no
115
- * refinements) or an object. `many` relations accept `where`/`orderBy`/`limit`
116
- * plus a nested `with`; `one` relations accept only a nested `with`. The
117
- * reserved `_count` key requests per-relation aggregate counts.
132
+ * refinements) or an object. `many` relations accept `where`/`orderBy`/`limit`/
133
+ * `select` plus a nested `with`; `one` relations accept `select` + a nested
134
+ * `with`. The reserved `_count` key requests per-relation aggregate counts.
118
135
  */
119
136
  type WithArg<DM, REL extends Record<keyof DM, object>, T extends keyof DM> = { [K in keyof REL[T]]?: REL[T][K] extends {
120
137
  __relationKind: "many";
@@ -125,18 +142,24 @@ type WithArg<DM, REL extends Record<keyof DM, object>, T extends keyof DM> = { [
125
142
  __relationKind: "one";
126
143
  __target: infer Target extends keyof DM;
127
144
  } ? boolean | {
145
+ select?: ReadonlyArray<keyof DM[Target] & string>;
128
146
  with?: WithArg<DM, REL, Target>;
129
147
  } : never } & {
130
148
  _count?: { [K in keyof REL[T]]?: true };
131
149
  };
132
- /** Resolve a single relation descriptor + its with-value to the loaded type. */
150
+ /**
151
+ * Resolve a single relation descriptor + its with-value to the loaded type,
152
+ * threading the nested `select` tuple into the projected child shape (the 5th
153
+ * `LoadWith` arg) so `with: { author: { select: ["name"] } }` narrows the loaded
154
+ * `author` to the selected columns + system fields.
155
+ */
133
156
  type LoadRelation<DM, REL extends Record<keyof DM, object>, R, WK> = R extends {
134
157
  __relationKind: "one";
135
158
  __target: infer Target extends keyof DM;
136
- } ? LoadWith<DM, REL, Target, NestedWithArgument<WK>> | null : R extends {
159
+ } ? LoadWith<DM, REL, Target, NestedWithArgument<WK>, NestedSelectArgument<WK>> | null : R extends {
137
160
  __relationKind: "many";
138
161
  __target: infer Target extends keyof DM;
139
- } ? LoadWith<DM, REL, Target, NestedWithArgument<WK>>[] : never;
162
+ } ? LoadWith<DM, REL, Target, NestedWithArgument<WK>, NestedSelectArgument<WK>>[] : never;
140
163
  /** The relation keys of `W` that were actually requested (not `false`/`undefined`). */
141
164
  type LoadedRelations<DM, REL extends Record<keyof DM, object>, T extends keyof DM, W> = { [K in keyof W as K extends keyof REL[T] ? (W[K] extends false | undefined ? never : K) : never]: K extends keyof REL[T] ? LoadRelation<DM, REL, REL[T][K], W[K]> : never };
142
165
  /** The `_count` projection of `W`, if any. */
@@ -145,8 +168,20 @@ type LoadedCount<W> = W extends {
145
168
  } ? {
146
169
  _count: { [K in keyof C]: number };
147
170
  } : {};
148
- /** `Doc&lt;T>` narrowed to exactly the relations requested in the with-arg `W`. */
149
- type LoadWith<DM, REL extends Record<keyof DM, object>, T extends keyof DM, W> = DM[T] & LoadedCount<W> & LoadedRelations<DM, REL, T, W>;
171
+ /** System columns a `select` projection always retains, so cursors and by-id reuse keep working. */
172
+ type SelectAlwaysKeep<DM, T extends keyof DM> = ("_creationTime" | "_id") & keyof DM[T];
173
+ /**
174
+ * `DM[T]` narrowed to the columns named by a `select` tuple `S` (plus the system
175
+ * fields). `undefined` (the default — no `select`) keeps the full document.
176
+ */
177
+ type ProjectDoc<DM, T extends keyof DM, S> = S extends ReadonlyArray<infer K> ? (K extends keyof DM[T] ? Pick<DM[T], (K & keyof DM[T]) | SelectAlwaysKeep<DM, T>> : DM[T]) : DM[T];
178
+ /**
179
+ * `Doc&lt;T>` narrowed to exactly the relations requested in the with-arg `W` and,
180
+ * when a `select` tuple `S` is supplied, to its projected columns. `S` defaults
181
+ * to `undefined` so the 4-argument form (the codegen-emitted callers) keeps the
182
+ * full document.
183
+ */
184
+ type LoadWith<DM, REL extends Record<keyof DM, object>, T extends keyof DM, W, S = undefined> = LoadedCount<W> & LoadedRelations<DM, REL, T, W> & ProjectDoc<DM, T, S>;
150
185
  /** Reducer applied by an aggregate (`avg`/`count`/`max`/`min`/`sum`). */
151
186
  type AggregateOp = "avg" | "count" | "max" | "min" | "sum";
152
187
  /**
@@ -260,15 +295,20 @@ interface TableReaderFacade<DM, REL extends Record<keyof DM, object>, RANK exten
260
295
  * uses to inject `baseWhere` and `restrictsCounts`.
261
296
  */
262
297
  count: (where?: RestrictableQueryOptionsOf<DM, REL, T> | WhereOf<DM, REL, T>) => Promise<number>;
263
- findFirst: <W extends WithArg<DM, REL, T> = {}>(args?: QueryArgsOf<DM, REL, T> & {
298
+ /** `true` when at least one row matches `where` (any row when omitted). RLS-filtered exactly like `findFirst`. */
299
+ exists: (where?: WhereOf<DM, REL, T>) => Promise<boolean>;
300
+ findFirst: <W extends WithArg<DM, REL, T> = {}, S extends ReadonlyArray<keyof DM[T] & string> | undefined = undefined>(args?: QueryArgsOf<DM, REL, T> & {
301
+ select?: S;
264
302
  with?: W;
265
- }) => Promise<LoadWith<DM, REL, T, W> | null>;
266
- findFirstOrThrow: <W extends WithArg<DM, REL, T> = {}>(args?: QueryArgsOf<DM, REL, T> & {
303
+ }) => Promise<LoadWith<DM, REL, T, W, S> | null>;
304
+ findFirstOrThrow: <W extends WithArg<DM, REL, T> = {}, S extends ReadonlyArray<keyof DM[T] & string> | undefined = undefined>(args?: QueryArgsOf<DM, REL, T> & {
305
+ select?: S;
267
306
  with?: W;
268
- }) => Promise<LoadWith<DM, REL, T, W>>;
269
- findMany: <W extends WithArg<DM, REL, T> = {}>(args?: QueryArgsOf<DM, REL, T> & {
307
+ }) => Promise<LoadWith<DM, REL, T, W, S>>;
308
+ findMany: <W extends WithArg<DM, REL, T> = {}, S extends ReadonlyArray<keyof DM[T] & string> | undefined = undefined>(args?: QueryArgsOf<DM, REL, T> & {
309
+ select?: S;
270
310
  with?: W;
271
- }) => Promise<QueryPage<LoadWith<DM, REL, T, W>>>;
311
+ }) => Promise<QueryPage<LoadWith<DM, REL, T, W, S>>>;
272
312
  get: (id: Id<string & T>) => Promise<DM[T] | null>;
273
313
  /**
274
314
  * Group rows by the named keys and apply `agg` per group (defaults to
@@ -299,6 +339,11 @@ interface TableReaderFacade<DM, REL extends Record<keyof DM, object>, RANK exten
299
339
  }
300
340
  /** Read-write typed table accessor exposed on `MutationCtx.db.&lt;table>` / `ActionCtx.db.&lt;table>`. */
301
341
  interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends Record<keyof DM, object>, RANK extends Record<keyof DM, string>, SEARCH extends Record<keyof DM, string>, T extends keyof DM> extends TableReaderFacade<DM, REL, RANK, SEARCH, T> {
342
+ /**
343
+ * Delete a row by id. On a `.softDelete()` table this flips the marker column
344
+ * (and cascades as a soft delete) instead of removing the row; use
345
+ * {@link TableWriterFacade.hardDelete} to force physical removal.
346
+ */
302
347
  delete: (id: Id<string & T>) => Promise<void>;
303
348
  /** Delete many rows in this table by id in one call; returns the *requested* id count (unknown ids are no-ops). Atomic within a mutation (a throw rolls the mutation back); an action has no transaction span. */
304
349
  deleteMany: (ids: ReadonlyArray<Id<string & T>>, options?: {
@@ -306,7 +351,21 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
306
351
  }) => Promise<{
307
352
  deleted: number;
308
353
  }>;
309
- insert: (values: IM[T]) => Promise<Id<string & T>>;
354
+ /** Physically remove a row (and physically cascade `onDelete`), bypassing `.softDelete()`. Same as `delete()` on a non-soft table. */
355
+ hardDelete: (id: Id<string & T>) => Promise<void>;
356
+ /**
357
+ * Insert a document, returning its minted id. With `{ skipDuplicates: true }`
358
+ * a UNIQUE-constraint breach resolves to `null` (the row already exists)
359
+ * instead of throwing — the return type widens to `Id | null` on that overload.
360
+ */
361
+ insert: {
362
+ (values: IM[T], options: {
363
+ skipDuplicates: true;
364
+ }): Promise<Id<string & T> | null>;
365
+ (values: IM[T], options?: {
366
+ skipDuplicates?: boolean;
367
+ }): Promise<Id<string & T>>;
368
+ };
310
369
  /** Insert many documents into this table in one call, returning the minted ids in input order. Atomic within a mutation (a throw rolls the mutation back); an action has no transaction span. */
311
370
  insertMany: (values: ReadonlyArray<IM[T]>, options?: {
312
371
  limit?: number;
@@ -320,9 +379,38 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
320
379
  limit?: number;
321
380
  }) => Promise<void>;
322
381
  replace: (id: Id<string & T>, values: IM[T]) => Promise<void>;
382
+ /** Un-soft-delete a row by id: clears the `.softDelete()` marker so list reads see it again. Throws on a non-soft table. */
383
+ restore: (id: Id<string & T>) => Promise<void>;
384
+ /**
385
+ * Insert when no existing row matches `target`, otherwise patch the match with
386
+ * `update` (defaulting to `create`). `target` names a `.unique()` column (or a
387
+ * tuple) used to look it up. Returns the row id and whether it was `created`.
388
+ * Composes `findFirst` + `insert`/`patch`, so RLS gates each step.
389
+ */
390
+ upsert: (args: {
391
+ create: IM[T];
392
+ target: UpsertTargetOf<DM, T>;
393
+ update?: Partial<IM[T]>;
394
+ }) => Promise<{
395
+ created: boolean;
396
+ id: Id<string & T>;
397
+ }>;
398
+ /** Sequential {@link TableWriterFacade.upsert} over many rows sharing one `target`; one result per input row, in order. */
399
+ upsertMany: (args: {
400
+ rows: ReadonlyArray<{
401
+ create: IM[T];
402
+ update?: Partial<IM[T]>;
403
+ }>;
404
+ target: UpsertTargetOf<DM, T>;
405
+ }) => Promise<{
406
+ created: boolean;
407
+ id: Id<string & T>;
408
+ }[]>;
323
409
  }
410
+ /** Conflict target for `upsert`/`upsertMany`: one column of table `T`, or a tuple of them. */
411
+ type UpsertTargetOf<DM, T extends keyof DM> = ReadonlyArray<keyof DM[T] & string> | (keyof DM[T] & string);
324
412
  /** Per-table read facade — `ctx.db.&lt;table>` on a `QueryCtx`. */
325
413
  type DatabaseReaderFacade<DM, REL extends Record<keyof DM, object>, RANK extends Record<keyof DM, string>, SEARCH extends Record<keyof DM, string>> = { readonly [T in keyof DM]: TableReaderFacade<DM, REL, RANK, SEARCH, T> };
326
414
  /** Per-table read-write facade — `ctx.db.&lt;table>` on a `MutationCtx` / `ActionCtx`. */
327
415
  type DatabaseWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends Record<keyof DM, object>, RANK extends Record<keyof DM, string>, SEARCH extends Record<keyof DM, string>> = { readonly [T in keyof DM]: TableWriterFacade<DM, IM, REL, RANK, SEARCH, T> };
328
- export { AggregateOp, DatabaseReaderFacade, DatabaseWriterFacade, GroupByEntry, Id, LoadWith, ManyRelationWhere, OneRelationWhere, OrderBy, QueryArgs, QueryArgsOf, QueryPage, RankPage, RankResult, RestrictableQueryOptions, RestrictableQueryOptionsOf, SearchFilterBuilder, SearchReader, TableAggregateOptions, TableAggregateOptionsOf, TableGroupByOptions, TableGroupByOptionsOf, TableRankOptions, TableRankPageOptions, TableReaderFacade, TableWriterFacade, Where, WhereOf, WhereOperators, WithArg };
416
+ export { AggregateOp, DatabaseReaderFacade, DatabaseWriterFacade, GroupByEntry, Id, LoadWith, ManyRelationWhere, OneRelationWhere, OrderBy, QueryArgs, QueryArgsOf, QueryPage, RankPage, RankResult, RestrictableQueryOptions, RestrictableQueryOptionsOf, SearchFilterBuilder, SearchReader, TableAggregateOptions, TableAggregateOptionsOf, TableGroupByOptions, TableGroupByOptionsOf, TableRankOptions, TableRankPageOptions, TableReaderFacade, TableWriterFacade, UpsertTargetOf, Where, WhereOf, WhereOperators, WithArg };
@@ -49,6 +49,13 @@ interface QueryArgs<TDocument> {
49
49
  cursor?: null | string;
50
50
  limit?: number;
51
51
  orderBy?: OrderBy<TDocument>[];
52
+ /**
53
+ * Project each returned row down to these columns (plus the system fields
54
+ * `_id`/`_creationTime`, always retained). Trims wire payload for wide rows;
55
+ * relations requested via `with` are still attached. Reactivity is unaffected —
56
+ * the engine still reads the whole row to track dependencies.
57
+ */
58
+ select?: ReadonlyArray<keyof TDocument & string>;
52
59
  where?: Where<TDocument>;
53
60
  }
54
61
  /**
@@ -97,6 +104,12 @@ type WhereOf<DM, REL extends Record<keyof DM, object>, T extends keyof DM> = Rel
97
104
  /** {@link QueryArgs} with the relation-aware {@link WhereOf} `where` typing. */
98
105
  interface QueryArgsOf<DM, REL extends Record<keyof DM, object>, T extends keyof DM> {
99
106
  cursor?: null | string;
107
+ /**
108
+ * Include soft-deleted rows (`.softDelete()` tables only). Default hides them;
109
+ * `true` returns deleted rows alongside live ones. No effect on a table
110
+ * without `.softDelete()`.
111
+ */
112
+ includeDeleted?: boolean;
100
113
  limit?: number;
101
114
  orderBy?: OrderBy<DM[T]>[];
102
115
  where?: WhereOf<DM, REL, T>;
@@ -110,11 +123,15 @@ interface QueryPage<TDocument> {
110
123
  type NestedWithArgument<WK> = WK extends {
111
124
  with: infer NW;
112
125
  } ? NW : {};
126
+ /** The nested `select` tuple inside a relation's with-value, or `undefined` (no projection). */
127
+ type NestedSelectArgument<WK> = WK extends {
128
+ select: infer S;
129
+ } ? S : undefined;
113
130
  /**
114
131
  * The `with` argument for table `T`: each relation can be `true` (load with no
115
- * refinements) or an object. `many` relations accept `where`/`orderBy`/`limit`
116
- * plus a nested `with`; `one` relations accept only a nested `with`. The
117
- * reserved `_count` key requests per-relation aggregate counts.
132
+ * refinements) or an object. `many` relations accept `where`/`orderBy`/`limit`/
133
+ * `select` plus a nested `with`; `one` relations accept `select` + a nested
134
+ * `with`. The reserved `_count` key requests per-relation aggregate counts.
118
135
  */
119
136
  type WithArg<DM, REL extends Record<keyof DM, object>, T extends keyof DM> = { [K in keyof REL[T]]?: REL[T][K] extends {
120
137
  __relationKind: "many";
@@ -125,18 +142,24 @@ type WithArg<DM, REL extends Record<keyof DM, object>, T extends keyof DM> = { [
125
142
  __relationKind: "one";
126
143
  __target: infer Target extends keyof DM;
127
144
  } ? boolean | {
145
+ select?: ReadonlyArray<keyof DM[Target] & string>;
128
146
  with?: WithArg<DM, REL, Target>;
129
147
  } : never } & {
130
148
  _count?: { [K in keyof REL[T]]?: true };
131
149
  };
132
- /** Resolve a single relation descriptor + its with-value to the loaded type. */
150
+ /**
151
+ * Resolve a single relation descriptor + its with-value to the loaded type,
152
+ * threading the nested `select` tuple into the projected child shape (the 5th
153
+ * `LoadWith` arg) so `with: { author: { select: ["name"] } }` narrows the loaded
154
+ * `author` to the selected columns + system fields.
155
+ */
133
156
  type LoadRelation<DM, REL extends Record<keyof DM, object>, R, WK> = R extends {
134
157
  __relationKind: "one";
135
158
  __target: infer Target extends keyof DM;
136
- } ? LoadWith<DM, REL, Target, NestedWithArgument<WK>> | null : R extends {
159
+ } ? LoadWith<DM, REL, Target, NestedWithArgument<WK>, NestedSelectArgument<WK>> | null : R extends {
137
160
  __relationKind: "many";
138
161
  __target: infer Target extends keyof DM;
139
- } ? LoadWith<DM, REL, Target, NestedWithArgument<WK>>[] : never;
162
+ } ? LoadWith<DM, REL, Target, NestedWithArgument<WK>, NestedSelectArgument<WK>>[] : never;
140
163
  /** The relation keys of `W` that were actually requested (not `false`/`undefined`). */
141
164
  type LoadedRelations<DM, REL extends Record<keyof DM, object>, T extends keyof DM, W> = { [K in keyof W as K extends keyof REL[T] ? (W[K] extends false | undefined ? never : K) : never]: K extends keyof REL[T] ? LoadRelation<DM, REL, REL[T][K], W[K]> : never };
142
165
  /** The `_count` projection of `W`, if any. */
@@ -145,8 +168,20 @@ type LoadedCount<W> = W extends {
145
168
  } ? {
146
169
  _count: { [K in keyof C]: number };
147
170
  } : {};
148
- /** `Doc&lt;T>` narrowed to exactly the relations requested in the with-arg `W`. */
149
- type LoadWith<DM, REL extends Record<keyof DM, object>, T extends keyof DM, W> = DM[T] & LoadedCount<W> & LoadedRelations<DM, REL, T, W>;
171
+ /** System columns a `select` projection always retains, so cursors and by-id reuse keep working. */
172
+ type SelectAlwaysKeep<DM, T extends keyof DM> = ("_creationTime" | "_id") & keyof DM[T];
173
+ /**
174
+ * `DM[T]` narrowed to the columns named by a `select` tuple `S` (plus the system
175
+ * fields). `undefined` (the default — no `select`) keeps the full document.
176
+ */
177
+ type ProjectDoc<DM, T extends keyof DM, S> = S extends ReadonlyArray<infer K> ? (K extends keyof DM[T] ? Pick<DM[T], (K & keyof DM[T]) | SelectAlwaysKeep<DM, T>> : DM[T]) : DM[T];
178
+ /**
179
+ * `Doc&lt;T>` narrowed to exactly the relations requested in the with-arg `W` and,
180
+ * when a `select` tuple `S` is supplied, to its projected columns. `S` defaults
181
+ * to `undefined` so the 4-argument form (the codegen-emitted callers) keeps the
182
+ * full document.
183
+ */
184
+ type LoadWith<DM, REL extends Record<keyof DM, object>, T extends keyof DM, W, S = undefined> = LoadedCount<W> & LoadedRelations<DM, REL, T, W> & ProjectDoc<DM, T, S>;
150
185
  /** Reducer applied by an aggregate (`avg`/`count`/`max`/`min`/`sum`). */
151
186
  type AggregateOp = "avg" | "count" | "max" | "min" | "sum";
152
187
  /**
@@ -260,15 +295,20 @@ interface TableReaderFacade<DM, REL extends Record<keyof DM, object>, RANK exten
260
295
  * uses to inject `baseWhere` and `restrictsCounts`.
261
296
  */
262
297
  count: (where?: RestrictableQueryOptionsOf<DM, REL, T> | WhereOf<DM, REL, T>) => Promise<number>;
263
- findFirst: <W extends WithArg<DM, REL, T> = {}>(args?: QueryArgsOf<DM, REL, T> & {
298
+ /** `true` when at least one row matches `where` (any row when omitted). RLS-filtered exactly like `findFirst`. */
299
+ exists: (where?: WhereOf<DM, REL, T>) => Promise<boolean>;
300
+ findFirst: <W extends WithArg<DM, REL, T> = {}, S extends ReadonlyArray<keyof DM[T] & string> | undefined = undefined>(args?: QueryArgsOf<DM, REL, T> & {
301
+ select?: S;
264
302
  with?: W;
265
- }) => Promise<LoadWith<DM, REL, T, W> | null>;
266
- findFirstOrThrow: <W extends WithArg<DM, REL, T> = {}>(args?: QueryArgsOf<DM, REL, T> & {
303
+ }) => Promise<LoadWith<DM, REL, T, W, S> | null>;
304
+ findFirstOrThrow: <W extends WithArg<DM, REL, T> = {}, S extends ReadonlyArray<keyof DM[T] & string> | undefined = undefined>(args?: QueryArgsOf<DM, REL, T> & {
305
+ select?: S;
267
306
  with?: W;
268
- }) => Promise<LoadWith<DM, REL, T, W>>;
269
- findMany: <W extends WithArg<DM, REL, T> = {}>(args?: QueryArgsOf<DM, REL, T> & {
307
+ }) => Promise<LoadWith<DM, REL, T, W, S>>;
308
+ findMany: <W extends WithArg<DM, REL, T> = {}, S extends ReadonlyArray<keyof DM[T] & string> | undefined = undefined>(args?: QueryArgsOf<DM, REL, T> & {
309
+ select?: S;
270
310
  with?: W;
271
- }) => Promise<QueryPage<LoadWith<DM, REL, T, W>>>;
311
+ }) => Promise<QueryPage<LoadWith<DM, REL, T, W, S>>>;
272
312
  get: (id: Id<string & T>) => Promise<DM[T] | null>;
273
313
  /**
274
314
  * Group rows by the named keys and apply `agg` per group (defaults to
@@ -299,6 +339,11 @@ interface TableReaderFacade<DM, REL extends Record<keyof DM, object>, RANK exten
299
339
  }
300
340
  /** Read-write typed table accessor exposed on `MutationCtx.db.&lt;table>` / `ActionCtx.db.&lt;table>`. */
301
341
  interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends Record<keyof DM, object>, RANK extends Record<keyof DM, string>, SEARCH extends Record<keyof DM, string>, T extends keyof DM> extends TableReaderFacade<DM, REL, RANK, SEARCH, T> {
342
+ /**
343
+ * Delete a row by id. On a `.softDelete()` table this flips the marker column
344
+ * (and cascades as a soft delete) instead of removing the row; use
345
+ * {@link TableWriterFacade.hardDelete} to force physical removal.
346
+ */
302
347
  delete: (id: Id<string & T>) => Promise<void>;
303
348
  /** Delete many rows in this table by id in one call; returns the *requested* id count (unknown ids are no-ops). Atomic within a mutation (a throw rolls the mutation back); an action has no transaction span. */
304
349
  deleteMany: (ids: ReadonlyArray<Id<string & T>>, options?: {
@@ -306,7 +351,21 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
306
351
  }) => Promise<{
307
352
  deleted: number;
308
353
  }>;
309
- insert: (values: IM[T]) => Promise<Id<string & T>>;
354
+ /** Physically remove a row (and physically cascade `onDelete`), bypassing `.softDelete()`. Same as `delete()` on a non-soft table. */
355
+ hardDelete: (id: Id<string & T>) => Promise<void>;
356
+ /**
357
+ * Insert a document, returning its minted id. With `{ skipDuplicates: true }`
358
+ * a UNIQUE-constraint breach resolves to `null` (the row already exists)
359
+ * instead of throwing — the return type widens to `Id | null` on that overload.
360
+ */
361
+ insert: {
362
+ (values: IM[T], options: {
363
+ skipDuplicates: true;
364
+ }): Promise<Id<string & T> | null>;
365
+ (values: IM[T], options?: {
366
+ skipDuplicates?: boolean;
367
+ }): Promise<Id<string & T>>;
368
+ };
310
369
  /** Insert many documents into this table in one call, returning the minted ids in input order. Atomic within a mutation (a throw rolls the mutation back); an action has no transaction span. */
311
370
  insertMany: (values: ReadonlyArray<IM[T]>, options?: {
312
371
  limit?: number;
@@ -320,9 +379,38 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
320
379
  limit?: number;
321
380
  }) => Promise<void>;
322
381
  replace: (id: Id<string & T>, values: IM[T]) => Promise<void>;
382
+ /** Un-soft-delete a row by id: clears the `.softDelete()` marker so list reads see it again. Throws on a non-soft table. */
383
+ restore: (id: Id<string & T>) => Promise<void>;
384
+ /**
385
+ * Insert when no existing row matches `target`, otherwise patch the match with
386
+ * `update` (defaulting to `create`). `target` names a `.unique()` column (or a
387
+ * tuple) used to look it up. Returns the row id and whether it was `created`.
388
+ * Composes `findFirst` + `insert`/`patch`, so RLS gates each step.
389
+ */
390
+ upsert: (args: {
391
+ create: IM[T];
392
+ target: UpsertTargetOf<DM, T>;
393
+ update?: Partial<IM[T]>;
394
+ }) => Promise<{
395
+ created: boolean;
396
+ id: Id<string & T>;
397
+ }>;
398
+ /** Sequential {@link TableWriterFacade.upsert} over many rows sharing one `target`; one result per input row, in order. */
399
+ upsertMany: (args: {
400
+ rows: ReadonlyArray<{
401
+ create: IM[T];
402
+ update?: Partial<IM[T]>;
403
+ }>;
404
+ target: UpsertTargetOf<DM, T>;
405
+ }) => Promise<{
406
+ created: boolean;
407
+ id: Id<string & T>;
408
+ }[]>;
323
409
  }
410
+ /** Conflict target for `upsert`/`upsertMany`: one column of table `T`, or a tuple of them. */
411
+ type UpsertTargetOf<DM, T extends keyof DM> = ReadonlyArray<keyof DM[T] & string> | (keyof DM[T] & string);
324
412
  /** Per-table read facade — `ctx.db.&lt;table>` on a `QueryCtx`. */
325
413
  type DatabaseReaderFacade<DM, REL extends Record<keyof DM, object>, RANK extends Record<keyof DM, string>, SEARCH extends Record<keyof DM, string>> = { readonly [T in keyof DM]: TableReaderFacade<DM, REL, RANK, SEARCH, T> };
326
414
  /** Per-table read-write facade — `ctx.db.&lt;table>` on a `MutationCtx` / `ActionCtx`. */
327
415
  type DatabaseWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends Record<keyof DM, object>, RANK extends Record<keyof DM, string>, SEARCH extends Record<keyof DM, string>> = { readonly [T in keyof DM]: TableWriterFacade<DM, IM, REL, RANK, SEARCH, T> };
328
- export { AggregateOp, DatabaseReaderFacade, DatabaseWriterFacade, GroupByEntry, Id, LoadWith, ManyRelationWhere, OneRelationWhere, OrderBy, QueryArgs, QueryArgsOf, QueryPage, RankPage, RankResult, RestrictableQueryOptions, RestrictableQueryOptionsOf, SearchFilterBuilder, SearchReader, TableAggregateOptions, TableAggregateOptionsOf, TableGroupByOptions, TableGroupByOptionsOf, TableRankOptions, TableRankPageOptions, TableReaderFacade, TableWriterFacade, Where, WhereOf, WhereOperators, WithArg };
416
+ export { AggregateOp, DatabaseReaderFacade, DatabaseWriterFacade, GroupByEntry, Id, LoadWith, ManyRelationWhere, OneRelationWhere, OrderBy, QueryArgs, QueryArgsOf, QueryPage, RankPage, RankResult, RestrictableQueryOptions, RestrictableQueryOptionsOf, SearchFilterBuilder, SearchReader, TableAggregateOptions, TableAggregateOptionsOf, TableGroupByOptions, TableGroupByOptionsOf, TableRankOptions, TableRankPageOptions, TableReaderFacade, TableWriterFacade, UpsertTargetOf, Where, WhereOf, WhereOperators, WithArg };
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Validator, Infer, v } from '@lunora/values';
2
2
  export { type ColumnValidator, type Id, type Infer, ValidationError, type Validator, type ValidatorKind, v } from '@lunora/values';
3
- import { ArgsValidator, InferArgs, RegisteredAction, ActionCtx, MutationCtx, RegisteredMutation, QueryCtx, RegisteredQuery, RegisteredStream, FunctionKind, LifecycleEvent, RegisteredLifecycleHook, TableDefinition, RegisteredFunction, VectorIndexDefinition, Schema, AggregateOp, RelationDefinition, GlobalBackend, OnDeleteAction, TriggerBuilder, TriggerDefinition, VectorEmbedder, VectorMetric, AggregateIndexDefinition, RankIndexDefinition } from "./types.mjs";
3
+ import { ArgsValidator, InferArgs, RegisteredAction, ActionCtx, MutationCtx, RegisteredMutation, QueryCtx, RegisteredQuery, RegisteredStream, FunctionKind, LifecycleEvent, RegisteredLifecycleHook, TableDefinition, RegisteredFunction, VectorIndexDefinition, Schema, AggregateOp, DurableObjectJurisdiction, RelationDefinition, GlobalBackend, OnDeleteAction, TriggerBuilder, TriggerDefinition, VectorEmbedder, VectorMetric, AggregateIndexDefinition, RankIndexDefinition } from "./types.mjs";
4
4
  export { type AnyApi, type AuthState, type DatabaseReader, type DatabaseWriter, type FunctionVisibility, type IndexDefinition, type IndexRangeBuilder, type LifecycleEventKind, type LunoraLogger, type PaginationOptions, type PaginationResult, type RankSortKey, type ReadOnlyStorage, type ScheduledFunctionDoc, type ScheduledJob, type Scheduler, type SearchFilterBuilder, type SearchIndexDefinition, type ShardMode, type Storage, type StorageMetadata, type SystemDatabaseReader, type SystemDoc, type SystemQuery, type SystemTableName, type TableReader, type TableVectorIndex, type TriggerAggregateOptions, type TriggerCtx, type TriggerDatabase, type TriggerDeleteEvent, type TriggerEvent, type TriggerGroupByEntry, type TriggerGroupByOptions, type TriggerHandler, type TriggerInsertEvent, type TriggerOp, type TriggerQueryArgs, type TriggerQueryPage, type TriggerRankOptions, type TriggerRankPageOptions, type TriggerRankResult, type TriggerRow, type TriggerTiming, type TriggerUpdateEvent, type VectorMatch, type VectorMatches, type VectorQueryInput, type VectorRecord, type VectorSearch, type VectorSearchReader, type VectorUpsertInput, type WorkflowCreateOptions, type WorkflowHandle, type WorkflowInstance, type WorkflowInstanceStatus, type WorkflowStatusResult, type Workflows, anyApi } from "./types.mjs";
5
5
  import { Context, Hono } from 'hono';
6
6
  import { b as Permission, R as Role, T as TypedDefinePolicyInput, a as Policy, D as DefinePolicyInput, W as WhereInput, c as RlsOptions } from "./packem_shared/types.d-DmvyEMD6.mjs";
@@ -325,21 +325,6 @@ declare class LunoraError extends Error {
325
325
  constructor(code: LunoraErrorCode, message?: string);
326
326
  }
327
327
  /**
328
- * The per-table `ctx.db` accessor (the `ctx.db.messages.findMany(...)` form) and
329
- * the kitcn-style `ctx.orm` namespace, as plain runtime helpers. This is the ONE
330
- * source of truth for the facade shape, shared by two callers so they can never
331
- * drift (a drift here is security-relevant — a facade accessor the RLS
332
- * middleware forgot to re-bind would read around policy). `@lunora/codegen`
333
- * emits `ctx.db`/`ctx.orm` by calling these over the raw shard writer (and the
334
- * D1 `globalDb` writer for `.global()` tables); the RLS middleware re-binds the
335
- * policy tables by calling them over the policy-enforcing wrapped writer.
336
- *
337
- * `bindTableFacade(writer, table)` pins `tableName` on the structural writer so
338
- * callers address rows by id (`get`/`delete`/`patch`/`replace`) or by the bound
339
- * table (everything else). The binding is identical regardless of which writer
340
- * is passed — that's the whole point.
341
- */
342
- /**
343
328
  * Minimal structural writer the facade binds over. Declared with **method**
344
329
  * syntax (not arrow properties) so a more-specifically-typed writer — both
345
330
  * `@lunora/do`'s `DatabaseWriterLike` and the RLS middleware's wrapped writer —
@@ -349,7 +334,9 @@ declare class LunoraError extends Error {
349
334
  interface FacadeWriterLike {
350
335
  aggregate(tableName: string, options: unknown): Promise<unknown>;
351
336
  count(tableName: string, where?: unknown): Promise<number>;
352
- delete(id: string, expectedTable?: string): Promise<void>;
337
+ delete(id: string, expectedTable?: string, options?: {
338
+ hard?: boolean;
339
+ }): Promise<void>;
353
340
  deleteMany?(ids: ReadonlyArray<string>, options?: {
354
341
  limit?: number;
355
342
  }, expectedTable?: string): Promise<{
@@ -377,6 +364,7 @@ interface FacadeWriterLike {
377
364
  rank(tableName: string, indexName: string, options: unknown): Promise<unknown>;
378
365
  rankPage(tableName: string, indexName: string, options?: unknown): Promise<unknown>;
379
366
  replace(id: string, document: Record<string, unknown>, expectedTable?: string): Promise<void>;
367
+ restore?(id: string, expectedTable?: string): Promise<void>;
380
368
  }
381
369
  /** The per-table accessor object returned for the `ctx.db` table form. */
382
370
  interface FacadeEntry {
@@ -388,12 +376,16 @@ interface FacadeEntry {
388
376
  }) => Promise<{
389
377
  deleted: number;
390
378
  }>;
379
+ /** `true` when at least one row matches `where` (or any row exists when omitted). Honors RLS like `findFirst`. */
380
+ exists: (where?: unknown) => Promise<boolean>;
391
381
  findFirst: (args?: unknown) => Promise<unknown>;
392
382
  findFirstOrThrow: (args?: unknown) => Promise<unknown>;
393
383
  findMany: (args?: unknown) => Promise<unknown>;
394
384
  get: (id: string) => Promise<unknown>;
395
385
  groupBy: (options: unknown) => Promise<unknown>;
396
- insert: (document: Record<string, unknown>) => Promise<string>;
386
+ /** Physically remove a row (and physically cascade), bypassing `.softDelete()`. */
387
+ hardDelete: (id: string) => Promise<void>;
388
+ insert: (document: Record<string, unknown>, options?: FacadeInsertOptions) => Promise<null | string>;
397
389
  insertMany: (documents: ReadonlyArray<Record<string, unknown>>, options?: {
398
390
  limit?: number;
399
391
  }) => Promise<string[]>;
@@ -407,8 +399,47 @@ interface FacadeEntry {
407
399
  rank: (indexName: string, options: unknown) => Promise<unknown>;
408
400
  rankPage: (indexName: string, options?: unknown) => Promise<unknown>;
409
401
  replace: (id: string, document: Record<string, unknown>) => Promise<void>;
402
+ /** Un-soft-delete a row: clears the `.softDelete()` marker (by-id, so it reaches a row list reads hide). */
403
+ restore: (id: string) => Promise<void>;
404
+ /** Insert when no row matches `target`, else patch the match. Composes `findFirst` + `insert`/`patch`, so RLS applies to each step. */
405
+ upsert: (args: UpsertArgs) => Promise<UpsertResult>;
406
+ /** Sequential `upsert` over many rows sharing one `target`; returns one result per input row in order. */
407
+ upsertMany: (args: UpsertManyArgs) => Promise<UpsertResult[]>;
410
408
  withSearchIndex: (indexName: string, search: (q: unknown) => unknown) => unknown;
411
409
  }
410
+ /** Options accepted by the per-table `insert` accessor. */
411
+ interface FacadeInsertOptions {
412
+ /**
413
+ * When `true`, a UNIQUE-constraint breach is swallowed: the insert becomes a
414
+ * silent no-op and resolves to `null` instead of throwing a `CONFLICT`. Any
415
+ * other error still propagates. Mirrors better-drizzle's `create({ skipDuplicates })`.
416
+ */
417
+ skipDuplicates?: boolean;
418
+ }
419
+ /** The conflict target for `upsert`/`upsertMany`: one field name or a tuple of them. */
420
+ type UpsertTarget = ReadonlyArray<string> | string;
421
+ /** Argument to the per-table `upsert` accessor. */
422
+ interface UpsertArgs {
423
+ /** Document inserted when no existing row matches the `target`. */
424
+ create: Record<string, unknown>;
425
+ /** Field(s) — typically a `.unique()` column or unique index — used to look up an existing row. */
426
+ target: UpsertTarget;
427
+ /** Patch applied when an existing row matches the `target`. Defaults to `create`. */
428
+ update?: Record<string, unknown>;
429
+ }
430
+ /** Result of an `upsert`: the row's id and whether it was freshly inserted (`true`) or updated (`false`). */
431
+ interface UpsertResult {
432
+ created: boolean;
433
+ id: string;
434
+ }
435
+ /** Argument to the per-table `upsertMany` accessor — a shared `target` plus per-row create/update payloads. */
436
+ interface UpsertManyArgs {
437
+ rows: ReadonlyArray<{
438
+ create: Record<string, unknown>;
439
+ update?: Record<string, unknown>;
440
+ }>;
441
+ target: UpsertTarget;
442
+ }
412
443
  /**
413
444
  * Bind a structural writer to one table, producing its `ctx.db` table accessor.
414
445
  *
@@ -426,7 +457,7 @@ declare const bindTableFacade: (writer: FacadeWriterLike, tableName: string) =>
426
457
  interface OrmLike {
427
458
  delete: (table: string, id: string) => Promise<void>;
428
459
  insert: (table: string) => {
429
- values: (document: Record<string, unknown>) => Promise<string>;
460
+ values: (document: Record<string, unknown>) => Promise<null | string>;
430
461
  };
431
462
  query: Record<string, FacadeEntry>;
432
463
  replace: (table: string, id: string) => {
@@ -1168,6 +1199,22 @@ interface TableBuilder<Shape extends Record<string, Validator> = Record<string,
1168
1199
  }) => TableBuilder<Shape>;
1169
1200
  /** Route storage by the named field — one DO per distinct value. */
1170
1201
  shardBy: (field: keyof Shape & string) => TableBuilder<Shape>;
1202
+ /**
1203
+ * Turn on soft delete. Adds a nullable timestamp column (`options.field`,
1204
+ * default `deletedAt`) and changes `ctx.db.&lt;table>.delete()` to **set** it
1205
+ * instead of removing the row; `onDelete: "cascade"` children are recursively
1206
+ * soft-deleted too. **List reads** (`findMany`/`findFirst`/`query()`/`count`/
1207
+ * `aggregate`/relation loads) then hide soft-deleted rows unless they pass
1208
+ * `includeDeleted: true`; by-id `get`/`patch`/`replace` and the new
1209
+ * `restore()` still address the row directly. `hardDelete()` physically
1210
+ * removes it (cascading as a real delete). Note: `includeDeleted` is a read
1211
+ * scope, not access control — anyone who can run the read can set it; a unique
1212
+ * index still rejects a new row that collides with a soft-deleted one (the row
1213
+ * physically persists).
1214
+ */
1215
+ softDelete: (options?: {
1216
+ field?: string;
1217
+ }) => TableBuilder<Shape>;
1171
1218
  /** Declare named lifecycle triggers fired inline within the write path. */
1172
1219
  triggers: (build: (t: TriggerBuilder<Shape>) => Record<string, TriggerDefinition>) => TableBuilder<Shape>;
1173
1220
  /** Declare a vector index over a single text field on this table. */
@@ -1190,7 +1237,7 @@ interface VectorIndexOptions {
1190
1237
  * Build a table definition. Returned object is both the table definition (for
1191
1238
  * `defineSchema`) and a fluent builder for indexes + sharding metadata.
1192
1239
  */
1193
- declare const defineTable: <Shape extends Record<string, Validator>>(shape: Shape) => TableBuilder<Shape>;
1240
+ declare const defineTable: <Shape extends Record<string, Validator>>(inputShape: Shape) => TableBuilder<Shape>;
1194
1241
  /**
1195
1242
  * Declare a standalone vector index (DSL Shape B). Pass the returned value in
1196
1243
  * the `vectorIndexes` map of {@link defineSchema} when the source is derived
@@ -1262,6 +1309,28 @@ type ExtendableSchema<T extends Record<string, TableDefinition>> = {
1262
1309
  readonly key: Key;
1263
1310
  }) => ExtendableSchema<PrefixedTables<X, Key> & T>;
1264
1311
  /**
1312
+ * Pin every Durable Object the app reaches — shards, fan-out, subscriptions,
1313
+ * the scheduler, and `ctx.containers` — to a Cloudflare data-residency
1314
+ * jurisdiction (`"eu"`, `"us"`, `"fedramp"`). Codegen reads this off the
1315
+ * schema and emits it into the generated worker's `createWorker({ jurisdiction })`
1316
+ * (and `ctx.scheduler` / `ctx.containers`). Non-mutating: returns a fresh
1317
+ * `ExtendableSchema`, so it composes with `.rls(...)` / `.extend(...)` in any order.
1318
+ *
1319
+ * ⚠️ **Set this once, before your first deploy — changing or removing it
1320
+ * strands data.** A Durable Object name maps to a *different* ID in each
1321
+ * jurisdiction, so toggling this on an existing app makes every shard, scheduler
1322
+ * job, and session DO resolve to a NEW, empty DO; the previous data stays in the
1323
+ * old jurisdiction's DOs and is no longer reachable. There is no in-place
1324
+ * migration — you would have to export from the old jurisdiction and import
1325
+ * into the new one.
1326
+ *
1327
+ * Note: this pins **DO-backed** state only. D1-backed state — `.global()`
1328
+ * tables and `@lunora/auth` sessions alike — is governed by D1's own location
1329
+ * settings, not this option.
1330
+ * @see https://developers.cloudflare.com/durable-objects/reference/data-location/
1331
+ */
1332
+ jurisdiction: (jurisdiction: DurableObjectJurisdiction) => ExtendableSchema<T>;
1333
+ /**
1265
1334
  * Turn on secure-by-default RLS for the whole schema. Every table is then
1266
1335
  * protected — the DO/D1 write path denies raw, non-RLS `ctx.db` access, so a
1267
1336
  * procedure that forgets `.use(rls(...))` fails closed. Opt a table out with
@@ -1562,7 +1631,9 @@ interface DatabaseWriterLike {
1562
1631
  */
1563
1632
  aggregate: (tableName: string, options: AggregateArgs) => Promise<null | number>;
1564
1633
  count: (tableName: string, whereOrArgs?: CountArgs | WhereInput) => Promise<number>;
1565
- delete: (id: string, expectedTable?: string) => Promise<void>;
1634
+ delete: (id: string, expectedTable?: string, options?: {
1635
+ hard?: boolean;
1636
+ }) => Promise<void>;
1566
1637
  deleteMany: (ids: ReadonlyArray<string>, options?: {
1567
1638
  limit?: number;
1568
1639
  }, expectedTable?: string) => Promise<{
@@ -1633,6 +1704,7 @@ interface DatabaseWriterLike {
1633
1704
  */
1634
1705
  rankPage: (tableName: string, indexName: string, options?: RankPageArgs) => Promise<QueryPage>;
1635
1706
  replace: (id: string, document: Record<string, unknown>, expectedTable?: string) => Promise<void>;
1707
+ restore?: (id: string, expectedTable?: string) => Promise<void>;
1636
1708
  }
1637
1709
  /**
1638
1710
  * What a procedure's `ctx.db` must structurally satisfy for the middleware
@@ -1738,4 +1810,4 @@ interface StorageContextIn {
1738
1810
  }
1739
1811
  declare const storageRules: <Context extends StorageContextIn = StorageContextIn>(rules: ReadonlyArray<StorageRule<Context>>, options?: StorageRulesOptions) => Middleware<Context, Context>;
1740
1812
  declare const VERSION = "0.0.0";
1741
- export { type ActionBuilder, type ActionCtx, type AggregateIndexDefinition, type AggregateIndexOptions, type AggregateOp, type ArgsValidator, type Component, type ComponentFunctions, type CreateOptions, type DataModelInit, type DefineComponentOptions, type DefinePluginOptions, type DefinePolicyInput, type DefinePresenceOptions, type DefineStorageRuleInput, type EmptyArgs, type EnvAccessor, type EnvKeyFailure, type EnvShape, type ExtendableSchema, type FacadeEntry, type FacadeWriterLike, type FunctionKind, type HttpActionCtx, type HttpActionHandler, type HttpMethod, type HttpRoute, type HttpRouteBuilder, type HttpRouteFactory, type HttpRouteHandlerOptions, type HttpStreamHandlerOptions, type InferArgs, type InferEnv, type InlineAggregateIndexOptions, type InlineRankIndexOptions, type InternalActionBuilder, type InternalMutationBuilder, type InternalQueryBuilder, type LifecycleEvent, type LifecycleHandler, type LunoraBuilders, LunoraEnvError, LunoraError, type LunoraErrorCode, type LunoraHttpApp, type LunoraHttpEnv, type LunoraRouteHandler, type ManyRelation, type MaskColumns, type MaskContext, type MaskFn, type MaskOptions, type MaskPolicies, type MaskStrategy, type Middleware, type MiddlewareNext, type MigrationDefinition, type MigrationDocument, type MigrationTransform, type MutationBuilder, type MutationCtx, type OnDeleteAction, type OneRelation, type OrmLike, DEFAULT_TTL_MS as PRESENCE_DEFAULT_TTL_MS, PRESENCE_TABLE, type Permission, type Plugin, type Policy, type PrefixedTables, type PresenceComponent, type PresenceFunctions, type PresenceMember, type ProtectPublicOptions, type QueryBuilder, type QueryCtx, type RankIndexDefinition, type RankIndexOptions, type RegisteredAction, type RegisteredFunction, type RegisteredLifecycleHook, type RegisteredMigration, type RegisteredMutation, type RegisteredQuery, type RegisteredStream, type RelationBuilder, type RelationDefinition, type RlsOptions, type Role, type Schema, type SchemaExtension, type StorageOperation, type StorageRule, type StorageRuleContext, type StorageRuleDecision, type StorageRulesOptions, type TableBuilder, type TableDefinition, type TerminalKind, type TriggerBuilder, type TriggerDefinition, type TypedDefinePolicyInput, VERSION, type VectorEmbedder, type VectorIndexDefinition, type VectorIndexOptions, type VectorMetric, type VectorizeOptions, type WhereInput, asBucketStorage, bindOrm, bindTableFacade, composePluginMiddleware, createPolicyDsl, defineAggregateIndex, defineComponent, defineEnv, defineMigration, definePermission, definePlugin, definePolicies, definePolicy, definePresence, defineRankIndex, defineRole, defineSchema, defineSchemaExtension, defineStorageRule, defineStorageRules, defineTable, defineVectorIndex, httpAction, httpRoute, httpRouter, initLunora, installPlugins, mask, mergeSchemaExtension, onConnect, onDisconnect, presenceExtension, protectPublic, redactSecrets, rls, serveStorageObject, storageRules };
1813
+ export { type ActionBuilder, type ActionCtx, type AggregateIndexDefinition, type AggregateIndexOptions, type AggregateOp, type ArgsValidator, type Component, type ComponentFunctions, type CreateOptions, type DataModelInit, type DefineComponentOptions, type DefinePluginOptions, type DefinePolicyInput, type DefinePresenceOptions, type DefineStorageRuleInput, type DurableObjectJurisdiction, type EmptyArgs, type EnvAccessor, type EnvKeyFailure, type EnvShape, type ExtendableSchema, type FacadeEntry, type FacadeWriterLike, type FunctionKind, type HttpActionCtx, type HttpActionHandler, type HttpMethod, type HttpRoute, type HttpRouteBuilder, type HttpRouteFactory, type HttpRouteHandlerOptions, type HttpStreamHandlerOptions, type InferArgs, type InferEnv, type InlineAggregateIndexOptions, type InlineRankIndexOptions, type InternalActionBuilder, type InternalMutationBuilder, type InternalQueryBuilder, type LifecycleEvent, type LifecycleHandler, type LunoraBuilders, LunoraEnvError, LunoraError, type LunoraErrorCode, type LunoraHttpApp, type LunoraHttpEnv, type LunoraRouteHandler, type ManyRelation, type MaskColumns, type MaskContext, type MaskFn, type MaskOptions, type MaskPolicies, type MaskStrategy, type Middleware, type MiddlewareNext, type MigrationDefinition, type MigrationDocument, type MigrationTransform, type MutationBuilder, type MutationCtx, type OnDeleteAction, type OneRelation, type OrmLike, DEFAULT_TTL_MS as PRESENCE_DEFAULT_TTL_MS, PRESENCE_TABLE, type Permission, type Plugin, type Policy, type PrefixedTables, type PresenceComponent, type PresenceFunctions, type PresenceMember, type ProtectPublicOptions, type QueryBuilder, type QueryCtx, type RankIndexDefinition, type RankIndexOptions, type RegisteredAction, type RegisteredFunction, type RegisteredLifecycleHook, type RegisteredMigration, type RegisteredMutation, type RegisteredQuery, type RegisteredStream, type RelationBuilder, type RelationDefinition, type RlsOptions, type Role, type Schema, type SchemaExtension, type StorageOperation, type StorageRule, type StorageRuleContext, type StorageRuleDecision, type StorageRulesOptions, type TableBuilder, type TableDefinition, type TerminalKind, type TriggerBuilder, type TriggerDefinition, type TypedDefinePolicyInput, VERSION, type VectorEmbedder, type VectorIndexDefinition, type VectorIndexOptions, type VectorMetric, type VectorizeOptions, type WhereInput, asBucketStorage, bindOrm, bindTableFacade, composePluginMiddleware, createPolicyDsl, defineAggregateIndex, defineComponent, defineEnv, defineMigration, definePermission, definePlugin, definePolicies, definePolicy, definePresence, defineRankIndex, defineRole, defineSchema, defineSchemaExtension, defineStorageRule, defineStorageRules, defineTable, defineVectorIndex, httpAction, httpRoute, httpRouter, initLunora, installPlugins, mask, mergeSchemaExtension, onConnect, onDisconnect, presenceExtension, protectPublic, redactSecrets, rls, serveStorageObject, storageRules };