@lunora/server 1.0.0-alpha.55 → 1.0.0-alpha.57
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 +21 -0
- package/dist/data-model.d.ts +21 -0
- package/dist/index.d.mts +708 -528
- package/dist/index.d.ts +708 -528
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/PRESENCE_DEFAULT_TTL_MS-DO2-TdzC.mjs +1 -0
- package/dist/packem_shared/asBucketStorage-BthCnWop.mjs +1 -0
- package/dist/packem_shared/buildMaskRegistry-BCIzKxdK.mjs +1 -0
- package/dist/packem_shared/{buildRlsReadRegistry-WdiqSj87.mjs → buildRlsReadRegistry-CA-aUi7I.mjs} +1 -1
- package/dist/packem_shared/composePluginMiddleware-B67TQ409.mjs +1 -0
- package/dist/packem_shared/defineAggregateIndex-DMhN3nby.mjs +1 -0
- package/dist/packem_shared/initLunora-DXCOVntr.mjs +1 -0
- package/dist/packem_shared/mask-DF7mtxQe.mjs +1 -0
- package/dist/packem_shared/optional-writer-override-CXXO30sZ.mjs +1 -0
- package/dist/packem_shared/plugin-B5pDeN17.mjs +1 -0
- package/dist/packem_shared/rls-tRDkICWZ.mjs +1 -0
- package/dist/rls/testing.mjs +1 -1
- package/dist/types.d.mts +38 -9
- package/dist/types.d.ts +38 -9
- package/dist/types.mjs +1 -1
- package/package.json +4 -4
- package/dist/packem_shared/PRESENCE_DEFAULT_TTL_MS-C9RX3Cl6.mjs +0 -1
- package/dist/packem_shared/asBucketStorage-1pFfH-Tn.mjs +0 -1
- package/dist/packem_shared/composePluginMiddleware-COr09CXA.mjs +0 -1
- package/dist/packem_shared/defineAggregateIndex-_gWNmkQZ.mjs +0 -1
- package/dist/packem_shared/initLunora-QNqOuG0A.mjs +0 -1
- package/dist/packem_shared/mask-C6Bi78qj.mjs +0 -1
- package/dist/packem_shared/rls-_iVsPvhX.mjs +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -10,19 +10,21 @@ import { b as Permission, R as Role, T as TypedDefinePolicyInput, a as Policy, D
|
|
|
10
10
|
export type { d as PolicyContext, e as PolicyDecision, f as PolicyDecisionOf, P as PolicyOperation } from "./packem_shared/types.d-C4CMJK8x.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
|
-
* Make any
|
|
13
|
+
* Make any resolved storage capability bucket-aware so `ctx.storage.bucket(name)`
|
|
14
14
|
* always resolves. A `createBucketStorage(...)` result already carries
|
|
15
15
|
* `.bucket` / `.bucketName` and is returned as-is; a single `createStorage(...)`
|
|
16
16
|
* (or the no-storage stub) is tagged as the `"default"` bucket, where
|
|
17
17
|
* `.bucket(name)` is the identity — single-bucket apps address one binding under
|
|
18
18
|
* every name.
|
|
19
19
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
20
|
+
* Lives here rather than in `@lunora/server` because two packages need it and
|
|
21
|
+
* neither may depend on the other: `@lunora/server` re-exports it as the runtime
|
|
22
|
+
* counterpart `_generated/shard.ts` imports, and `@lunora/runtime` uses it to
|
|
23
|
+
* build `ctx.storage` for an HTTP action from the worker's own R2 bindings.
|
|
24
|
+
* Inlined into each `dist` by the bundler, so no dependency edge is created.
|
|
25
|
+
*
|
|
26
|
+
* The input is genuinely heterogeneous (a thunk result cast through `unknown`),
|
|
27
|
+
* so the signature is `unknown → unknown`; callers cast the result.
|
|
26
28
|
*/
|
|
27
29
|
declare const asBucketStorage: (raw: unknown) => unknown;
|
|
28
30
|
/** Builder discriminator. Codegen reads this kind. */
|
|
@@ -583,18 +585,29 @@ type HttpMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PU
|
|
|
583
585
|
/**
|
|
584
586
|
* Context handed to an HTTP action handler. A narrower view of {@link ActionContext}:
|
|
585
587
|
* HTTP actions run in the worker (the "action runtime"), separate from the
|
|
586
|
-
* transactional store, so there is no direct `db` / `vectors`
|
|
587
|
-
*
|
|
588
|
-
* `
|
|
588
|
+
* transactional store, so there is no direct `db` / `vectors` surface — reach the
|
|
589
|
+
* data layer through `runQuery` / `runMutation` / `runAction`, which forward to
|
|
590
|
+
* the owning shard. `db`'s absence is principled: an HTTP handler is not
|
|
591
|
+
* transactional.
|
|
592
|
+
*
|
|
593
|
+
* `scheduler` and `storage` ARE present, because neither needs the shard — the
|
|
594
|
+
* scheduler talks to the scheduler DO, and R2 is a worker binding an HTTP
|
|
595
|
+
* handler can reach where an action does. Both are optional: each exists only
|
|
596
|
+
* when the app declared the matching capability (`.scheduler(...)` /
|
|
597
|
+
* `.storage(...)`) on the generated app builder.
|
|
589
598
|
*
|
|
590
|
-
*
|
|
591
|
-
*
|
|
592
|
-
*
|
|
593
|
-
*
|
|
594
|
-
*
|
|
599
|
+
* Omitting them was costly out of proportion to the gap. Without `scheduler`,
|
|
600
|
+
* "receive webhook → enqueue the real work → return 200" — the shape HTTP
|
|
601
|
+
* actions exist for — forced a hop through a mutation plus a closed allow-list
|
|
602
|
+
* of target strings, because a function reference cannot cross the RPC boundary
|
|
603
|
+
* and a free-form target on an unauthenticated endpoint is a "call any internal
|
|
604
|
+
* function" primitive. Without `storage`, any helper the ctx was threaded into
|
|
605
|
+
* had to be typed for its storage-touching branch, so a handler was barred from
|
|
606
|
+
* the helper even on the branches that never went near storage.
|
|
595
607
|
*/
|
|
596
608
|
type HttpActionCtx = Pick<ActionCtx, "auth" | "cache" | "fetch" | "runAction" | "runMutation" | "runQuery"> & {
|
|
597
609
|
readonly scheduler?: ActionCtx["scheduler"];
|
|
610
|
+
readonly storage?: ActionCtx["storage"];
|
|
598
611
|
};
|
|
599
612
|
/** A raw handler wrapped by {@link httpAction}. Receives the raw request, returns the raw response. */
|
|
600
613
|
type HttpActionHandler = (context: HttpActionCtx, request: Request) => Promise<Response> | Response;
|
|
@@ -967,456 +980,197 @@ declare const clampLimit: (limit: number | undefined, fallback: number, maxLimit
|
|
|
967
980
|
*/
|
|
968
981
|
declare const defineListArgs: <TDocument>() => <F extends ListFilterShape<TDocument>, O extends keyof TDocument & string>(config: DefineListArgsConfig<F, O>) => ListArgsSpec<TDocument, F, O>;
|
|
969
982
|
/**
|
|
970
|
-
*
|
|
971
|
-
* `
|
|
972
|
-
*
|
|
973
|
-
*
|
|
974
|
-
*
|
|
975
|
-
*
|
|
976
|
-
*
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
983
|
+
* Structural mirrors of `@lunora/shard-engine`'s rank-page-row shapes
|
|
984
|
+
* (`RankPageRowKey` / `RankPageRow` / `ShardRankPageResult`) — the return type
|
|
985
|
+
* of the writer's `rankPageRows` seam, the cross-shard companion to
|
|
986
|
+
* `rankPage`.
|
|
987
|
+
*
|
|
988
|
+
* Shared by `../rls/middleware` and `../mask/middleware`: both wrap
|
|
989
|
+
* `rankPageRows` structurally (no `@lunora/shard-engine` import, mirroring how
|
|
990
|
+
* every other method on their `DatabaseWriterLike`/`MaskDatabase` projections
|
|
991
|
+
* is hand-mirrored rather than imported) and both need the exact same result
|
|
992
|
+
* shape to type their overrides. A single copy here means the two wrappers
|
|
993
|
+
* can't drift out of lockstep with each other — see AGENTS.md's platform
|
|
994
|
+
* parity note on `ShardSqlExec` and the canonical binding `*Like` projections
|
|
995
|
+
* shipping wrong for exactly this reason (two hand-maintained mirrors of one
|
|
996
|
+
* upstream type).
|
|
997
|
+
*/
|
|
998
|
+
/** Structural mirror of `@lunora/shard-engine`'s `RankPageRowKey`. */
|
|
999
|
+
interface RankPageRowKeyLike {
|
|
1000
|
+
partitionKey: string;
|
|
1001
|
+
rowId: string;
|
|
1002
|
+
sortValues: ReadonlyArray<unknown>;
|
|
1003
|
+
}
|
|
1004
|
+
/** Structural mirror of `@lunora/shard-engine`'s `RankPageRow`. */
|
|
1005
|
+
interface RankPageRowLike {
|
|
1006
|
+
doc: Record<string, unknown>;
|
|
1007
|
+
key: RankPageRowKeyLike;
|
|
1008
|
+
}
|
|
1009
|
+
/** Structural mirror of `@lunora/shard-engine`'s `ShardRankPageResult` — the `rankPageRows` return shape. */
|
|
1010
|
+
interface ShardRankPageResultLike {
|
|
1011
|
+
directions: ReadonlyArray<"asc" | "desc">;
|
|
1012
|
+
hasMore: boolean;
|
|
1013
|
+
rows: ReadonlyArray<RankPageRowLike>;
|
|
991
1014
|
}
|
|
992
1015
|
/**
|
|
993
|
-
*
|
|
994
|
-
* {@link
|
|
995
|
-
*
|
|
996
|
-
* or format-preserving tokens. A function that **throws** fails closed — the
|
|
997
|
-
* cell is redacted to `null`, never leaked raw.
|
|
1016
|
+
* The prefixed tables a single plugin `P` contributes, or an empty map when it
|
|
1017
|
+
* ships no schema extension. Mirrors {@link PrefixedTables} at the plugin level
|
|
1018
|
+
* so {@link InstalledTables} can fold a tuple of plugins.
|
|
998
1019
|
*/
|
|
999
|
-
type
|
|
1020
|
+
type ExtensionTablesOf<P> = P extends {
|
|
1021
|
+
readonly extension: SchemaExtension<infer X> & {
|
|
1022
|
+
readonly key: infer K;
|
|
1023
|
+
};
|
|
1024
|
+
} ? K extends string ? PrefixedTables<X, K> : Record<never, never> : Record<never, never>;
|
|
1000
1025
|
/**
|
|
1001
|
-
*
|
|
1002
|
-
*
|
|
1003
|
-
*
|
|
1004
|
-
* the right choice for any value that must actually be kept secret.
|
|
1005
|
-
* - `"hash"` — replace with a stable token (unsalted 32-bit FNV-1a hex) so the
|
|
1006
|
-
* same input always yields the same token (joinable/groupable client-side).
|
|
1007
|
-
* **This is NOT a confidentiality control.** It is a non-cryptographic,
|
|
1008
|
-
* unsalted, deterministic, narrow (~2^32) digest: low-entropy values (emails,
|
|
1009
|
-
* phone numbers, SSNs) are brute-force-recoverable by the very caller you are
|
|
1010
|
-
* masking from, and identical values always produce identical tokens across
|
|
1011
|
-
* rows/columns/tenants (enabling correlation). Use `"hash"` ONLY when you want a
|
|
1012
|
-
* stable pseudonym for grouping/joining and leaking the value is acceptable —
|
|
1013
|
-
* never to hide sensitive PII. For PII that must stay hidden, use `"redact"`.
|
|
1014
|
-
* - a {@link MaskFn} — author-defined transform (partial mask, role-aware reveal).
|
|
1026
|
+
* Fold a tuple of plugins onto a base table map `T`, accumulating each plugin's
|
|
1027
|
+
* auto-prefixed extension tables left-to-right — the type-level mirror of
|
|
1028
|
+
* {@link installPlugins} applying `mergeSchemaExtension` for each plugin in turn.
|
|
1015
1029
|
*/
|
|
1016
|
-
type
|
|
1017
|
-
/** Per-column strategy map for one table: `{ email: "redact", phone: maskMiddle }`. */
|
|
1018
|
-
type MaskColumns<Context = unknown> = Record<string, MaskStrategy<Context>>;
|
|
1030
|
+
type InstalledTables<T extends Record<string, TableDefinition>, Plugins extends ReadonlyArray<unknown>> = Plugins extends readonly [infer Head, ...infer Rest] ? InstalledTables<ExtensionTablesOf<Head> & T, Rest> : T;
|
|
1019
1031
|
/**
|
|
1020
|
-
*
|
|
1021
|
-
*
|
|
1022
|
-
*
|
|
1023
|
-
*
|
|
1032
|
+
* Union every plugin's `ContextOut` in a tuple — the type-level mirror of the
|
|
1033
|
+
* `ctx.api.<key>` additions {@link composePluginMiddleware} accumulates as each
|
|
1034
|
+
* plugin middleware runs. Independent of the incoming context, which the builder
|
|
1035
|
+
* infers at the `.use(...)` site.
|
|
1024
1036
|
*/
|
|
1025
|
-
type
|
|
1037
|
+
type ComposedOut<Plugins extends ReadonlyArray<unknown>> = Plugins extends readonly [infer Head, ...infer Rest] ? ComposedOut<Rest> & (Head extends Plugin<any, any, infer Out> ? Out : unknown) : unknown;
|
|
1026
1038
|
/**
|
|
1027
|
-
*
|
|
1028
|
-
*
|
|
1029
|
-
*
|
|
1030
|
-
*
|
|
1031
|
-
* not listed grants no permissions (fails closed for unknown roles).
|
|
1032
|
-
* - `bypass` is a procedure-wide escape hatch: when it returns `true` the whole
|
|
1033
|
-
* mask is skipped (the caller sees raw values). Use it for a privileged
|
|
1034
|
-
* viewer — `bypass: ({ auth }) => auth.can("pii:view")`. Prefer this over
|
|
1035
|
-
* branching every column when an entire class of caller should see clear data.
|
|
1039
|
+
* Schema fragment a plugin contributes. Same shape as the `tables` map
|
|
1040
|
+
* passed to `defineSchema`. Optional `vectorIndexes` mirror the top-level
|
|
1041
|
+
* `defineSchema` argument so a plugin can ship vector decls alongside its
|
|
1042
|
+
* tables.
|
|
1036
1043
|
*/
|
|
1037
|
-
interface
|
|
1038
|
-
|
|
1039
|
-
readonly
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1044
|
+
interface SchemaExtension<T extends Record<string, TableDefinition> = Record<string, TableDefinition>> {
|
|
1045
|
+
/** Stable key identifying the plugin that owns this extension. */
|
|
1046
|
+
readonly key: string;
|
|
1047
|
+
/**
|
|
1048
|
+
* Extension tables, keyed by **bare** name (e.g. `buckets`). At merge time
|
|
1049
|
+
* each is auto-prefixed with `key` (`ratelimit_buckets`) so it can't
|
|
1050
|
+
* collide with an app table; do **not** namespace manually.
|
|
1051
|
+
*/
|
|
1052
|
+
readonly tables: T;
|
|
1053
|
+
/**
|
|
1054
|
+
* Optional standalone vector indexes the plugin ships, keyed by index
|
|
1055
|
+
* name. Merged into the host schema's `vectorIndexes`; a key collision
|
|
1056
|
+
* with the base schema is a hard error (same policy as tables).
|
|
1057
|
+
*/
|
|
1058
|
+
readonly vectorIndexes?: Record<string, VectorIndexDefinition>;
|
|
1045
1059
|
}
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1060
|
+
/**
|
|
1061
|
+
* Build a {@link SchemaExtension}. The `key` is a runtime tag (used for
|
|
1062
|
+
* error messages on collision) and a type-level brand.
|
|
1063
|
+
*/
|
|
1064
|
+
declare const defineSchemaExtension: <T extends Record<string, TableDefinition>>(key: string, options: {
|
|
1065
|
+
tables: T;
|
|
1066
|
+
vectorIndexes?: Record<string, VectorIndexDefinition>;
|
|
1067
|
+
}) => SchemaExtension<T>;
|
|
1068
|
+
/**
|
|
1069
|
+
* A plugin packages an optional schema extension and optional middleware.
|
|
1070
|
+
* Both are independently usable: an app can install only the schema (e.g.
|
|
1071
|
+
* for plugins that ship background workers but no per-request behavior)
|
|
1072
|
+
* or only the middleware (plugins that augment ctx without persistent
|
|
1073
|
+
* state).
|
|
1074
|
+
*/
|
|
1075
|
+
interface Plugin<TExtension extends Record<string, TableDefinition> = Record<string, TableDefinition>, TContextIn = unknown, TContextOut = TContextIn> {
|
|
1076
|
+
/**
|
|
1077
|
+
* Optional schema extension. Apps install via
|
|
1078
|
+
* `defineSchema(...).extend(plugin.extension)`.
|
|
1079
|
+
*/
|
|
1080
|
+
readonly extension?: SchemaExtension<TExtension>;
|
|
1081
|
+
/** Stable key identifying the plugin. Matches `extension.key` when set. */
|
|
1082
|
+
readonly key: string;
|
|
1083
|
+
/**
|
|
1084
|
+
* Optional middleware. Users attach with `c.query.use(plugin.middleware)`.
|
|
1085
|
+
* The middleware can extend `ctx`; convention is to attach helpers under
|
|
1086
|
+
* `ctx.api.<key>`, e.g.
|
|
1087
|
+
*
|
|
1088
|
+
* ```ts
|
|
1089
|
+
* middleware: ({ ctx, next }) =>
|
|
1090
|
+
* next({ ctx: { api: { ...ctx.api, ratelimit: api } } })
|
|
1091
|
+
* ```
|
|
1092
|
+
*/
|
|
1093
|
+
readonly middleware?: Middleware<TContextIn, TContextOut>;
|
|
1053
1094
|
}
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1095
|
+
/** Options to {@link definePlugin}. */
|
|
1096
|
+
interface DefinePluginOptions<TExtension extends Record<string, TableDefinition>, TContextIn, TContextOut> {
|
|
1097
|
+
extension?: SchemaExtension<TExtension>;
|
|
1098
|
+
middleware?: Middleware<TContextIn, TContextOut>;
|
|
1058
1099
|
}
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1100
|
+
/**
|
|
1101
|
+
* Call signatures for {@link definePlugin}. When `extension` is supplied the
|
|
1102
|
+
* returned plugin's `extension` is typed as PRESENT (not `?`), so the
|
|
1103
|
+
* canonical install pattern `defineSchema(...).extend(plugin.extension)`
|
|
1104
|
+
* typechecks without a non-null assertion — the shape every scaffold template
|
|
1105
|
+
* ships. The bare-options signature keeps `extension` optional for plugins
|
|
1106
|
+
* that carry only middleware.
|
|
1107
|
+
*/
|
|
1108
|
+
interface DefinePluginFunction {
|
|
1109
|
+
<TExtension extends Record<string, TableDefinition>, TContextIn = unknown, TContextOut = TContextIn>(key: string, options: DefinePluginOptions<TExtension, TContextIn, TContextOut> & {
|
|
1110
|
+
extension: SchemaExtension<TExtension>;
|
|
1111
|
+
}): Plugin<TExtension, TContextIn, TContextOut> & {
|
|
1112
|
+
readonly extension: SchemaExtension<TExtension>;
|
|
1063
1113
|
};
|
|
1064
|
-
|
|
1065
|
-
where?: unknown;
|
|
1114
|
+
<TExtension extends Record<string, TableDefinition>, TContextIn = unknown, TContextOut = TContextIn>(key: string, options: DefinePluginOptions<TExtension, TContextIn, TContextOut>): Plugin<TExtension, TContextIn, TContextOut>;
|
|
1066
1115
|
}
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1116
|
+
/**
|
|
1117
|
+
* Package a schema extension + middleware as a reusable plugin. Either
|
|
1118
|
+
* field is optional — `definePlugin("foo", {})` is valid but degenerate.
|
|
1119
|
+
*/
|
|
1120
|
+
declare const definePlugin: DefinePluginFunction;
|
|
1121
|
+
/**
|
|
1122
|
+
* Bundle of registered functions a {@link Component} ships. Keys are the
|
|
1123
|
+
* function's local name (e.g. `check`, `reset`); the registered function
|
|
1124
|
+
* value carries its own kind / args / handler.
|
|
1125
|
+
*
|
|
1126
|
+
* Users re-export from their own lunora module so codegen picks them up:
|
|
1127
|
+
*
|
|
1128
|
+
* ```ts
|
|
1129
|
+
* // lunora/ratelimit.ts
|
|
1130
|
+
* import { ratelimit } from "@vendor/ratelimit-component";
|
|
1131
|
+
* export const { check, reset } = ratelimit.functions;
|
|
1132
|
+
* // Emits as `ratelimit:check` / `ratelimit:reset` in the generated `api`.
|
|
1133
|
+
* ```
|
|
1134
|
+
*
|
|
1135
|
+
* Codegen follows the re-export back to the bundled `query/mutation/action`
|
|
1136
|
+
* call (property access or destructuring both work), so the functions land in
|
|
1137
|
+
* the generated `api` under the re-exporting file's namespace.
|
|
1138
|
+
*/
|
|
1139
|
+
type ComponentFunctions = Readonly<Record<string, RegisteredFunction<any, any, FunctionKind>>>;
|
|
1140
|
+
/**
|
|
1141
|
+
* Component = {@link Plugin} with a bundle of registered functions. The
|
|
1142
|
+
* extension + middleware + functions are independent: a component can ship
|
|
1143
|
+
* functions without a schema (e.g. a stateless utility), or a schema
|
|
1144
|
+
* without functions (e.g. shared table definitions), and any combination.
|
|
1145
|
+
*/
|
|
1146
|
+
interface Component<TExtension extends Record<string, TableDefinition> = Record<string, TableDefinition>, TContextIn = unknown, TContextOut = TContextIn, F extends ComponentFunctions = ComponentFunctions> extends Plugin<TExtension, TContextIn, TContextOut> {
|
|
1147
|
+
readonly functions: F;
|
|
1148
|
+
}
|
|
1149
|
+
interface DefineComponentOptions<TExtension extends Record<string, TableDefinition>, TContextIn, TContextOut, F extends ComponentFunctions> extends DefinePluginOptions<TExtension, TContextIn, TContextOut> {
|
|
1150
|
+
/** Registered functions the component ships. Keys are the function's local name. */
|
|
1151
|
+
functions?: F;
|
|
1081
1152
|
}
|
|
1082
1153
|
/**
|
|
1083
|
-
*
|
|
1084
|
-
*
|
|
1085
|
-
*
|
|
1086
|
-
*
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
findFirstOrThrow: (tableName: string, args?: QueryArgs$1) => Promise<Record<string, unknown>>;
|
|
1104
|
-
findMany: (tableName: string, args?: QueryArgs$1) => Promise<QueryPage$1>;
|
|
1105
|
-
get: (id: string, expectedTable?: string) => Promise<Record<string, unknown> | null>;
|
|
1106
|
-
groupBy: (tableName: string, options: GroupByArgs$1) => Promise<ReadonlyArray<{
|
|
1107
|
-
key: Record<string, unknown>;
|
|
1108
|
-
value: null | number;
|
|
1109
|
-
}>>;
|
|
1110
|
-
insert: (tableName: string, document: Record<string, unknown>) => Promise<string>;
|
|
1111
|
-
insertMany: (tableName: string, documents: ReadonlyArray<Record<string, unknown>>, options?: {
|
|
1112
|
-
limit?: number;
|
|
1113
|
-
skipDuplicates?: boolean;
|
|
1114
|
-
}) => Promise<(string | null)[]>;
|
|
1115
|
-
lookupById?: (id: string, expectedTable?: string) => Promise<null | {
|
|
1116
|
-
row: Record<string, unknown>;
|
|
1117
|
-
tableName: string;
|
|
1118
|
-
}>;
|
|
1119
|
-
patch: (id: string, patch: Record<string, unknown>, expectedTable?: string) => Promise<void>;
|
|
1120
|
-
patchMany: (patches: ReadonlyArray<{
|
|
1121
|
-
id: string;
|
|
1122
|
-
patch: Record<string, unknown>;
|
|
1123
|
-
}>, options?: {
|
|
1124
|
-
limit?: number;
|
|
1125
|
-
}) => Promise<{
|
|
1126
|
-
patched: number;
|
|
1127
|
-
}>;
|
|
1128
|
-
patchWhere?: (tableName: string, args: {
|
|
1129
|
-
patch: Record<string, unknown>;
|
|
1130
|
-
where: Record<string, unknown>;
|
|
1131
|
-
}, options?: {
|
|
1132
|
-
limit?: number;
|
|
1133
|
-
}) => Promise<{
|
|
1134
|
-
patched: number;
|
|
1135
|
-
}>;
|
|
1136
|
-
query: (tableName: string) => TableReaderLike$1;
|
|
1137
|
-
rank: (tableName: string, indexName: string, options: unknown) => Promise<null | {
|
|
1138
|
-
position: number;
|
|
1139
|
-
total: number;
|
|
1140
|
-
}>;
|
|
1141
|
-
rankBefore?: (tableName: string, indexName: string, options: unknown) => Promise<{
|
|
1142
|
-
before: number;
|
|
1143
|
-
total: number;
|
|
1144
|
-
}>;
|
|
1145
|
-
rankPage: (tableName: string, indexName: string, options?: unknown) => Promise<QueryPage$1>;
|
|
1146
|
-
replace: (id: string, document: Record<string, unknown>, expectedTable?: string) => Promise<void>;
|
|
1147
|
-
}
|
|
1148
|
-
/** Roles list source on the context. Tolerant of older auth states (mirrors RLS's `AuthLike`). */
|
|
1149
|
-
type AuthLike$1 = {
|
|
1150
|
-
getIdentity?: () => Promise<Record<string, unknown> | null>;
|
|
1151
|
-
roles?: ReadonlyArray<string>;
|
|
1152
|
-
userId?: null | string;
|
|
1153
|
-
};
|
|
1154
|
-
interface MaskContextIn {
|
|
1155
|
-
auth?: AuthLike$1;
|
|
1156
|
-
db: MaskDatabase;
|
|
1157
|
-
}
|
|
1158
|
-
/**
|
|
1159
|
-
* Procedure-builder middleware. Apply per-request via `.use(mask(policies))`.
|
|
1160
|
-
* Closes over the policy map at builder-construction time; resolves identity +
|
|
1161
|
-
* the `bypass` decision per call against the live ctx.
|
|
1162
|
-
*
|
|
1163
|
-
* IMPORTANT: a mask is in scope only for procedures whose builder chain
|
|
1164
|
-
* includes this middleware — opt-in, never global (the same invariant as RLS).
|
|
1165
|
-
*/
|
|
1166
|
-
declare const mask: <Context extends MaskContextIn = MaskContextIn>(policies: MaskPolicies<Context>, options?: MaskOptions<Context>) => Middleware<Context, Context>;
|
|
1167
|
-
/** A document handed to a migration transform: the stored row including `_id`/`_creationTime`. */
|
|
1168
|
-
type MigrationDocument = Record<string, unknown>;
|
|
1169
|
-
/**
|
|
1170
|
-
* Transform applied to one document. Return a new document to rewrite the row,
|
|
1171
|
-
* or `undefined` to leave it untouched (skipped, not counted as changed). The
|
|
1172
|
-
* runner always preserves the original `_id` and `_creationTime`, so the
|
|
1173
|
-
* returned document neither needs to nor should change row identity.
|
|
1174
|
-
*/
|
|
1175
|
-
type MigrationTransform = (document: MigrationDocument) => MigrationDocument | undefined | void;
|
|
1176
|
-
interface MigrationDefinition {
|
|
1177
|
-
/** Rows fetched and rewritten per batch. Defaults to the runner's batch size when omitted. */
|
|
1178
|
-
readonly batchSize?: number;
|
|
1179
|
-
/** Optional reverse transform, applied by `migrate down`. */
|
|
1180
|
-
readonly down?: MigrationTransform;
|
|
1181
|
-
/** Stable, unique identifier — the key per-shard run-state is tracked under. */
|
|
1182
|
-
readonly id: string;
|
|
1183
|
-
/** Table whose documents this migration iterates. */
|
|
1184
|
-
readonly table: string;
|
|
1185
|
-
/** Forward transform, applied to every row by `migrate up`. */
|
|
1186
|
-
readonly up: MigrationTransform;
|
|
1187
|
-
}
|
|
1188
|
-
/** A {@link MigrationDefinition} plus the codegen discovery marker. */
|
|
1189
|
-
interface RegisteredMigration extends MigrationDefinition {
|
|
1190
|
-
readonly __lunoraMigration: true;
|
|
1191
|
-
}
|
|
1192
|
-
/** Declare an online data migration. See the module docs for runtime semantics. */
|
|
1193
|
-
declare const defineMigration: (definition: MigrationDefinition) => RegisteredMigration;
|
|
1194
|
-
/**
|
|
1195
|
-
* A mutator declaration. `server` is authoritative; `client` is the optimistic
|
|
1196
|
-
* twin (optional — omit it to let the optimistic write fall through to the
|
|
1197
|
-
* server round-trip with no local preview). Both receive the same validated
|
|
1198
|
-
* `args`.
|
|
1199
|
-
*/
|
|
1200
|
-
interface MutatorDefinition<Args extends ValidatorMap = ValidatorMap, ServerContext = MutationCtx, ClientTx = unknown, R = unknown> {
|
|
1201
|
-
/**
|
|
1202
|
-
* Validator for the mutator's arguments. Validated on the DO before `server`
|
|
1203
|
-
* runs and (when present) on the client before `client` runs, so both impls
|
|
1204
|
-
* see the same parsed shape. Omit for a parameterless mutator.
|
|
1205
|
-
*/
|
|
1206
|
-
readonly args?: Args;
|
|
1207
|
-
/**
|
|
1208
|
-
* Optimistic client implementation. Runs in a TanStack DB transaction
|
|
1209
|
-
* against the local collections; its writes are applied immediately and
|
|
1210
|
-
* automatically rolled back / rebased as the authoritative result syncs
|
|
1211
|
-
* back. Pure and side-effect-free beyond the local store. Omit to skip the
|
|
1212
|
-
* local preview.
|
|
1213
|
-
*/
|
|
1214
|
-
readonly client?: (tx: ClientTx, args: InferValidatorMap<Args>) => Promise<void> | void;
|
|
1215
|
-
/**
|
|
1216
|
-
* Owner-scope the write: names the column carrying the row owner (e.g.
|
|
1217
|
-
* `owner: "userId"`). Before `server` runs, the mutator requires a verified
|
|
1218
|
-
* identity, rejects a client-supplied owner that disagrees with it, and sets
|
|
1219
|
-
* the column to the verified value — so the impl reads `args[owner]` without
|
|
1220
|
-
* trusting the client and never repeats the check by hand.
|
|
1221
|
-
*
|
|
1222
|
-
* This replaces the "every mutator opens with `assertOwner(ctx, args.userId)`"
|
|
1223
|
-
* pattern, and is the write-side counterpart to an `owner`-scoped
|
|
1224
|
-
* {@link import("./shapes").ShapeDefinition}. Unlike a shape it takes the column
|
|
1225
|
-
* NAME rather than `true`: a shape is bound to one `table`, so the table's
|
|
1226
|
-
* `.ownedBy(field)` resolves unambiguously, whereas one mutator may write
|
|
1227
|
-
* several tables and has no single owning table to read it from.
|
|
1228
|
-
*
|
|
1229
|
-
* Declare the column `v.optional(...)` to leave it off the wire entirely; it is
|
|
1230
|
-
* injected either way.
|
|
1231
|
-
*/
|
|
1232
|
-
readonly owner?: string;
|
|
1233
|
-
/**
|
|
1234
|
-
* Authoritative server implementation. Runs inside the shard DO with a full
|
|
1235
|
-
* {@link MutationContext} (`ctx.db` writer); its writes append to `__cdc_log`
|
|
1236
|
-
* and poke back to subscribers. This is the source of truth — the client
|
|
1237
|
-
* impl is only a prediction of it.
|
|
1238
|
-
*/
|
|
1239
|
-
readonly server: (context: ServerContext, args: InferValidatorMap<Args>) => Promise<R> | R;
|
|
1240
|
-
}
|
|
1241
|
-
/**
|
|
1242
|
-
* A {@link MutatorDefinition} plus the codegen discovery marker and a
|
|
1243
|
-
* dispatch-shaped `handler` (validates `args`, then runs `server`) so the DO
|
|
1244
|
-
* invokes a mutator exactly like a registered procedure.
|
|
1245
|
-
*/
|
|
1246
|
-
interface RegisteredMutator<Args extends ValidatorMap = ValidatorMap, ServerContext = MutationCtx, ClientTx = unknown, R = unknown> extends MutatorDefinition<Args, ServerContext, ClientTx, R> {
|
|
1247
|
-
readonly __lunoraMutator: true;
|
|
1248
|
-
/** Validate `rawArgs`, then run the authoritative `server` impl. Used by the DO push path. */
|
|
1249
|
-
readonly handler: (context: ServerContext, rawArgs: Record<string, unknown>) => Promise<R>;
|
|
1250
|
-
/**
|
|
1251
|
-
* Marks the dispatch kind so codegen can register the mutator in the same
|
|
1252
|
-
* `LUNORA_FUNCTIONS` table queries/mutations use — the DO's `handleRpc`
|
|
1253
|
-
* reads `kind === "mutation"` to wrap the authoritative `server` impl in the
|
|
1254
|
-
* shard's BEGIN/COMMIT span (all-or-nothing writes), exactly like an
|
|
1255
|
-
* ordinary `mutation`.
|
|
1256
|
-
*/
|
|
1257
|
-
readonly kind: "mutation";
|
|
1258
|
-
}
|
|
1259
|
-
/** Declare a custom mutator. See the module docs for runtime semantics. */
|
|
1260
|
-
declare const defineMutator: <Args extends ValidatorMap = ValidatorMap, ServerContext = MutationCtx, ClientTx = unknown, R = unknown>(definition: MutatorDefinition<Args, ServerContext, ClientTx, R>) => RegisteredMutator<Args, ServerContext, ClientTx, R>;
|
|
1261
|
-
/**
|
|
1262
|
-
* The prefixed tables a single plugin `P` contributes, or an empty map when it
|
|
1263
|
-
* ships no schema extension. Mirrors {@link PrefixedTables} at the plugin level
|
|
1264
|
-
* so {@link InstalledTables} can fold a tuple of plugins.
|
|
1265
|
-
*/
|
|
1266
|
-
type ExtensionTablesOf<P> = P extends {
|
|
1267
|
-
readonly extension: SchemaExtension<infer X> & {
|
|
1268
|
-
readonly key: infer K;
|
|
1269
|
-
};
|
|
1270
|
-
} ? K extends string ? PrefixedTables<X, K> : Record<never, never> : Record<never, never>;
|
|
1271
|
-
/**
|
|
1272
|
-
* Fold a tuple of plugins onto a base table map `T`, accumulating each plugin's
|
|
1273
|
-
* auto-prefixed extension tables left-to-right — the type-level mirror of
|
|
1274
|
-
* {@link installPlugins} applying `mergeSchemaExtension` for each plugin in turn.
|
|
1275
|
-
*/
|
|
1276
|
-
type InstalledTables<T extends Record<string, TableDefinition>, Plugins extends ReadonlyArray<unknown>> = Plugins extends readonly [infer Head, ...infer Rest] ? InstalledTables<ExtensionTablesOf<Head> & T, Rest> : T;
|
|
1277
|
-
/**
|
|
1278
|
-
* Union every plugin's `ContextOut` in a tuple — the type-level mirror of the
|
|
1279
|
-
* `ctx.api.<key>` additions {@link composePluginMiddleware} accumulates as each
|
|
1280
|
-
* plugin middleware runs. Independent of the incoming context, which the builder
|
|
1281
|
-
* infers at the `.use(...)` site.
|
|
1282
|
-
*/
|
|
1283
|
-
type ComposedOut<Plugins extends ReadonlyArray<unknown>> = Plugins extends readonly [infer Head, ...infer Rest] ? ComposedOut<Rest> & (Head extends Plugin<any, any, infer Out> ? Out : unknown) : unknown;
|
|
1284
|
-
/**
|
|
1285
|
-
* Schema fragment a plugin contributes. Same shape as the `tables` map
|
|
1286
|
-
* passed to `defineSchema`. Optional `vectorIndexes` mirror the top-level
|
|
1287
|
-
* `defineSchema` argument so a plugin can ship vector decls alongside its
|
|
1288
|
-
* tables.
|
|
1289
|
-
*/
|
|
1290
|
-
interface SchemaExtension<T extends Record<string, TableDefinition> = Record<string, TableDefinition>> {
|
|
1291
|
-
/** Stable key identifying the plugin that owns this extension. */
|
|
1292
|
-
readonly key: string;
|
|
1293
|
-
/**
|
|
1294
|
-
* Extension tables, keyed by **bare** name (e.g. `buckets`). At merge time
|
|
1295
|
-
* each is auto-prefixed with `key` (`ratelimit_buckets`) so it can't
|
|
1296
|
-
* collide with an app table; do **not** namespace manually.
|
|
1297
|
-
*/
|
|
1298
|
-
readonly tables: T;
|
|
1299
|
-
/**
|
|
1300
|
-
* Optional standalone vector indexes the plugin ships, keyed by index
|
|
1301
|
-
* name. Merged into the host schema's `vectorIndexes`; a key collision
|
|
1302
|
-
* with the base schema is a hard error (same policy as tables).
|
|
1303
|
-
*/
|
|
1304
|
-
readonly vectorIndexes?: Record<string, VectorIndexDefinition>;
|
|
1305
|
-
}
|
|
1306
|
-
/**
|
|
1307
|
-
* Build a {@link SchemaExtension}. The `key` is a runtime tag (used for
|
|
1308
|
-
* error messages on collision) and a type-level brand.
|
|
1309
|
-
*/
|
|
1310
|
-
declare const defineSchemaExtension: <T extends Record<string, TableDefinition>>(key: string, options: {
|
|
1311
|
-
tables: T;
|
|
1312
|
-
vectorIndexes?: Record<string, VectorIndexDefinition>;
|
|
1313
|
-
}) => SchemaExtension<T>;
|
|
1314
|
-
/**
|
|
1315
|
-
* A plugin packages an optional schema extension and optional middleware.
|
|
1316
|
-
* Both are independently usable: an app can install only the schema (e.g.
|
|
1317
|
-
* for plugins that ship background workers but no per-request behavior)
|
|
1318
|
-
* or only the middleware (plugins that augment ctx without persistent
|
|
1319
|
-
* state).
|
|
1320
|
-
*/
|
|
1321
|
-
interface Plugin<TExtension extends Record<string, TableDefinition> = Record<string, TableDefinition>, TContextIn = unknown, TContextOut = TContextIn> {
|
|
1322
|
-
/**
|
|
1323
|
-
* Optional schema extension. Apps install via
|
|
1324
|
-
* `defineSchema(...).extend(plugin.extension)`.
|
|
1325
|
-
*/
|
|
1326
|
-
readonly extension?: SchemaExtension<TExtension>;
|
|
1327
|
-
/** Stable key identifying the plugin. Matches `extension.key` when set. */
|
|
1328
|
-
readonly key: string;
|
|
1329
|
-
/**
|
|
1330
|
-
* Optional middleware. Users attach with `c.query.use(plugin.middleware)`.
|
|
1331
|
-
* The middleware can extend `ctx`; convention is to attach helpers under
|
|
1332
|
-
* `ctx.api.<key>`, e.g.
|
|
1333
|
-
*
|
|
1334
|
-
* ```ts
|
|
1335
|
-
* middleware: ({ ctx, next }) =>
|
|
1336
|
-
* next({ ctx: { api: { ...ctx.api, ratelimit: api } } })
|
|
1337
|
-
* ```
|
|
1338
|
-
*/
|
|
1339
|
-
readonly middleware?: Middleware<TContextIn, TContextOut>;
|
|
1340
|
-
}
|
|
1341
|
-
/** Options to {@link definePlugin}. */
|
|
1342
|
-
interface DefinePluginOptions<TExtension extends Record<string, TableDefinition>, TContextIn, TContextOut> {
|
|
1343
|
-
extension?: SchemaExtension<TExtension>;
|
|
1344
|
-
middleware?: Middleware<TContextIn, TContextOut>;
|
|
1345
|
-
}
|
|
1346
|
-
/**
|
|
1347
|
-
* Call signatures for {@link definePlugin}. When `extension` is supplied the
|
|
1348
|
-
* returned plugin's `extension` is typed as PRESENT (not `?`), so the
|
|
1349
|
-
* canonical install pattern `defineSchema(...).extend(plugin.extension)`
|
|
1350
|
-
* typechecks without a non-null assertion — the shape every scaffold template
|
|
1351
|
-
* ships. The bare-options signature keeps `extension` optional for plugins
|
|
1352
|
-
* that carry only middleware.
|
|
1353
|
-
*/
|
|
1354
|
-
interface DefinePluginFunction {
|
|
1355
|
-
<TExtension extends Record<string, TableDefinition>, TContextIn = unknown, TContextOut = TContextIn>(key: string, options: DefinePluginOptions<TExtension, TContextIn, TContextOut> & {
|
|
1356
|
-
extension: SchemaExtension<TExtension>;
|
|
1357
|
-
}): Plugin<TExtension, TContextIn, TContextOut> & {
|
|
1358
|
-
readonly extension: SchemaExtension<TExtension>;
|
|
1359
|
-
};
|
|
1360
|
-
<TExtension extends Record<string, TableDefinition>, TContextIn = unknown, TContextOut = TContextIn>(key: string, options: DefinePluginOptions<TExtension, TContextIn, TContextOut>): Plugin<TExtension, TContextIn, TContextOut>;
|
|
1361
|
-
}
|
|
1362
|
-
/**
|
|
1363
|
-
* Package a schema extension + middleware as a reusable plugin. Either
|
|
1364
|
-
* field is optional — `definePlugin("foo", {})` is valid but degenerate.
|
|
1365
|
-
*/
|
|
1366
|
-
declare const definePlugin: DefinePluginFunction;
|
|
1367
|
-
/**
|
|
1368
|
-
* Bundle of registered functions a {@link Component} ships. Keys are the
|
|
1369
|
-
* function's local name (e.g. `check`, `reset`); the registered function
|
|
1370
|
-
* value carries its own kind / args / handler.
|
|
1371
|
-
*
|
|
1372
|
-
* Users re-export from their own lunora module so codegen picks them up:
|
|
1373
|
-
*
|
|
1374
|
-
* ```ts
|
|
1375
|
-
* // lunora/ratelimit.ts
|
|
1376
|
-
* import { ratelimit } from "@vendor/ratelimit-component";
|
|
1377
|
-
* export const { check, reset } = ratelimit.functions;
|
|
1378
|
-
* // Emits as `ratelimit:check` / `ratelimit:reset` in the generated `api`.
|
|
1379
|
-
* ```
|
|
1380
|
-
*
|
|
1381
|
-
* Codegen follows the re-export back to the bundled `query/mutation/action`
|
|
1382
|
-
* call (property access or destructuring both work), so the functions land in
|
|
1383
|
-
* the generated `api` under the re-exporting file's namespace.
|
|
1384
|
-
*/
|
|
1385
|
-
type ComponentFunctions = Readonly<Record<string, RegisteredFunction<any, any, FunctionKind>>>;
|
|
1386
|
-
/**
|
|
1387
|
-
* Component = {@link Plugin} with a bundle of registered functions. The
|
|
1388
|
-
* extension + middleware + functions are independent: a component can ship
|
|
1389
|
-
* functions without a schema (e.g. a stateless utility), or a schema
|
|
1390
|
-
* without functions (e.g. shared table definitions), and any combination.
|
|
1391
|
-
*/
|
|
1392
|
-
interface Component<TExtension extends Record<string, TableDefinition> = Record<string, TableDefinition>, TContextIn = unknown, TContextOut = TContextIn, F extends ComponentFunctions = ComponentFunctions> extends Plugin<TExtension, TContextIn, TContextOut> {
|
|
1393
|
-
readonly functions: F;
|
|
1394
|
-
}
|
|
1395
|
-
interface DefineComponentOptions<TExtension extends Record<string, TableDefinition>, TContextIn, TContextOut, F extends ComponentFunctions> extends DefinePluginOptions<TExtension, TContextIn, TContextOut> {
|
|
1396
|
-
/** Registered functions the component ships. Keys are the function's local name. */
|
|
1397
|
-
functions?: F;
|
|
1398
|
-
}
|
|
1399
|
-
/**
|
|
1400
|
-
* Convenience wrapper around {@link definePlugin} that also bundles a set
|
|
1401
|
-
* of registered functions. The resulting `component.functions` object is a
|
|
1402
|
-
* record of `name → registered query/mutation/action`; consumers
|
|
1403
|
-
* re-export entries so codegen discovers them as user functions:
|
|
1404
|
-
*
|
|
1405
|
-
* ```ts
|
|
1406
|
-
* export const ratelimit = defineComponent("ratelimit", {
|
|
1407
|
-
* // Bare `buckets` merges in as `ratelimit_buckets`.
|
|
1408
|
-
* extension: defineSchemaExtension("ratelimit", { tables: { buckets } }),
|
|
1409
|
-
* middleware: ({ ctx, next }) => next({ ctx: { ...ctx, ratelimit: api(ctx) } }),
|
|
1410
|
-
* functions: {
|
|
1411
|
-
* check: query.input({ key: v.string() }).query(async ({ ctx, args }) => ...),
|
|
1412
|
-
* reset: mutation.input({ key: v.string() }).mutation(async ({ ctx, args }) => ...),
|
|
1413
|
-
* },
|
|
1414
|
-
* });
|
|
1415
|
-
* ```
|
|
1416
|
-
*
|
|
1417
|
-
* Re-exporting an entry (by property access or destructuring) is enough for
|
|
1418
|
-
* codegen to discover it in the host app's namespace — the discovery resolver
|
|
1419
|
-
* chases the re-export back to the bundled registration call.
|
|
1154
|
+
* Convenience wrapper around {@link definePlugin} that also bundles a set
|
|
1155
|
+
* of registered functions. The resulting `component.functions` object is a
|
|
1156
|
+
* record of `name → registered query/mutation/action`; consumers
|
|
1157
|
+
* re-export entries so codegen discovers them as user functions:
|
|
1158
|
+
*
|
|
1159
|
+
* ```ts
|
|
1160
|
+
* export const ratelimit = defineComponent("ratelimit", {
|
|
1161
|
+
* // Bare `buckets` merges in as `ratelimit_buckets`.
|
|
1162
|
+
* extension: defineSchemaExtension("ratelimit", { tables: { buckets } }),
|
|
1163
|
+
* middleware: ({ ctx, next }) => next({ ctx: { ...ctx, ratelimit: api(ctx) } }),
|
|
1164
|
+
* functions: {
|
|
1165
|
+
* check: query.input({ key: v.string() }).query(async ({ ctx, args }) => ...),
|
|
1166
|
+
* reset: mutation.input({ key: v.string() }).mutation(async ({ ctx, args }) => ...),
|
|
1167
|
+
* },
|
|
1168
|
+
* });
|
|
1169
|
+
* ```
|
|
1170
|
+
*
|
|
1171
|
+
* Re-exporting an entry (by property access or destructuring) is enough for
|
|
1172
|
+
* codegen to discover it in the host app's namespace — the discovery resolver
|
|
1173
|
+
* chases the re-export back to the bundled registration call.
|
|
1420
1174
|
*/
|
|
1421
1175
|
declare const defineComponent: <TExtension extends Record<string, TableDefinition>, TContextIn = unknown, TContextOut = TContextIn, F extends ComponentFunctions = ComponentFunctions>(key: string, options: DefineComponentOptions<TExtension, TContextIn, TContextOut, F>) => Component<TExtension, TContextIn, TContextOut, F>;
|
|
1422
1176
|
/**
|
|
@@ -1439,6 +1193,16 @@ type PrefixedTables<X extends Record<string, TableDefinition>, Key extends strin
|
|
|
1439
1193
|
* collisions are impossible. The only remaining hard error is two extensions
|
|
1440
1194
|
* sharing the same `key` and producing the same prefixed table (or vector
|
|
1441
1195
|
* index) name — silent shadow would let one plugin hijack another's data.
|
|
1196
|
+
*
|
|
1197
|
+
* Re-runs {@link validateIndexFields} against the merged table set before
|
|
1198
|
+
* returning: `defineSchema` only validates the tables it was called with, so
|
|
1199
|
+
* without this an extension-contributed index with a typo'd/out-of-shape
|
|
1200
|
+
* field (or a duplicate name within one kind) would never be checked at all.
|
|
1201
|
+
* Re-validating the whole merged set (base + prefixed extension tables) is
|
|
1202
|
+
* cheap and idempotent for the base tables, which already passed this same
|
|
1203
|
+
* check when the base schema was built. Both callers of this function —
|
|
1204
|
+
* `withExtend.extend()` (`./schema`) and `installPlugins` (below) — get the
|
|
1205
|
+
* re-validation for free from this single call site (plan 258 §4/§9 Q3).
|
|
1442
1206
|
*/
|
|
1443
1207
|
declare const mergeSchemaExtension: <T extends Record<string, TableDefinition>, X extends Record<string, TableDefinition>, Key extends string = string>(base: Schema<T>, extension: SchemaExtension<X> & {
|
|
1444
1208
|
readonly key: Key;
|
|
@@ -1570,7 +1334,7 @@ interface TableBuilder<Shape extends Record<string, Validator> = Record<string,
|
|
|
1570
1334
|
backend?: GlobalBackend;
|
|
1571
1335
|
}) => TableBuilder<Shape>;
|
|
1572
1336
|
/** Add a secondary index. */
|
|
1573
|
-
index: (name: string, fields: ReadonlyArray<string>, options?: {
|
|
1337
|
+
index: (name: string, fields: ReadonlyArray<(keyof Shape & string) | (typeof SYSTEM_INDEX_FIELDS)[number]>, options?: {
|
|
1574
1338
|
unique?: boolean;
|
|
1575
1339
|
}) => TableBuilder<Shape>;
|
|
1576
1340
|
/**
|
|
@@ -1692,101 +1456,510 @@ declare const defineTable: <Shape extends Record<string, Validator>>(inputShape:
|
|
|
1692
1456
|
*/
|
|
1693
1457
|
declare const defineVectorIndex: (options: VectorIndexOptions) => VectorIndexDefinition;
|
|
1694
1458
|
/**
|
|
1695
|
-
* Options for the standalone `defineAggregateIndex(name, opts)` helper (DSL
|
|
1696
|
-
* Shape B). Unlike the inline `.aggregateIndex(...)` builder, this form takes
|
|
1697
|
-
* the owning table explicitly via `on` — handy when a single counter wants to
|
|
1698
|
-
* live next to the schema map rather than inside a table chain.
|
|
1459
|
+
* Options for the standalone `defineAggregateIndex(name, opts)` helper (DSL
|
|
1460
|
+
* Shape B). Unlike the inline `.aggregateIndex(...)` builder, this form takes
|
|
1461
|
+
* the owning table explicitly via `on` — handy when a single counter wants to
|
|
1462
|
+
* live next to the schema map rather than inside a table chain.
|
|
1463
|
+
*/
|
|
1464
|
+
interface AggregateIndexOptions {
|
|
1465
|
+
by?: ReadonlyArray<string>;
|
|
1466
|
+
field?: string;
|
|
1467
|
+
on: string;
|
|
1468
|
+
op?: AggregateOp;
|
|
1469
|
+
where?: Record<string, unknown>;
|
|
1470
|
+
}
|
|
1471
|
+
/**
|
|
1472
|
+
* Declare a standalone aggregate index. Pass the returned value to
|
|
1473
|
+
* `defineSchema(tables, vectorIndexes, aggregateIndexes)` keyed by index name —
|
|
1474
|
+
* the schema attaches it to `tables[on].aggregateIndexes` so runtime consumers
|
|
1475
|
+
* (DO + D1) read every index uniformly off the table definition.
|
|
1476
|
+
*/
|
|
1477
|
+
declare const defineAggregateIndex: (name: string, options: AggregateIndexOptions) => AggregateIndexDefinition;
|
|
1478
|
+
/**
|
|
1479
|
+
* Options for the standalone `defineRankIndex(name, opts)` helper (DSL Shape B).
|
|
1480
|
+
* Mirrors the inline `.rankIndex(...)` builder but takes the owning table via
|
|
1481
|
+
* `table` so it can sit next to the schema map.
|
|
1482
|
+
*/
|
|
1483
|
+
interface RankIndexOptions {
|
|
1484
|
+
partitionBy?: ReadonlyArray<string>;
|
|
1485
|
+
sortBy: ReadonlyArray<{
|
|
1486
|
+
direction?: "asc" | "desc";
|
|
1487
|
+
field: string;
|
|
1488
|
+
}>;
|
|
1489
|
+
table: string;
|
|
1490
|
+
where?: Record<string, unknown>;
|
|
1491
|
+
}
|
|
1492
|
+
/**
|
|
1493
|
+
* Declare a standalone rank index. Pass the returned value to
|
|
1494
|
+
* `defineSchema(tables, vectorIndexes, aggregateIndexes, rankIndexes)` keyed
|
|
1495
|
+
* by index name — the schema attaches it to `tables[on].rankIndexes`.
|
|
1496
|
+
*/
|
|
1497
|
+
declare const defineRankIndex: (name: string, options: RankIndexOptions) => RankIndexDefinition;
|
|
1498
|
+
/**
|
|
1499
|
+
* Build the application schema. The first argument is the table map; the
|
|
1500
|
+
* optional second argument registers standalone `defineVectorIndex(...)`
|
|
1501
|
+
* declarations (DSL Shape B) keyed by index name. The optional third argument
|
|
1502
|
+
* registers standalone `defineAggregateIndex(...)` declarations (DSL Shape B);
|
|
1503
|
+
* the optional fourth argument registers standalone `defineRankIndex(...)`
|
|
1504
|
+
* declarations. Both are folded into the matching `tables[on].*Indexes` array
|
|
1505
|
+
* so runtime backends read every index uniformly off the table definition.
|
|
1506
|
+
*/
|
|
1507
|
+
/**
|
|
1508
|
+
* Schema with an in-place `.extend(plugin.extension)` method. Used so apps
|
|
1509
|
+
* can compose plugin schemas: `defineSchema({...}).extend(authPlugin.extension)`.
|
|
1510
|
+
*
|
|
1511
|
+
* `extend` is non-mutating — returns a fresh `ExtendableSchema` containing
|
|
1512
|
+
* the merged tables. Extension tables are auto-namespaced by the extension
|
|
1513
|
+
* `key` (`buckets` → `ratelimit_buckets`), so the merged type carries the
|
|
1514
|
+
* prefixed names via {@link PrefixedTables}. Chains:
|
|
1515
|
+
* `defineSchema(...).extend(a).extend(b)` is the typed equivalent of merging
|
|
1516
|
+
* `a`'s prefixed tables then `b`'s.
|
|
1517
|
+
*/
|
|
1518
|
+
type ExtendableSchema<T extends Record<string, TableDefinition>> = {
|
|
1519
|
+
extend: <X extends Record<string, TableDefinition>, Key extends string>(extension: SchemaExtension<X> & {
|
|
1520
|
+
readonly key: Key;
|
|
1521
|
+
}) => ExtendableSchema<PrefixedTables<X, Key> & T>;
|
|
1522
|
+
/**
|
|
1523
|
+
* Pin every Durable Object the app reaches — shards, fan-out, subscriptions,
|
|
1524
|
+
* the scheduler, and `ctx.containers` — to a Cloudflare data-residency
|
|
1525
|
+
* jurisdiction (`"eu"`, `"us"`, `"fedramp"`). Codegen reads this off the
|
|
1526
|
+
* schema and emits it into the generated worker's `createWorker({ jurisdiction })`
|
|
1527
|
+
* (and `ctx.scheduler` / `ctx.containers`). Non-mutating: returns a fresh
|
|
1528
|
+
* `ExtendableSchema`, so it composes with `.rls(...)` / `.extend(...)` in any order.
|
|
1529
|
+
*
|
|
1530
|
+
* ⚠️ **Set this once, before your first deploy — changing or removing it
|
|
1531
|
+
* strands data.** A Durable Object name maps to a *different* ID in each
|
|
1532
|
+
* jurisdiction, so toggling this on an existing app makes every shard, scheduler
|
|
1533
|
+
* job, and session DO resolve to a NEW, empty DO; the previous data stays in the
|
|
1534
|
+
* old jurisdiction's DOs and is no longer reachable. There is no in-place
|
|
1535
|
+
* migration — you would have to export from the old jurisdiction and import
|
|
1536
|
+
* into the new one.
|
|
1537
|
+
*
|
|
1538
|
+
* Note: this pins **DO-backed** state only. D1-backed state — `.global()`
|
|
1539
|
+
* tables and `@lunora/auth` sessions alike — is governed by D1's own location
|
|
1540
|
+
* settings, not this option.
|
|
1541
|
+
* @see https://developers.cloudflare.com/durable-objects/reference/data-location/
|
|
1542
|
+
*/
|
|
1543
|
+
jurisdiction: (jurisdiction: DurableObjectJurisdiction) => ExtendableSchema<T>;
|
|
1544
|
+
/**
|
|
1545
|
+
* Turn on secure-by-default RLS for the whole schema. Every table is then
|
|
1546
|
+
* protected — the DO/D1 write path denies raw, non-RLS `ctx.db` access, so a
|
|
1547
|
+
* procedure that forgets `.use(rls(...))` fails closed. Opt a table out with
|
|
1548
|
+
* `.public()`. Non-mutating: returns a fresh `ExtendableSchema` carrying the
|
|
1549
|
+
* mode, so `.rls("required")` composes with `.extend(...)` either order.
|
|
1550
|
+
*/
|
|
1551
|
+
rls: (mode: "required") => ExtendableSchema<T>;
|
|
1552
|
+
} & Schema<T>;
|
|
1553
|
+
/**
|
|
1554
|
+
* Columns every row carries implicitly (never part of a table's declared
|
|
1555
|
+
* `shape`), so `.index()` may legitimately name them. The single source for
|
|
1556
|
+
* both the compile-time allow-list (`TableBuilder["index"]`'s `fields` type,
|
|
1557
|
+
* via `(typeof SYSTEM_INDEX_FIELDS)[number]`) and the runtime cross-check
|
|
1558
|
+
* below (via `SYSTEM_INDEX_FIELDS_SET`) — declared once so the two can't
|
|
1559
|
+
* drift apart.
|
|
1560
|
+
*/
|
|
1561
|
+
declare const SYSTEM_INDEX_FIELDS: readonly ["_creationTime", "_id"];
|
|
1562
|
+
/**
|
|
1563
|
+
* Per-table, per-KIND index→declared-fields map: for each table, each index
|
|
1564
|
+
* KIND (`index` | `rank` | `geo`) that has at least one declared index maps
|
|
1565
|
+
* to a name→fields record for that kind only. Distilled by
|
|
1566
|
+
* {@link indexFieldsFromSchema}; this is the shape `mask()`'s
|
|
1567
|
+
* `MaskOptions.indexFields` expects (see `./mask/types`), so a table not
|
|
1568
|
+
* present here (no declared indexes of any kind) is simply absent from the
|
|
1569
|
+
* map rather than mapped to `{}`, and a kind with no declared indexes on a
|
|
1570
|
+
* table that HAS other kinds is simply absent from that table's entry.
|
|
1571
|
+
*
|
|
1572
|
+
* Kept per kind (rather than one flat name→fields record) because the engine
|
|
1573
|
+
* resolves `withIndex`/`withGeoIndex`/rank reads in THREE separate
|
|
1574
|
+
* namespaces (`tableDefinition.indexes` / `.geoIndexes` / `.rankIndexes` —
|
|
1575
|
+
* see `@lunora/shard-engine`'s `ctx-db.ts`), so the same name can legally and
|
|
1576
|
+
* unambiguously denote a different index per kind. A flat map would let one
|
|
1577
|
+
* kind's fields silently shadow another's for a colliding name, producing a
|
|
1578
|
+
* wrong-namespace answer from the mask guard (checking the wrong index's
|
|
1579
|
+
* fields) instead of the documented fail-open (missing lookup) — see plan 258.
|
|
1580
|
+
*/
|
|
1581
|
+
type IndexFieldsByTable = Readonly<Record<string, {
|
|
1582
|
+
readonly geo?: Readonly<Record<string, ReadonlyArray<string>>>;
|
|
1583
|
+
readonly index?: Readonly<Record<string, ReadonlyArray<string>>>;
|
|
1584
|
+
readonly rank?: Readonly<Record<string, ReadonlyArray<string>>>;
|
|
1585
|
+
}>>;
|
|
1586
|
+
declare const indexFieldsFromSchema: (schema: Schema) => IndexFieldsByTable;
|
|
1587
|
+
declare const defineSchema: <T extends Record<string, TableDefinition>>(tables: T, vectorIndexes?: Record<string, VectorIndexDefinition>, aggregateIndexes?: Record<string, AggregateIndexDefinition>, rankIndexes?: Record<string, RankIndexDefinition>) => ExtendableSchema<T>;
|
|
1588
|
+
/**
|
|
1589
|
+
* Context handed to a {@link MaskFn} (and to {@link MaskOptions.bypass}). The
|
|
1590
|
+
* `auth` shape mirrors RLS's `PolicyContext.auth` one-for-one — same identity
|
|
1591
|
+
* resolver, same `can(...)` permission check — so an author can branch a mask
|
|
1592
|
+
* on the caller's role/permission. `row` is the full pre-mask row the column
|
|
1593
|
+
* belongs to; `column` is the column currently being masked. Both are absent
|
|
1594
|
+
* when the context is used for the procedure-wide `bypass` check (no specific
|
|
1595
|
+
* cell is in play yet).
|
|
1596
|
+
*/
|
|
1597
|
+
interface MaskContext<Context = unknown> {
|
|
1598
|
+
readonly auth: {
|
|
1599
|
+
/** `true` when any of the request's `roles` grants `permission` (see {@link MaskOptions.roles}). Fails closed for unregistered roles. */
|
|
1600
|
+
readonly can: (permission: Permission | string) => boolean;
|
|
1601
|
+
readonly identity?: Record<string, unknown> | null;
|
|
1602
|
+
readonly roles: ReadonlyArray<string>;
|
|
1603
|
+
readonly userId: null | string;
|
|
1604
|
+
};
|
|
1605
|
+
/** The column currently being masked. Present only inside a per-cell {@link MaskFn}. */
|
|
1606
|
+
readonly column?: string;
|
|
1607
|
+
readonly ctx: Context;
|
|
1608
|
+
/** The full pre-mask row the masked cell belongs to. Present only inside a per-cell {@link MaskFn}. */
|
|
1609
|
+
readonly row?: Record<string, unknown>;
|
|
1610
|
+
}
|
|
1611
|
+
/**
|
|
1612
|
+
* A custom masking function. Receives the raw cell value and the
|
|
1613
|
+
* {@link MaskContext}, returns the value to surface. Use it for partial masks
|
|
1614
|
+
* (`maskMiddle(phone)`), role-aware reveals (`ctx.auth.can(...) ? value : null`),
|
|
1615
|
+
* or format-preserving tokens. A function that **throws** fails closed — the
|
|
1616
|
+
* cell is redacted to `null`, never leaked raw.
|
|
1617
|
+
*/
|
|
1618
|
+
type MaskFn<Context = unknown> = (value: unknown, context: MaskContext<Context>) => unknown;
|
|
1619
|
+
/**
|
|
1620
|
+
* How a column is masked:
|
|
1621
|
+
*
|
|
1622
|
+
* - `"redact"` — drop the value to `null`. The simplest, safest strategy, and
|
|
1623
|
+
* the right choice for any value that must actually be kept secret.
|
|
1624
|
+
* - `"hash"` — replace with a stable token (unsalted 32-bit FNV-1a hex) so the
|
|
1625
|
+
* same input always yields the same token (joinable/groupable client-side).
|
|
1626
|
+
* **This is NOT a confidentiality control.** It is a non-cryptographic,
|
|
1627
|
+
* unsalted, deterministic, narrow (~2^32) digest: low-entropy values (emails,
|
|
1628
|
+
* phone numbers, SSNs) are brute-force-recoverable by the very caller you are
|
|
1629
|
+
* masking from, and identical values always produce identical tokens across
|
|
1630
|
+
* rows/columns/tenants (enabling correlation). Use `"hash"` ONLY when you want a
|
|
1631
|
+
* stable pseudonym for grouping/joining and leaking the value is acceptable —
|
|
1632
|
+
* never to hide sensitive PII. For PII that must stay hidden, use `"redact"`.
|
|
1633
|
+
* - a {@link MaskFn} — author-defined transform (partial mask, role-aware reveal).
|
|
1634
|
+
*/
|
|
1635
|
+
type MaskStrategy<Context = unknown> = "hash" | "redact" | MaskFn<Context>;
|
|
1636
|
+
/** Per-column strategy map for one table: `{ email: "redact", phone: maskMiddle }`. */
|
|
1637
|
+
type MaskColumns<Context = unknown> = Record<string, MaskStrategy<Context>>;
|
|
1638
|
+
/**
|
|
1639
|
+
* The mask declaration passed to `mask(...)`: a table → column → strategy map.
|
|
1640
|
+
* Deliberately a plain object literal so the codegen feeder can statically read
|
|
1641
|
+
* which columns a procedure masks (powering the `mask_uncovered_pii_column`
|
|
1642
|
+
* advisor lint), exactly as the RLS feeder reads policy tables.
|
|
1643
|
+
*/
|
|
1644
|
+
type MaskPolicies<Context = unknown> = Record<string, MaskColumns<Context>>;
|
|
1645
|
+
/**
|
|
1646
|
+
* Options for `mask(policies, options)`.
|
|
1647
|
+
*
|
|
1648
|
+
* - `roles` registers the role→permission grants that back `ctx.auth.can(...)`
|
|
1649
|
+
* inside a {@link MaskFn} — identical to `rls(policies, { roles })`. A role
|
|
1650
|
+
* not listed grants no permissions (fails closed for unknown roles).
|
|
1651
|
+
* - `bypass` is a procedure-wide escape hatch: when it returns `true` the whole
|
|
1652
|
+
* mask is skipped (the caller sees raw values). Use it for a privileged
|
|
1653
|
+
* viewer — `bypass: ({ auth }) => auth.can("pii:view")`. Prefer this over
|
|
1654
|
+
* branching every column when an entire class of caller should see clear data.
|
|
1655
|
+
* - `indexFields` closes the bare-index-scan / rank / geo position oracle (see
|
|
1656
|
+
* the `mask/middleware` module docblock's "Residual read-position oracles" section).
|
|
1657
|
+
*/
|
|
1658
|
+
interface MaskOptions<Context = unknown> {
|
|
1659
|
+
readonly bypass?: (context: MaskContext<Context>) => boolean;
|
|
1660
|
+
/**
|
|
1661
|
+
* Per-table, per-KIND index→declared-fields map (regular index `fields`
|
|
1662
|
+
* under `index`; rank index `sortBy` ∪ `partitionBy` under `rank`; geo
|
|
1663
|
+
* index `field` under `geo`). Supplied to close the bare-index-scan /
|
|
1664
|
+
* rank / geo position oracle: a `withIndex(name)` with no range callback,
|
|
1665
|
+
* a `rank`/`rankPage`/`rankBefore` read, or a `withGeoIndex` read, over an
|
|
1666
|
+
* index whose DECLARED fields (for that read's own kind) intersect a
|
|
1667
|
+
* masked column, is rejected. Kept per kind — rather than one flat
|
|
1668
|
+
* name→fields map — because the engine resolves `withIndex` /
|
|
1669
|
+
* `withGeoIndex` / rank reads in three separate namespaces, so the same
|
|
1670
|
+
* index name can legally denote a different index per kind; a flat map
|
|
1671
|
+
* would let one kind's fields shadow another's for a colliding name.
|
|
1672
|
+
* OPTIONAL and additive — omit it and behaviour is unchanged (the oracle
|
|
1673
|
+
* stays open, exactly as before this option existed). Build it with
|
|
1674
|
+
* `indexFieldsFromSchema` (exported from `@lunora/server`):
|
|
1675
|
+
* `mask(policies, { indexFields: indexFieldsFromSchema(schema) })`.
|
|
1676
|
+
*/
|
|
1677
|
+
readonly indexFields?: IndexFieldsByTable;
|
|
1678
|
+
readonly roles?: ReadonlyArray<Role>;
|
|
1679
|
+
}
|
|
1680
|
+
interface QueryPage$1 {
|
|
1681
|
+
continueCursor: null | string;
|
|
1682
|
+
isDone: boolean;
|
|
1683
|
+
page: Record<string, unknown>[];
|
|
1684
|
+
}
|
|
1685
|
+
interface QueryArgs$1 {
|
|
1686
|
+
baseWhere?: unknown;
|
|
1687
|
+
cursor?: null | string;
|
|
1688
|
+
limit?: number;
|
|
1689
|
+
orderBy?: ReadonlyArray<Record<string, unknown>>;
|
|
1690
|
+
where?: unknown;
|
|
1691
|
+
with?: Record<string, unknown>;
|
|
1692
|
+
}
|
|
1693
|
+
interface AggregateArgs$1 {
|
|
1694
|
+
field?: string;
|
|
1695
|
+
op: string;
|
|
1696
|
+
where?: unknown;
|
|
1697
|
+
}
|
|
1698
|
+
interface GroupByArgs$1 {
|
|
1699
|
+
agg?: {
|
|
1700
|
+
field?: string;
|
|
1701
|
+
op: string;
|
|
1702
|
+
};
|
|
1703
|
+
by: ReadonlyArray<string>;
|
|
1704
|
+
where?: unknown;
|
|
1705
|
+
}
|
|
1706
|
+
/** One row of a `.collectWithScores()` result — mirrors `@lunora/shard-engine`'s `ScoredDocument`. */
|
|
1707
|
+
type ScoredDocument = GeoScoredDocument | SearchScoredDocument;
|
|
1708
|
+
/** A `.withGeoIndex()` row — mirrors `@lunora/shard-engine`'s `GeoScoredDocument`. */
|
|
1709
|
+
interface GeoScoredDocument {
|
|
1710
|
+
distanceMeters: null | number;
|
|
1711
|
+
document: Record<string, unknown>;
|
|
1712
|
+
score?: never;
|
|
1713
|
+
}
|
|
1714
|
+
/** A `.withSearchIndex()` row — mirrors `@lunora/shard-engine`'s `SearchScoredDocument`. */
|
|
1715
|
+
interface SearchScoredDocument {
|
|
1716
|
+
distanceMeters?: never;
|
|
1717
|
+
document: Record<string, unknown>;
|
|
1718
|
+
score: number;
|
|
1719
|
+
}
|
|
1720
|
+
interface TableReaderLike$1 {
|
|
1721
|
+
[Symbol.asyncIterator]: () => AsyncIterator<Record<string, unknown>>;
|
|
1722
|
+
collect: () => Promise<Record<string, unknown>[]>;
|
|
1723
|
+
collectWithScores: () => Promise<ScoredDocument[]>;
|
|
1724
|
+
filter: (predicate: (document: Record<string, unknown>) => boolean) => TableReaderLike$1;
|
|
1725
|
+
first: () => Promise<Record<string, unknown> | null>;
|
|
1726
|
+
order: (direction: "asc" | "desc") => TableReaderLike$1;
|
|
1727
|
+
paginate: (options: {
|
|
1728
|
+
cursor?: null | string;
|
|
1729
|
+
numItems: number;
|
|
1730
|
+
}) => Promise<QueryPage$1>;
|
|
1731
|
+
take: (limit: number) => Promise<Record<string, unknown>[]>;
|
|
1732
|
+
unique: () => Promise<Record<string, unknown> | null>;
|
|
1733
|
+
withGeoIndex: (indexName: string, build: (q: unknown) => unknown) => TableReaderLike$1;
|
|
1734
|
+
withIndex: (indexName: string, range?: (q: unknown) => unknown) => TableReaderLike$1;
|
|
1735
|
+
withSearchIndex: (indexName: string, search: (q: unknown) => unknown) => TableReaderLike$1;
|
|
1736
|
+
}
|
|
1737
|
+
/**
|
|
1738
|
+
* Structural projection of the runtime ORM writer — the same subset
|
|
1739
|
+
* `../rls/middleware` mirrors, so the wrapper is interchangeable between
|
|
1740
|
+
* `@lunora/do`'s and `@lunora/d1`'s `DatabaseWriterLike` without an
|
|
1741
|
+
* inter-package dependency. `rankBefore` is optional (the D1 twin omits it).
|
|
1699
1742
|
*/
|
|
1700
|
-
interface
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1743
|
+
interface MaskDatabase {
|
|
1744
|
+
aggregate: (tableName: string, options: AggregateArgs$1) => Promise<null | number>;
|
|
1745
|
+
count: (tableName: string, whereOrArgs?: unknown) => Promise<number>;
|
|
1746
|
+
delete: (id: string, expectedTable?: string) => Promise<void>;
|
|
1747
|
+
deleteMany: (ids: ReadonlyArray<string>, options?: {
|
|
1748
|
+
limit?: number;
|
|
1749
|
+
}) => Promise<{
|
|
1750
|
+
deleted: number;
|
|
1751
|
+
}>;
|
|
1752
|
+
deleteWhere?: (tableName: string, where: Record<string, unknown>, options?: {
|
|
1753
|
+
limit?: number;
|
|
1754
|
+
}) => Promise<{
|
|
1755
|
+
deleted: number;
|
|
1756
|
+
}>;
|
|
1757
|
+
findFirst: (tableName: string, args?: QueryArgs$1) => Promise<Record<string, unknown> | null>;
|
|
1758
|
+
findFirstOrThrow: (tableName: string, args?: QueryArgs$1) => Promise<Record<string, unknown>>;
|
|
1759
|
+
findMany: (tableName: string, args?: QueryArgs$1) => Promise<QueryPage$1>;
|
|
1760
|
+
get: (id: string, expectedTable?: string) => Promise<Record<string, unknown> | null>;
|
|
1761
|
+
groupBy: (tableName: string, options: GroupByArgs$1) => Promise<ReadonlyArray<{
|
|
1762
|
+
key: Record<string, unknown>;
|
|
1763
|
+
value: null | number;
|
|
1764
|
+
}>>;
|
|
1765
|
+
insert: (tableName: string, document: Record<string, unknown>) => Promise<string>;
|
|
1766
|
+
insertMany: (tableName: string, documents: ReadonlyArray<Record<string, unknown>>, options?: {
|
|
1767
|
+
limit?: number;
|
|
1768
|
+
skipDuplicates?: boolean;
|
|
1769
|
+
}) => Promise<(string | null)[]>;
|
|
1770
|
+
lookupById?: (id: string, expectedTable?: string) => Promise<null | {
|
|
1771
|
+
row: Record<string, unknown>;
|
|
1772
|
+
tableName: string;
|
|
1773
|
+
}>;
|
|
1774
|
+
patch: (id: string, patch: Record<string, unknown>, expectedTable?: string) => Promise<void>;
|
|
1775
|
+
patchMany: (patches: ReadonlyArray<{
|
|
1776
|
+
id: string;
|
|
1777
|
+
patch: Record<string, unknown>;
|
|
1778
|
+
}>, options?: {
|
|
1779
|
+
limit?: number;
|
|
1780
|
+
}) => Promise<{
|
|
1781
|
+
patched: number;
|
|
1782
|
+
}>;
|
|
1783
|
+
patchWhere?: (tableName: string, args: {
|
|
1784
|
+
patch: Record<string, unknown>;
|
|
1785
|
+
where: Record<string, unknown>;
|
|
1786
|
+
}, options?: {
|
|
1787
|
+
limit?: number;
|
|
1788
|
+
}) => Promise<{
|
|
1789
|
+
patched: number;
|
|
1790
|
+
}>;
|
|
1791
|
+
query: (tableName: string) => TableReaderLike$1;
|
|
1792
|
+
rank: (tableName: string, indexName: string, options: unknown) => Promise<null | {
|
|
1793
|
+
position: number;
|
|
1794
|
+
total: number;
|
|
1795
|
+
}>;
|
|
1796
|
+
rankBefore?: (tableName: string, indexName: string, options: unknown) => Promise<{
|
|
1797
|
+
before: number;
|
|
1798
|
+
total: number;
|
|
1799
|
+
}>;
|
|
1800
|
+
rankPage: (tableName: string, indexName: string, options?: unknown) => Promise<QueryPage$1>;
|
|
1801
|
+
/** Cross-shard companion to `rankPage`, gated the same way `rankPage` is masked below. */
|
|
1802
|
+
rankPageRows?: (tableName: string, indexName: string, options?: unknown) => Promise<ShardRankPageResultLike>;
|
|
1803
|
+
replace: (id: string, document: Record<string, unknown>, expectedTable?: string) => Promise<void>;
|
|
1804
|
+
}
|
|
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
|
+
interface MaskContextIn {
|
|
1812
|
+
auth?: AuthLike$1;
|
|
1813
|
+
db: MaskDatabase;
|
|
1706
1814
|
}
|
|
1707
1815
|
/**
|
|
1708
|
-
*
|
|
1709
|
-
*
|
|
1710
|
-
* the
|
|
1711
|
-
*
|
|
1816
|
+
* Procedure-builder middleware. Apply per-request via `.use(mask(policies))`.
|
|
1817
|
+
* Closes over the policy map at builder-construction time; resolves identity +
|
|
1818
|
+
* the `bypass` decision per call against the live ctx.
|
|
1819
|
+
*
|
|
1820
|
+
* IMPORTANT: a mask is in scope only for procedures whose builder chain
|
|
1821
|
+
* includes this middleware — opt-in, never global (the same invariant as RLS).
|
|
1712
1822
|
*/
|
|
1713
|
-
declare const
|
|
1823
|
+
declare const mask: <Context extends MaskContextIn = MaskContextIn>(policies: MaskPolicies<Context>, options?: MaskOptions<Context>) => Middleware<Context, Context>;
|
|
1824
|
+
/** Project-wide masked-column registry: every table any registered function masks, unioned. */
|
|
1825
|
+
type MaskRegistry = ReadonlyMap<string, ReadonlySet<string>>;
|
|
1714
1826
|
/**
|
|
1715
|
-
*
|
|
1716
|
-
*
|
|
1717
|
-
* `
|
|
1827
|
+
* Build the project-wide masked-column registry from the registered functions
|
|
1828
|
+
* (pass `Object.values(LUNORA_FUNCTIONS)`) — the mask-column twin of
|
|
1829
|
+
* `buildRlsReadRegistry`. Unions every function's `.use(mask(...))` columns
|
|
1830
|
+
* per table: a column masked by ANY registered function counts as masked in
|
|
1831
|
+
* the registry — there is no "which procedure would this shape have gone
|
|
1832
|
+
* through" question to narrow by, so the union is the only safe answer.
|
|
1718
1833
|
*/
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1834
|
+
declare const buildMaskRegistry: (functions: Iterable<unknown>) => MaskRegistry;
|
|
1835
|
+
/** A document handed to a migration transform: the stored row including `_id`/`_creationTime`. */
|
|
1836
|
+
type MigrationDocument = Record<string, unknown>;
|
|
1837
|
+
/**
|
|
1838
|
+
* The read surface a transform reaches through its `ctx`.
|
|
1839
|
+
*
|
|
1840
|
+
* Read-only by design: the runner accounts for exactly one rewrite per row read,
|
|
1841
|
+
* and a transform writing directly would make that count describe something
|
|
1842
|
+
* other than what happened. Scoped to the shard the runner is walking.
|
|
1843
|
+
*/
|
|
1844
|
+
interface MigrationReader {
|
|
1845
|
+
count: (table: string, where?: Record<string, unknown>) => Promise<number>;
|
|
1846
|
+
findFirst: (table: string, args?: Record<string, unknown>) => Promise<MigrationDocument | null>;
|
|
1847
|
+
findMany: (table: string, args?: Record<string, unknown>) => Promise<{
|
|
1848
|
+
isDone: boolean;
|
|
1849
|
+
page: MigrationDocument[];
|
|
1724
1850
|
}>;
|
|
1725
|
-
|
|
1726
|
-
|
|
1851
|
+
get: (id: string, expectedTable?: string) => Promise<MigrationDocument | null>;
|
|
1852
|
+
}
|
|
1853
|
+
/** The context handed to a transform alongside the row. */
|
|
1854
|
+
interface MigrationCtx {
|
|
1855
|
+
db: MigrationReader;
|
|
1727
1856
|
}
|
|
1728
1857
|
/**
|
|
1729
|
-
*
|
|
1730
|
-
* `
|
|
1731
|
-
*
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
*
|
|
1736
|
-
*
|
|
1737
|
-
*
|
|
1738
|
-
*
|
|
1739
|
-
*
|
|
1740
|
-
*
|
|
1741
|
-
*
|
|
1858
|
+
* Transform applied to one document. Return a new document to rewrite the row,
|
|
1859
|
+
* or `undefined` to leave it untouched (skipped, not counted as changed). The
|
|
1860
|
+
* runner always preserves the original `_id` and `_creationTime`, so the
|
|
1861
|
+
* returned document neither needs to nor should change row identity.
|
|
1862
|
+
*
|
|
1863
|
+
* The second parameter carries a shard-scoped reader. Without it a transform
|
|
1864
|
+
* could only rewrite the row it was handed — enough for a backfill whose new
|
|
1865
|
+
* value is a pure function of the old row (`displayName = name ?? "Anonymous"`),
|
|
1866
|
+
* but not for the shape people actually write: read the parent, copy a field
|
|
1867
|
+
* down onto its children.
|
|
1868
|
+
*
|
|
1869
|
+
* May return a promise, since a cross-table read is asynchronous.
|
|
1870
|
+
*
|
|
1871
|
+
* **A shard key cannot be backfilled this way, even with a reader.** A row whose
|
|
1872
|
+
* shard-key field is unset does not belong to any shard, so a shard-scoped query
|
|
1873
|
+
* will not enumerate it; and writing the key would have to MOVE the row to a
|
|
1874
|
+
* different Durable Object, which a per-shard runner cannot do. Re-keying is an
|
|
1875
|
+
* export → transform → import, not a migration.
|
|
1742
1876
|
*/
|
|
1877
|
+
type MigrationTransform = (document: MigrationDocument, ctx: MigrationCtx) => MigrationDocument | Promise<MigrationDocument | undefined | void> | undefined | void;
|
|
1878
|
+
interface MigrationDefinition {
|
|
1879
|
+
/** Rows fetched and rewritten per batch. Defaults to the runner's batch size when omitted. */
|
|
1880
|
+
readonly batchSize?: number;
|
|
1881
|
+
/** Optional reverse transform, applied by `migrate down`. */
|
|
1882
|
+
readonly down?: MigrationTransform;
|
|
1883
|
+
/** Stable, unique identifier — the key per-shard run-state is tracked under. */
|
|
1884
|
+
readonly id: string;
|
|
1885
|
+
/** Table whose documents this migration iterates. */
|
|
1886
|
+
readonly table: string;
|
|
1887
|
+
/** Forward transform, applied to every row by `migrate up`. */
|
|
1888
|
+
readonly up: MigrationTransform;
|
|
1889
|
+
}
|
|
1890
|
+
/** A {@link MigrationDefinition} plus the codegen discovery marker. */
|
|
1891
|
+
interface RegisteredMigration extends MigrationDefinition {
|
|
1892
|
+
readonly __lunoraMigration: true;
|
|
1893
|
+
}
|
|
1894
|
+
/** Declare an online data migration. See the module docs for runtime semantics. */
|
|
1895
|
+
declare const defineMigration: (definition: MigrationDefinition) => RegisteredMigration;
|
|
1743
1896
|
/**
|
|
1744
|
-
*
|
|
1745
|
-
*
|
|
1746
|
-
*
|
|
1747
|
-
* `
|
|
1748
|
-
* the merged tables. Extension tables are auto-namespaced by the extension
|
|
1749
|
-
* `key` (`buckets` → `ratelimit_buckets`), so the merged type carries the
|
|
1750
|
-
* prefixed names via {@link PrefixedTables}. Chains:
|
|
1751
|
-
* `defineSchema(...).extend(a).extend(b)` is the typed equivalent of merging
|
|
1752
|
-
* `a`'s prefixed tables then `b`'s.
|
|
1897
|
+
* A mutator declaration. `server` is authoritative; `client` is the optimistic
|
|
1898
|
+
* twin (optional — omit it to let the optimistic write fall through to the
|
|
1899
|
+
* server round-trip with no local preview). Both receive the same validated
|
|
1900
|
+
* `args`.
|
|
1753
1901
|
*/
|
|
1754
|
-
|
|
1755
|
-
extend: <X extends Record<string, TableDefinition>, Key extends string>(extension: SchemaExtension<X> & {
|
|
1756
|
-
readonly key: Key;
|
|
1757
|
-
}) => ExtendableSchema<PrefixedTables<X, Key> & T>;
|
|
1902
|
+
interface MutatorDefinition<Args extends ValidatorMap = ValidatorMap, ServerContext = MutationCtx, ClientTx = unknown, R = unknown> {
|
|
1758
1903
|
/**
|
|
1759
|
-
*
|
|
1760
|
-
* the
|
|
1761
|
-
*
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1904
|
+
* Validator for the mutator's arguments. Validated on the DO before `server`
|
|
1905
|
+
* runs and (when present) on the client before `client` runs, so both impls
|
|
1906
|
+
* see the same parsed shape. Omit for a parameterless mutator.
|
|
1907
|
+
*/
|
|
1908
|
+
readonly args?: Args;
|
|
1909
|
+
/**
|
|
1910
|
+
* Optimistic client implementation. Runs in a TanStack DB transaction
|
|
1911
|
+
* against the local collections; its writes are applied immediately and
|
|
1912
|
+
* automatically rolled back / rebased as the authoritative result syncs
|
|
1913
|
+
* back. Pure and side-effect-free beyond the local store. Omit to skip the
|
|
1914
|
+
* local preview.
|
|
1915
|
+
*/
|
|
1916
|
+
readonly client?: (tx: ClientTx, args: InferValidatorMap<Args>) => Promise<void> | void;
|
|
1917
|
+
/**
|
|
1918
|
+
* Owner-scope the write: names the column carrying the row owner (e.g.
|
|
1919
|
+
* `owner: "userId"`). Before `server` runs, the mutator requires a verified
|
|
1920
|
+
* identity, rejects a client-supplied owner that disagrees with it, and sets
|
|
1921
|
+
* the column to the verified value — so the impl reads `args[owner]` without
|
|
1922
|
+
* trusting the client and never repeats the check by hand.
|
|
1765
1923
|
*
|
|
1766
|
-
*
|
|
1767
|
-
*
|
|
1768
|
-
*
|
|
1769
|
-
*
|
|
1770
|
-
*
|
|
1771
|
-
*
|
|
1772
|
-
* into the new one.
|
|
1924
|
+
* This replaces the "every mutator opens with `assertOwner(ctx, args.userId)`"
|
|
1925
|
+
* pattern, and is the write-side counterpart to an `owner`-scoped
|
|
1926
|
+
* {@link import("./shapes").ShapeDefinition}. Unlike a shape it takes the column
|
|
1927
|
+
* NAME rather than `true`: a shape is bound to one `table`, so the table's
|
|
1928
|
+
* `.ownedBy(field)` resolves unambiguously, whereas one mutator may write
|
|
1929
|
+
* several tables and has no single owning table to read it from.
|
|
1773
1930
|
*
|
|
1774
|
-
*
|
|
1775
|
-
*
|
|
1776
|
-
* settings, not this option.
|
|
1777
|
-
* @see https://developers.cloudflare.com/durable-objects/reference/data-location/
|
|
1931
|
+
* Declare the column `v.optional(...)` to leave it off the wire entirely; it is
|
|
1932
|
+
* injected either way.
|
|
1778
1933
|
*/
|
|
1779
|
-
|
|
1934
|
+
readonly owner?: string;
|
|
1780
1935
|
/**
|
|
1781
|
-
*
|
|
1782
|
-
*
|
|
1783
|
-
*
|
|
1784
|
-
*
|
|
1785
|
-
* mode, so `.rls("required")` composes with `.extend(...)` either order.
|
|
1936
|
+
* Authoritative server implementation. Runs inside the shard DO with a full
|
|
1937
|
+
* {@link MutationContext} (`ctx.db` writer); its writes append to `__cdc_log`
|
|
1938
|
+
* and poke back to subscribers. This is the source of truth — the client
|
|
1939
|
+
* impl is only a prediction of it.
|
|
1786
1940
|
*/
|
|
1787
|
-
|
|
1788
|
-
}
|
|
1789
|
-
|
|
1941
|
+
readonly server: (context: ServerContext, args: InferValidatorMap<Args>) => Promise<R> | R;
|
|
1942
|
+
}
|
|
1943
|
+
/**
|
|
1944
|
+
* A {@link MutatorDefinition} plus the codegen discovery marker and a
|
|
1945
|
+
* dispatch-shaped `handler` (validates `args`, then runs `server`) so the DO
|
|
1946
|
+
* invokes a mutator exactly like a registered procedure.
|
|
1947
|
+
*/
|
|
1948
|
+
interface RegisteredMutator<Args extends ValidatorMap = ValidatorMap, ServerContext = MutationCtx, ClientTx = unknown, R = unknown> extends MutatorDefinition<Args, ServerContext, ClientTx, R> {
|
|
1949
|
+
readonly __lunoraMutator: true;
|
|
1950
|
+
/** Validate `rawArgs`, then run the authoritative `server` impl. Used by the DO push path. */
|
|
1951
|
+
readonly handler: (context: ServerContext, rawArgs: Record<string, unknown>) => Promise<R>;
|
|
1952
|
+
/**
|
|
1953
|
+
* Marks the dispatch kind so codegen can register the mutator in the same
|
|
1954
|
+
* `LUNORA_FUNCTIONS` table queries/mutations use — the DO's `handleRpc`
|
|
1955
|
+
* reads `kind === "mutation"` to wrap the authoritative `server` impl in the
|
|
1956
|
+
* shard's BEGIN/COMMIT span (all-or-nothing writes), exactly like an
|
|
1957
|
+
* ordinary `mutation`.
|
|
1958
|
+
*/
|
|
1959
|
+
readonly kind: "mutation";
|
|
1960
|
+
}
|
|
1961
|
+
/** Declare a custom mutator. See the module docs for runtime semantics. */
|
|
1962
|
+
declare const defineMutator: <Args extends ValidatorMap = ValidatorMap, ServerContext = MutationCtx, ClientTx = unknown, R = unknown>(definition: MutatorDefinition<Args, ServerContext, ClientTx, R>) => RegisteredMutator<Args, ServerContext, ClientTx, R>;
|
|
1790
1963
|
/** Default time-to-live for a presence row: a heartbeat keeps a member "present" for this long. */
|
|
1791
1964
|
declare const DEFAULT_TTL_MS = 3e4;
|
|
1792
1965
|
declare const PRESENCE_BARE_TABLE = "present";
|
|
@@ -2174,6 +2347,13 @@ interface DatabaseWriterLike {
|
|
|
2174
2347
|
* Required for the same reason as `aggregate`.
|
|
2175
2348
|
*/
|
|
2176
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>;
|
|
2177
2357
|
replace: (id: string, document: Record<string, unknown>, expectedTable?: string) => Promise<void>;
|
|
2178
2358
|
restore?: (id: string, expectedTable?: string) => Promise<void>;
|
|
2179
2359
|
/**
|
|
@@ -2455,4 +2635,4 @@ interface StorageContextIn {
|
|
|
2455
2635
|
}
|
|
2456
2636
|
declare const storageRules: <Context extends StorageContextIn = StorageContextIn>(rules: ReadonlyArray<StorageRule<Context>>, options?: StorageRulesOptions) => Middleware<Context, Context>;
|
|
2457
2637
|
declare const VERSION = "0.0.0";
|
|
2458
|
-
export { type ActionBuilder, type ActionCtx, type AggregateIndexDefinition, type AggregateIndexOptions, type AggregateOp, type ArgsValidator, type Component, type ComponentFunctions, type CreateOptions, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, type DataModelInit, type DefineComponentOptions, type DefineIdentityOptions, type DefineListArgsConfig, type DefinePluginOptions, type DefinePolicyInput, type DefinePresenceOptions, type DefineStorageRuleInput, type DurableObjectJurisdiction, type EmptyArgs, type EnvAccessor, type EnvKeyFailure, type EnvShape, type ExposeConfig, 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 IdentityContract, type IdentityRejectMode, type IdentityValidation, type InferArgs, type InferEnv, type InferIdentity, type InlineAggregateIndexOptions, type InlineRankIndexOptions, type InternalActionBuilder, type InternalMutationBuilder, type InternalQueryBuilder, type LifecycleEvent, type LifecycleHandler, type ListArgsSpec, type ListArgsValidators, type ListArgsValue, type ListFilterOperators, type ListOrderByEntry, type ListWhere, type LunoraBuilders, LunoraEnvError, LunoraError, 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 MutatorDefinition, 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 RegisteredMutator, type RegisteredQuery, type RegisteredShape, type RegisteredStream, type RelationBuilder, type RelationDefinition, type RlsOptions, type RlsReadRegistry, type Role, type Schema, type SchemaExtension, type ShapeDefinition, type ShapeReadWhereRequest, 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, allowAll, asBucketStorage, bindOrm, bindTableFacade, buildRlsReadRegistry, clampLimit, composePluginMiddleware, composeShapeReadWhere, createPolicyDsl, createSecrets, defineAggregateIndex, defineComponent, defineEnv, defineIdentity, defineListArgs, defineMigration, defineMutator, definePermission, definePlugin, definePolicies, definePolicy, definePresence, defineRankIndex, defineRole, defineSchema, defineSchemaExtension, defineShape, defineStorageRule, defineStorageRules, defineTable, defineVectorIndex, deny, httpAction, httpRoute, httpRouter, initLunora, installPlugins, isDeny, isSafeHeaderValue, mask, mergeSchemaExtension, onConnect, onDisconnect, presenceExtension, protectPublic, redactSecrets, rls, serveStorageObject, storageRules, toWhereInput };
|
|
2638
|
+
export { type ActionBuilder, type ActionCtx, type AggregateIndexDefinition, type AggregateIndexOptions, type AggregateOp, type ArgsValidator, type Component, type ComponentFunctions, type CreateOptions, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, type DataModelInit, type DefineComponentOptions, type DefineIdentityOptions, type DefineListArgsConfig, type DefinePluginOptions, type DefinePolicyInput, type DefinePresenceOptions, type DefineStorageRuleInput, type DurableObjectJurisdiction, type EmptyArgs, type EnvAccessor, type EnvKeyFailure, type EnvShape, type ExposeConfig, 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 IdentityContract, type IdentityRejectMode, type IdentityValidation, type IndexFieldsByTable, type InferArgs, type InferEnv, type InferIdentity, type InlineAggregateIndexOptions, type InlineRankIndexOptions, type InternalActionBuilder, type InternalMutationBuilder, type InternalQueryBuilder, type LifecycleEvent, type LifecycleHandler, type ListArgsSpec, type ListArgsValidators, type ListArgsValue, type ListFilterOperators, type ListOrderByEntry, type ListWhere, type LunoraBuilders, LunoraEnvError, LunoraError, type LunoraHttpApp, type LunoraHttpEnv, type LunoraRouteHandler, type ManyRelation, type MaskColumns, type MaskContext, type MaskFn, type MaskOptions, type MaskPolicies, type MaskRegistry, type MaskStrategy, type Middleware, type MiddlewareNext, type MigrationCtx, type MigrationDefinition, type MigrationDocument, type MigrationReader, type MigrationTransform, type MutationBuilder, type MutationCtx, type MutatorDefinition, 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 RegisteredMutator, type RegisteredQuery, type RegisteredShape, type RegisteredStream, type RelationBuilder, type RelationDefinition, type RlsOptions, type RlsReadRegistry, type Role, type Schema, type SchemaExtension, type ShapeDefinition, type ShapeReadWhereRequest, 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, allowAll, asBucketStorage, bindOrm, bindTableFacade, buildMaskRegistry, buildRlsReadRegistry, clampLimit, composePluginMiddleware, composeShapeReadWhere, createPolicyDsl, createSecrets, defineAggregateIndex, defineComponent, defineEnv, defineIdentity, defineListArgs, defineMigration, defineMutator, definePermission, definePlugin, definePolicies, definePolicy, definePresence, defineRankIndex, defineRole, defineSchema, defineSchemaExtension, defineShape, defineStorageRule, defineStorageRules, defineTable, defineVectorIndex, deny, httpAction, httpRoute, httpRouter, indexFieldsFromSchema, initLunora, installPlugins, isDeny, isSafeHeaderValue, mask, mergeSchemaExtension, onConnect, onDisconnect, presenceExtension, protectPublic, redactSecrets, rls, serveStorageObject, storageRules, toWhereInput };
|