@lunora/server 1.0.0-alpha.85 → 1.0.0-alpha.86

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/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- import { Validator, Infer, v, ValidatorMap, InferValidatorMap, ColumnValidator } from '@lunora/values';
1
+ import { Validator, Infer, v, Id, ValidatorMap, InferValidatorMap, ColumnValidator } from '@lunora/values';
2
2
  export { type ColumnValidator, type GeoPoint, type Id, type Infer, ValidationError, type Validator, type ValidatorKind, v } from '@lunora/values';
3
- import { ArgsValidator, InferArgs, RegisteredAction, ExposeConfig, X402ProcedureConfig, ActionCtx, MutationCtx, RegisteredMutation, QueryCtx, RegisteredQuery, DurableStreamOptions, RegisteredStream, FunctionKind, Secrets, TableDefinition, RegisteredFunction, VectorIndexDefinition, Schema, AggregateOp, GlobalBackend, RelationDefinition, OnDeleteAction, SearchLanguage, SearchStrategy, ExternalSourceDefinition, TriggerBuilder, TriggerDefinition, VectorEmbedder, VectorMetric, DurableObjectJurisdiction, AggregateIndexDefinition, RankIndexDefinition, LifecycleEvent, ShardInitEvent, RegisteredLifecycleHook } from "./types.mjs";
3
+ import { ArgsValidator, InferArgs, RegisteredAction, ExposeConfig, X402ProcedureConfig, ActionCtx, MutationCtx, RegisteredMutation, QueryCtx, RegisteredQuery, DurableStreamOptions, RegisteredStream, FunctionKind, TableDefinition, RegisteredFunction, VectorIndexDefinition, Schema, AggregateOp, GlobalBackend, RelationDefinition, OnDeleteAction, SearchLanguage, SearchStrategy, ExternalSourceDefinition, TriggerBuilder, TriggerDefinition, VectorEmbedder, VectorMetric, DurableObjectJurisdiction, AggregateIndexDefinition, RankIndexDefinition, Secrets, LifecycleEvent, ShardInitEvent, RegisteredLifecycleHook } from "./types.mjs";
4
4
  export { type AnyApi, type AuthState, type CachePurge, type DatabaseReader, type DatabaseWriter, type FunctionVisibility, type GeoBoundingBox, type GeoFilterBuilder, type GeoIndexDefinition, type GeoPointInput, type IndexDefinition, type IndexRangeBuilder, type LifecycleEventKind, type LogFields, type LunoraLogMethod, type LunoraLogger, type LunoraMetrics, type LunoraTracer, type LunoraWideEvent, type MutationStorage, type PaginationOptions, type PaginationResult, type RankSortKey, type ReadOnlyStorage, type RestCacheConfig, type RunQueryOptions, type ScheduledFunctionDoc, type ScheduledJob, type Scheduler, type SearchFilterBuilder, type SearchIndexDefinition, type ShardMode, type SpanEvaluation, type SpanHandle, type SpanKind, type SpanLink, type SpanOptions, type Storage, type StorageMetadata, type StorageObjectHead, type SystemDatabaseReader, type SystemDoc, type SystemQuery, type SystemTableName, type TableReader, type TableVectorIndex, type TriggerAggregateOptions, type TriggerCtx, type TriggerDatabase, type TriggerDeleteEvent, type TriggerEvent, type TriggerGroupByEntry, type TriggerGroupByOptions, type TriggerHandler, type TriggerInsertEvent, type TriggerOp, type TriggerQueryArgs, type TriggerQueryPage, type TriggerRankOptions, type TriggerRankPageOptions, type TriggerRankResult, type TriggerRow, type TriggerTiming, type TriggerUpdateEvent, type TtlDefinition, type VectorMatch, type VectorMatches, type VectorQueryInput, type VectorRecord, type VectorSearch, type VectorSearchReader, type VectorUpsertInput, type WorkflowCreateOptions, type WorkflowEventDefinition, type WorkflowHandle, type WorkflowInstance, type WorkflowInstanceStatus, type WorkflowStatusResult, type Workflows, anyApi } from "./types.mjs";
5
5
  import { LunoraError as LunoraError$1, LunoraErrorCode } from '@lunora/errors';
6
6
  export type { LunoraErrorCode } from '@lunora/errors';
@@ -9,24 +9,6 @@ import { WhereOperators, QueryArgs as QueryArgs$2 } from "./data-model.mjs";
9
9
  import { W as WhereInput, a as Policy, b as RlsOptions, c as Permission, R as Role, T as TypedDefinePolicyInput, D as DefinePolicyInput } from "./packem_shared/types.d-B-pIn8rE.mjs";
10
10
  export type { d as PolicyContext, e as PolicyDecision, f as PolicyDecisionOf, P as PolicyOperation } from "./packem_shared/types.d-B-pIn8rE.mjs";
11
11
  export { type CronJob, type CronJobsBuilder, type CronScheduleKind, type DailySchedule, type IntervalSchedule, type MonthlySchedule, type WeeklySchedule, cronJobs } from '@lunora/scheduler';
