@lunora/server 1.0.0-alpha.192 → 1.0.0-alpha.194
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 +165 -14
- package/dist/data-model.d.ts +165 -14
- package/dist/in-process.mjs +1 -1
- package/dist/index.d.mts +59 -3
- package/dist/index.d.ts +59 -3
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/{ACTION_CACHE_DEFAULT_TTL_MS-DITNUhX1.mjs → ACTION_CACHE_DEFAULT_TTL_MS-CPywsACf.mjs} +1 -1
- package/dist/packem_shared/{DOCUMENT_HISTORY_REDACTED_FIELDS-BYeHnULU.mjs → DOCUMENT_HISTORY_REDACTED_FIELDS-D2Yzbu0B.mjs} +1 -1
- package/dist/packem_shared/{PRESENCE_DEFAULT_TTL_MS-Bvno49rr.mjs → PRESENCE_DEFAULT_TTL_MS-BH2zGHxn.mjs} +1 -1
- package/dist/packem_shared/{assertShapesDeclareReadPolicies-CUB_PC20.mjs → assertShapesDeclareReadPolicies-DV6ejDpe.mjs} +1 -1
- package/dist/packem_shared/bindOrm-BaAMwCFL.mjs +1 -0
- package/dist/packem_shared/{composePluginMiddleware-bf3t7KZi.mjs → composePluginMiddleware-CSwsfLtS.mjs} +1 -1
- package/dist/packem_shared/{defineAggregateIndex--ttNAY7M.mjs → defineAggregateIndex-DR1_vB45.mjs} +1 -1
- package/dist/packem_shared/{defineShape-raxlSVvO.mjs → defineShape-dWV0tQBF.mjs} +1 -1
- package/dist/packem_shared/mask-DDttugol.mjs +1 -0
- package/dist/packem_shared/middleware-BZAwl2WQ.mjs +1 -0
- package/dist/packem_shared/plugin-DsVYnlmv.mjs +1 -0
- package/dist/packem_shared/rls-CpVetPZf.mjs +1 -0
- package/dist/packem_shared/{storageRules-BQx91H4g.mjs → storageRules-DUWOC6r7.mjs} +1 -1
- package/dist/rls/testing.mjs +1 -1
- package/package.json +4 -4
- package/dist/packem_shared/bindOrm-D_hFUjmr.mjs +0 -1
- package/dist/packem_shared/mask-0D6SL3i5.mjs +0 -1
- package/dist/packem_shared/middleware-DAVx_tP1.mjs +0 -1
- package/dist/packem_shared/plugin-xbEqjwqP.mjs +0 -1
- package/dist/packem_shared/rls-CpSeGhdp.mjs +0 -1
package/dist/data-model.d.mts
CHANGED
|
@@ -37,14 +37,53 @@ interface WhereOperators<T> {
|
|
|
37
37
|
ne?: T;
|
|
38
38
|
notIn?: T[];
|
|
39
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* A value stored as a plain JS object: not a scalar (an `Id<T>` is a branded string, which is an `object` to
|
|
42
|
+
* TypeScript but has no keys worth offering), an array, a date, bytes, a bigint or a function.
|
|
43
|
+
*/
|
|
44
|
+
type IsPlainObject<V> = V extends string | number | boolean | bigint | symbol ? false : V extends ReadonlyArray<unknown> ? false : V extends Date | Uint8Array | ArrayBuffer | bigint | ((...arguments_: never[]) => unknown) ? false : V extends object ? true : false;
|
|
45
|
+
/** The dotted paths below an object, to three steps. */
|
|
46
|
+
type SubPaths<V, Depth extends unknown[]> = Depth["length"] extends 3 ? never : [IsPlainObject<V>] extends [true] ? { [K in keyof V & string]-?: K | `${K}.${SubPaths<NonNullable<V[K]>, [...Depth, 0]>}`; }[keyof V & string] : never;
|
|
47
|
+
/** The type at the end of dotted path `P` below `V`. */
|
|
48
|
+
type PathValue<V, P extends string> = P extends `${infer Head}.${infer Rest}` ? Head extends keyof V ? PathValue<NonNullable<V[Head]>, Rest> : never : P extends keyof V ? V[P] : never;
|
|
49
|
+
/**
|
|
50
|
+
* Every dotted path into an object-valued column of `Doc` (`"profile.address.city"`), at most four segments
|
|
51
|
+
* counting the column. A column that is not a plain object contributes none.
|
|
52
|
+
*/
|
|
53
|
+
type ColumnPaths<Doc> = { [K in keyof Doc & string]-?: [IsPlainObject<NonNullable<Doc[K]>>] extends [true] ? `${K}.${SubPaths<NonNullable<Doc[K]>, []>}` : never; }[keyof Doc & string];
|
|
54
|
+
/** The type at the end of a {@link ColumnPaths} path. */
|
|
55
|
+
type DocPathValue<Doc, P extends string> = P extends `${infer Column}.${infer Rest}` ? Column extends keyof Doc ? PathValue<NonNullable<Doc[Column]>, Rest> : never : never;
|
|
56
|
+
type ScalarLeaf = boolean | number | string | null | undefined;
|
|
57
|
+
/** The dotted paths into an object column that end at a string, number or boolean. */
|
|
58
|
+
type ScalarPaths<Doc> = { [P in ColumnPaths<Doc>]: [DocPathValue<Doc, P>] extends [ScalarLeaf] ? P : never; }[ColumnPaths<Doc>];
|
|
59
|
+
/**
|
|
60
|
+
* `where` keys that reach into an object column: `{ "profile.plan": "pro" }`. Only paths that end at a string,
|
|
61
|
+
* number or boolean are offered — an object, array, date, bigint or bytes leaf has no single SQL comparison.
|
|
62
|
+
*
|
|
63
|
+
* `unknown` (the identity for `&`) when there are none, never `{}`: intersecting with an empty object type
|
|
64
|
+
* switches off the weak-type check that rejects a `where` key naming nothing.
|
|
65
|
+
*/
|
|
66
|
+
type PathWhere<Doc, Paths extends string = ScalarPaths<Doc>> = [Paths] extends [never] ? unknown : { [P in Paths]?: DocPathValue<Doc, P> | WhereOperators<DocPathValue<Doc, P>>; };
|
|
67
|
+
/** `patch` keys that set one value inside an object column, keeping its siblings: `{ "profile.plan": "pro" }`. */
|
|
68
|
+
type PathPatch<Doc, Paths extends string = ColumnPaths<Doc>> = [Paths] extends [never] ? unknown : { [P in Paths]?: DocPathValue<Doc, P>; };
|
|
40
69
|
/** A typed `where` tree over a document's columns. */
|
|
41
|
-
type Where<TDocument> = { [K in keyof TDocument]?: TDocument[K] | WhereOperators<TDocument[K]>; } & {
|
|
70
|
+
type Where<TDocument> = PathWhere<TDocument> & { [K in keyof TDocument]?: TDocument[K] | WhereOperators<TDocument[K]>; } & {
|
|
42
71
|
AND?: Where<TDocument>[];
|
|
43
72
|
NOT?: Where<TDocument>;
|
|
44
73
|
OR?: Where<TDocument>[];
|
|
45
74
|
};
|
|
46
|
-
/**
|
|
47
|
-
|
|
75
|
+
/**
|
|
76
|
+
* One ordering entry; `orderBy` is an ordered list. `{ field: "asc" | "desc" }` sorts NULLs first
|
|
77
|
+
* ascending and last descending. `{ field: { sort: "desc", nulls: "first" } }` places them yourself.
|
|
78
|
+
*
|
|
79
|
+
* A placement other than the default can change the query plan (see Pagination in the docs), so
|
|
80
|
+
* measure a hot read. It has no effect on a column that cannot hold NULL. Keep the same `orderBy` for every page of a
|
|
81
|
+
* paginated read, as a cursor is only valid against the ordering that minted it.
|
|
82
|
+
*/
|
|
83
|
+
type OrderBy<TDocument> = Partial<Record<keyof TDocument | ScalarPaths<TDocument>, "asc" | "desc" | {
|
|
84
|
+
nulls: "first" | "last";
|
|
85
|
+
sort: "asc" | "desc";
|
|
86
|
+
}>>;
|
|
48
87
|
interface QueryArgs<TDocument> {
|
|
49
88
|
cursor?: null | string;
|
|
50
89
|
limit?: number;
|
|
@@ -96,7 +135,7 @@ type RelationWhere<DM, REL extends Record<keyof DM, object>, T extends keyof DM>
|
|
|
96
135
|
* `Where<DM[T]>` stays the column-only structural mirror for back-compat; the
|
|
97
136
|
* table facade threads `REL` through this richer form.
|
|
98
137
|
*/
|
|
99
|
-
type WhereOf<DM, REL extends Record<keyof DM, object>, T extends keyof DM> = RelationWhere<DM, REL, T> & { [K in keyof DM[T]]?: DM[T][K] | WhereOperators<DM[T][K]>; } & {
|
|
138
|
+
type WhereOf<DM, REL extends Record<keyof DM, object>, T extends keyof DM> = PathWhere<DM[T]> & RelationWhere<DM, REL, T> & { [K in keyof DM[T]]?: DM[T][K] | WhereOperators<DM[T][K]>; } & {
|
|
100
139
|
AND?: WhereOf<DM, REL, T>[];
|
|
101
140
|
NOT?: WhereOf<DM, REL, T>;
|
|
102
141
|
OR?: WhereOf<DM, REL, T>[];
|
|
@@ -348,6 +387,20 @@ interface TableReaderFacade<DM, REL extends Record<keyof DM, object>, RANK exten
|
|
|
348
387
|
count: (where?: RestrictableQueryOptionsOf<DM, REL, T> | WhereOf<DM, REL, T>) => Promise<number>;
|
|
349
388
|
/** `true` when at least one row matches `where` (any row when omitted). RLS-filtered exactly like `findFirst`. */
|
|
350
389
|
exists: (where?: WhereOf<DM, REL, T>) => Promise<boolean>;
|
|
390
|
+
/**
|
|
391
|
+
* Describe how this table would run `findMany(args)` without running it: the SQL, its bound
|
|
392
|
+
* parameters, and the database's own plan, one line per step. Use it to check that a filter is
|
|
393
|
+
* served by an index (`SEARCH … USING INDEX by_room`) rather than a scan (`SCAN …`).
|
|
394
|
+
*
|
|
395
|
+
* Honors RLS and soft delete exactly like the read, so the plan is the one your caller would get.
|
|
396
|
+
* Explaining does not subscribe a live query to this table. A relation filter in `where` is resolved
|
|
397
|
+
* first with an ordinary read of the related table, which does subscribe to that table, since the ids
|
|
398
|
+
* it matched are part of `params`. Takes no `with` or `select`: neither changes the statement.
|
|
399
|
+
*
|
|
400
|
+
* `params` carries values your RLS policies injected and, for a relation filter, the ids it matched.
|
|
401
|
+
* Keep the result on the server rather than returning it to a client.
|
|
402
|
+
*/
|
|
403
|
+
explain: (args?: QueryArgsOf<DM, REL, T>) => Promise<QueryPlan>;
|
|
351
404
|
findFirst: <W extends WithArg<DM, REL, T> = {}, S extends ReadonlyArray<keyof DM[T] & string> | undefined = undefined>(args?: QueryArgsOf<DM, REL, T> & {
|
|
352
405
|
select?: S;
|
|
353
406
|
with?: W;
|
|
@@ -442,10 +495,10 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
|
|
|
442
495
|
* instead of throwing — the return type widens to `Id | null` on that overload.
|
|
443
496
|
*/
|
|
444
497
|
insert: {
|
|
445
|
-
(values: IM
|
|
498
|
+
(values: InsertValues<DM, IM, REL, T>, options: {
|
|
446
499
|
skipDuplicates: true;
|
|
447
500
|
}): Promise<Id<string & T> | null>;
|
|
448
|
-
(values: IM
|
|
501
|
+
(values: InsertValues<DM, IM, REL, T>, options?: {
|
|
449
502
|
skipDuplicates?: boolean;
|
|
450
503
|
}): Promise<Id<string & T>>;
|
|
451
504
|
};
|
|
@@ -464,7 +517,7 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
|
|
|
464
517
|
skipDuplicates?: boolean;
|
|
465
518
|
}): Promise<Id<string & T>[]>;
|
|
466
519
|
};
|
|
467
|
-
patch: (id: Id<string & T>, values:
|
|
520
|
+
patch: (id: Id<string & T>, values: PatchValues<IM[T]> & RelationWrites<DM, REL, T>) => Promise<void>;
|
|
468
521
|
/**
|
|
469
522
|
* Patch many rows in this table. Pass an array of `{ id, values }` or
|
|
470
523
|
* `{ where, values }` to patch matching rows with the same values. Returns
|
|
@@ -473,7 +526,7 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
|
|
|
473
526
|
patchMany: {
|
|
474
527
|
(patches: ReadonlyArray<{
|
|
475
528
|
id: Id<string & T>;
|
|
476
|
-
values:
|
|
529
|
+
values: PatchValues<IM[T]>;
|
|
477
530
|
}>, options?: {
|
|
478
531
|
limit?: number;
|
|
479
532
|
}): Promise<{
|
|
@@ -481,7 +534,7 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
|
|
|
481
534
|
}>;
|
|
482
535
|
(args: {
|
|
483
536
|
limit?: number;
|
|
484
|
-
values:
|
|
537
|
+
values: PatchValues<IM[T]>;
|
|
485
538
|
where: Partial<DM[T]>;
|
|
486
539
|
}): Promise<{
|
|
487
540
|
patched: number;
|
|
@@ -497,9 +550,9 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
|
|
|
497
550
|
* Composes `findFirst` + `insert`/`patch`, so RLS gates each step.
|
|
498
551
|
*/
|
|
499
552
|
upsert: (args: {
|
|
500
|
-
create: IM
|
|
553
|
+
create: InsertValues<DM, IM, REL, T>;
|
|
501
554
|
target: UpsertTargetOf<DM, T>;
|
|
502
|
-
update?:
|
|
555
|
+
update?: PatchValues<IM[T]> & RelationWrites<DM, REL, T>;
|
|
503
556
|
}) => Promise<{
|
|
504
557
|
created: boolean;
|
|
505
558
|
id: Id<string & T>;
|
|
@@ -507,8 +560,8 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
|
|
|
507
560
|
/** Sequential {@link TableWriterFacade.upsert} over many rows sharing one `target`; one result per input row, in order. */
|
|
508
561
|
upsertMany: (args: {
|
|
509
562
|
rows: ReadonlyArray<{
|
|
510
|
-
create: IM
|
|
511
|
-
update?:
|
|
563
|
+
create: InsertValues<DM, IM, REL, T>;
|
|
564
|
+
update?: PatchValues<IM[T]> & RelationWrites<DM, REL, T>;
|
|
512
565
|
}>;
|
|
513
566
|
target: UpsertTargetOf<DM, T>;
|
|
514
567
|
}) => Promise<{
|
|
@@ -518,8 +571,106 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
|
|
|
518
571
|
}
|
|
519
572
|
/** Conflict target for `upsert`/`upsertMany`: one column of table `T`, or a tuple of them. */
|
|
520
573
|
type UpsertTargetOf<DM, T extends keyof DM> = ReadonlyArray<keyof DM[T] & string> | (keyof DM[T] & string);
|
|
574
|
+
/**
|
|
575
|
+
* An atomic update for a number column, applied to the value the row holds when the
|
|
576
|
+
* write runs: `{ increment: 1 }`, `{ decrement: 1 }`, `{ multiply: 2 }`, `{ divide: 2 }`.
|
|
577
|
+
* The column must already hold a finite number; a result that is not finite is rejected.
|
|
578
|
+
*/
|
|
579
|
+
type NumberFieldOperator = {
|
|
580
|
+
decrement: number;
|
|
581
|
+
divide?: never;
|
|
582
|
+
increment?: never;
|
|
583
|
+
multiply?: never;
|
|
584
|
+
} | {
|
|
585
|
+
decrement?: never;
|
|
586
|
+
divide: number;
|
|
587
|
+
increment?: never;
|
|
588
|
+
multiply?: never;
|
|
589
|
+
} | {
|
|
590
|
+
decrement?: never;
|
|
591
|
+
divide?: never;
|
|
592
|
+
increment: number;
|
|
593
|
+
multiply?: never;
|
|
594
|
+
} | {
|
|
595
|
+
decrement?: never;
|
|
596
|
+
divide?: never;
|
|
597
|
+
increment?: never;
|
|
598
|
+
multiply: number;
|
|
599
|
+
};
|
|
600
|
+
/** An atomic update for a boolean column: `{ toggle: true }` flips the stored value. */
|
|
601
|
+
interface BooleanFieldOperator {
|
|
602
|
+
toggle: true;
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* The values a `patch` accepts: any column's own type, and for a number or boolean
|
|
606
|
+
* column also an atomic operator ({@link NumberFieldOperator}, {@link BooleanFieldOperator}).
|
|
607
|
+
*/
|
|
608
|
+
type PatchValues<Row> = PathPatch<Row> & { [K in keyof Row]?: Row[K] | OperatorFor<NonNullable<Row[K]>>; };
|
|
609
|
+
/**
|
|
610
|
+
* The operator a column of type `T` takes: arithmetic when `T` is exactly `number` (so a literal union
|
|
611
|
+
* such as `1 | 2` is out — the result could leave the set — and so is `number | string`, which the
|
|
612
|
+
* store does not treat as a number column), `{ toggle: true }` when it is exactly `boolean`.
|
|
613
|
+
*/
|
|
614
|
+
type OperatorFor<T> = [T] extends [number] ? [number] extends [T] ? NumberFieldOperator : never : [T] extends [boolean] ? [boolean] extends [T] ? BooleanFieldOperator : never : never;
|
|
615
|
+
/** What `explain` returns: the SQL a read compiles to, its bound parameters, and the database's plan for it. */
|
|
616
|
+
interface QueryPlan {
|
|
617
|
+
/** The bound parameters, in order. */
|
|
618
|
+
params: unknown[];
|
|
619
|
+
/** One line per plan step, as the database reports it. */
|
|
620
|
+
plan: string[];
|
|
621
|
+
/** The statement the read compiles to. */
|
|
622
|
+
sql: string;
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* Nested write for a to-one relation: point the row at `Target` (`connect`), or clear the link (`disconnect`, which
|
|
626
|
+
* needs a foreign key that can be empty). One or the other, not both.
|
|
627
|
+
*/
|
|
628
|
+
type ToOneRelationWrite<TargetId> = {
|
|
629
|
+
connect: TargetId;
|
|
630
|
+
disconnect?: never;
|
|
631
|
+
} | {
|
|
632
|
+
connect?: never;
|
|
633
|
+
disconnect: true;
|
|
634
|
+
};
|
|
635
|
+
/**
|
|
636
|
+
* Nested write for a to-many relation: point `Target` rows at this one (`connect`), release them (`disconnect`, which
|
|
637
|
+
* needs a foreign key that can be empty), or replace the whole list (`set`: rows not named are released). `set`
|
|
638
|
+
* cannot be combined with the other two.
|
|
639
|
+
*/
|
|
640
|
+
type ToManyRelationWrite<TargetId> = {
|
|
641
|
+
connect?: never;
|
|
642
|
+
disconnect?: never;
|
|
643
|
+
set: ReadonlyArray<TargetId>;
|
|
644
|
+
} | {
|
|
645
|
+
connect?: ReadonlyArray<TargetId>;
|
|
646
|
+
disconnect?: ReadonlyArray<TargetId>;
|
|
647
|
+
set?: never;
|
|
648
|
+
};
|
|
649
|
+
/**
|
|
650
|
+
* Nested relation writes accepted by `insert`, `patch` and `upsert`, keyed by relation name:
|
|
651
|
+
* `{ author: { connect: userId } }`, `{ posts: { set: [a, b] } }`. A table with no relations contributes none
|
|
652
|
+
* (`unknown`, the identity for `&`, never `{}`: an empty object type would switch off the weak-type check).
|
|
653
|
+
*/
|
|
654
|
+
type RelationWrites<DM, REL extends Record<keyof DM, object>, T extends keyof DM> = [keyof REL[T]] extends [never] ? unknown : { [K in keyof REL[T]]?: REL[T][K] extends {
|
|
655
|
+
__relationKind: "one";
|
|
656
|
+
__target: infer Target extends keyof DM;
|
|
657
|
+
} ? ToOneRelationWrite<Id<string & Target>> : REL[T][K] extends {
|
|
658
|
+
__relationKind: "many";
|
|
659
|
+
__target: infer Target extends keyof DM;
|
|
660
|
+
} ? ToManyRelationWrite<Id<string & Target>> : never; };
|
|
661
|
+
/** The foreign-key columns of a table's to-one relations — the keys a nested `connect` supplies. */
|
|
662
|
+
type OneRelationFields<RelT> = { [K in keyof RelT]: RelT[K] extends {
|
|
663
|
+
__field: infer Field extends string;
|
|
664
|
+
__relationKind: "one";
|
|
665
|
+
} ? Field : never; }[keyof RelT];
|
|
666
|
+
/**
|
|
667
|
+
* What `insert` accepts: the row as it is, or the row without its to-one foreign keys plus the nested writes that
|
|
668
|
+
* supply them. Leaving a key out with no `connect` to supply it is not caught by the type — the store's own
|
|
669
|
+
* validation rejects the missing field.
|
|
670
|
+
*/
|
|
671
|
+
type InsertValues<DM, IM extends Record<keyof DM, object>, REL extends Record<keyof DM, object>, T extends keyof DM> = IM[T] | (Omit<IM[T], OneRelationFields<REL[T]>> & RelationWrites<DM, REL, T>);
|
|
521
672
|
/** Per-table read facade — `ctx.db.<table>` on a `QueryCtx`. */
|
|
522
673
|
type DatabaseReaderFacade<DM, REL extends Record<keyof DM, object>, RANK extends Record<keyof DM, string>, SEARCH extends Record<keyof DM, string>, GEO extends Record<keyof DM, string> = Record<keyof DM, never>> = { readonly [T in keyof DM]: TableReaderFacade<DM, REL, RANK, SEARCH, T, GEO>; };
|
|
523
674
|
/** Per-table read-write facade — `ctx.db.<table>` on a `MutationCtx` / `ActionCtx`. */
|
|
524
675
|
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>, GEO extends Record<keyof DM, string> = Record<keyof DM, never>> = { readonly [T in keyof DM]: TableWriterFacade<DM, IM, REL, RANK, SEARCH, T, GEO>; };
|
|
525
|
-
export { AggregateOp, DatabaseReaderFacade, DatabaseWriterFacade, GeoBoundingBox, GeoFilterBuilder, GeoPointInput, GeoReader, 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 };
|
|
676
|
+
export { AggregateOp, DatabaseReaderFacade, DatabaseWriterFacade, GeoBoundingBox, GeoFilterBuilder, GeoPointInput, GeoReader, GroupByEntry, Id, InsertValues, LoadWith, ManyRelationWhere, OneRelationWhere, OrderBy, PatchValues, QueryArgs, QueryArgsOf, QueryPage, QueryPlan, RankPage, RankResult, RelationWrites, RestrictableQueryOptions, RestrictableQueryOptionsOf, SearchFilterBuilder, SearchReader, TableAggregateOptions, TableAggregateOptionsOf, TableGroupByOptions, TableGroupByOptionsOf, TableRankOptions, TableRankPageOptions, TableReaderFacade, TableWriterFacade, ToManyRelationWrite, ToOneRelationWrite, UpsertTargetOf, Where, WhereOf, WhereOperators, WithArg };
|
package/dist/data-model.d.ts
CHANGED
|
@@ -37,14 +37,53 @@ interface WhereOperators<T> {
|
|
|
37
37
|
ne?: T;
|
|
38
38
|
notIn?: T[];
|
|
39
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* A value stored as a plain JS object: not a scalar (an `Id<T>` is a branded string, which is an `object` to
|
|
42
|
+
* TypeScript but has no keys worth offering), an array, a date, bytes, a bigint or a function.
|
|
43
|
+
*/
|
|
44
|
+
type IsPlainObject<V> = V extends string | number | boolean | bigint | symbol ? false : V extends ReadonlyArray<unknown> ? false : V extends Date | Uint8Array | ArrayBuffer | bigint | ((...arguments_: never[]) => unknown) ? false : V extends object ? true : false;
|
|
45
|
+
/** The dotted paths below an object, to three steps. */
|
|
46
|
+
type SubPaths<V, Depth extends unknown[]> = Depth["length"] extends 3 ? never : [IsPlainObject<V>] extends [true] ? { [K in keyof V & string]-?: K | `${K}.${SubPaths<NonNullable<V[K]>, [...Depth, 0]>}`; }[keyof V & string] : never;
|
|
47
|
+
/** The type at the end of dotted path `P` below `V`. */
|
|
48
|
+
type PathValue<V, P extends string> = P extends `${infer Head}.${infer Rest}` ? Head extends keyof V ? PathValue<NonNullable<V[Head]>, Rest> : never : P extends keyof V ? V[P] : never;
|
|
49
|
+
/**
|
|
50
|
+
* Every dotted path into an object-valued column of `Doc` (`"profile.address.city"`), at most four segments
|
|
51
|
+
* counting the column. A column that is not a plain object contributes none.
|
|
52
|
+
*/
|
|
53
|
+
type ColumnPaths<Doc> = { [K in keyof Doc & string]-?: [IsPlainObject<NonNullable<Doc[K]>>] extends [true] ? `${K}.${SubPaths<NonNullable<Doc[K]>, []>}` : never; }[keyof Doc & string];
|
|
54
|
+
/** The type at the end of a {@link ColumnPaths} path. */
|
|
55
|
+
type DocPathValue<Doc, P extends string> = P extends `${infer Column}.${infer Rest}` ? Column extends keyof Doc ? PathValue<NonNullable<Doc[Column]>, Rest> : never : never;
|
|
56
|
+
type ScalarLeaf = boolean | number | string | null | undefined;
|
|
57
|
+
/** The dotted paths into an object column that end at a string, number or boolean. */
|
|
58
|
+
type ScalarPaths<Doc> = { [P in ColumnPaths<Doc>]: [DocPathValue<Doc, P>] extends [ScalarLeaf] ? P : never; }[ColumnPaths<Doc>];
|
|
59
|
+
/**
|
|
60
|
+
* `where` keys that reach into an object column: `{ "profile.plan": "pro" }`. Only paths that end at a string,
|
|
61
|
+
* number or boolean are offered — an object, array, date, bigint or bytes leaf has no single SQL comparison.
|
|
62
|
+
*
|
|
63
|
+
* `unknown` (the identity for `&`) when there are none, never `{}`: intersecting with an empty object type
|
|
64
|
+
* switches off the weak-type check that rejects a `where` key naming nothing.
|
|
65
|
+
*/
|
|
66
|
+
type PathWhere<Doc, Paths extends string = ScalarPaths<Doc>> = [Paths] extends [never] ? unknown : { [P in Paths]?: DocPathValue<Doc, P> | WhereOperators<DocPathValue<Doc, P>>; };
|
|
67
|
+
/** `patch` keys that set one value inside an object column, keeping its siblings: `{ "profile.plan": "pro" }`. */
|
|
68
|
+
type PathPatch<Doc, Paths extends string = ColumnPaths<Doc>> = [Paths] extends [never] ? unknown : { [P in Paths]?: DocPathValue<Doc, P>; };
|
|
40
69
|
/** A typed `where` tree over a document's columns. */
|
|
41
|
-
type Where<TDocument> = { [K in keyof TDocument]?: TDocument[K] | WhereOperators<TDocument[K]>; } & {
|
|
70
|
+
type Where<TDocument> = PathWhere<TDocument> & { [K in keyof TDocument]?: TDocument[K] | WhereOperators<TDocument[K]>; } & {
|
|
42
71
|
AND?: Where<TDocument>[];
|
|
43
72
|
NOT?: Where<TDocument>;
|
|
44
73
|
OR?: Where<TDocument>[];
|
|
45
74
|
};
|
|
46
|
-
/**
|
|
47
|
-
|
|
75
|
+
/**
|
|
76
|
+
* One ordering entry; `orderBy` is an ordered list. `{ field: "asc" | "desc" }` sorts NULLs first
|
|
77
|
+
* ascending and last descending. `{ field: { sort: "desc", nulls: "first" } }` places them yourself.
|
|
78
|
+
*
|
|
79
|
+
* A placement other than the default can change the query plan (see Pagination in the docs), so
|
|
80
|
+
* measure a hot read. It has no effect on a column that cannot hold NULL. Keep the same `orderBy` for every page of a
|
|
81
|
+
* paginated read, as a cursor is only valid against the ordering that minted it.
|
|
82
|
+
*/
|
|
83
|
+
type OrderBy<TDocument> = Partial<Record<keyof TDocument | ScalarPaths<TDocument>, "asc" | "desc" | {
|
|
84
|
+
nulls: "first" | "last";
|
|
85
|
+
sort: "asc" | "desc";
|
|
86
|
+
}>>;
|
|
48
87
|
interface QueryArgs<TDocument> {
|
|
49
88
|
cursor?: null | string;
|
|
50
89
|
limit?: number;
|
|
@@ -96,7 +135,7 @@ type RelationWhere<DM, REL extends Record<keyof DM, object>, T extends keyof DM>
|
|
|
96
135
|
* `Where<DM[T]>` stays the column-only structural mirror for back-compat; the
|
|
97
136
|
* table facade threads `REL` through this richer form.
|
|
98
137
|
*/
|
|
99
|
-
type WhereOf<DM, REL extends Record<keyof DM, object>, T extends keyof DM> = RelationWhere<DM, REL, T> & { [K in keyof DM[T]]?: DM[T][K] | WhereOperators<DM[T][K]>; } & {
|
|
138
|
+
type WhereOf<DM, REL extends Record<keyof DM, object>, T extends keyof DM> = PathWhere<DM[T]> & RelationWhere<DM, REL, T> & { [K in keyof DM[T]]?: DM[T][K] | WhereOperators<DM[T][K]>; } & {
|
|
100
139
|
AND?: WhereOf<DM, REL, T>[];
|
|
101
140
|
NOT?: WhereOf<DM, REL, T>;
|
|
102
141
|
OR?: WhereOf<DM, REL, T>[];
|
|
@@ -348,6 +387,20 @@ interface TableReaderFacade<DM, REL extends Record<keyof DM, object>, RANK exten
|
|
|
348
387
|
count: (where?: RestrictableQueryOptionsOf<DM, REL, T> | WhereOf<DM, REL, T>) => Promise<number>;
|
|
349
388
|
/** `true` when at least one row matches `where` (any row when omitted). RLS-filtered exactly like `findFirst`. */
|
|
350
389
|
exists: (where?: WhereOf<DM, REL, T>) => Promise<boolean>;
|
|
390
|
+
/**
|
|
391
|
+
* Describe how this table would run `findMany(args)` without running it: the SQL, its bound
|
|
392
|
+
* parameters, and the database's own plan, one line per step. Use it to check that a filter is
|
|
393
|
+
* served by an index (`SEARCH … USING INDEX by_room`) rather than a scan (`SCAN …`).
|
|
394
|
+
*
|
|
395
|
+
* Honors RLS and soft delete exactly like the read, so the plan is the one your caller would get.
|
|
396
|
+
* Explaining does not subscribe a live query to this table. A relation filter in `where` is resolved
|
|
397
|
+
* first with an ordinary read of the related table, which does subscribe to that table, since the ids
|
|
398
|
+
* it matched are part of `params`. Takes no `with` or `select`: neither changes the statement.
|
|
399
|
+
*
|
|
400
|
+
* `params` carries values your RLS policies injected and, for a relation filter, the ids it matched.
|
|
401
|
+
* Keep the result on the server rather than returning it to a client.
|
|
402
|
+
*/
|
|
403
|
+
explain: (args?: QueryArgsOf<DM, REL, T>) => Promise<QueryPlan>;
|
|
351
404
|
findFirst: <W extends WithArg<DM, REL, T> = {}, S extends ReadonlyArray<keyof DM[T] & string> | undefined = undefined>(args?: QueryArgsOf<DM, REL, T> & {
|
|
352
405
|
select?: S;
|
|
353
406
|
with?: W;
|
|
@@ -442,10 +495,10 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
|
|
|
442
495
|
* instead of throwing — the return type widens to `Id | null` on that overload.
|
|
443
496
|
*/
|
|
444
497
|
insert: {
|
|
445
|
-
(values: IM
|
|
498
|
+
(values: InsertValues<DM, IM, REL, T>, options: {
|
|
446
499
|
skipDuplicates: true;
|
|
447
500
|
}): Promise<Id<string & T> | null>;
|
|
448
|
-
(values: IM
|
|
501
|
+
(values: InsertValues<DM, IM, REL, T>, options?: {
|
|
449
502
|
skipDuplicates?: boolean;
|
|
450
503
|
}): Promise<Id<string & T>>;
|
|
451
504
|
};
|
|
@@ -464,7 +517,7 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
|
|
|
464
517
|
skipDuplicates?: boolean;
|
|
465
518
|
}): Promise<Id<string & T>[]>;
|
|
466
519
|
};
|
|
467
|
-
patch: (id: Id<string & T>, values:
|
|
520
|
+
patch: (id: Id<string & T>, values: PatchValues<IM[T]> & RelationWrites<DM, REL, T>) => Promise<void>;
|
|
468
521
|
/**
|
|
469
522
|
* Patch many rows in this table. Pass an array of `{ id, values }` or
|
|
470
523
|
* `{ where, values }` to patch matching rows with the same values. Returns
|
|
@@ -473,7 +526,7 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
|
|
|
473
526
|
patchMany: {
|
|
474
527
|
(patches: ReadonlyArray<{
|
|
475
528
|
id: Id<string & T>;
|
|
476
|
-
values:
|
|
529
|
+
values: PatchValues<IM[T]>;
|
|
477
530
|
}>, options?: {
|
|
478
531
|
limit?: number;
|
|
479
532
|
}): Promise<{
|
|
@@ -481,7 +534,7 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
|
|
|
481
534
|
}>;
|
|
482
535
|
(args: {
|
|
483
536
|
limit?: number;
|
|
484
|
-
values:
|
|
537
|
+
values: PatchValues<IM[T]>;
|
|
485
538
|
where: Partial<DM[T]>;
|
|
486
539
|
}): Promise<{
|
|
487
540
|
patched: number;
|
|
@@ -497,9 +550,9 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
|
|
|
497
550
|
* Composes `findFirst` + `insert`/`patch`, so RLS gates each step.
|
|
498
551
|
*/
|
|
499
552
|
upsert: (args: {
|
|
500
|
-
create: IM
|
|
553
|
+
create: InsertValues<DM, IM, REL, T>;
|
|
501
554
|
target: UpsertTargetOf<DM, T>;
|
|
502
|
-
update?:
|
|
555
|
+
update?: PatchValues<IM[T]> & RelationWrites<DM, REL, T>;
|
|
503
556
|
}) => Promise<{
|
|
504
557
|
created: boolean;
|
|
505
558
|
id: Id<string & T>;
|
|
@@ -507,8 +560,8 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
|
|
|
507
560
|
/** Sequential {@link TableWriterFacade.upsert} over many rows sharing one `target`; one result per input row, in order. */
|
|
508
561
|
upsertMany: (args: {
|
|
509
562
|
rows: ReadonlyArray<{
|
|
510
|
-
create: IM
|
|
511
|
-
update?:
|
|
563
|
+
create: InsertValues<DM, IM, REL, T>;
|
|
564
|
+
update?: PatchValues<IM[T]> & RelationWrites<DM, REL, T>;
|
|
512
565
|
}>;
|
|
513
566
|
target: UpsertTargetOf<DM, T>;
|
|
514
567
|
}) => Promise<{
|
|
@@ -518,8 +571,106 @@ interface TableWriterFacade<DM, IM extends Record<keyof DM, object>, REL extends
|
|
|
518
571
|
}
|
|
519
572
|
/** Conflict target for `upsert`/`upsertMany`: one column of table `T`, or a tuple of them. */
|
|
520
573
|
type UpsertTargetOf<DM, T extends keyof DM> = ReadonlyArray<keyof DM[T] & string> | (keyof DM[T] & string);
|
|
574
|
+
/**
|
|
575
|
+
* An atomic update for a number column, applied to the value the row holds when the
|
|
576
|
+
* write runs: `{ increment: 1 }`, `{ decrement: 1 }`, `{ multiply: 2 }`, `{ divide: 2 }`.
|
|
577
|
+
* The column must already hold a finite number; a result that is not finite is rejected.
|
|
578
|
+
*/
|
|
579
|
+
type NumberFieldOperator = {
|
|
580
|
+
decrement: number;
|
|
581
|
+
divide?: never;
|
|
582
|
+
increment?: never;
|
|
583
|
+
multiply?: never;
|
|
584
|
+
} | {
|
|
585
|
+
decrement?: never;
|
|
586
|
+
divide: number;
|
|
587
|
+
increment?: never;
|
|
588
|
+
multiply?: never;
|
|
589
|
+
} | {
|
|
590
|
+
decrement?: never;
|
|
591
|
+
divide?: never;
|
|
592
|
+
increment: number;
|
|
593
|
+
multiply?: never;
|
|
594
|
+
} | {
|
|
595
|
+
decrement?: never;
|
|
596
|
+
divide?: never;
|
|
597
|
+
increment?: never;
|
|
598
|
+
multiply: number;
|
|
599
|
+
};
|
|
600
|
+
/** An atomic update for a boolean column: `{ toggle: true }` flips the stored value. */
|
|
601
|
+
interface BooleanFieldOperator {
|
|
602
|
+
toggle: true;
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* The values a `patch` accepts: any column's own type, and for a number or boolean
|
|
606
|
+
* column also an atomic operator ({@link NumberFieldOperator}, {@link BooleanFieldOperator}).
|
|
607
|
+
*/
|
|
608
|
+
type PatchValues<Row> = PathPatch<Row> & { [K in keyof Row]?: Row[K] | OperatorFor<NonNullable<Row[K]>>; };
|
|
609
|
+
/**
|
|
610
|
+
* The operator a column of type `T` takes: arithmetic when `T` is exactly `number` (so a literal union
|
|
611
|
+
* such as `1 | 2` is out — the result could leave the set — and so is `number | string`, which the
|
|
612
|
+
* store does not treat as a number column), `{ toggle: true }` when it is exactly `boolean`.
|
|
613
|
+
*/
|
|
614
|
+
type OperatorFor<T> = [T] extends [number] ? [number] extends [T] ? NumberFieldOperator : never : [T] extends [boolean] ? [boolean] extends [T] ? BooleanFieldOperator : never : never;
|
|
615
|
+
/** What `explain` returns: the SQL a read compiles to, its bound parameters, and the database's plan for it. */
|
|
616
|
+
interface QueryPlan {
|
|
617
|
+
/** The bound parameters, in order. */
|
|
618
|
+
params: unknown[];
|
|
619
|
+
/** One line per plan step, as the database reports it. */
|
|
620
|
+
plan: string[];
|
|
621
|
+
/** The statement the read compiles to. */
|
|
622
|
+
sql: string;
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* Nested write for a to-one relation: point the row at `Target` (`connect`), or clear the link (`disconnect`, which
|
|
626
|
+
* needs a foreign key that can be empty). One or the other, not both.
|
|
627
|
+
*/
|
|
628
|
+
type ToOneRelationWrite<TargetId> = {
|
|
629
|
+
connect: TargetId;
|
|
630
|
+
disconnect?: never;
|
|
631
|
+
} | {
|
|
632
|
+
connect?: never;
|
|
633
|
+
disconnect: true;
|
|
634
|
+
};
|
|
635
|
+
/**
|
|
636
|
+
* Nested write for a to-many relation: point `Target` rows at this one (`connect`), release them (`disconnect`, which
|
|
637
|
+
* needs a foreign key that can be empty), or replace the whole list (`set`: rows not named are released). `set`
|
|
638
|
+
* cannot be combined with the other two.
|
|
639
|
+
*/
|
|
640
|
+
type ToManyRelationWrite<TargetId> = {
|
|
641
|
+
connect?: never;
|
|
642
|
+
disconnect?: never;
|
|
643
|
+
set: ReadonlyArray<TargetId>;
|
|
644
|
+
} | {
|
|
645
|
+
connect?: ReadonlyArray<TargetId>;
|
|
646
|
+
disconnect?: ReadonlyArray<TargetId>;
|
|
647
|
+
set?: never;
|
|
648
|
+
};
|
|
649
|
+
/**
|
|
650
|
+
* Nested relation writes accepted by `insert`, `patch` and `upsert`, keyed by relation name:
|
|
651
|
+
* `{ author: { connect: userId } }`, `{ posts: { set: [a, b] } }`. A table with no relations contributes none
|
|
652
|
+
* (`unknown`, the identity for `&`, never `{}`: an empty object type would switch off the weak-type check).
|
|
653
|
+
*/
|
|
654
|
+
type RelationWrites<DM, REL extends Record<keyof DM, object>, T extends keyof DM> = [keyof REL[T]] extends [never] ? unknown : { [K in keyof REL[T]]?: REL[T][K] extends {
|
|
655
|
+
__relationKind: "one";
|
|
656
|
+
__target: infer Target extends keyof DM;
|
|
657
|
+
} ? ToOneRelationWrite<Id<string & Target>> : REL[T][K] extends {
|
|
658
|
+
__relationKind: "many";
|
|
659
|
+
__target: infer Target extends keyof DM;
|
|
660
|
+
} ? ToManyRelationWrite<Id<string & Target>> : never; };
|
|
661
|
+
/** The foreign-key columns of a table's to-one relations — the keys a nested `connect` supplies. */
|
|
662
|
+
type OneRelationFields<RelT> = { [K in keyof RelT]: RelT[K] extends {
|
|
663
|
+
__field: infer Field extends string;
|
|
664
|
+
__relationKind: "one";
|
|
665
|
+
} ? Field : never; }[keyof RelT];
|
|
666
|
+
/**
|
|
667
|
+
* What `insert` accepts: the row as it is, or the row without its to-one foreign keys plus the nested writes that
|
|
668
|
+
* supply them. Leaving a key out with no `connect` to supply it is not caught by the type — the store's own
|
|
669
|
+
* validation rejects the missing field.
|
|
670
|
+
*/
|
|
671
|
+
type InsertValues<DM, IM extends Record<keyof DM, object>, REL extends Record<keyof DM, object>, T extends keyof DM> = IM[T] | (Omit<IM[T], OneRelationFields<REL[T]>> & RelationWrites<DM, REL, T>);
|
|
521
672
|
/** Per-table read facade — `ctx.db.<table>` on a `QueryCtx`. */
|
|
522
673
|
type DatabaseReaderFacade<DM, REL extends Record<keyof DM, object>, RANK extends Record<keyof DM, string>, SEARCH extends Record<keyof DM, string>, GEO extends Record<keyof DM, string> = Record<keyof DM, never>> = { readonly [T in keyof DM]: TableReaderFacade<DM, REL, RANK, SEARCH, T, GEO>; };
|
|
523
674
|
/** Per-table read-write facade — `ctx.db.<table>` on a `MutationCtx` / `ActionCtx`. */
|
|
524
675
|
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>, GEO extends Record<keyof DM, string> = Record<keyof DM, never>> = { readonly [T in keyof DM]: TableWriterFacade<DM, IM, REL, RANK, SEARCH, T, GEO>; };
|
|
525
|
-
export { AggregateOp, DatabaseReaderFacade, DatabaseWriterFacade, GeoBoundingBox, GeoFilterBuilder, GeoPointInput, GeoReader, 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 };
|
|
676
|
+
export { AggregateOp, DatabaseReaderFacade, DatabaseWriterFacade, GeoBoundingBox, GeoFilterBuilder, GeoPointInput, GeoReader, GroupByEntry, Id, InsertValues, LoadWith, ManyRelationWhere, OneRelationWhere, OrderBy, PatchValues, QueryArgs, QueryArgsOf, QueryPage, QueryPlan, RankPage, RankResult, RelationWrites, RestrictableQueryOptions, RestrictableQueryOptionsOf, SearchFilterBuilder, SearchReader, TableAggregateOptions, TableAggregateOptionsOf, TableGroupByOptions, TableGroupByOptionsOf, TableRankOptions, TableRankPageOptions, TableReaderFacade, TableWriterFacade, ToManyRelationWrite, ToOneRelationWrite, UpsertTargetOf, Where, WhereOf, WhereOperators, WithArg };
|
package/dist/in-process.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{LunoraError as b}from"@lunora/errors";import{runShardMigrations as w,TransactionHeadroomTracker as d,createShardCtxDb as R,RLS_UNWRAP_SYMBOL as T}from"@lunora/shard-engine";import{beginDeferredSchedules as g}from"./packem_shared/beginDeferredSchedules-CmmdpWRS.mjs";import{bindTableFacade as y}from"./packem_shared/bindOrm-
|
|
1
|
+
import{LunoraError as b}from"@lunora/errors";import{runShardMigrations as w,TransactionHeadroomTracker as d,createShardCtxDb as R,RLS_UNWRAP_SYMBOL as T}from"@lunora/shard-engine";import{beginDeferredSchedules as g}from"./packem_shared/beginDeferredSchedules-CmmdpWRS.mjs";import{bindTableFacade as y}from"./packem_shared/bindOrm-BaAMwCFL.mjs";const k=r=>{if(r===null||typeof r.userId!="string"||r.userId.length===0)return{claims:null,userId:null};const{userId:e,...s}=r;return{claims:Object.keys(s).length>0?s:null,userId:e}};class S extends d{current=new d;reset(){this.current=new d}headroom(){return this.current.headroom()}recordRead(e){this.current.recordRead(e)}recordWrite(e){this.current.recordWrite(e)}}const x=(r,e)=>{const{scheduler:s,sql:a}=e,i=r;w(a,i);const c=new S,h=t=>{const n=t;for(const o of Object.keys(i.tables))n[o]=y(t,o);return t},I=t=>{const n=R({auth:{identity:t.claims,userId:t.userId},enforceRls:e.enforceRls??!0,headroom:c,schema:i,sql:a}),o=n[T]??n;return{database:h(n),rawDatabase:h(o)}},u=t=>{a.exec.call(a,t)};let m=Promise.resolve();return{createWriters:I,resetHeadroom:()=>{c.reset()},runInTransaction:t=>{const n=async()=>{const f=g({scheduler:s});c.reset(),u("BEGIN");try{const l=await t();return u("COMMIT"),await f(!0),l}catch(l){try{u("ROLLBACK")}catch{}throw await f(!1),l}},o=m.then(n);return m=o.then(()=>{},()=>{}),o}}},p=r=>{if(typeof r!="object"||r===null)return;const{kind:e}=r;if(e==="query"||e==="mutation"||e==="action")return e},A=(r,e,s,a,i)=>{const c=p(e);if(c!==r)throw new b("INTERNAL",`expected a registered ${r}, received a ${c??"non-function"} reference`);if(!i&&e.visibility==="internal")throw new b("INTERNAL",`This ${r} is an internal function — it is unreachable from the external RPC boundary in production. Call it through ctx.run${r.charAt(0).toUpperCase()}${r.slice(1)} from another function instead.`);return Promise.resolve(e.handler(s,a??{}))};export{x as createInProcessRuntime,p as registeredFunctionKind,k as resolveInProcessIdentity,A as runRegisteredFunction};
|