12
- /**
13
- * Make any resolved storage capability bucket-aware so `ctx.storage.bucket(name)`
14
- * always resolves. A `createBucketStorage(...)` result already carries
15
- * `.bucket` / `.bucketName` and is returned as-is; a single `createStorage(...)`
16
- * (or the no-storage stub) is tagged as the `"default"` bucket, where
17
- * `.bucket(name)` is the identity — single-bucket apps address one binding under
18
- * every name.
19
- *
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.
28
- */
29
- declare const asBucketStorage: (raw: unknown) => unknown;
30
12
  /**
31
13
  * Options for the `.stream()` terminal. `durable: true` is shorthand for
32
14
  * `durable: {}` — the runtime only ever sees the object form.
@@ -303,53 +285,6 @@ interface DataModelInit<DataModel> {
303
285
  readonly __dataModel?: DataModel;
304
286
  create: (options?: CreateOptions) => LunoraBuilders;
305
287
  }
306
- /**
307
- * Entry point for the procedure builder. `dataModel<DM>()` binds the generated
308
- * `DataModel` (phantom for now), and `.create()` yields the public root builders
309
- * plus their `internal*` counterparts.
310
- */
311
- declare const initLunora: {
312
- dataModel: <DataModel>() => DataModelInit<DataModel>;
313
- };
314
- /**
315
- * Build the `ctx.secrets` reader from the worker `env`. `get(name)` resolves
316
- * `env[name].get()` — the `secrets_store_secrets[]` binding of that name. An
317
- * absent or non-Secrets-Store binding throws a directed error pointing at the
318
- * wrangler config; the lookup is lazy, so an unused secret never resolves.
319
- */
320
- declare const createSecrets: (env: Record<string, unknown>) => Secrets;
321
- /**
322
- * Wrap a storage facade so it also accepts `deleteAfterCommit(key)`.
323
- *
324
- * Call once per dispatch, outside any read-stamping wrapper: `bucket()` delegates
325
- * to the wrapped facade, so a sub-facade is still stamped by whatever wrapped it.
326
- * @param storage the bucket-aware facade from `asBucketStorage`
327
- */
328
- declare const withDeferredDeletes: (storage: unknown) => unknown;
329
- /** How a flush ended, so a caller can assert on it without this module owning a logger. */
330
- interface DeferredDeleteFlushResult {
331
- /** How many keys were attempted. */
332
- attempted: number;
333
- /** Keys whose delete did not happen, with the reason. Empty when everything succeeded. */
334
- failures: {
335
- error: unknown;
336
- key: string;
337
- }[];
338
- }
339
- /**
340
- * Delete everything queued on `context.storage`, draining the queue as it goes,
341
- * and report each failure through `context.log`.
342
- *
343
- * Draining first means a second flush of the same dispatch is a no-op rather than
344
- * a second round of deletes.
345
- *
346
- * Never throws. A flush runs after the write committed, so there is no longer
347
- * anything to fail into: rejecting here could only turn a leaked object into a
348
- * failed response for a write that already succeeded. Failures are logged and
349
- * also returned, so a dispatch can call this and ignore the result.
350
- * @param context the dispatch context; a context with no queued deletes is a no-op
351
- */
352
- declare const flushDeferredDeletes: (context: unknown) => Promise<DeferredDeleteFlushResult>;
353
288
  /**
354
289
  * The prefixed tables a single plugin `P` contributes, or an empty map when it
355
290
  * ships no schema extension. Mirrors {@link PrefixedTables} at the plugin level
@@ -984,6 +919,202 @@ type IndexFieldsByTable = Readonly<Record<string, {
984
919
  }>>;
985
920
  declare const indexFieldsFromSchema: (schema: Schema) => IndexFieldsByTable;
986
921
  declare const defineSchema: <T extends Record<string, TableDefinition>>(tables: T, vectorIndexes?: Record<string, VectorIndexDefinition>, aggregateIndexes?: Record<string, AggregateIndexDefinition>, rankIndexes?: Record<string, RankIndexDefinition>) => ExtendableSchema<T>;
922
+ /** Default lifetime of a cached entry: one hour. */
923
+ declare const DEFAULT_ACTION_CACHE_TTL_MS: number;
924
+ declare const ACTION_CACHE_BARE_TABLE = "entries";
925
+ /**
926
+ * The prefixed table name the extension produces at merge time. The handlers and
927
+ * helpers read/write this name directly so they always agree with the merged
928
+ * schema.
929
+ */
930
+ declare const ACTION_CACHE_TABLE: "actionCache_entries";
931
+ /**
932
+ * The slice of an index-range builder this preset uses. Mirrors `IndexRangeBuilder`
933
+ * field-for-field so the real `ctx.db` query builder is assignable — the generated
934
+ * `ctx.db.query` is typed per table, and a helper holding a runtime string needs
935
+ * the wide overload.
936
+ */
937
+ interface ActionCacheIndexRange {
938
+ eq: (field: string, value: unknown) => ActionCacheIndexRange;
939
+ gt: (field: string, value: unknown) => ActionCacheIndexRange;
940
+ gte: (field: string, value: unknown) => ActionCacheIndexRange;
941
+ lt: (field: string, value: unknown) => ActionCacheIndexRange;
942
+ lte: (field: string, value: unknown) => ActionCacheIndexRange;
943
+ }
944
+ /** The slice of a `ctx.db` table query this preset relies on. */
945
+ interface ActionCacheQuery {
946
+ first: () => Promise<Record<string, unknown> | null>;
947
+ order: (direction: "asc" | "desc") => ActionCacheQuery;
948
+ take: (limit: number) => Promise<Record<string, unknown>[]>;
949
+ withIndex: (indexName: string, range?: (q: ActionCacheIndexRange) => ActionCacheIndexRange) => ActionCacheQuery;
950
+ }
951
+ /**
952
+ * The slice of the ORM writer (`ctx.db` on an action or mutation) the helpers
953
+ * need. The real `DatabaseWriter` is structurally assignable, so pass `ctx.db`
954
+ * directly.
955
+ */
956
+ interface ActionCacheDatabase {
957
+ delete: <T extends string>(id: Id<T>) => Promise<void>;
958
+ insert: (table: string, document: Record<string, unknown>) => Promise<unknown>;
959
+ patch: <T extends string>(id: Id<T>, patch: Record<string, unknown>) => Promise<void>;
960
+ query: (table: string) => ActionCacheQuery;
961
+ }
962
+ /** The slice of a function context the helpers need — just its writer. */
963
+ interface ActionCacheContext {
964
+ db: ActionCacheDatabase;
965
+ }
966
+ /** Options for {@link defineActionCache}. */
967
+ interface DefineActionCacheOptions {
968
+ /**
969
+ * Cap on the serialized size (bytes) of one cached value. A larger result is
970
+ * returned but not stored. Defaults to 512 KB; a non-finite value falls back
971
+ * to the default.
972
+ */
973
+ maxValueBytes?: number;
974
+ /**
975
+ * How long (ms) an entry stays fresh. A read past it reports a miss.
976
+ * Defaults to one hour.
977
+ */
978
+ ttlMs?: number;
979
+ }
980
+ /** The registered functions an action-cache component ships. */
981
+ interface ActionCacheFunctions {
982
+ /**
983
+ * Internal mutation that hard-deletes expired entries, oldest first, and
984
+ * reports how many it removed. Every miss already reaps a few rows
985
+ * opportunistically, so an app with steady traffic stays bounded without
986
+ * this; schedule it on a cron to reclaim entries whose names went quiet.
987
+ *
988
+ * Returns `{ deleted }`; compare it against `limit` to decide whether to run
989
+ * again rather than assuming one pass drained the table. A caller-supplied
990
+ * `limit` is clamped — `take()` has no ceiling of its own.
991
+ */
992
+ purgeExpired: RegisteredMutation<{
993
+ limit: ReturnType<typeof v.optional>;
994
+ }, {
995
+ deleted: number;
996
+ }>;
997
+ }
998
+ /**
999
+ * SHA-256 of `name` and the serialized args, hex.
1000
+ *
1001
+ * Hashed rather than stored: call sites routinely pass an entire model request,
1002
+ * which is tens of kilobytes. As an indexed column that would be wasteful and
1003
+ * would run into column-size limits; a digest is fixed-width and indexes cleanly.
1004
+ * The NUL separator keeps `("ab", "c")` and `("a", "bc")` from colliding.
1005
+ * @param name the logical cache namespace (usually the action's name)
1006
+ * @param argumentsKey the arguments, already serialized by {@link serializeArgs}
1007
+ */
1008
+ declare const cacheKeyFor: (name: string, argumentsKey: string) => Promise<string>;
1009
+ /**
1010
+ * The component shape {@link defineActionCache} returns: the extension, the
1011
+ * registered functions, and the helpers an action calls directly.
1012
+ */
1013
+ type ActionCacheComponent = {
1014
+ functions: ActionCacheFunctions;
1015
+ /** Drop the entry for exactly this `name` + `args`. Resolves whether or not one existed. */
1016
+ invalidate: (context: ActionCacheContext, name: string, args: unknown) => Promise<void>;
1017
+ /**
1018
+ * Drop every entry under `name`, whatever its arguments.
1019
+ *
1020
+ * `complete` is `false` when the paging bound was reached with rows still
1021
+ * matching — call again. A plain count could not tell "dropped all of them"
1022
+ * apart from "dropped the first few thousand".
1023
+ */
1024
+ invalidateAll: (context: ActionCacheContext, name: string) => Promise<{
1025
+ complete: boolean;
1026
+ deleted: number;
1027
+ }>;
1028
+ /**
1029
+ * Return the cached result for `name` + `args`, or run `compute` and cache it.
1030
+ *
1031
+ * `args` is keyed through the wire codec with sorted keys, so two calls agree
1032
+ * whenever their arguments are structurally equal — key order does not matter,
1033
+ * and `bigint` / `Date` / bytes arguments key distinctly rather than colliding.
1034
+ */
1035
+ wrap: <T>(context: ActionCacheContext, name: string, args: unknown, compute: () => Promise<T>) => Promise<T>;
1036
+ } & Component<{
1037
+ [ACTION_CACHE_BARE_TABLE]: ReturnType<typeof defineTable>;
1038
+ }>;
1039
+ /**
1040
+ * The action-cache schema extension: one `entries` table, auto-namespaced to
1041
+ * `actionCache_entries` at merge time.
1042
+ */
1043
+ declare const actionCacheExtension: SchemaExtension<{
1044
+ [ACTION_CACHE_BARE_TABLE]: ReturnType<typeof defineTable>;
1045
+ }>;
1046
+ /**
1047
+ * Build an action-cache {@link Component} — schema extension, `purgeExpired`, and
1048
+ * the `wrap` / `invalidate` / `invalidateAll` helpers — wired to one TTL.
1049
+ * @param options cache configuration (TTL, value-size cap).
1050
+ * @returns a component bundling the extension, the functions, and the helpers.
1051
+ */
1052
+ declare const defineActionCache: (options?: DefineActionCacheOptions) => ActionCacheComponent;
1053
+ /**
1054
+ * Make any resolved storage capability bucket-aware so `ctx.storage.bucket(name)`
1055
+ * always resolves. A `createBucketStorage(...)` result already carries
1056
+ * `.bucket` / `.bucketName` and is returned as-is; a single `createStorage(...)`
1057
+ * (or the no-storage stub) is tagged as the `"default"` bucket, where
1058
+ * `.bucket(name)` is the identity — single-bucket apps address one binding under
1059
+ * every name.
1060
+ *
1061
+ * Lives here rather than in `@lunora/server` because two packages need it and
1062
+ * neither may depend on the other: `@lunora/server` re-exports it as the runtime
1063
+ * counterpart `_generated/shard.ts` imports, and `@lunora/runtime` uses it to
1064
+ * build `ctx.storage` for an HTTP action from the worker's own R2 bindings.
1065
+ * Inlined into each `dist` by the bundler, so no dependency edge is created.
1066
+ *
1067
+ * The input is genuinely heterogeneous (a thunk result cast through `unknown`),
1068
+ * so the signature is `unknown → unknown`; callers cast the result.
1069
+ */
1070
+ declare const asBucketStorage: (raw: unknown) => unknown;
1071
+ /**
1072
+ * Entry point for the procedure builder. `dataModel<DM>()` binds the generated
1073
+ * `DataModel` (phantom for now), and `.create()` yields the public root builders
1074
+ * plus their `internal*` counterparts.
1075
+ */
1076
+ declare const initLunora: {
1077
+ dataModel: <DataModel>() => DataModelInit<DataModel>;
1078
+ };
1079
+ /**
1080
+ * Build the `ctx.secrets` reader from the worker `env`. `get(name)` resolves
1081
+ * `env[name].get()` — the `secrets_store_secrets[]` binding of that name. An
1082
+ * absent or non-Secrets-Store binding throws a directed error pointing at the
1083
+ * wrangler config; the lookup is lazy, so an unused secret never resolves.
1084
+ */
1085
+ declare const createSecrets: (env: Record<string, unknown>) => Secrets;
1086
+ /**
1087
+ * Wrap a storage facade so it also accepts `deleteAfterCommit(key)`.
1088
+ *
1089
+ * Call once per dispatch, outside any read-stamping wrapper: `bucket()` delegates
1090
+ * to the wrapped facade, so a sub-facade is still stamped by whatever wrapped it.
1091
+ * @param storage the bucket-aware facade from `asBucketStorage`
1092
+ */
1093
+ declare const withDeferredDeletes: (storage: unknown) => unknown;
1094
+ /** How a flush ended, so a caller can assert on it without this module owning a logger. */
1095
+ interface DeferredDeleteFlushResult {
1096
+ /** How many keys were attempted. */
1097
+ attempted: number;
1098
+ /** Keys whose delete did not happen, with the reason. Empty when everything succeeded. */
1099
+ failures: {
1100
+ error: unknown;
1101
+ key: string;
1102
+ }[];
1103
+ }
1104
+ /**
1105
+ * Delete everything queued on `context.storage`, draining the queue as it goes,
1106
+ * and report each failure through `context.log`.
1107
+ *
1108
+ * Draining first means a second flush of the same dispatch is a no-op rather than
1109
+ * a second round of deletes.
1110
+ *
1111
+ * Never throws. A flush runs after the write committed, so there is no longer
1112
+ * anything to fail into: rejecting here could only turn a leaked object into a
1113
+ * failed response for a write that already succeeded. Failures are logged and
1114
+ * also returned, so a dispatch can call this and ignore the result.
1115
+ * @param context the dispatch context; a context with no queued deletes is a no-op
1116
+ */
1117
+ declare const flushDeferredDeletes: (context: unknown) => Promise<DeferredDeleteFlushResult>;
987
1118
  /**
988
1119
  * Fields never written into a snapshot, whatever table they appear on.
989
1120
  *
@@ -2964,4 +3095,4 @@ interface StorageContextIn {
2964
3095
  }
2965
3096
  declare const storageRules: <Context extends StorageContextIn = StorageContextIn>(rules: ReadonlyArray<StorageRule<Context>>, options?: StorageRulesOptions) => Middleware<Context, Context>;
2966
3097
  declare const VERSION = "0.0.0";
2967
- export { type ActionBuilder, type ActionCtx, type AggregateIndexDefinition, type AggregateIndexOptions, type AggregateOp, type ArgsValidator, type Component, type ComponentFunctions, type CreateOptions, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_REDACTED_FIELDS as DOCUMENT_HISTORY_REDACTED_FIELDS, DOCUMENT_HISTORY_TABLE, type DataModelInit, type DeferredDeleteFlushResult, type DefineComponentOptions, type DefineDocumentHistoryOptions, type DefineIdentityOptions, type DefineListArgsConfig, type DefinePluginOptions, type DefinePolicyInput, type DefinePresenceOptions, type DefineStorageRuleInput, type DocumentHistoryComponent, type DocumentHistoryEntry, type DocumentHistoryFunctions, type DurableObjectJurisdiction, type DurableStreamOptions, 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 ReactorHandler, type ReactorOutcome, type ReactorSelect, type RegisteredAction, type RegisteredFunction, type RegisteredLifecycleHook, type RegisteredMigration, type RegisteredMutation, type RegisteredMutator, type RegisteredQuery, type RegisteredReactor, type RegisteredShape, type RegisteredStream, type RelationBuilder, type RelationDefinition, type RlsOptions, type RlsReadRegistry, type Role, type Schema, type SchemaExtension, type ShapeDefinition, type ShapeReadWhereRequest, type ShardInitEvent, type ShardInitHandler, 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, defineDocumentHistory, defineEnv, defineIdentity, defineListArgs, defineMigration, defineMutator, definePermission, definePlugin, definePolicies, definePolicy, definePresence, defineRankIndex, defineRole, defineSchema, defineSchemaExtension, defineShape, defineStorageRule, defineStorageRules, defineTable, defineVectorIndex, deny, documentHistoryExtension, flushDeferredDeletes, httpAction, httpRoute, httpRouter, indexFieldsFromSchema, initLunora, installPlugins, isDeny, isSafeHeaderValue, mask, mergeSchemaExtension, onConnect, onDisconnect, onQueryChange, onShardInit, presenceExtension, protectPublic, redactSecrets, rls, serveStorageObject, storageRules, toWhereInput, withDeferredDeletes };
3098
+ export { DEFAULT_ACTION_CACHE_TTL_MS as ACTION_CACHE_DEFAULT_TTL_MS, ACTION_CACHE_TABLE, type ActionBuilder, type ActionCacheComponent, type ActionCacheContext, type ActionCacheDatabase, type ActionCacheFunctions, type ActionCtx, type AggregateIndexDefinition, type AggregateIndexOptions, type AggregateOp, type ArgsValidator, type Component, type ComponentFunctions, type CreateOptions, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_REDACTED_FIELDS as DOCUMENT_HISTORY_REDACTED_FIELDS, DOCUMENT_HISTORY_TABLE, type DataModelInit, type DeferredDeleteFlushResult, type DefineActionCacheOptions, type DefineComponentOptions, type DefineDocumentHistoryOptions, type DefineIdentityOptions, type DefineListArgsConfig, type DefinePluginOptions, type DefinePolicyInput, type DefinePresenceOptions, type DefineStorageRuleInput, type DocumentHistoryComponent, type DocumentHistoryEntry, type DocumentHistoryFunctions, type DurableObjectJurisdiction, type DurableStreamOptions, 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 ReactorHandler, type ReactorOutcome, type ReactorSelect, type RegisteredAction, type RegisteredFunction, type RegisteredLifecycleHook, type RegisteredMigration, type RegisteredMutation, type RegisteredMutator, type RegisteredQuery, type RegisteredReactor, type RegisteredShape, type RegisteredStream, type RelationBuilder, type RelationDefinition, type RlsOptions, type RlsReadRegistry, type Role, type Schema, type SchemaExtension, type ShapeDefinition, type ShapeReadWhereRequest, type ShardInitEvent, type ShardInitHandler, 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, actionCacheExtension, allowAll, asBucketStorage, bindOrm, bindTableFacade, buildMaskRegistry, buildRlsReadRegistry, cacheKeyFor, clampLimit, composePluginMiddleware, composeShapeReadWhere, createPolicyDsl, createSecrets, defineActionCache, defineAggregateIndex, defineComponent, defineDocumentHistory, defineEnv, defineIdentity, defineListArgs, defineMigration, defineMutator, definePermission, definePlugin, definePolicies, definePolicy, definePresence, defineRankIndex, defineRole, defineSchema, defineSchemaExtension, defineShape, defineStorageRule, defineStorageRules, defineTable, defineVectorIndex, deny, documentHistoryExtension, flushDeferredDeletes, httpAction, httpRoute, httpRouter, indexFieldsFromSchema, initLunora, installPlugins, isDeny, isSafeHeaderValue, mask, mergeSchemaExtension, onConnect, onDisconnect, onQueryChange, onShardInit, presenceExtension, protectPublic, redactSecrets, rls, serveStorageObject, storageRules, toWhereInput, withDeferredDeletes };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { Validator, Infer, v, ValidatorMap, InferValidatorMap, ColumnValidator } from '@lunora/values';
1
+ import { Validator, Infer, v, Id, ValidatorMap, InferValidatorMap, ColumnValidator } from '@lunora/values';
2
2
  export { type ColumnValidator, type GeoPoint, type Id, type Infer, ValidationError, type Validator, type ValidatorKind, v } from '@lunora/values';
3
- import { ArgsValidator, InferArgs, RegisteredAction, ExposeConfig, X402ProcedureConfig, ActionCtx, MutationCtx, RegisteredMutation, QueryCtx, RegisteredQuery, DurableStreamOptions, RegisteredStream, FunctionKind, Secrets, TableDefinition, RegisteredFunction, VectorIndexDefinition, Schema, AggregateOp, GlobalBackend, RelationDefinition, OnDeleteAction, SearchLanguage, SearchStrategy, ExternalSourceDefinition, TriggerBuilder, TriggerDefinition, VectorEmbedder, VectorMetric, DurableObjectJurisdiction, AggregateIndexDefinition, RankIndexDefinition, LifecycleEvent, ShardInitEvent, RegisteredLifecycleHook } from "./types.js";
3
+ import { ArgsValidator, InferArgs, RegisteredAction, ExposeConfig, X402ProcedureConfig, ActionCtx, MutationCtx, RegisteredMutation, QueryCtx, RegisteredQuery, DurableStreamOptions, RegisteredStream, FunctionKind, TableDefinition, RegisteredFunction, VectorIndexDefinition, Schema, AggregateOp, GlobalBackend, RelationDefinition, OnDeleteAction, SearchLanguage, SearchStrategy, ExternalSourceDefinition, TriggerBuilder, TriggerDefinition, VectorEmbedder, VectorMetric, DurableObjectJurisdiction, AggregateIndexDefinition, RankIndexDefinition, Secrets, LifecycleEvent, ShardInitEvent, RegisteredLifecycleHook } from "./types.js";
4
4
  export { type AnyApi, type AuthState, type CachePurge, type DatabaseReader, type DatabaseWriter, type FunctionVisibility, type GeoBoundingBox, type GeoFilterBuilder, type GeoIndexDefinition, type GeoPointInput, type IndexDefinition, type IndexRangeBuilder, type LifecycleEventKind, type LogFields, type LunoraLogMethod, type LunoraLogger, type LunoraMetrics, type LunoraTracer, type LunoraWideEvent, type MutationStorage, type PaginationOptions, type PaginationResult, type RankSortKey, type ReadOnlyStorage, type RestCacheConfig, type RunQueryOptions, type ScheduledFunctionDoc, type ScheduledJob, type Scheduler, type SearchFilterBuilder, type SearchIndexDefinition, type ShardMode, type SpanEvaluation, type SpanHandle, type SpanKind, type SpanLink, type SpanOptions, type Storage, type StorageMetadata, type StorageObjectHead, type SystemDatabaseReader, type SystemDoc, type SystemQuery, type SystemTableName, type TableReader, type TableVectorIndex, type TriggerAggregateOptions, type TriggerCtx, type TriggerDatabase, type TriggerDeleteEvent, type TriggerEvent, type TriggerGroupByEntry, type TriggerGroupByOptions, type TriggerHandler, type TriggerInsertEvent, type TriggerOp, type TriggerQueryArgs, type TriggerQueryPage, type TriggerRankOptions, type TriggerRankPageOptions, type TriggerRankResult, type TriggerRow, type TriggerTiming, type TriggerUpdateEvent, type TtlDefinition, type VectorMatch, type VectorMatches, type VectorQueryInput, type VectorRecord, type VectorSearch, type VectorSearchReader, type VectorUpsertInput, type WorkflowCreateOptions, type WorkflowEventDefinition, type WorkflowHandle, type WorkflowInstance, type WorkflowInstanceStatus, type WorkflowStatusResult, type Workflows, anyApi } from "./types.js";
5
5
  import { LunoraError as LunoraError$1, LunoraErrorCode } from '@lunora/errors';
6
6
  export type { LunoraErrorCode } from '@lunora/errors';
@@ -9,24 +9,6 @@ import { WhereOperators, QueryArgs as QueryArgs$2 } from "./data-model.js";
9
9
  import { W as WhereInput, a as Policy, b as RlsOptions, c as Permission, R as Role, T as TypedDefinePolicyInput, D as DefinePolicyInput } from "./packem_shared/types.d-CdPDEjhz.js";
10
10
  export type { d as PolicyContext, e as PolicyDecision, f as PolicyDecisionOf, P as PolicyOperation } from "./packem_shared/types.d-CdPDEjhz.js";
11
11
  export { type CronJob, type CronJobsBuilder, type CronScheduleKind, type DailySchedule, type IntervalSchedule, type MonthlySchedule, type WeeklySchedule, cronJobs } from '@lunora/scheduler';
12
- /**
13
- * Make any resolved storage capability bucket-aware so `ctx.storage.bucket(name)`
14
- * always resolves. A `createBucketStorage(...)` result already carries
15
- * `.bucket` / `.bucketName` and is returned as-is; a single `createStorage(...)`
16
- * (or the no-storage stub) is tagged as the `"default"` bucket, where
17
- * `.bucket(name)` is the identity — single-bucket apps address one binding under
18
- * every name.
19
- *
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.
28
- */
29
- declare const asBucketStorage: (raw: unknown) => unknown;
30
12
  /**
31
13
  * Options for the `.stream()` terminal. `durable: true` is shorthand for
32
14
  * `durable: {}` — the runtime only ever sees the object form.
@@ -303,53 +285,6 @@ interface DataModelInit<DataModel> {
303
285
  readonly __dataModel?: DataModel;
304
286
  create: (options?: CreateOptions) => LunoraBuilders;
305
287
  }
306
- /**
307
- * Entry point for the procedure builder. `dataModel<DM>()` binds the generated
308
- * `DataModel` (phantom for now), and `.create()` yields the public root builders
309
- * plus their `internal*` counterparts.
310
- */
311
- declare const initLunora: {
312
- dataModel: <DataModel>() => DataModelInit<DataModel>;
313
- };
314
- /**
315
- * Build the `ctx.secrets` reader from the worker `env`. `get(name)` resolves
316
- * `env[name].get()` — the `secrets_store_secrets[]` binding of that name. An
317
- * absent or non-Secrets-Store binding throws a directed error pointing at the
318
- * wrangler config; the lookup is lazy, so an unused secret never resolves.
319
- */
320
- declare const createSecrets: (env: Record<string, unknown>) => Secrets;
321
- /**
322
- * Wrap a storage facade so it also accepts `deleteAfterCommit(key)`.
323
- *
324
- * Call once per dispatch, outside any read-stamping wrapper: `bucket()` delegates
325
- * to the wrapped facade, so a sub-facade is still stamped by whatever wrapped it.
326
- * @param storage the bucket-aware facade from `asBucketStorage`
327
- */
328
- declare const withDeferredDeletes: (storage: unknown) => unknown;
329
- /** How a flush ended, so a caller can assert on it without this module owning a logger. */
330
- interface DeferredDeleteFlushResult {
331
- /** How many keys were attempted. */
332
- attempted: number;
333
- /** Keys whose delete did not happen, with the reason. Empty when everything succeeded. */
334
- failures: {
335
- error: unknown;
336
- key: string;
337
- }[];
338
- }
339
- /**
340
- * Delete everything queued on `context.storage`, draining the queue as it goes,
341
- * and report each failure through `context.log`.
342
- *
343
- * Draining first means a second flush of the same dispatch is a no-op rather than
344
- * a second round of deletes.
345
- *
346
- * Never throws. A flush runs after the write committed, so there is no longer
347
- * anything to fail into: rejecting here could only turn a leaked object into a
348
- * failed response for a write that already succeeded. Failures are logged and
349
- * also returned, so a dispatch can call this and ignore the result.
350
- * @param context the dispatch context; a context with no queued deletes is a no-op
351
- */
352
- declare const flushDeferredDeletes: (context: unknown) => Promise<DeferredDeleteFlushResult>;
353
288
  /**
354
289
  * The prefixed tables a single plugin `P` contributes, or an empty map when it
355
290
  * ships no schema extension. Mirrors {@link PrefixedTables} at the plugin level
@@ -984,6 +919,202 @@ type IndexFieldsByTable = Readonly<Record<string, {
984
919
  }>>;
985
920
  declare const indexFieldsFromSchema: (schema: Schema) => IndexFieldsByTable;
986
921
  declare const defineSchema: <T extends Record<string, TableDefinition>>(tables: T, vectorIndexes?: Record<string, VectorIndexDefinition>, aggregateIndexes?: Record<string, AggregateIndexDefinition>, rankIndexes?: Record<string, RankIndexDefinition>) => ExtendableSchema<T>;
922
+ /** Default lifetime of a cached entry: one hour. */
923
+ declare const DEFAULT_ACTION_CACHE_TTL_MS: number;
924
+ declare const ACTION_CACHE_BARE_TABLE = "entries";
925
+ /**
926
+ * The prefixed table name the extension produces at merge time. The handlers and
927
+ * helpers read/write this name directly so they always agree with the merged
928
+ * schema.
929
+ */
930
+ declare const ACTION_CACHE_TABLE: "actionCache_entries";
931
+ /**
932
+ * The slice of an index-range builder this preset uses. Mirrors `IndexRangeBuilder`
933
+ * field-for-field so the real `ctx.db` query builder is assignable — the generated
934
+ * `ctx.db.query` is typed per table, and a helper holding a runtime string needs
935
+ * the wide overload.
936
+ */
937
+ interface ActionCacheIndexRange {
938
+ eq: (field: string, value: unknown) => ActionCacheIndexRange;
939
+ gt: (field: string, value: unknown) => ActionCacheIndexRange;
940
+ gte: (field: string, value: unknown) => ActionCacheIndexRange;
941
+ lt: (field: string, value: unknown) => ActionCacheIndexRange;
942
+ lte: (field: string, value: unknown) => ActionCacheIndexRange;
943
+ }
944
+ /** The slice of a `ctx.db` table query this preset relies on. */
945
+ interface ActionCacheQuery {
946
+ first: () => Promise<Record<string, unknown> | null>;
947
+ order: (direction: "asc" | "desc") => ActionCacheQuery;
948
+ take: (limit: number) => Promise<Record<string, unknown>[]>;
949
+ withIndex: (indexName: string, range?: (q: ActionCacheIndexRange) => ActionCacheIndexRange) => ActionCacheQuery;
950
+ }
951
+ /**
952
+ * The slice of the ORM writer (`ctx.db` on an action or mutation) the helpers
953
+ * need. The real `DatabaseWriter` is structurally assignable, so pass `ctx.db`
954
+ * directly.
955
+ */
956
+ interface ActionCacheDatabase {
957
+ delete: <T extends string>(id: Id<T>) => Promise<void>;
958
+ insert: (table: string, document: Record<string, unknown>) => Promise<unknown>;
959
+ patch: <T extends string>(id: Id<T>, patch: Record<string, unknown>) => Promise<void>;
960
+ query: (table: string) => ActionCacheQuery;
961
+ }
962
+ /** The slice of a function context the helpers need — just its writer. */
963
+ interface ActionCacheContext {
964
+ db: ActionCacheDatabase;
965
+ }
966
+ /** Options for {@link defineActionCache}. */
967
+ interface DefineActionCacheOptions {
968
+ /**
969
+ * Cap on the serialized size (bytes) of one cached value. A larger result is
970
+ * returned but not stored. Defaults to 512 KB; a non-finite value falls back
971
+ * to the default.
972
+ */
973
+ maxValueBytes?: number;
974
+ /**
975
+ * How long (ms) an entry stays fresh. A read past it reports a miss.
976
+ * Defaults to one hour.
977
+ */
978
+ ttlMs?: number;
979
+ }
980
+ /** The registered functions an action-cache component ships. */
981
+ interface ActionCacheFunctions {
982
+ /**
983
+ * Internal mutation that hard-deletes expired entries, oldest first, and
984
+ * reports how many it removed. Every miss already reaps a few rows
985
+ * opportunistically, so an app with steady traffic stays bounded without
986
+ * this; schedule it on a cron to reclaim entries whose names went quiet.
987
+ *
988
+ * Returns `{ deleted }`; compare it against `limit` to decide whether to run
989
+ * again rather than assuming one pass drained the table. A caller-supplied
990
+ * `limit` is clamped — `take()` has no ceiling of its own.
991
+ */
992
+ purgeExpired: RegisteredMutation<{
993
+ limit: ReturnType<typeof v.optional>;
994
+ }, {
995
+ deleted: number;
996
+ }>;
997
+ }
998
+ /**
999
+ * SHA-256 of `name` and the serialized args, hex.
1000
+ *
1001
+ * Hashed rather than stored: call sites routinely pass an entire model request,
1002
+ * which is tens of kilobytes. As an indexed column that would be wasteful and
1003
+ * would run into column-size limits; a digest is fixed-width and indexes cleanly.
1004
+ * The NUL separator keeps `("ab", "c")` and `("a", "bc")` from colliding.
1005
+ * @param name the logical cache namespace (usually the action's name)
1006
+ * @param argumentsKey the arguments, already serialized by {@link serializeArgs}
1007
+ */
1008
+ declare const cacheKeyFor: (name: string, argumentsKey: string) => Promise<string>;
1009
+ /**
1010
+ * The component shape {@link defineActionCache} returns: the extension, the
1011
+ * registered functions, and the helpers an action calls directly.
1012
+ */
1013
+ type ActionCacheComponent = {
1014
+ functions: ActionCacheFunctions;
1015
+ /** Drop the entry for exactly this `name` + `args`. Resolves whether or not one existed. */
1016
+ invalidate: (context: ActionCacheContext, name: string, args: unknown) => Promise<void>;
1017
+ /**
1018
+ * Drop every entry under `name`, whatever its arguments.
1019
+ *
1020
+ * `complete` is `false` when the paging bound was reached with rows still
1021
+ * matching — call again. A plain count could not tell "dropped all of them"
1022
+ * apart from "dropped the first few thousand".
1023
+ */
1024
+ invalidateAll: (context: ActionCacheContext, name: string) => Promise<{
1025
+ complete: boolean;
1026
+ deleted: number;
1027
+ }>;
1028
+ /**
1029
+ * Return the cached result for `name` + `args`, or run `compute` and cache it.
1030
+ *
1031
+ * `args` is keyed through the wire codec with sorted keys, so two calls agree
1032
+ * whenever their arguments are structurally equal — key order does not matter,
1033
+ * and `bigint` / `Date` / bytes arguments key distinctly rather than colliding.
1034
+ */
1035
+ wrap: <T>(context: ActionCacheContext, name: string, args: unknown, compute: () => Promise<T>) => Promise<T>;
1036
+ } & Component<{
1037
+ [ACTION_CACHE_BARE_TABLE]: ReturnType<typeof defineTable>;
1038
+ }>;
1039
+ /**
1040
+ * The action-cache schema extension: one `entries` table, auto-namespaced to
1041
+ * `actionCache_entries` at merge time.
1042
+ */
1043
+ declare const actionCacheExtension: SchemaExtension<{
1044
+ [ACTION_CACHE_BARE_TABLE]: ReturnType<typeof defineTable>;
1045
+ }>;
1046
+ /**
1047
+ * Build an action-cache {@link Component} — schema extension, `purgeExpired`, and
1048
+ * the `wrap` / `invalidate` / `invalidateAll` helpers — wired to one TTL.
1049
+ * @param options cache configuration (TTL, value-size cap).
1050
+ * @returns a component bundling the extension, the functions, and the helpers.
1051
+ */
1052
+ declare const defineActionCache: (options?: DefineActionCacheOptions) => ActionCacheComponent;
1053
+ /**
1054
+ * Make any resolved storage capability bucket-aware so `ctx.storage.bucket(name)`
1055
+ * always resolves. A `createBucketStorage(...)` result already carries
1056
+ * `.bucket` / `.bucketName` and is returned as-is; a single `createStorage(...)`
1057
+ * (or the no-storage stub) is tagged as the `"default"` bucket, where
1058
+ * `.bucket(name)` is the identity — single-bucket apps address one binding under
1059
+ * every name.
1060
+ *
1061
+ * Lives here rather than in `@lunora/server` because two packages need it and
1062
+ * neither may depend on the other: `@lunora/server` re-exports it as the runtime
1063
+ * counterpart `_generated/shard.ts` imports, and `@lunora/runtime` uses it to
1064
+ * build `ctx.storage` for an HTTP action from the worker's own R2 bindings.
1065
+ * Inlined into each `dist` by the bundler, so no dependency edge is created.
1066
+ *
1067
+ * The input is genuinely heterogeneous (a thunk result cast through `unknown`),
1068
+ * so the signature is `unknown → unknown`; callers cast the result.
1069
+ */
1070
+ declare const asBucketStorage: (raw: unknown) => unknown;
1071
+ /**
1072
+ * Entry point for the procedure builder. `dataModel<DM>()` binds the generated
1073
+ * `DataModel` (phantom for now), and `.create()` yields the public root builders
1074
+ * plus their `internal*` counterparts.
1075
+ */
1076
+ declare const initLunora: {
1077
+ dataModel: <DataModel>() => DataModelInit<DataModel>;
1078
+ };
1079
+ /**
1080
+ * Build the `ctx.secrets` reader from the worker `env`. `get(name)` resolves
1081
+ * `env[name].get()` — the `secrets_store_secrets[]` binding of that name. An
1082
+ * absent or non-Secrets-Store binding throws a directed error pointing at the
1083
+ * wrangler config; the lookup is lazy, so an unused secret never resolves.
1084
+ */
1085
+ declare const createSecrets: (env: Record<string, unknown>) => Secrets;
1086
+ /**
1087
+ * Wrap a storage facade so it also accepts `deleteAfterCommit(key)`.
1088
+ *
1089
+ * Call once per dispatch, outside any read-stamping wrapper: `bucket()` delegates
1090
+ * to the wrapped facade, so a sub-facade is still stamped by whatever wrapped it.
1091
+ * @param storage the bucket-aware facade from `asBucketStorage`
1092
+ */
1093
+ declare const withDeferredDeletes: (storage: unknown) => unknown;
1094
+ /** How a flush ended, so a caller can assert on it without this module owning a logger. */
1095
+ interface DeferredDeleteFlushResult {
1096
+ /** How many keys were attempted. */
1097
+ attempted: number;
1098
+ /** Keys whose delete did not happen, with the reason. Empty when everything succeeded. */
1099
+ failures: {
1100
+ error: unknown;
1101
+ key: string;
1102
+ }[];
1103
+ }
1104
+ /**
1105
+ * Delete everything queued on `context.storage`, draining the queue as it goes,
1106
+ * and report each failure through `context.log`.
1107
+ *
1108
+ * Draining first means a second flush of the same dispatch is a no-op rather than
1109
+ * a second round of deletes.
1110
+ *
1111
+ * Never throws. A flush runs after the write committed, so there is no longer
1112
+ * anything to fail into: rejecting here could only turn a leaked object into a
1113
+ * failed response for a write that already succeeded. Failures are logged and
1114
+ * also returned, so a dispatch can call this and ignore the result.
1115
+ * @param context the dispatch context; a context with no queued deletes is a no-op
1116
+ */
1117
+ declare const flushDeferredDeletes: (context: unknown) => Promise<DeferredDeleteFlushResult>;
987
1118
  /**
988
1119
  * Fields never written into a snapshot, whatever table they appear on.
989
1120
  *
@@ -2964,4 +3095,4 @@ interface StorageContextIn {
2964
3095
  }
2965
3096
  declare const storageRules: <Context extends StorageContextIn = StorageContextIn>(rules: ReadonlyArray<StorageRule<Context>>, options?: StorageRulesOptions) => Middleware<Context, Context>;
2966
3097
  declare const VERSION = "0.0.0";
2967
- export { type ActionBuilder, type ActionCtx, type AggregateIndexDefinition, type AggregateIndexOptions, type AggregateOp, type ArgsValidator, type Component, type ComponentFunctions, type CreateOptions, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_REDACTED_FIELDS as DOCUMENT_HISTORY_REDACTED_FIELDS, DOCUMENT_HISTORY_TABLE, type DataModelInit, type DeferredDeleteFlushResult, type DefineComponentOptions, type DefineDocumentHistoryOptions, type DefineIdentityOptions, type DefineListArgsConfig, type DefinePluginOptions, type DefinePolicyInput, type DefinePresenceOptions, type DefineStorageRuleInput, type DocumentHistoryComponent, type DocumentHistoryEntry, type DocumentHistoryFunctions, type DurableObjectJurisdiction, type DurableStreamOptions, 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 ReactorHandler, type ReactorOutcome, type ReactorSelect, type RegisteredAction, type RegisteredFunction, type RegisteredLifecycleHook, type RegisteredMigration, type RegisteredMutation, type RegisteredMutator, type RegisteredQuery, type RegisteredReactor, type RegisteredShape, type RegisteredStream, type RelationBuilder, type RelationDefinition, type RlsOptions, type RlsReadRegistry, type Role, type Schema, type SchemaExtension, type ShapeDefinition, type ShapeReadWhereRequest, type ShardInitEvent, type ShardInitHandler, 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, defineDocumentHistory, defineEnv, defineIdentity, defineListArgs, defineMigration, defineMutator, definePermission, definePlugin, definePolicies, definePolicy, definePresence, defineRankIndex, defineRole, defineSchema, defineSchemaExtension, defineShape, defineStorageRule, defineStorageRules, defineTable, defineVectorIndex, deny, documentHistoryExtension, flushDeferredDeletes, httpAction, httpRoute, httpRouter, indexFieldsFromSchema, initLunora, installPlugins, isDeny, isSafeHeaderValue, mask, mergeSchemaExtension, onConnect, onDisconnect, onQueryChange, onShardInit, presenceExtension, protectPublic, redactSecrets, rls, serveStorageObject, storageRules, toWhereInput, withDeferredDeletes };
3098
+ export { DEFAULT_ACTION_CACHE_TTL_MS as ACTION_CACHE_DEFAULT_TTL_MS, ACTION_CACHE_TABLE, type ActionBuilder, type ActionCacheComponent, type ActionCacheContext, type ActionCacheDatabase, type ActionCacheFunctions, type ActionCtx, type AggregateIndexDefinition, type AggregateIndexOptions, type AggregateOp, type ArgsValidator, type Component, type ComponentFunctions, type CreateOptions, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_REDACTED_FIELDS as DOCUMENT_HISTORY_REDACTED_FIELDS, DOCUMENT_HISTORY_TABLE, type DataModelInit, type DeferredDeleteFlushResult, type DefineActionCacheOptions, type DefineComponentOptions, type DefineDocumentHistoryOptions, type DefineIdentityOptions, type DefineListArgsConfig, type DefinePluginOptions, type DefinePolicyInput, type DefinePresenceOptions, type DefineStorageRuleInput, type DocumentHistoryComponent, type DocumentHistoryEntry, type DocumentHistoryFunctions, type DurableObjectJurisdiction, type DurableStreamOptions, 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 ReactorHandler, type ReactorOutcome, type ReactorSelect, type RegisteredAction, type RegisteredFunction, type RegisteredLifecycleHook, type RegisteredMigration, type RegisteredMutation, type RegisteredMutator, type RegisteredQuery, type RegisteredReactor, type RegisteredShape, type RegisteredStream, type RelationBuilder, type RelationDefinition, type RlsOptions, type RlsReadRegistry, type Role, type Schema, type SchemaExtension, type ShapeDefinition, type ShapeReadWhereRequest, type ShardInitEvent, type ShardInitHandler, 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, actionCacheExtension, allowAll, asBucketStorage, bindOrm, bindTableFacade, buildMaskRegistry, buildRlsReadRegistry, cacheKeyFor, clampLimit, composePluginMiddleware, composeShapeReadWhere, createPolicyDsl, createSecrets, defineActionCache, defineAggregateIndex, defineComponent, defineDocumentHistory, defineEnv, defineIdentity, defineListArgs, defineMigration, defineMutator, definePermission, definePlugin, definePolicies, definePolicy, definePresence, defineRankIndex, defineRole, defineSchema, defineSchemaExtension, defineShape, defineStorageRule, defineStorageRules, defineTable, defineVectorIndex, deny, documentHistoryExtension, flushDeferredDeletes, httpAction, httpRoute, httpRouter, indexFieldsFromSchema, initLunora, installPlugins, isDeny, isSafeHeaderValue, mask, mergeSchemaExtension, onConnect, onDisconnect, onQueryChange, onShardInit, presenceExtension, protectPublic, redactSecrets, rls, serveStorageObject, storageRules, toWhereInput, withDeferredDeletes };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{initLunora as t}from"./packem_shared/initLunora-B2sfmFJ6.mjs";import{createSecrets as i}from"./packem_shared/createSecrets-CyrEddTF.mjs";import{flushDeferredDeletes as a,withDeferredDeletes as s}from"./packem_shared/flushDeferredDeletes-DEJXlhop.mjs";import{DOCUMENT_HISTORY_REDACTED_FIELDS as d,DOCUMENT_HISTORY_TABLE as p,defineDocumentHistory as x,documentHistoryExtension as c}from"./packem_shared/DOCUMENT_HISTORY_REDACTED_FIELDS-B5M6QNiq.mjs";import{LunoraEnvError as E,defineEnv as u,redactSecrets as S}from"./packem_shared/LunoraEnvError-ByvihJFy.mjs";import{LunoraError as R}from"./packem_shared/LunoraError-DcKdk9Ti.mjs";import{bindOrm as D,bindTableFacade as T}from"./packem_shared/bindOrm-lWdeDi9P.mjs";import{httpAction as L,httpRoute as A,httpRouter as _,isSafeHeaderValue as y,serveStorageObject as P}from"./packem_shared/httpAction-D3b9-YiY.mjs";import{defineIdentity as M}from"./packem_shared/defineIdentity-DwkNKwYa.mjs";import{onConnect as F,onDisconnect as O,onShardInit as k}from"./packem_shared/onConnect-BLRoOpv2.mjs";import{DEFAULT_LIMIT as N,DEFAULT_MAX_LIMIT as U,clampLimit as v,defineListArgs as V}from"./packem_shared/DEFAULT_LIMIT-DC-M6faS.mjs";import{defineMigration as B}from"./packem_shared/defineMigration-7GI9Qbtd.mjs";import{defineMutator as W}from"./packem_shared/defineMutator-DKy8UtbB.mjs";import{c as J,d as Q,a as X,b as q,e as z,f as G,g as K,h as Z,i as $,j as ee,k as re,m as oe}from"./packem_shared/plugin-DQcLxTx1.mjs";import{PRESENCE_DEFAULT_TTL_MS as ne,PRESENCE_TABLE as ie,definePresence as fe,presenceExtension as ae}from"./packem_shared/PRESENCE_DEFAULT_TTL_MS-BpSPSCwL.mjs";import{protectPublic as me}from"./packem_shared/protectPublic-Bo4G9xaV.mjs";import{onQueryChange as pe}from"./packem_shared/onQueryChange-DDxYz2CF.mjs";import{defineShape as ce}from"./packem_shared/defineShape-DYxbNl5W.mjs";import{anyApi as Ee}from"./types.mjs";import{cronJobs as Se}from"@lunora/scheduler";import{ValidationError as Re,v as he}from"@lunora/values";import{allowAll as Te,deny as Ie,isDeny as Le,toWhereInput as Ae}from"./packem_shared/allowAll-DkRAgItV.mjs";import{asBucketStorage as ye}from"./packem_shared/asBucketStorage-BthCnWop.mjs";import{buildMaskRegistry as be}from"./packem_shared/buildMaskRegistry-72SL8fJn.mjs";import{buildRlsReadRegistry as Ce,composeShapeReadWhere as Fe}from"./packem_shared/buildRlsReadRegistry-Deq8inqS.mjs";import{createPolicyDsl as ke,definePermission as He,definePolicies as Ne,definePolicy as Ue,defineRole as ve}from"./packem_shared/createPolicyDsl-DNfByAUX.mjs";import{defineStorageRule as we,defineStorageRules as Be}from"./packem_shared/defineStorageRule-BvxHVq3b.mjs";import{mask as We}from"./packem_shared/mask-Da7q82ZC.mjs";import{r as Je}from"./packem_shared/middleware-DEW0yLvU.mjs";import{storageRules as Xe}from"./packem_shared/storageRules-CyaiZ0av.mjs";const e="0.0.0";export{N as DEFAULT_LIMIT,U as DEFAULT_MAX_LIMIT,d as DOCUMENT_HISTORY_REDACTED_FIELDS,p as DOCUMENT_HISTORY_TABLE,E as LunoraEnvError,R as LunoraError,ne as PRESENCE_DEFAULT_TTL_MS,ie as PRESENCE_TABLE,e as VERSION,Re as ValidationError,Te as allowAll,Ee as anyApi,ye as asBucketStorage,D as bindOrm,T as bindTableFacade,be as buildMaskRegistry,Ce as buildRlsReadRegistry,v as clampLimit,J as composePluginMiddleware,Fe as composeShapeReadWhere,ke as createPolicyDsl,i as createSecrets,Se as cronJobs,Q as defineAggregateIndex,X as defineComponent,x as defineDocumentHistory,u as defineEnv,M as defineIdentity,V as defineListArgs,B as defineMigration,W as defineMutator,He as definePermission,q as definePlugin,Ne as definePolicies,Ue as definePolicy,fe as definePresence,z as defineRankIndex,ve as defineRole,G as defineSchema,K as defineSchemaExtension,ce as defineShape,we as defineStorageRule,Be as defineStorageRules,Z as defineTable,$ as defineVectorIndex,Ie as deny,c as documentHistoryExtension,a as flushDeferredDeletes,L as httpAction,A as httpRoute,_ as httpRouter,ee as indexFieldsFromSchema,t as initLunora,re as installPlugins,Le as isDeny,y as isSafeHeaderValue,We as mask,oe as mergeSchemaExtension,F as onConnect,O as onDisconnect,pe as onQueryChange,k as onShardInit,ae as presenceExtension,me as protectPublic,S as redactSecrets,Je as rls,P as serveStorageObject,Xe as storageRules,Ae as toWhereInput,he as v,s as withDeferredDeletes};
1
+ import{ACTION_CACHE_DEFAULT_TTL_MS as t,ACTION_CACHE_TABLE as n,actionCacheExtension as i,cacheKeyFor as a,defineActionCache as f}from"./packem_shared/ACTION_CACHE_DEFAULT_TTL_MS-DNK5WUNn.mjs";import{initLunora as m}from"./packem_shared/initLunora-B2sfmFJ6.mjs";import{createSecrets as p}from"./packem_shared/createSecrets-CyrEddTF.mjs";import{flushDeferredDeletes as c,withDeferredDeletes as l}from"./packem_shared/flushDeferredDeletes-DEJXlhop.mjs";import{DOCUMENT_HISTORY_REDACTED_FIELDS as u,DOCUMENT_HISTORY_TABLE as S,defineDocumentHistory as T,documentHistoryExtension as h}from"./packem_shared/DOCUMENT_HISTORY_REDACTED_FIELDS-KTkC4xOc.mjs";import{LunoraEnvError as g,defineEnv as R,redactSecrets as _}from"./packem_shared/LunoraEnvError-ByvihJFy.mjs";import{LunoraError as L}from"./packem_shared/LunoraError-DcKdk9Ti.mjs";import{bindOrm as I,bindTableFacade as y}from"./packem_shared/bindOrm-lWdeDi9P.mjs";import{httpAction as P,httpRoute as b,httpRouter as F,isSafeHeaderValue as O,serveStorageObject as H}from"./packem_shared/httpAction-D3b9-YiY.mjs";import{defineIdentity as U}from"./packem_shared/defineIdentity-DwkNKwYa.mjs";import{onConnect as v,onDisconnect as B,onShardInit as V}from"./packem_shared/onConnect-BLRoOpv2.mjs";import{DEFAULT_LIMIT as j,DEFAULT_MAX_LIMIT as W,clampLimit as Y,defineListArgs as J}from"./packem_shared/DEFAULT_LIMIT-DC-M6faS.mjs";import{defineMigration as Q}from"./packem_shared/defineMigration-7GI9Qbtd.mjs";import{defineMutator as q}from"./packem_shared/defineMutator-DKy8UtbB.mjs";import{c as G,d as Z,a as $,b as ee,e as oe,f as re,g as te,h as ne,i as ie,j as ae,k as fe,m as se}from"./packem_shared/plugin-DQcLxTx1.mjs";import{PRESENCE_DEFAULT_TTL_MS as de,PRESENCE_TABLE as pe,definePresence as xe,presenceExtension as ce}from"./packem_shared/PRESENCE_DEFAULT_TTL_MS-BpSPSCwL.mjs";import{protectPublic as Ee}from"./packem_shared/protectPublic-Bo4G9xaV.mjs";import{onQueryChange as Se}from"./packem_shared/onQueryChange-UvArB8bh.mjs";import{defineShape as he}from"./packem_shared/defineShape-DYxbNl5W.mjs";import{anyApi as ge}from"./types.mjs";import{cronJobs as _e}from"@lunora/scheduler";import{ValidationError as Le,v as Ce}from"@lunora/values";import{allowAll as ye,deny as Me,isDeny as Pe,toWhereInput as be}from"./packem_shared/allowAll-DkRAgItV.mjs";import{asBucketStorage as Oe}from"./packem_shared/asBucketStorage-BthCnWop.mjs";import{buildMaskRegistry as Ne}from"./packem_shared/buildMaskRegistry-72SL8fJn.mjs";import{buildRlsReadRegistry as ke,composeShapeReadWhere as ve}from"./packem_shared/buildRlsReadRegistry-Deq8inqS.mjs";import{createPolicyDsl as Ve,definePermission as we,definePolicies as je,definePolicy as We,defineRole as Ye}from"./packem_shared/createPolicyDsl-DNfByAUX.mjs";import{defineStorageRule as Ke,defineStorageRules as Qe}from"./packem_shared/defineStorageRule-BvxHVq3b.mjs";import{mask as qe}from"./packem_shared/mask-Da7q82ZC.mjs";import{r as Ge}from"./packem_shared/middleware-DEW0yLvU.mjs";import{storageRules as $e}from"./packem_shared/storageRules-CyaiZ0av.mjs";const e="0.0.0";export{t as ACTION_CACHE_DEFAULT_TTL_MS,n as ACTION_CACHE_TABLE,j as DEFAULT_LIMIT,W as DEFAULT_MAX_LIMIT,u as DOCUMENT_HISTORY_REDACTED_FIELDS,S as DOCUMENT_HISTORY_TABLE,g as LunoraEnvError,L as LunoraError,de as PRESENCE_DEFAULT_TTL_MS,pe as PRESENCE_TABLE,e as VERSION,Le as ValidationError,i as actionCacheExtension,ye as allowAll,ge as anyApi,Oe as asBucketStorage,I as bindOrm,y as bindTableFacade,Ne as buildMaskRegistry,ke as buildRlsReadRegistry,a as cacheKeyFor,Y as clampLimit,G as composePluginMiddleware,ve as composeShapeReadWhere,Ve as createPolicyDsl,p as createSecrets,_e as cronJobs,f as defineActionCache,Z as defineAggregateIndex,$ as defineComponent,T as defineDocumentHistory,R as defineEnv,U as defineIdentity,J as defineListArgs,Q as defineMigration,q as defineMutator,we as definePermission,ee as definePlugin,je as definePolicies,We as definePolicy,xe as definePresence,oe as defineRankIndex,Ye as defineRole,re as defineSchema,te as defineSchemaExtension,he as defineShape,Ke as defineStorageRule,Qe as defineStorageRules,ne as defineTable,ie as defineVectorIndex,Me as deny,h as documentHistoryExtension,c as flushDeferredDeletes,P as httpAction,b as httpRoute,F as httpRouter,ae as indexFieldsFromSchema,m as initLunora,fe as installPlugins,Pe as isDeny,O as isSafeHeaderValue,qe as mask,se as mergeSchemaExtension,v as onConnect,B as onDisconnect,Se as onQueryChange,V as onShardInit,ce as presenceExtension,Ee as protectPublic,_ as redactSecrets,Ge as rls,H as serveStorageObject,$e as storageRules,be as toWhereInput,Ce as v,l as withDeferredDeletes};
@@ -0,0 +1 @@
1
+ import{isLunoraError as S}from"@lunora/errors";import{v as d}from"@lunora/values";import{e as f,d as U}from"./wire-codec-hZHn-Ooo.mjs";import{s as D}from"./stable-key-ITGZkfuz.mjs";import{initLunora as F}from"./initLunora-B2sfmFJ6.mjs";import{g as k,h as q,a as B}from"./plugin-DQcLxTx1.mjs";const P=i=>D(f(i)),R=3600*1e3,H=512*1024,V=8,b=64,K=64,W=256,$=4096,u="actionCache",h="entries",c=`${u}_${h}`,T=i=>i===void 0?"":P(i),x=async(i,m)=>{const A=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(`${i}\0${m}`));return[...new Uint8Array(A)].map(y=>y.toString(16).padStart(2,"0")).join("")},G=k(u,{tables:{[h]:q({expiresAt:d.number(),key:d.string(),name:d.string(),value:d.string()}).index("byKey",["key"],{unique:!0}).index("byName",["name"]).index("byExpiresAt",["expiresAt"])}}),{internalMutation:J}=F.dataModel().create(),te=(i={})=>{const m=i.ttlMs!==void 0&&Number.isFinite(i.ttlMs)?Math.max(1,Math.floor(i.ttlMs)):R,A=i.maxValueBytes!==void 0&&Number.isFinite(i.maxValueBytes)?Math.max(1,Math.floor(i.maxValueBytes)):H,y=async(e,t)=>{const n=(await e.db.query(c).withIndex("byExpiresAt").order("asc").take(V)).filter(r=>r.expiresAt<=t);await Promise.all(n.map(async r=>e.db.delete(r._id)))},C=async(e,t)=>e.db.query(c).withIndex("byKey",a=>a.eq("key",t)).first(),N=new Set(["CONFLICT","NOT_FOUND","NOT_UNIQUE"]),I=async(e,t,a)=>{try{await(t?e.db.patch(t._id,{expiresAt:a.expiresAt,value:a.value}):e.db.insert(c,a))}catch(n){if(S(n)&&N.has(n.code))return;throw n}},M=async(e,t,a,n)=>{const r=T(a),s=await x(t,r),l=Date.now(),o=await C(e,s);if(o&&o.expiresAt>l)return U(JSON.parse(o.value)).v;const p=await n(),w=JSON.stringify(f({v:p})),E=Date.now(),O=E+m;return new TextEncoder().encode(w).length<=A?await I(e,o,{expiresAt:O,key:s,name:t,value:w}):o&&await e.db.delete(o._id),await y(e,E),p},L=async(e,t,a)=>{const n=await x(t,T(a)),r=await e.db.query(c).withIndex("byKey",s=>s.eq("key",n)).take(b);await Promise.all(r.map(async s=>e.db.delete(s._id)))},_=async(e,t,a,n)=>{if(n>=K)return{complete:!1,deleted:a};const r=await e.db.query(c).withIndex("byName",s=>s.eq("name",t)).take(b);return r.length===0?{complete:!0,deleted:a}:(await Promise.all(r.map(async s=>e.db.delete(s._id))),_(e,t,a+r.length,n+1))},g=async(e,t)=>_(e,t,0,0),v=J.input({limit:d.optional(d.number())}).mutation(async({args:e,ctx:t})=>{const a=Date.now(),n=e.limit!==void 0&&Number.isFinite(e.limit)?Math.min($,Math.max(1,Math.floor(e.limit))):W,s=(await t.db.query(c).withIndex("byExpiresAt").order("asc").take(n)).filter(l=>l.expiresAt<=a);return await Promise.all(s.map(async l=>t.db.delete(l._id))),{deleted:s.length}});return{...B(u,{extension:G,functions:{purgeExpired:v}}),invalidate:L,invalidateAll:g,wrap:M}};export{R as ACTION_CACHE_DEFAULT_TTL_MS,c as ACTION_CACHE_TABLE,G as actionCacheExtension,x as cacheKeyFor,te as defineActionCache};
@@ -0,0 +1 @@
1
+ import{v as r}from"@lunora/values";import{d as A,e as h}from"./wire-codec-hZHn-Ooo.mjs";import{initLunora as v}from"./initLunora-B2sfmFJ6.mjs";import{g as x,h as R,a as U}from"./plugin-DQcLxTx1.mjs";const H=2160*60*60*1e3,q=64*1024,E=200,C=64,F=512,y=16,L=["_commitSeq","seq"],B=["accessToken","apiKey","backupCodes","clientSecret","hashedPassword","password","privateKey","refreshToken","secret","totpSecret"],p="documentHistory",I="versions",l=`${p}_${I}`,P=x(p,{tables:{[I]:R({doc:r.optional(r.string()),documentId:r.string(),op:r.union(r.literal("delete"),r.literal("insert"),r.literal("update")),previous:r.optional(r.string()),recordedAt:r.number(),seq:r.number(),tableName:r.string(),truncated:r.optional(r.boolean())}).commitOrdered().index("byDocumentRecordedAt",["documentId","recordedAt","seq"]).index("byRecordedAt",["recordedAt"])}}),{internalMutation:Y,internalQuery:j}=v.dataModel().create(),X=(d={})=>{const T=d.retentionMs!==void 0&&Number.isFinite(d.retentionMs)?Math.max(1,Math.floor(d.retentionMs)):H,_=d.maxSnapshotBytes!==void 0&&Number.isFinite(d.maxSnapshotBytes)?Math.max(1,Math.floor(d.maxSnapshotBytes)):q,D=new Set([...B,...d.redact??[]]);let b=0;const M=()=>(b+=1,b),m=(e,t=0)=>{if(Array.isArray(e))return t>=y?void 0:e.map(o=>m(o,t+1));if(typeof e!="object"||e===null||Object.getPrototypeOf(e)!==Object.prototype&&Object.getPrototypeOf(e)!==null)return e;if(!(t>=y))return Object.fromEntries(Object.entries(e).filter(([o])=>!D.has(o)).map(([o,i])=>[o,m(i,t+1)]))},f=e=>{if(e===void 0)return;const t=JSON.stringify(h(m(e)));return new TextEncoder().encode(t).length>_?void 0:t},u=async(e,t)=>{const o=f(t.doc),i=f(t.previous),n=t.doc!==void 0&&o===void 0||t.previous!==void 0&&i===void 0;await e.db.insert(l,{documentId:t.documentId,op:t.op,recordedAt:Date.now(),seq:M(),tableName:t.tableName,...n?{truncated:!0}:{},...o===void 0?{}:{doc:o},...i===void 0?{}:{previous:i}})},S=e=>({documentHistoryDelete:e.afterDelete(async(t,o)=>u(t,{documentId:o.id,op:"delete",previous:o.previous,tableName:o.table})),documentHistoryInsert:e.afterInsert(async(t,o)=>u(t,{doc:o.doc,documentId:o.id,op:"insert",tableName:o.table})),documentHistoryUpdate:e.afterUpdate(async(t,o)=>u(t,{doc:o.doc,documentId:o.id,op:"update",previous:o.previous,tableName:o.table}))}),N=j.input({before:r.optional(r.number()),documentId:r.string(),limit:r.optional(r.number())}).query(async({args:e,ctx:t})=>{const o=e.limit!==void 0&&Number.isFinite(e.limit)?Math.max(1,Math.floor(e.limit)):E,i=await t.db.query(l).withIndex("byDocumentRecordedAt",n=>e.before===void 0?n.eq("documentId",e.documentId):n.eq("documentId",e.documentId).lte("recordedAt",e.before)).order("desc").take(o);return i.sort((n,a)=>{for(const c of L){const s=(a[c]??0)-(n[c]??0);if(s!==0)return s}return 0}),i.map(n=>({documentId:n.documentId,op:n.op,recordedAt:n.recordedAt,tableName:n.tableName,...n.doc===void 0?{}:{doc:A(JSON.parse(n.doc))},...n.previous===void 0?{}:{previous:A(JSON.parse(n.previous))},...n.truncated===!0?{truncated:!0}:{}}))}),O=Y.input({limit:r.optional(r.number())}).mutation(async({args:e,ctx:t})=>{const o=Date.now()-T,i=e.limit!==void 0&&Number.isFinite(e.limit)?Math.max(1,Math.floor(e.limit)):F;let n=0;for(let a=0;a<C&&n<i;a+=1){const c=await t.db.query(l).withIndex("byRecordedAt",s=>s.lt("recordedAt",o)).order("asc").take(Math.min(E,i-n));if(c.length===0)return{deleted:n};await Promise.all(c.map(async s=>t.db.delete(s._id))),n+=c.length}return{deleted:n}});return{...U(p,{extension:P,functions:{listForDocument:N,vacuum:O}}),record:S}};export{B as DOCUMENT_HISTORY_REDACTED_FIELDS,l as DOCUMENT_HISTORY_TABLE,X as defineDocumentHistory,P as documentHistoryExtension};
@@ -0,0 +1 @@
1
+ import{f as e,F as o,a as c}from"./fnv1a-D6VtE8WR.mjs";import{s as f}from"./stable-key-ITGZkfuz.mjs";const l=r=>`${e(r,o)}${e(r,c)}`,m=(r,i)=>({args:{},handler:async(a,s)=>{const n=await r(a),t=l(f(n));return t===s?.previousDigest?{digest:t,ran:!1}:(await i(a,n),{digest:t,ran:!0})},kind:"mutation",lifecycle:"reactor",visibility:"internal"});export{m as onQueryChange};
@@ -0,0 +1 @@
1
+ const f=(t,n)=>t<n?-1:t>n?1:0,s=t=>{if(t===void 0)return"null";if(typeof t=="bigint")throw new TypeError("stableStringify: cannot use a bigint in a stable JSON cache key — pass it as a string, or use stableWireKey");if(typeof t=="number"){if(Number.isNaN(t))return"nan";if(t===1/0)return"inf";if(t===-1/0)return"-inf";if(Object.is(t,-0))return"-0"}if(t===null||typeof t!="object")return JSON.stringify(t);if(Array.isArray(t))return`[${t.map(r=>s(r)).join(",")}]`;const n=Object.getPrototypeOf(t);if(n!==null&&n!==Object.prototype){const r=t.constructor?.name??"value";throw new TypeError(`stableStringify: cannot use a ${r} in a stable JSON cache key — only plain objects, arrays, and JSON primitives are supported (wire-typed values key via stableWireKey)`)}const i=t,y=Object.keys(i).toSorted(f),e=[];for(const r of y){const o=i[r];o!==void 0&&e.push(`${JSON.stringify(r)}:${s(o)}`)}return`{${e.join(",")}}`};export{s};
@@ -0,0 +1 @@
1
+ const A=e=>{let t="";for(let o=0;o<e.length;o+=32768)t+=String.fromCharCode(...e.subarray(o,o+32768));return btoa(t)},E=e=>{const t=atob(e),f=new Uint8Array(t.length);for(let o=0;o<t.length;o+=1)f[o]=t.codePointAt(o)??0;return f},i="$lunora.wire$";const d="__proto__",m={BigInt64Array,BigUint64Array,Float32Array,Float64Array,Int8Array,Int16Array,Int32Array,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array},w={Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError},p=e=>{if(e===null||typeof e!="object")return!1;const t=Object.getPrototypeOf(e);return t===null||t===Object.prototype},u=(e,t=0)=>{if(t>64)throw new RangeError("wire-codec: value nesting exceeds the 64-level limit");if(e===void 0)return[i,"undefined"];if(e===null)return null;const f=typeof e;if(f==="bigint")return[i,"bigint",e.toString()];if(f==="number"){const r=e;return Number.isNaN(r)?[i,"nan"]:r===1/0?[i,"inf"]:r===-1/0?[i,"-inf"]:r}if(f!=="object")return e;if(e instanceof Date)return[i,"date",u(e.getTime(),t+1)];if(e instanceof Error){const r=e,n={};for(const a of Object.keys(r))r[a]!==void 0&&(n[a]=u(r[a],t+1));const c=[i,"error",r.name,r.message,n];return r.cause!==void 0&&c.push(u(r.cause,t+1)),c}if(e instanceof URL)return[i,"url",e.href];if(e instanceof Map)return[i,"map",[...e.entries()].map(([r,n])=>[u(r,t+1),u(n,t+1)])];if(e instanceof Set)return[i,"set",[...e].map(r=>u(r,t+1))];if(e instanceof ArrayBuffer)return[i,"bytes",A(new Uint8Array(e)),"ArrayBuffer"];if(ArrayBuffer.isView(e)){const r=e,n=r.constructor.name,c=new Uint8Array(r.buffer,r.byteOffset,r.byteLength);return n==="Uint8Array"?[i,"bytes",A(c)]:[i,"bytes",A(c),n]}if(Array.isArray(e)){const r=e.map(n=>u(n,t+1));return r.length>0&&r[0]===i?[i,"arr",r]:r}if(!p(e)){const r=e.constructor?.name??"value";throw new TypeError(`wire-codec: cannot encode a ${r} over the Lunora wire — only plain objects, arrays, and the supported built-ins (Date, Error, URL, Map, Set, ArrayBuffer/typed arrays, bigint) round-trip`)}const o=e,s={};for(const r of Object.keys(o)){const n=o[r];if(n===void 0)continue;const c=u(n,t+1);r===d?Object.defineProperty(s,r,{configurable:!0,enumerable:!0,value:c,writable:!0}):s[r]=c}return s},y=(e,t=0)=>{if(t>64)throw new RangeError("wire-codec: value nesting exceeds the 64-level limit");if(e===null||typeof e!="object")return e;if(Array.isArray(e)){if(e[0]===i)switch(e[1]){case"-inf":return-1/0;case"arr":return e[2].map(r=>y(r,t+1));case"bigint":{const r=e[2];if(typeof r!="string"||r.length>1024||!/^-?\d+$/.test(r))throw new RangeError("wire-codec: invalid or over-long bigint (max 1024 digits)");return BigInt(r)}case"date":return new Date(y(e[2],t+1));case"map":return new Map(e[2].map(([r,n])=>[y(r,t+1),y(n,t+1)]));case"set":return new Set(e[2].map(r=>y(r,t+1)));case"url":return new URL(e[2]);case"error":{const r=e[2],n=e[3],c=(Object.hasOwn(w,r)?w[r]:void 0)??Error,a=new c(n);a.name!==r&&Object.defineProperty(a,"name",{configurable:!0,value:r,writable:!0});const g=y(e[4],t+1);for(const b of Object.keys(g))b===d?Object.defineProperty(a,b,{configurable:!0,enumerable:!0,value:g[b],writable:!0}):a[b]=g[b];return e.length>5&&Object.defineProperty(a,"cause",{configurable:!0,value:y(e[5],t+1),writable:!0}),a}case"bytes":{const r=E(e[2]),n=e[3]??"Uint8Array";if(n==="ArrayBuffer")return r.buffer.byteLength===r.byteLength?r.buffer:r.slice().buffer;const c=Object.hasOwn(m,n)?m[n]:void 0;return c?new c(r.slice().buffer):r}case"inf":return 1/0;case"nan":return Number.NaN;case"undefined":return;default:return e.map(r=>y(r,t+1))}return e.map(s=>y(s,t+1))}const f=e,o={};for(const s of Object.keys(f)){const r=y(f[s],t+1);s===d?Object.defineProperty(o,s,{configurable:!0,enumerable:!0,value:r,writable:!0}):o[s]=r}return o};export{y as d,u as e};
package/dist/types.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { ValidatorMap, InferValidatorMap, Id, Validator, Infer } from '@lunora/values';
1
+ import { ValidatorMap, InferValidatorMap, Validator, Infer, Id } from '@lunora/values';
2
2
  /**
3
3
  * The set of languages a `.searchIndex()` can declare, in one place.
4
4
  *
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ValidatorMap, InferValidatorMap, Id, Validator, Infer } from '@lunora/values';
1
+ import { ValidatorMap, InferValidatorMap, Validator, Infer, Id } from '@lunora/values';
2
2
  /**
3
3
  * The set of languages a `.searchIndex()` can declare, in one place.
4
4
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/server",
3
- "version": "1.0.0-alpha.85",
3
+ "version": "1.0.0-alpha.86",
4
4
  "description": "Server primitives for Lunora: defineSchema, defineTable, query, mutation, and action",
5
5
  "keywords": [
6
6
  "backend",
@@ -68,7 +68,7 @@
68
68
  "dependencies": {
69
69
  "@lunora/errors": "1.0.0-alpha.24",
70
70
  "@lunora/scheduler": "1.0.0-alpha.39",
71
- "@lunora/values": "1.0.0-alpha.29",
71
+ "@lunora/values": "1.0.0-alpha.30",
72
72
  "drizzle-orm": "^0.45.2",
73
73
  "hono": "^4.13.1"
74
74
  },
@@ -1 +0,0 @@
1
- import{v as a}from"@lunora/values";import{initLunora as k}from"./initLunora-B2sfmFJ6.mjs";import{g as C,h as L,a as P}from"./plugin-DQcLxTx1.mjs";const T=e=>{let r="";for(let d=0;d<e.length;d+=32768)r+=String.fromCharCode(...e.subarray(d,d+32768));return btoa(r)},F=e=>{const r=atob(e),y=new Uint8Array(r.length);for(let d=0;d<r.length;d+=1)y[d]=r.codePointAt(d)??0;return y},f="$lunora.wire$",_=64,R=1024,N="__proto__",M={BigInt64Array,BigUint64Array,Float32Array,Float64Array,Int8Array,Int16Array,Int32Array,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array},h={Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError},H=e=>{if(e===null||typeof e!="object")return!1;const r=Object.getPrototypeOf(e);return r===null||r===Object.prototype},A=(e,r=0)=>{if(r>_)throw new RangeError(`wire-codec: value nesting exceeds the ${_}-level limit`);if(e===void 0)return[f,"undefined"];if(e===null)return null;const y=typeof e;if(y==="bigint")return[f,"bigint",e.toString()];if(y==="number"){const t=e;return Number.isNaN(t)?[f,"nan"]:t===1/0?[f,"inf"]:t===-1/0?[f,"-inf"]:t}if(y!=="object")return e;if(e instanceof Date)return[f,"date",A(e.getTime(),r+1)];if(e instanceof Error){const t=e,c={};for(const b of Object.keys(t))t[b]!==void 0&&(c[b]=A(t[b],r+1));const u=[f,"error",t.name,t.message,c];return t.cause!==void 0&&u.push(A(t.cause,r+1)),u}if(e instanceof URL)return[f,"url",e.href];if(e instanceof Map)return[f,"map",[...e.entries()].map(([t,c])=>[A(t,r+1),A(c,r+1)])];if(e instanceof Set)return[f,"set",[...e].map(t=>A(t,r+1))];if(e instanceof ArrayBuffer)return[f,"bytes",T(new Uint8Array(e)),"ArrayBuffer"];if(ArrayBuffer.isView(e)){const t=e,c=t.constructor.name,u=new Uint8Array(t.buffer,t.byteOffset,t.byteLength);return c==="Uint8Array"?[f,"bytes",T(u)]:[f,"bytes",T(u),c]}if(Array.isArray(e)){const t=e.map(c=>A(c,r+1));return t.length>0&&t[0]===f?[f,"arr",t]:t}if(!H(e)){const t=e.constructor?.name??"value";throw new TypeError(`wire-codec: cannot encode a ${t} over the Lunora wire — only plain objects, arrays, and the supported built-ins (Date, Error, URL, Map, Set, ArrayBuffer/typed arrays, bigint) round-trip`)}const d=e,m={};for(const t of Object.keys(d)){const c=d[t];if(c===void 0)continue;const u=A(c,r+1);t===N?Object.defineProperty(m,t,{configurable:!0,enumerable:!0,value:u,writable:!0}):m[t]=u}return m},l=(e,r=0)=>{if(r>_)throw new RangeError(`wire-codec: value nesting exceeds the ${_}-level limit`);if(e===null||typeof e!="object")return e;if(Array.isArray(e)){if(e[0]===f)switch(e[1]){case"-inf":return-1/0;case"arr":return e[2].map(t=>l(t,r+1));case"bigint":{const t=e[2];if(typeof t!="string"||t.length>R||!/^-?\d+$/.test(t))throw new RangeError(`wire-codec: invalid or over-long bigint (max ${R} digits)`);return BigInt(t)}case"date":return new Date(l(e[2],r+1));case"map":return new Map(e[2].map(([t,c])=>[l(t,r+1),l(c,r+1)]));case"set":return new Set(e[2].map(t=>l(t,r+1)));case"url":return new URL(e[2]);case"error":{const t=e[2],c=e[3],u=(Object.hasOwn(h,t)?h[t]:void 0)??Error,b=new u(c);b.name!==t&&Object.defineProperty(b,"name",{configurable:!0,value:t,writable:!0});const I=l(e[4],r+1);for(const E of Object.keys(I))E===N?Object.defineProperty(b,E,{configurable:!0,enumerable:!0,value:I[E],writable:!0}):b[E]=I[E];return e.length>5&&Object.defineProperty(b,"cause",{configurable:!0,value:l(e[5],r+1),writable:!0}),b}case"bytes":{const t=F(e[2]),c=e[3]??"Uint8Array";if(c==="ArrayBuffer")return t.buffer.byteLength===t.byteLength?t.buffer:t.slice().buffer;const u=Object.hasOwn(M,c)?M[c]:void 0;return u?new u(t.slice().buffer):t}case"inf":return 1/0;case"nan":return Number.NaN;case"undefined":return;default:return e.map(t=>l(t,r+1))}return e.map(m=>l(m,r+1))}const y=e,d={};for(const m of Object.keys(y)){const t=l(y[m],r+1);m===N?Object.defineProperty(d,m,{configurable:!0,enumerable:!0,value:t,writable:!0}):d[m]=t}return d},q=2160*60*60*1e3,Y=64*1024,U=200,$=64,J=512,x=16,K=["_commitSeq","seq"],X=["accessToken","apiKey","backupCodes","clientSecret","hashedPassword","password","privateKey","refreshToken","secret","totpSecret"],D="documentHistory",j="versions",S=`${D}_${j}`,G=C(D,{tables:{[j]:L({doc:a.optional(a.string()),documentId:a.string(),op:a.union(a.literal("delete"),a.literal("insert"),a.literal("update")),previous:a.optional(a.string()),recordedAt:a.number(),seq:a.number(),tableName:a.string(),truncated:a.optional(a.boolean())}).commitOrdered().index("byDocumentRecordedAt",["documentId","recordedAt","seq"]).index("byRecordedAt",["recordedAt"])}}),{internalMutation:V,internalQuery:W}=k.dataModel().create(),ee=(e={})=>{const r=e.retentionMs!==void 0&&Number.isFinite(e.retentionMs)?Math.max(1,Math.floor(e.retentionMs)):q,y=e.maxSnapshotBytes!==void 0&&Number.isFinite(e.maxSnapshotBytes)?Math.max(1,Math.floor(e.maxSnapshotBytes)):Y,d=new Set([...X,...e.redact??[]]);let m=0;const t=()=>(m+=1,m),c=(n,o=0)=>{if(Array.isArray(n))return o>=x?void 0:n.map(i=>c(i,o+1));if(typeof n!="object"||n===null||Object.getPrototypeOf(n)!==Object.prototype&&Object.getPrototypeOf(n)!==null)return n;if(!(o>=x))return Object.fromEntries(Object.entries(n).filter(([i])=>!d.has(i)).map(([i,p])=>[i,c(p,o+1)]))},u=n=>{if(n===void 0)return;const o=JSON.stringify(A(c(n)));return new TextEncoder().encode(o).length>y?void 0:o},b=async(n,o)=>{const i=u(o.doc),p=u(o.previous),s=o.doc!==void 0&&i===void 0||o.previous!==void 0&&p===void 0;await n.db.insert(S,{documentId:o.documentId,op:o.op,recordedAt:Date.now(),seq:t(),tableName:o.tableName,...s?{truncated:!0}:{},...i===void 0?{}:{doc:i},...p===void 0?{}:{previous:p}})},I=n=>({documentHistoryDelete:n.afterDelete(async(o,i)=>b(o,{documentId:i.id,op:"delete",previous:i.previous,tableName:i.table})),documentHistoryInsert:n.afterInsert(async(o,i)=>b(o,{doc:i.doc,documentId:i.id,op:"insert",tableName:i.table})),documentHistoryUpdate:n.afterUpdate(async(o,i)=>b(o,{doc:i.doc,documentId:i.id,op:"update",previous:i.previous,tableName:i.table}))}),E=W.input({before:a.optional(a.number()),documentId:a.string(),limit:a.optional(a.number())}).query(async({args:n,ctx:o})=>{const i=n.limit!==void 0&&Number.isFinite(n.limit)?Math.max(1,Math.floor(n.limit)):U,p=await o.db.query(S).withIndex("byDocumentRecordedAt",s=>n.before===void 0?s.eq("documentId",n.documentId):s.eq("documentId",n.documentId).lte("recordedAt",n.before)).order("desc").take(i);return p.sort((s,w)=>{for(const g of K){const O=(w[g]??0)-(s[g]??0);if(O!==0)return O}return 0}),p.map(s=>({documentId:s.documentId,op:s.op,recordedAt:s.recordedAt,tableName:s.tableName,...s.doc===void 0?{}:{doc:l(JSON.parse(s.doc))},...s.previous===void 0?{}:{previous:l(JSON.parse(s.previous))},...s.truncated===!0?{truncated:!0}:{}}))}),B=V.input({limit:a.optional(a.number())}).mutation(async({args:n,ctx:o})=>{const i=Date.now()-r,p=n.limit!==void 0&&Number.isFinite(n.limit)?Math.max(1,Math.floor(n.limit)):J;let s=0;for(let w=0;w<$&&s<p;w+=1){const g=await o.db.query(S).withIndex("byRecordedAt",O=>O.lt("recordedAt",i)).order("asc").take(Math.min(U,p-s));if(g.length===0)return{deleted:s};await Promise.all(g.map(async O=>o.db.delete(O._id))),s+=g.length}return{deleted:s}});return{...P(D,{extension:G,functions:{listForDocument:E,vacuum:B}}),record:I}};export{X as DOCUMENT_HISTORY_REDACTED_FIELDS,S as DOCUMENT_HISTORY_TABLE,ee as defineDocumentHistory,G as documentHistoryExtension};
@@ -1 +0,0 @@
1
- import{f as c,F as f,a as y}from"./fnv1a-D6VtE8WR.mjs";const p=t=>`${c(t,f)}${c(t,y)}`,u=(t,n)=>t<n?-1:t>n?1:0,o=t=>{if(t===void 0)return"null";if(typeof t=="bigint")throw new TypeError("stableStringify: cannot use a bigint in a stable JSON cache key — pass it as a string, or use stableWireKey");if(typeof t=="number"){if(Number.isNaN(t))return"nan";if(t===1/0)return"inf";if(t===-1/0)return"-inf";if(Object.is(t,-0))return"-0"}if(t===null||typeof t!="object")return JSON.stringify(t);if(Array.isArray(t))return`[${t.map(r=>o(r)).join(",")}]`;const n=Object.getPrototypeOf(t);if(n!==null&&n!==Object.prototype){const r=t.constructor?.name??"value";throw new TypeError(`stableStringify: cannot use a ${r} in a stable JSON cache key — only plain objects, arrays, and JSON primitives are supported (wire-typed values key via stableWireKey)`)}const e=t,s=Object.keys(e).toSorted(u),i=[];for(const r of s){const a=e[r];a!==void 0&&i.push(`${JSON.stringify(r)}:${o(a)}`)}return`{${i.join(",")}}`},g=(t,n)=>({args:{},handler:async(e,s)=>{const i=await t(e),r=p(o(i));return r===s?.previousDigest?{digest:r,ran:!1}:(await n(e,i),{digest:r,ran:!0})},kind:"mutation",lifecycle:"reactor",visibility:"internal"});export{g as onQueryChange};