cvx-kit 0.1.19 → 0.1.21

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.
Files changed (80) hide show
  1. package/README.md +50 -2
  2. package/dist/errors.d.mts +3 -2
  3. package/dist/errors.mjs +1 -1
  4. package/dist/errors.mjs.map +1 -1
  5. package/dist/filters.d.mts +4 -0
  6. package/dist/filters.mjs +1 -0
  7. package/dist/index.d.mts +3 -3
  8. package/dist/modules/contracts/errors.d.mts +218 -0
  9. package/dist/modules/contracts/errors.mjs +1 -1
  10. package/dist/modules/contracts/errors.mjs.map +1 -1
  11. package/dist/modules/effect/crud.d.mts +28 -0
  12. package/dist/querying/cursors.d.mts +30 -4
  13. package/dist/querying/cursors.mjs +1 -1
  14. package/dist/querying/cursors.mjs.map +1 -1
  15. package/dist/querying/execution.d.mts +14 -3
  16. package/dist/querying/execution.mjs +1 -1
  17. package/dist/querying/execution.mjs.map +1 -1
  18. package/dist/querying/failures.d.mts +13 -0
  19. package/dist/querying/failures.mjs +2 -0
  20. package/dist/querying/failures.mjs.map +1 -0
  21. package/dist/querying/filters.d.mts +43 -44
  22. package/dist/querying/filters.mjs +1 -1
  23. package/dist/querying/filters.mjs.map +1 -1
  24. package/dist/querying/planner.d.mts +13 -16
  25. package/dist/querying/planner.mjs +1 -1
  26. package/dist/querying/planner.mjs.map +1 -1
  27. package/dist/querying/relationships.d.mts +24 -7
  28. package/dist/querying/relationships.mjs +1 -1
  29. package/dist/querying/relationships.mjs.map +1 -1
  30. package/dist/querying/schema-snapshot.d.mts +29 -0
  31. package/dist/querying/schema-snapshot.mjs +2 -0
  32. package/dist/querying/schema-snapshot.mjs.map +1 -0
  33. package/dist/querying/search.d.mts +69 -0
  34. package/dist/querying/search.mjs +2 -0
  35. package/dist/querying/search.mjs.map +1 -0
  36. package/dist/querying/security.d.mts +19 -2
  37. package/dist/querying/security.mjs +1 -1
  38. package/dist/querying/security.mjs.map +1 -1
  39. package/dist/querying/shared/ast.d.mts +28 -0
  40. package/dist/querying/shared/ast.mjs +2 -0
  41. package/dist/querying/shared/ast.mjs.map +1 -0
  42. package/dist/querying/shared/contract.d.mts +104 -0
  43. package/dist/querying/shared/contract.mjs +2 -0
  44. package/dist/querying/shared/contract.mjs.map +1 -0
  45. package/dist/querying/shared/evaluate.d.mts +7 -0
  46. package/dist/querying/shared/evaluate.mjs +2 -0
  47. package/dist/querying/shared/evaluate.mjs.map +1 -0
  48. package/dist/querying/shared/filters.d.mts +31 -0
  49. package/dist/querying/shared/filters.mjs +2 -0
  50. package/dist/querying/shared/filters.mjs.map +1 -0
  51. package/dist/querying.d.mts +47 -16
  52. package/dist/querying.mjs +1 -1
  53. package/dist/querying.mjs.map +1 -1
  54. package/dist/react/failures.d.mts +23 -0
  55. package/dist/react/failures.mjs +2 -0
  56. package/dist/react/failures.mjs.map +1 -0
  57. package/dist/react/optimistic.d.mts +47 -0
  58. package/dist/react/optimistic.mjs +2 -0
  59. package/dist/react/optimistic.mjs.map +1 -0
  60. package/dist/react/pagination-state.d.mts +40 -0
  61. package/dist/react/pagination-state.mjs +2 -0
  62. package/dist/react/pagination-state.mjs.map +1 -0
  63. package/dist/react/use-command.d.mts +23 -0
  64. package/dist/react/use-command.mjs +2 -0
  65. package/dist/react/use-command.mjs.map +1 -0
  66. package/dist/react/use-paginated-list.d.mts +32 -0
  67. package/dist/react/use-paginated-list.mjs +2 -0
  68. package/dist/react/use-paginated-list.mjs.map +1 -0
  69. package/dist/react.d.mts +6 -0
  70. package/dist/react.mjs +1 -0
  71. package/dist/relations-public.d.mts +2 -2
  72. package/dist/relations.d.mts +65 -22
  73. package/dist/relations.mjs +1 -1
  74. package/dist/relations.mjs.map +1 -1
  75. package/dist/zod-convex.mjs +1 -1
  76. package/dist/zod-convex.mjs.map +1 -1
  77. package/dist/zod-table.d.mts +15 -1
  78. package/dist/zod-table.mjs +1 -1
  79. package/dist/zod-table.mjs.map +1 -1
  80. package/package.json +21 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-paginated-list.mjs","names":["epoch","usePaginatedList","options","pageSize","skip","args","effectiveArgs","identity","getFunctionName","query","convexToJson","stored","setState","useState","initialPagination","state","queries","useMemo","key","interval","paginationOpts","results","useQueries","reconcilePagination","errors","queryErrors","failure","decodeFailure","queryFailure","invalid","view","paginationView","currentEpoch","previous","nextPagination"],"sources":["../../src/react/use-paginated-list.ts"],"sourcesContent":["import { useMemo, useState } from 'react'\nimport { useQueries } from 'convex/react'\nimport {\n\tgetFunctionName,\n\ttype FunctionArgs,\n\ttype FunctionReference,\n\ttype FunctionReturnType,\n\ttype PaginationOptions,\n} from 'convex/server'\nimport { convexToJson, type Value } from 'convex/values'\nimport { queryErrors } from '../modules/contracts/errors'\nimport { decodeFailure, type FailureContract, type FailureOf } from './failures'\nimport {\n\tinitialPagination,\n\treconcilePagination,\n\tnextPagination,\n\tpaginationView,\n\ttype ListPage,\n} from './pagination-state'\n\nexport type ListQueryReference = FunctionReference<\n\t'query',\n\t'public',\n\t{ paginationOpts: PaginationOptions },\n\tListPage\n>\nexport type PaginatedList<\n\tQuery extends ListQueryReference,\n\tContract extends FailureContract = typeof queryErrors,\n> = {\n\trows: FunctionReturnType<Query>['page']\n\tisLoading: boolean\n\thasNextPage: boolean\n\tisFetchingNextPage: boolean\n\tfetchNextPage: () => void\n\tresetKey: string\n\tcompleteness: FunctionReturnType<Query>['completeness'] | undefined\n\tfailure: FailureOf<Contract> | undefined\n}\nexport type PaginatedListOptions<Contract extends FailureContract = typeof queryErrors> = {\n\t/** Integer 1..100. Initial target for native search; browse uses fixed adjacent pages. */\n\tpageSize: number\n\tonInvalidCursor?: 'restart' | 'throw'\n\t/** Explicit server contract; generated references do not carry error metadata. Defaults to queryErrors. */\n\terrors?: Contract\n\t/** Convex value identifying the current auth/scope/reset generation. Never a credential. */\n\tresetIdentity?: Value\n}\ntype IntervalPagination = {\n\tnumItems: number\n\tcursor: string | null\n\tid: number\n\tendCursor?: string\n}\nlet epoch = 0\n/** Reactive engine-backed list: fixed browse ranges or SDK-journal search windows. Empty pages advance manually. */\nexport function usePaginatedList<\n\tQuery extends ListQueryReference,\n\tContract extends FailureContract = typeof queryErrors,\n>(\n\tquery: Query,\n\targs: Omit<FunctionArgs<Query>, 'paginationOpts'> | 'skip',\n\toptions: PaginatedListOptions<Contract>,\n): PaginatedList<Query, Contract> {\n\tconst { pageSize } = options\n\tif (!Number.isInteger(pageSize) || pageSize < 1 || pageSize > 100)\n\t\tthrow new Error('pageSize must be an integer from 1 to 100')\n\tconst skip = args === 'skip'\n\t// Convex's public encoder sorts object keys recursively and preserves array order, IDs, bytes and int64.\n\t// SAFETY: FunctionArgs are Convex values; pagination transport is owned exclusively by this hook.\n\tconst effectiveArgs = skip ? {} : (args as Record<string, Value>)\n\tconst identity = JSON.stringify([\n\t\tgetFunctionName(query),\n\t\tconvexToJson(effectiveArgs),\n\t\tconvexToJson(options.resetIdentity ?? null),\n\t\tpageSize,\n\t\tskip,\n\t])\n\tconst [stored, setState] = useState(() =>\n\t\tinitialPagination<FunctionReturnType<Query>>(identity, ++epoch, skip),\n\t)\n\tlet state = stored\n\tif (state.identity !== identity) state = initialPagination(identity, ++epoch, skip)\n\tconst queries = useMemo(\n\t\t() =>\n\t\t\tObject.fromEntries(\n\t\t\t\tObject.entries(state.intervals).map(([key, interval]) => {\n\t\t\t\t\tconst paginationOpts: IntervalPagination = {\n\t\t\t\t\t\tnumItems: pageSize,\n\t\t\t\t\t\tcursor: interval.cursor,\n\t\t\t\t\t\tid: state.epoch,\n\t\t\t\t\t}\n\t\t\t\t\tif (interval.endCursor !== undefined) paginationOpts.endCursor = interval.endCursor\n\t\t\t\t\treturn [key, { query, args: { ...effectiveArgs, paginationOpts } }]\n\t\t\t\t}),\n\t\t\t),\n\t\t// Equivalent args/references must keep subscriptions stable; identity encodes their effective values.\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t\t[state.intervals, state.epoch, identity],\n\t)\n\t// SAFETY: useQueries returns each complete endpoint result or an Error for the keyed subscription.\n\tconst results = useQueries(queries) as Record<\n\t\tstring,\n\t\tFunctionReturnType<Query> | Error | undefined\n\t>\n\tstate = reconcilePagination(state, results)\n\tconst errors = options.errors ?? queryErrors\n\tlet failure = state.error ? decodeFailure(state.error, errors) : undefined\n\t// Both the explicit decoder and the fixed query contract must validate the actual transported envelope.\n\tconst queryFailure = state.error ? decodeFailure(state.error, queryErrors) : undefined\n\tconst invalid =\n\t\tstate.error &&\n\t\tfailure?._tag === 'DeclaredFailure' &&\n\t\tfailure.code === 'invalid-cursor' &&\n\t\tqueryFailure?._tag === 'DeclaredFailure' &&\n\t\tqueryFailure.code === 'invalid-cursor'\n\tif (invalid && options.onInvalidCursor !== 'throw' && !state.restarted) {\n\t\tstate = initialPagination(identity, ++epoch, skip, true)\n\t\tfailure = undefined\n\t}\n\tif (state !== stored) setState(state)\n\tif (invalid && options.onInvalidCursor === 'throw') throw state.error\n\tconst view = paginationView(state)\n\tconst currentEpoch = state.epoch\n\treturn {\n\t\t...view,\n\t\t// SAFETY: the controller concatenates unmodified elements from this query's validated page DTOs.\n\t\trows: view.rows as FunctionReturnType<Query>['page'],\n\t\tcompleteness: view.completeness,\n\t\t// SAFETY: omitted errors selects the default Contract parameter; an explicit contract owns its decoder.\n\t\tfailure: failure as FailureOf<Contract> | undefined,\n\t\tresetKey: `${identity}:${state.restarted ? 1 : 0}`,\n\t\tfetchNextPage: () =>\n\t\t\tsetState((previous) =>\n\t\t\t\tprevious.epoch === currentEpoch && previous.identity === identity\n\t\t\t\t\t? nextPagination(previous)\n\t\t\t\t\t: previous,\n\t\t\t),\n\t}\n}\n"],"mappings":"8ZAsDA,IAAIA,EAAQ,EAEZ,SAAgBC,EAIf,EACA,EACA,EACiC,CACjC,GAAM,CAAE,YAAaC,EACrB,GAAI,CAAC,OAAO,UAAUC,CAAQ,GAAKA,EAAW,GAAKA,EAAW,IAC7D,MAAU,MAAM,2CAA2C,EAC5D,IAAMC,EAAOC,IAAS,OAGhBC,EAAgBF,EAAO,CAAC,EAAKC,EAC7BE,EAAW,KAAK,UAAU,CAC/BC,EAAgBC,CAAK,EACrBC,EAAaJ,CAAa,EAC1BI,EAAaR,EAAQ,eAAiB,IAAI,EAC1CC,EACAC,CACD,CAAC,EACK,CAACO,EAAQC,GAAYC,MAC1BC,EAA6CP,EAAU,EAAEP,EAAOI,CAAI,CACrE,EACIW,EAAQJ,EACRI,EAAM,WAAaR,IAAU,EAAQO,EAAkBP,EAAU,EAAEP,EAAOI,CAAI,GAClF,IAAMY,EAAUC,MAEd,OAAO,YACN,OAAO,QAAQF,EAAM,SAAS,CAAC,CAAC,KAAK,CAACG,EAAKC,KAAc,CACxD,IAAMC,EAAqC,CAC1C,SAAUjB,EACV,OAAQgB,EAAS,OACjB,GAAIJ,EAAM,KACX,EAEA,OADII,EAAS,YAAc,IAAA,KAAW,EAAe,UAAYA,EAAS,WACnE,CAACD,EAAK,CAAE,QAAO,KAAM,CAAE,GAAGZ,EAAe,gBAAe,CAAE,CAAC,CACnE,CAAC,CACF,EAGD,CAACS,EAAM,UAAWA,EAAM,MAAOR,CAAQ,CACxC,EAEMc,EAAUC,EAAWN,CAAO,EAIlC,EAAQO,EAAoBR,EAAOM,CAAO,EAC1C,IAAMG,EAAStB,EAAQ,QAAUuB,EAC7BC,EAAUX,EAAM,MAAQY,EAAcZ,EAAM,MAAOS,CAAM,EAAI,IAAA,GAE3DI,EAAeb,EAAM,MAAQY,EAAcZ,EAAM,MAAOU,CAAW,EAAI,IAAA,GACvEI,EACLd,EAAM,OACNW,GAAS,OAAS,mBAClBA,EAAQ,OAAS,kBACjBE,GAAc,OAAS,mBACvBA,EAAa,OAAS,iBAMvB,GALIC,GAAW3B,EAAQ,kBAAoB,SAAW,CAACa,EAAM,YAC5D,EAAQD,EAAkBP,EAAU,EAAEP,EAAOI,EAAM,EAAI,EACvD,EAAU,IAAA,IAEPW,IAAUJ,GAAQC,EAASG,CAAK,EAChCc,GAAW3B,EAAQ,kBAAoB,QAAS,MAAMa,EAAM,MAChE,IAAMe,EAAOC,EAAehB,CAAK,EAC3BiB,EAAejB,EAAM,MAC3B,MAAO,CACN,GAAGe,EAEH,KAAMA,EAAK,KACX,aAAcA,EAAK,aAEV,UACT,SAAU,GAAGvB,EAAS,GAAG,KAAM,YAC/B,kBACCK,EAAU,GACTqB,EAAS,QAAUD,GAAgBC,EAAS,WAAa1B,EACtD2B,EAAeD,CAAQ,EACvBA,CACJ,CACF,CACD"}
@@ -0,0 +1,6 @@
1
+ import { DeclaredFailure, DecodedFailure, ErrorContract, UnknownFailure, queryErrors } from "./modules/contracts/errors.mjs";
2
+ import { FailureHandlers, decodeFailure, matchFailure } from "./react/failures.mjs";
3
+ import { Command, CommandResult, useCommand } from "./react/use-command.mjs";
4
+ import { ListQueryReference, PaginatedList, PaginatedListOptions, usePaginatedList } from "./react/use-paginated-list.mjs";
5
+ import { OptimisticInterval, OptimisticList, OptimisticListDescriptor, OptimisticOrder, defineOptimisticList } from "./react/optimistic.mjs";
6
+ export { type Command, type CommandResult, type DeclaredFailure, type DecodedFailure, type ErrorContract, type FailureHandlers, type ListQueryReference, type OptimisticInterval, type OptimisticList, type OptimisticListDescriptor, type OptimisticOrder, type PaginatedList, type PaginatedListOptions, type UnknownFailure, decodeFailure, defineOptimisticList, matchFailure, queryErrors, useCommand, usePaginatedList };
package/dist/react.mjs ADDED
@@ -0,0 +1 @@
1
+ import{queryErrors as e}from"./modules/contracts/errors.mjs";import{decodeFailure as t,matchFailure as n}from"./react/failures.mjs";import{useCommand as r}from"./react/use-command.mjs";import{usePaginatedList as i}from"./react/use-paginated-list.mjs";import{defineOptimisticList as a}from"./react/optimistic.mjs";export{t as decodeFailure,a as defineOptimisticList,n as matchFailure,e as queryErrors,r as useCommand,i as usePaginatedList};
@@ -1,2 +1,2 @@
1
- import { BranchBuilder, FieldReference, RelationBuilder, RelationDeclarations, RelationEdge, RelationFilterSelection, RelationFilters, RelationRegistry, RelationRegistryIdentity, RelationRow, RelationSelection, RelationTable, RelationTableHelpers, RelationTables, ThroughReference, defineRelations } from "./relations.mjs";
2
- export { type BranchBuilder, type FieldReference, type RelationBuilder, type RelationDeclarations, type RelationEdge, type RelationFilterSelection, type RelationFilters, type RelationRegistry, type RelationRegistryIdentity, type RelationRow, type RelationSelection, type RelationTable, type RelationTableHelpers, type RelationTables, type ThroughReference, defineRelations };
1
+ import { BranchBuilder, FieldGroupMode, FieldGroupRequest, FieldReference, RelationBuilder, RelationDeclarations, RelationEdge, RelationFilterSelection, RelationFilters, RelationGroupSelection, RelationRegistry, RelationRegistryIdentity, RelationRow, RelationSelection, RelationTable, RelationTableHelpers, RelationTables, ThroughReference, defineRelations } from "./relations.mjs";
2
+ export { type BranchBuilder, type FieldGroupMode, type FieldGroupRequest, type FieldReference, type RelationBuilder, type RelationDeclarations, type RelationEdge, type RelationFilterSelection, type RelationFilters, type RelationGroupSelection, type RelationRegistry, type RelationRegistryIdentity, type RelationRow, type RelationSelection, type RelationTable, type RelationTableHelpers, type RelationTables, type ThroughReference, defineRelations };
@@ -1,6 +1,10 @@
1
- import { FieldSchemas, PaginationOptionsSchema, ScalarPredicate, ScalarSelection } from "./querying/filters.mjs";
1
+ import { FilterContract, SharedFilters } from "./querying/shared/contract.mjs";
2
+ import "./filters.mjs";
3
+ import { FieldSchemas } from "./querying/shared/filters.mjs";
4
+ import { PaginationOptionsSchema, ScalarPredicate, ScalarSelection } from "./querying/filters.mjs";
5
+ import { EnginePaginationResult } from "./zod-table.mjs";
2
6
  import { ConvexValidatorFromZod } from "convex-helpers/server/zod4";
3
- import { PaginationResult, TableDefinition } from "convex/server";
7
+ import { TableDefinition } from "convex/server";
4
8
  import { z } from "zod";
5
9
  import { GenericId, GenericValidator, ValidatorJSON } from "convex/values";
6
10
  //#region src/relations.d.ts
@@ -11,8 +15,48 @@ export interface RelationTable {
11
15
  publicDto: z.ZodObject | z.ZodDiscriminatedUnion<any, string>;
12
16
  table: TableDefinition;
13
17
  dto(includeId: true): z.ZodType;
18
+ /** Whole stored fields; schemas are captured from the native table, never a DTO transform. */
19
+ fieldGroups?: Readonly<Record<string, readonly string[]>>;
14
20
  }
15
21
  export type RelationTables = Record<string, RelationTable>;
22
+ export type FieldGroupMode = 'if-permitted' | 'required';
23
+ export type FieldGroupRequest<T extends RelationTable> = { [K in keyof NonNullable<T['fieldGroups']>]?: FieldGroupMode; };
24
+ /** Separate from relation keys so existing selection syntax remains unambiguous. */
25
+ export type RelationGroupSelection<Tables extends RelationTables, D extends RelationDeclarations, T extends keyof Tables, L extends readonly 1[] = readonly [1, 1, 1, 1]> = {
26
+ fieldGroups?: FieldGroupRequest<Tables[T]>;
27
+ relations?: L extends readonly [] ? never : { [K in keyof Edges<D, T>]?: RelationGroupSelection<Tables, D, Extract<Target<Edges<D, T>[K]>, keyof Tables>, Tail<L>>; };
28
+ };
29
+ /** Internal admitted runtime tree, independent of user relation names. */
30
+ export interface GroupSelection {
31
+ fieldGroups?: Readonly<Record<string, FieldGroupMode>>;
32
+ relations?: Readonly<Record<string, GroupSelection>>;
33
+ }
34
+ export type ExactGroupSelection<Tables extends RelationTables, D extends RelationDeclarations, T extends keyof Tables, G> = G & { [K in keyof G]: K extends 'fieldGroups' ? G[K] & { [N in keyof G[K]]: N extends keyof FieldGroupRequest<Tables[T]> ? FieldGroupMode : never; } : K extends 'relations' ? G[K] & { [N in keyof G[K]]: N extends keyof Edges<D, T> ? ExactGroupSelection<Tables, D, Extract<Target<Edges<D, T>[N]>, keyof Tables>, G[K][N]> : never; } : never; };
35
+ type StoredValue<V extends GenericValidator> = GenericValidator extends V ? V['type'] : V extends {
36
+ kind: 'object';
37
+ fields: infer F extends Record<string, GenericValidator>;
38
+ } ? { [K in keyof F as F[K]['isOptional'] extends 'optional' ? never : K]: StoredValue<F[K]>; } & { [K in keyof F as F[K]['isOptional'] extends 'optional' ? K : never]?: StoredValue<F[K]>; } : V extends {
39
+ kind: 'array';
40
+ element: infer E extends GenericValidator;
41
+ } ? StoredValue<E>[] : V extends {
42
+ kind: 'union';
43
+ members: infer M extends GenericValidator[];
44
+ } ? StoredValue<M[number]> : V extends {
45
+ kind: 'record';
46
+ key: infer K extends GenericValidator;
47
+ value: infer E extends GenericValidator;
48
+ } ? Record<Extract<K['type'], string>, StoredValue<E>> : V['type'];
49
+ type GroupStoredRow<T extends RelationTable, Row, Stored = StoredValue<ConvexValidatorFromZod<T['schema'], 'required'>>> = [Tags<T>] extends [never] ? Stored : Extract<Stored, Pick<Row, Extract<Discriminator<T>, keyof Row>>>;
50
+ type GroupFields<T extends RelationTable, G, Row> = T extends {
51
+ fieldGroups: infer Definitions extends Readonly<Record<string, readonly string[]>>;
52
+ } ? { [K in keyof G & keyof Definitions]: Pick<GroupStoredRow<T, Row>, Extract<Definitions[K][number], keyof GroupStoredRow<T, Row>>>; } : {};
53
+ type UnionToIntersection<U> = (U extends unknown ? (x: U) => void : never) extends ((x: infer I) => void) ? I : never;
54
+ type IncludedFields<T extends RelationTable, G, Row> = G extends {
55
+ fieldGroups: infer Requests;
56
+ } ? UnionToIntersection<{ [K in keyof Requests & keyof GroupFields<T, Requests, Row>]: Requests[K] extends 'required' ? GroupFields<T, Requests, Row>[K] : Partial<GroupFields<T, Requests, Row>[K]>; }[keyof Requests & keyof GroupFields<T, Requests, Row>]> : {};
57
+ type NestedGroups<G, K extends PropertyKey> = G extends {
58
+ relations: infer R;
59
+ } ? K extends keyof R ? R[K] : {} : {};
16
60
  /** Internal named declaration dependency; excluded from the supported relations facade. */
17
61
  export interface SelectionMask {
18
62
  [key: string]: true | SelectionMask;
@@ -133,12 +177,13 @@ type PublicRow<T extends RelationTable> = z.output<T['publicDto']> & {
133
177
  _id: GenericId<T['tableName']>;
134
178
  };
135
179
  export type ScopedRelationRow<Row, Scope extends string, Key extends PropertyKey> = [Scope] extends [never] ? Row : Extract<Row, Record<Key, Scope>>;
136
- type ComposeRelationRow<Tables extends RelationTables, D extends RelationDeclarations, T extends keyof Tables, S, Level extends readonly 1[], Row> = Row extends unknown ? Row & (Level extends readonly [] ? {} : { [K in keyof S]: K extends keyof Edges<D, T> ? Edges<D, T>[K] extends RelationEdge<string, infer Target, infer C, infer SourceScope, infer TargetScope> ? C extends 'one' ? ([SourceScope] extends [never] ? true : Row extends ScopedRelationRow<Row, SourceScope, Discriminator<Tables[T]>> ? true : false) extends true ? ScopedRelationRow<RelationRow<Tables, D, Extract<Target, keyof Tables>, S[K] extends true ? {} : S[K], Tail<Level>>, TargetScope, Discriminator<Tables[Extract<Target, keyof Tables>]>> | null : null : PaginationResult<ScopedRelationRow<RelationRow<Tables, D, Extract<Target, keyof Tables>, S[K] extends true ? {} : S[K], Tail<Level>>, TargetScope, Discriminator<Tables[Extract<Target, keyof Tables>]>>> : never : never; }) : never;
137
- export type RelationRow<Tables extends RelationTables, D extends RelationDeclarations, T extends keyof Tables, S, Level extends readonly 1[] = Depth> = ComposeRelationRow<Tables, D, T, S, Level, PublicRow<Tables[T]>>;
138
- export type RelationQueryRow<Tables extends RelationTables, D extends RelationDeclarations, T extends keyof Tables, S, Scope extends string = never> = ScopedRelationRow<RelationRow<Tables, D, T, S>, Scope, Discriminator<Tables[T]>>;
180
+ type ComposeRelationRow<Tables extends RelationTables, D extends RelationDeclarations, T extends keyof Tables, S, Level extends readonly 1[], Row, G = {}> = Row extends unknown ? Row & IncludedFields<Tables[T], G, Row> & (Level extends readonly [] ? {} : { [K in keyof S]: K extends keyof Edges<D, T> ? Edges<D, T>[K] extends RelationEdge<string, infer Target, infer C, infer SourceScope, infer TargetScope> ? C extends 'one' ? ([SourceScope] extends [never] ? true : Row extends ScopedRelationRow<Row, SourceScope, Discriminator<Tables[T]>> ? true : false) extends true ? ScopedRelationRow<RelationRow<Tables, D, Extract<Target, keyof Tables>, S[K] extends true ? {} : S[K], Tail<Level>, NestedGroups<G, K>>, TargetScope, Discriminator<Tables[Extract<Target, keyof Tables>]>> | null : null : EnginePaginationResult<ScopedRelationRow<RelationRow<Tables, D, Extract<Target, keyof Tables>, S[K] extends true ? {} : S[K], Tail<Level>, NestedGroups<G, K>>, TargetScope, Discriminator<Tables[Extract<Target, keyof Tables>]>>> : never : never; }) : never;
181
+ export type RelationRow<Tables extends RelationTables, D extends RelationDeclarations, T extends keyof Tables, S, Level extends readonly 1[] = Depth, G = {}> = ComposeRelationRow<Tables, D, T, S, Level, PublicRow<Tables[T]>, G>;
182
+ export type RelationQueryRow<Tables extends RelationTables, D extends RelationDeclarations, T extends keyof Tables, S, Scope extends string = never, G = {}> = ScopedRelationRow<RelationRow<Tables, D, T, S, Depth, G>, Scope, Discriminator<Tables[T]>>;
139
183
  export interface RelationTableHelpers<Tables extends RelationTables, D extends RelationDeclarations, T extends keyof Tables> {
184
+ filters<F extends Record<string, GenericValidator>>(contract: FilterContract<F>): PaginationOptionsSchema<SharedFilters<F>, SharedFilters<F, 'input'>>;
140
185
  paginationOpts<const S extends RelationFilterSelection<Tables, D, T>>(selection: ExactFilterMask<Tables, D, T, S>): PaginationOptionsSchema<RelationFilters<Tables, D, T, S>, RelationFilters<Tables, D, T, S, 'input'>>;
141
- pageDto<const S extends RelationSelection<Tables, D, T>>(selection: ExactOutputMask<Tables, D, T, S>): z.ZodType<PaginationResult<RelationRow<Tables, D, T, S>>>;
186
+ pageDto<const S extends RelationSelection<Tables, D, T>, const G extends RelationGroupSelection<Tables, D, T> = {}>(selection: ExactOutputMask<Tables, D, T, S>, groups?: ExactGroupSelection<Tables, D, T, G>): z.ZodType<EnginePaginationResult<RelationRow<Tables, D, T, S, Depth, G>>>;
142
187
  }
143
188
  export interface RelationRegistryIdentity {
144
189
  readonly identity: string;
@@ -156,7 +201,15 @@ export interface RelationFieldMetadata {
156
201
  readonly idTables: readonly string[];
157
202
  readonly native: Readonly<ValidatorJSON>;
158
203
  }
204
+ export interface SearchIndexMetadata {
205
+ readonly name: string;
206
+ readonly searchField: string;
207
+ readonly filterFields: readonly string[];
208
+ readonly staged: boolean;
209
+ }
159
210
  export interface RelationTableMetadata {
211
+ readonly searchIndexes: readonly SearchIndexMetadata[];
212
+ readonly fieldGroups: Readonly<Record<string, readonly string[]>>;
160
213
  readonly fields: Readonly<Record<string, RelationFieldMetadata>>;
161
214
  readonly variant?: {
162
215
  readonly discriminator: string;
@@ -173,18 +226,17 @@ export interface RelationMetadata {
173
226
  }
174
227
  /** No ID-field inference and no readers: this registry owns declarations/schema helpers only. */
175
228
  export declare function defineRelations<const Tables extends RelationTables, const D extends RelationDeclarations>(tables: Tables, declare: (r: RelationBuilder<Tables>, branch: BranchBuilder<Tables>) => D & ExactDeclarations<Tables, D>): RelationRegistry<Tables, D>;
176
- /** Internal owned executor bridge. Not an advertised root API. Every operation
177
- * rechecks the live registry, including cached plans and individual projections.
178
- */
229
+ /** Internal owned executor bridge. Source ownership is checked once by each engine. */
179
230
  export declare function getRelationExecutor(registry: RelationRegistryIdentity): Readonly<{
180
- assertUnchanged: () => void;
231
+ streamSchema: import("convex/server").SchemaDefinition<import("convex/server").GenericSchema, boolean>;
232
+ groups(table: string, groups: GroupSelection): GroupSelection;
181
233
  validateDocument: (table: string, row: Record<string, import('convex/values').Value>) => void;
182
- assertNativeTable: (table: string, definition: TableDefinition) => void;
183
234
  assertSchema: (tables: Readonly<Record<string, TableDefinition>>) => void;
184
235
  pagination(table: string): z.ZodObject<{
185
236
  cursor: z.ZodUnion<readonly [z.ZodString, z.ZodNull]>;
186
237
  endCursor: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNull]>>;
187
238
  id: z.ZodOptional<z.ZodNumber>;
239
+ onEmptyBudget: z.ZodOptional<z.ZodLiteral<"split">>;
188
240
  numItems: z.ZodNumber;
189
241
  maximumRowsRead: z.ZodOptional<z.ZodNumber>;
190
242
  maximumBytesRead: z.ZodOptional<z.ZodNumber>;
@@ -194,17 +246,8 @@ export declare function getRelationExecutor(registry: RelationRegistryIdentity):
194
246
  desc: "desc";
195
247
  }>>;
196
248
  }, z.core.$strict>;
197
- page(table: string, selection: SelectionMask): z.ZodObject<{
198
- page: z.ZodArray<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
199
- isDone: z.ZodBoolean;
200
- continueCursor: z.ZodString;
201
- splitCursor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
202
- pageStatus: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
203
- SplitRecommended: "SplitRecommended";
204
- SplitRequired: "SplitRequired";
205
- }>>>;
206
- }, z.core.$strip>;
207
- project(tables: Readonly<Record<string, TableDefinition>>, table: string, row: Record<string, import('convex/values').Value>, eligible: () => boolean): Record<string, unknown> | null;
249
+ select(table: string, selection: SelectionMask): void;
250
+ project(table: string, row: Record<string, import('convex/values').Value>, eligible: () => boolean, groups?: readonly string[]): Record<string, unknown> | null;
208
251
  }>;
209
252
  /** Internal compiler/engine adapter. Registry identity alone cannot forge a registry. */
210
253
  export declare function getRelationMetadata(registry: RelationRegistryIdentity): RelationMetadata;
@@ -1,2 +1,2 @@
1
- import{nativePagination as e,relationFilterSchema as t,scalarPredicateSchema as n}from"./querying/filters.mjs";import{paginated as r}from"./zod-table.mjs";import{convexToZod as i,zodToConvex as a}from"convex-helpers/server/zod4";import{z as o}from"zod";import{v as s}from"convex/values";const c=Symbol(`relationField`),l=Symbol(`relationEdge`),u=/* @__PURE__ */ new WeakMap,d=/* @__PURE__ */ new WeakMap,f=/* @__PURE__ */ new WeakMap,p=/* @__PURE__ */ new WeakMap,m=/* @__PURE__ */ new WeakSet,h=/* @__PURE__ */ new WeakSet,g=o.object({indexes:o.array(o.object({indexDescriptor:o.string(),fields:o.array(o.string())}))});function _(n,i){let l={},_=/* @__PURE__ */ new Set,v=/* @__PURE__ */ new Map,y={},b={},w={};for(let[e,t]of Object.entries(n)){if(t.tableName!==e||[`one`,`many`,`__proto__`,`constructor`,`prototype`].includes(e))throw Error(`Invalid relation table "${e}"`);let n=t.dto(!0);if(!(n instanceof o.ZodObject)&&!(n instanceof o.ZodDiscriminatedUnion))throw Error(`Expected object or discriminated union DTO`);let r=H(n),i=F(t.table);R(i.documentType);let u=N(e,t.schema,n,i.documentType),d=g.parse(i).indexes.map(e=>({name:e.indexDescriptor,fields:[...e.fields]})).sort((e,t)=>e.name.localeCompare(t.name));R(I(a(n))),l[e]={...u,indexes:d,dto:n,assertUnchanged:r};let h=(t,n)=>{let r=Object.create(null);function i(t,r,a){let o={[c]:void 0,table:e,field:t,guard:n,forTable(e){if(n)throw Error(`forTable on branch-scoped fields is unsupported`);if(!T(r)?.includes(e))throw Error(`Invalid native ID member selection`);if(!Object.hasOwn(l,e))throw Error(`Native ID member table is not registered`);let a=Q(r)?s.union(s.id(e),s.null()):s.id(e);return i(t,r.isOptional===`optional`?s.optional(a):a,Object.freeze({table:e}))},through(e){if(a||p.has(e))throw Error(`forTable with through is unsupported`);let t=f.get(e);if(!_.has(e)||!t||!E(r,t))throw Error(`Invalid junction field or registry`);let n=Object.freeze({base:o,junction:e});return m.add(n),n}};return f.set(o,r),a&&p.set(o,a),_.add(o),Object.freeze(o)}for(let[e,n]of Object.entries(t))r[e]=i(e,n);return Object.freeze(r)};if(y[e]=h(u.fields),u.branches)for(let[t,n]of Object.entries(u.branches.options))v.set(JSON.stringify([e,t]),h(n.fields,Object.freeze({discriminator:u.branches.discriminator,tag:t})));b[e]=t=>C(e,`one`,t,_),w[e]=t=>C(e,`many`,t,_)}let D=i(Object.freeze({...y,one:Object.freeze(b),many:Object.freeze(w)}),((e,t)=>{let n=v.get(JSON.stringify([e,t]));if(!n)throw Error(`Unknown variant scope "${e}.${t}"`);return n})),k=Object.fromEntries(Object.entries(D).map(([e,t])=>[e,Object.freeze({...t})]));Object.freeze(k);for(let[e,t]of Object.entries(k)){if(!Object.hasOwn(n,e))throw Error(`Unknown source table "${e}"`);for(let[n,r]of Object.entries(t)){if(l[e].allFields.has(n)||l[e].branches&&[`variant`,`variants`].includes(n)||[`and`,`or`,`not`,`fields`,`then`,`__proto__`,`constructor`,`prototype`].includes(n))throw Error(`Relation name collision "${n}"`);if(!h.has(r)||!_.has(S(r.from))||!_.has(S(r.to))||r.source!==e)throw Error(`Relation source bucket mismatch`);O(r,l)}}let P={metadata:l,declarations:k},z={};for(let i of Object.keys(n))z[i]={paginationOpts(n){return K(P),x(n),J(e.extend({filters:t(j(P,i,n)).optional(),order:o.enum([`asc`,`desc`]).optional()}),()=>K(P))},pageDto(e){return K(P),x(e),J(r(M(P,i,e)).result,()=>K(P))}};let B=JSON.stringify([2,Object.entries(l).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,Object.entries(t.fields).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,t.isOptional,I(t)]),t.branches?[t.branches.discriminator,Object.entries(t.branches.options).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,Object.entries(t.fields).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,t.isOptional,I(t)])])]:null,t.indexes,L(I(a(t.dto)))]),Object.entries(k).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,Object.entries(t).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,t.cardinality,t.target,A(t.from),A(t.to)])])]),V=Object.freeze({identity:B,version:1,tables:Object.freeze(z)});u.set(V,Z(P));let U=Object.freeze({...n}),W=Object.fromEntries(Object.entries(U).map(([e,t])=>{let n=G(t.schema,`stored`),r=G(t.publicDto,`dto`),i=t.table.validator,a=i.isOptional,o=JSON.stringify(F(t.table));return[e,()=>{if(n(),r(),t.table.validator!==i||i.isOptional!==a||JSON.stringify(F(t.table))!==o)throw Error(`Native schema mutated after registry construction: ${e}`)}]}));for(let[e,t]of Object.entries(l)){if(!t.branches)continue;let n=t.assertUnchanged;t.assertUnchanged=()=>{n(),W[e]()}}return d.set(V,{internal:P,tables:U,assertStoredUnchanged:()=>{for(let e of Object.values(W))e()},assertNativeTable(e,t){if(!Object.hasOwn(U,e)||U[e].table!==t)throw Error(`Native schema/table ownership disagrees with relation registry`);W[e]()}}),V}function v(a){let c=d.get(a);if(!c)throw Error(`Unknown relation registry`);let l=()=>{K(c.internal),c.assertStoredUnchanged()},u=e=>{l();let t=Object.keys(c.tables);if(t.length!==Object.keys(e).length||t.some(t=>e[t]!==c.tables[t].table))throw Error(`Native schema/table ownership disagrees with relation registry`)};l();let f=/* @__PURE__ */ new WeakMap,p=/* @__PURE__ */ new Map,m=/* @__PURE__ */ new Map,h=/* @__PURE__ */ new WeakMap;function g(e,t){l();let n=c.internal.metadata[e];if(!n)throw Error(`Unknown query table`);if(!n.branches)return;let r=o.string().safeParse(t[n.branches.discriminator]),a=r.success&&Object.hasOwn(n.branches.options,r.data)?n.branches.options[r.data]:void 0;if(!a)throw Error(`Invalid variant document`);let u=Object.fromEntries(Object.keys(a.fields).filter(e=>Object.hasOwn(t,e)).map(e=>[e,t[e]])),d=f.get(a);d||(d=i(s.object(a.fields)),f.set(a,d)),d.parse(u)}return Object.freeze({assertUnchanged:l,validateDocument:g,assertNativeTable:c.assertNativeTable,assertSchema:u,pagination(r){l();let i=c.internal;function a(e,t,r){let o=JSON.stringify([e,t,r??null]),s=m.get(o);if(s)return s;let c=i.metadata[e];if(!c)throw Error(`Unknown query table`);let l=JSON.stringify([e,r??null]),u=p.get(l);if(!u){u={};for(let[e,t]of Object.entries(r===void 0?c.fields:c.branches.options[r].fields))b(t)&&(u[e]=n(t).optional());p.set(l,u)}let d={fields:u,variants:c.branches&&r===void 0&&t<4?{discriminator:c.branches.discriminator,options:Object.fromEntries(Object.keys(c.branches.options).map(n=>[n,a(e,t+1,n)]))}:void 0,relations:t>=4?{}:Object.fromEntries(Object.entries(i.declarations[e]??{}).map(([e,n])=>[e,{cardinality:n.cardinality,target:a(n.target,t+1)}]))};return m.set(o,d),d}return e.extend({filters:t(a(r,0),h).optional(),order:o.enum([`asc`,`desc`]).optional()})},page(e,t){return l(),x(t),r(M(c.internal,e,t)).result},project(e,t,n,r){if(u(e),!r())return null;let i=c.internal.metadata[t];if(!i)throw Error(`Unknown query table`);let a=i.branches?i.branches.options[String(n[i.branches.discriminator])]:void 0;if(i.branches&&!a)throw Error(`Invalid variant document`);let s=a?.dto??i.dto;if(!(s instanceof o.ZodObject))throw Error(`Invalid variant DTO`);return g(t,n),s.parse(Object.fromEntries(Object.keys(s.shape).filter(e=>Object.hasOwn(n,e)).map(e=>[e,n[e]])))}})}function y(e){let t=u.get(e);if(!t)throw Error(`Unknown relation registry`);return t}function b(e){return[`id`,`string`,`float64`,`int64`,`boolean`,`null`,`literal`].includes(e.kind)||e.kind===`union`&&e.members.every(b)}function x(e){let t=[{value:e,depth:0,ancestors:[]}],n=0;for(;t.length;){let{value:e,depth:r,ancestors:i}=t.pop();if(++n>256||r>4||i.includes(e))throw Error(`Selection cycle or depth/node budget exceeded`);let a=Object.getPrototypeOf(e);if(a!==Object.prototype&&a!==null)throw Error(`Invalid selection`);let o=Reflect.ownKeys(e);if(o.length+n+t.length>256)throw Error(`Selection node budget exceeded`);for(let a of o){let o=Object.getOwnPropertyDescriptor(e,a);if(!o.enumerable||!(`value`in o)||String(a)!==a)throw Error(`Invalid selection property`);if(o.value!==!0)t.push({value:o.value,depth:r+1,ancestors:[...i,e]});else if(++n>256)throw Error(`Selection node budget exceeded`)}}}function S(e){return`base`in e?e.base:e}function C(e,t,n,r){for(let e of[n.from,n.to])if(!r.has(S(e))||`base`in e&&(!m.has(e)||!r.has(e.junction)))throw Error(`Foreign registry or invalid field reference`);if(S(n.to).table!==e)throw Error(`Wrong relation target table`);let i=Object.freeze({[l]:!0,source:S(n.from).table,target:e,cardinality:t,from:n.from,to:n.to,sourceGuard:S(n.from).guard,targetGuard:S(n.to).guard,junctionGuard:w(n.from,n.to),sourceMember:p.get(S(n.from)),targetMember:p.get(S(n.to))});return h.add(i),i}function w(e,t){let n=`base`in e?e.junction.guard:void 0,r=`base`in t?t.junction.guard:void 0;if(n&&r&&(n.discriminator!==r.discriminator||n.tag!==r.tag))throw Error(`Contradictory junction scopes`);return n??r}function T(e){if(e.kind===`id`)return[e.tableName];if(e.kind===`null`)return[];if(e.kind!==`union`)return null;let t=e.members.map(T);return t.some(e=>e===null)?null:[...new Set(t.flatMap(e=>e))].sort()}function E(e,t){let n=D(e);return n.length>0&&JSON.stringify(n)===JSON.stringify(D(t))}function D(e){if(e.kind===`union`)return[...new Set(e.members.flatMap(D))].sort();if(e.kind===`null`)return[];if(![`id`,`string`,`float64`,`int64`,`boolean`,`literal`].includes(e.kind))throw Error(`Unsupported relation field kind`);return[JSON.stringify(I(e))]}function O(e,t){let n=e.from,r=e.to;if(`base`in n!=`base`in r)throw Error(`Both relation legs must use through`);if(`base`in n&&`base`in r){if(n.junction.table!==r.junction.table)throw Error(`Different junction tables`);k(t,n.junction.table,n.junction.field,e.junctionGuard),k(t,e.target,r.base.field,e.targetGuard);return}if(!E(f.get(S(n)),f.get(S(r))))throw Error(`Incompatible relation field types`);k(t,e.target,S(r).field,e.targetGuard)}function k(e,t,n,r){if(n!==`_id`&&!e[t].indexes.some(e=>{let t=e.fields.indexOf(n);return t>=0&&e.fields.slice(0,t).every(e=>e===r?.discriminator)}))throw Error(`No active index begins with or has a guarded prefix for "${t}.${n}"`)}function A(e){return`base`in e?[e.base.table,e.base.field,e.base.guard??null,e.junction.table,e.junction.field,e.junction.guard??null]:p.has(e)?[e.table,e.field,e.guard??null,p.get(e)]:[e.table,e.field,e.guard??null]}function j(e,t,r,i=0,a){let o={},s={},c=e.metadata[t],l={};for(let[u,d]of Object.entries(r)){if(u===`variants`&&d!==!0&&c.branches&&a===void 0){if(i>=4)throw Error(`Invalid variant selection`);for(let[n,a]of Object.entries(d)){if(!Object.hasOwn(c.branches.options,n)||a===!0)throw Error(`Unknown variant filter selection`);l[n]=j(e,t,{...Object.fromEntries(Object.entries(r).filter(([e])=>e!==`variants`)),...a},i+1,n)}continue}let f=(a===void 0?c.fields:c.branches.options[a].fields)[u],p=e.declarations[t]?.[u];if(d===!0&&f)o[u]=n(f).optional();else if(d!==!0&&p&&i<4)s[u]={cardinality:p.cardinality,target:j(e,p.target,d,i+1)};else throw Error(`Invalid relation filter selection "${t}.${u}"`)}return{fields:o,relations:s,variants:c.branches&&a===void 0?{discriminator:c.branches.discriminator,options:l}:void 0}}function M(e,t,n,i=0){let a={};for(let[s,c]of Object.entries(n)){let n=e.declarations[t]?.[s];if(!n||i>=4)throw Error(`Unknown or too deep relation "${t}.${s}"`);let l=c===!0?e.metadata[n.target].dto:M(e,n.target,c,i+1);if(n.targetGuard){if(!(l instanceof o.ZodDiscriminatedUnion))throw Error(`Invalid target scope`);l=l.options.find(e=>e.shape[n.targetGuard.discriminator]instanceof o.ZodLiteral&&e.shape[n.targetGuard.discriminator].value===n.targetGuard.tag)}a[s]=n.cardinality===`one`?l.nullable():r(l).result}let s=e.metadata[t];function c(n,r){let i={...a};for(let n of Object.keys(i)){let a=e.declarations[t][n];a.sourceGuard&&r!==a.sourceGuard.tag&&a.cardinality===`one`&&(i[n]=o.null())}return J(n.extend(i).strict(),()=>K(e))}if(s.branches){let t=Object.entries(s.branches.options).map(([e,t])=>c(t.dto,e));return X(o.discriminatedUnion(s.branches.discriminator,[t[0],...t.slice(1)]),()=>K(e))}if(!(s.dto instanceof o.ZodObject))throw Error(`Expected object DTO`);return c(s.dto)}function N(e,t,n,r){if(t instanceof o.ZodObject&&n instanceof o.ZodObject){let n=a(t).fields;return z(e,n,r),{fields:n,allFields:new Set(Object.keys(n))}}if(!(t instanceof o.ZodDiscriminatedUnion)||!(n instanceof o.ZodDiscriminatedUnion))throw Error(`Expected matching discriminated union boundaries "${e}"`);let i=t._zod.def.discriminator;if(n._zod.def.discriminator!==i)throw Error(`DTO discriminator mismatch`);function c(e){let t=Object.create(null);for(let n of e.options){if(!(n instanceof o.ZodObject))throw Error(`Variant branches must be objects`);let e=n.shape[i];if(!(e instanceof o.ZodLiteral)||e.values.size!==1)throw Error(`Variant tags must be unique required string literals`);let r=o.string().safeParse(e.value);if(!r.success||Object.hasOwn(t,r.data))throw Error(`Variant tags must be unique required string literals`);t[r.data]=n}if(Object.keys(t).length===0)throw Error(`Expected at least one variant branch`);return t}let l=c(t),u=c(n);if(Object.keys(l).sort().join(`\0`)!==Object.keys(u).sort().join(`\0`))throw Error(`DTO variant tags mismatch`);let d={discriminator:i,options:Object.create(null)},f=[];for(let[t,n]of Object.entries(l)){let r=a(n).fields,{_id:i,_creationTime:o,...c}=r;z(e,r,I(s.object(c))),f.push(s.object(c)),d.options[t]={fields:r,dto:u[t]}}if(L(r)!==L(I(s.union(...f))))throw Error(`Native stored document disagrees with boundary "${e}"`);let p=Object.values(d.options).map(e=>e.fields),m={};for(let e of Object.keys(p[0])){if(!p.every(t=>Object.hasOwn(t,e))||e!==i&&!p.every(t=>P(t[e],p[0][e])))continue;let t=p.map(t=>t[e]),n=s.union(...t);m[e]=t.some(e=>e.isOptional===`optional`)?s.optional(n):n}return{fields:m,branches:d,allFields:new Set(p.flatMap(e=>Object.keys(e)))}}function P(e,t){try{return E(e,t)}catch{return L(I(e))===L(I(t))}}function F(e){return e.export()}function I(e){return e.json}function L(e){if(Array.isArray(e))return`[${e.map(L).join(`,`)}]`;if(e!==null&&Object(e)===e){let t=e;return`{${Object.keys(t).sort().map(e=>`${JSON.stringify(e)}:${L(t[e])}`).join(`,`)}}`}return JSON.stringify(e)}function R(e){if(e===null||Object(e)!==e)return;let t=e;if(t.type===`any`)throw Error(`Unsupported native validation form`);for(let e of Object.values(t))R(e)}function z(e,t,n){let{_id:r,_creationTime:i,...a}=t;if(!r||!i||L(I(r))!==L(I(s.id(e)))||L(I(i))!==L(I(s.number()))||r.isOptional!==`required`||i.isOptional!==`required`||L(n)!==L(I(s.object(a))))throw Error(`Native stored document disagrees with boundary "${e}"`)}const B=o.object({field:o.string()}),V=new Set([B,B.pick({field:!0}),B.omit({field:!0}),B.extend({other:o.string()}),B.safeExtend({other:o.string()}),B.merge(o.object({other:o.string()})),B.partial(),B.required()].flatMap(e=>{let t=Object.getOwnPropertyDescriptor(e._zod.def,`shape`)?.get;return t?[Function.prototype.toString.call(t)]:[]}));function H(e){return G(e,`dto`)}const U=Function.prototype.toString.call(Object.getOwnPropertyDescriptor(o.string().default(``)._zod.def,`defaultValue`).get),W=Function.prototype.toString.call(Object.getOwnPropertyDescriptor(o.string().prefault(``)._zod.def,`defaultValue`).get);function G(e,t){let n=[],r=/* @__PURE__ */ new Set,i=[],a=/* @__PURE__ */ new Set,s=/* @__PURE__ */ new Set,c=[];function l(e,u){if(s.has(e))throw Error(`Unsupported cyclic DTO schema`);if(!a.has(e)){if(u>32||n.length>=4096)throw Error(`DTO schema graph budget exceeded`);a.add(e),s.add(e);try{if(e instanceof RegExp&&i.push({expression:e,source:e.source,flags:e.flags}),e instanceof o.core.$ZodCheck&&`check`in e._zod.def){if(t===`dto`&&e._zod.def.check===`overwrite`)throw Error(`Unsupported DTO overwrite check`);l(e._zod.def,u+1),n.push({object:e._zod,exactKeys:!1,keys:[`def`,`check`],values:[`def`,`check`].map(t=>Object.getOwnPropertyDescriptor(e._zod,t))});return}if(e instanceof o.core.$ZodType){let i=e._zod.def;if(t===`dto`&&(![`object`,`array`,`optional`,`nullable`,`nonoptional`,`union`,`intersection`,`tuple`,`record`,`string`,`number`,`boolean`,`bigint`,`null`,`never`,`literal`,`enum`].includes(i.type)||`coerce`in i&&i.coerce))throw Error(`Unsupported DTO schema "${i.type}"`);if(t===`stored`&&(i.type==="default"||i.type===`prefault`)){let e=Object.getOwnPropertyDescriptor(i,`defaultValue`);if(e?.get){if(e.set||Function.prototype.toString.call(e.get)!==(i.type==="default"?U:W))throw Error(`Unsupported stored schema accessor`);r.add(i)}}if(e instanceof o.ZodUnion&&(l(e.options,u+1),n.push({object:e,exactKeys:!1,keys:[`options`],values:[Object.getOwnPropertyDescriptor(e,`options`)]})),i.type===`object`){let t=Object.getOwnPropertyDescriptor(i,`shape`);if(t?.get){if(t.set||!V.has(Function.prototype.toString.call(t.get)))throw Error(`Unsupported DTO schema accessor`);let e=i.shape;l(e,u+1),Object.getOwnPropertyDescriptor(i,`shape`)?.get&&c.push({definition:i,fields:e})}if(e instanceof o.ZodObject){let t=Object.getOwnPropertyDescriptor(e,`shape`);if(t&&!(`value`in t))throw Error(`Unsupported DTO schema accessor`);l(e.shape,u+1)}}l(i,u+1),n.push({object:e._zod,exactKeys:!1,keys:[`def`],values:[Object.getOwnPropertyDescriptor(e._zod,`def`)]});return}let a=Reflect.ownKeys(e),s=a.map(t=>Object.getOwnPropertyDescriptor(e,t));if(s.some((t,n)=>!(`value`in t)&&!c.some(({definition:t})=>t===e&&a[n]===`shape`)&&!(r.has(e)&&a[n]===`defaultValue`)))throw Error(`Unsupported DTO schema accessor`);n.push({object:e,exactKeys:!0,keys:a,values:s});for(let e of s)e.value!==null&&Object(e.value)===e.value&&!(e.value instanceof Function)&&l(e.value,u+1)}finally{s.delete(e)}}}return l(e,0),()=>{for(let e of i)if(e.expression.source!==e.source||e.expression.flags!==e.flags)throw Error(`DTO schema mutated after registry construction`);for(let e of n){let t=e.keys;if(e.exactKeys&&Reflect.ownKeys(e.object).length!==t.length)throw Error(`DTO schema mutated after registry construction`);for(let n=0;n<t.length;n++){if(e.object instanceof RegExp&&t[n]===`lastIndex`)continue;let r=Object.getOwnPropertyDescriptor(e.object,t[n]),i=e.values[n];if(!r||r.value!==i.value||r.get!==i.get||r.set!==i.set||r.enumerable!==i.enumerable)throw Error(`DTO schema mutated after registry construction`)}}for(let{definition:e,fields:t}of c){let n=e.shape,r=Reflect.ownKeys(t);if(Reflect.ownKeys(n).length!==r.length||r.some(e=>Object.getOwnPropertyDescriptor(n,e)?.value!==Object.getOwnPropertyDescriptor(t,e)?.value))throw Error(`DTO schema mutated after registry construction`)}}}function K(e){for(let t of Object.values(e.metadata))t.assertUnchanged()}const q=o.core.$constructor(`GuardedDtoObject`,(e,t)=>{let n=t;o.ZodObject.init(e,t),e._zod.deferred??=[],e._zod.deferred.push(()=>{let t=e._zod.run;e._zod.run=(e,r)=>{try{n.assertUnchanged()}catch{return e.issues.push({code:`custom`,input:e.value,message:`DTO schema mutated after registry construction`}),e}return t(e,r)}})});function J(e,t){let n=e.shape,r={...e._zod.def,assertUnchanged:t};return Object.defineProperty(r,"shape",{enumerable:!0,configurable:!0,get:()=>(t(),n)}),new q(r)}const Y=o.core.$constructor(`GuardedDtoUnion`,(e,t)=>{let n=t;o.ZodDiscriminatedUnion.init(e,t),e._zod.deferred??=[],e._zod.deferred.push(()=>{let t=e._zod.run;e._zod.run=(e,r)=>{try{n.assertUnchanged()}catch{return e.issues.push({code:`custom`,input:e.value,message:`DTO schema mutated after registry construction`}),e}return t(e,r)}})});function X(e,t){let n=e.options,r={...e._zod.def,assertUnchanged:t};return Object.defineProperty(r,"options",{enumerable:!0,configurable:!0,get:()=>(t(),n)}),new Y(r)}function Z(e){let t={};for(let[n,r]of Object.entries(e.metadata)){let e={};for(let[t,n]of Object.entries(r.fields))e[t]=Object.freeze({kind:n.kind,optional:n.isOptional===`optional`,nullable:Q(n),idTables:Object.freeze($(n)),native:ee(I(n))});t[n]=Object.freeze({fields:Object.freeze(e),variant:r.branches?Object.freeze({discriminator:r.branches.discriminator,tags:Object.freeze(Object.keys(r.branches.options))}):void 0,indexes:Object.freeze(r.indexes.map(e=>Object.freeze({name:e.name,fields:Object.freeze([...e.fields])})))})}return Object.freeze({tables:Object.freeze(t),declarations:e.declarations})}function Q(e){return e.kind===`null`||e.kind===`union`&&e.members.some(Q)}function $(e){return e.kind===`id`?[e.tableName]:e.kind===`union`?[...new Set(e.members.flatMap($))].sort():[]}function ee(e){let t=structuredClone(e),n=[t];for(;n.length;){let e=n.pop();if(Object(e)!==e)continue;let t=e;Object.freeze(t),n.push(...Object.values(t))}return t}export{_ as defineRelations,v as getRelationExecutor,y as getRelationMetadata};
1
+ import{relationFilterSchema as e}from"./querying/shared/filters.mjs";import{zodToConvex as t}from"./zod-convex.mjs";import{nativePagination as n,scalarPredicateSchema as r}from"./querying/filters.mjs";import{paginated as i}from"./zod-table.mjs";import{captureDto as a,materializeDto as o}from"./querying/schema-snapshot.mjs";import{convexToZod as s}from"convex-helpers/server/zod4";import{defineSchema as c,defineTable as l}from"convex/server";import{z as u}from"zod";import{v as d}from"convex/values";const f=a(n),p=Symbol(`relationField`),m=Symbol(`relationEdge`),h=/* @__PURE__ */ new WeakMap,g=/* @__PURE__ */ new WeakMap,_=/* @__PURE__ */ new WeakMap,v=/* @__PURE__ */ new WeakMap,y=/* @__PURE__ */ new WeakSet,b=/* @__PURE__ */ new WeakSet,x=u.object({indexDescriptor:u.string(),searchField:u.string(),filterFields:u.array(u.string())}),S=u.object({searchIndexes:u.array(x),stagedSearchIndexes:u.array(x),indexes:u.array(u.object({indexDescriptor:u.string(),fields:u.array(u.string())}))});function C(n,r){let m={},x={},C=/* @__PURE__ */ new Set,w=/* @__PURE__ */ new Map,T={},O={},k={};for(let[e,r]of Object.entries(n)){if(r.tableName!==e||[`one`,`many`,`__proto__`,`constructor`,`prototype`].includes(e))throw Error(`Invalid relation table "${e}"`);let n=Object.getOwnPropertyDescriptor(r,`table`);if(!n||!(`value`in n))throw Error(`Unsupported native table accessor`);let i=n.value;G(i),Z(r.schema,`stored`),Z(r.publicDto,`dto`);let c=r.dto(!0);if(!(c instanceof u.ZodObject)&&!(c instanceof u.ZodDiscriminatedUnion))throw Error(`Expected object or discriminated union DTO`);Z(c,`dto`);let l=a(c),f=o(l);if(!(f instanceof u.ZodObject)&&!(f instanceof u.ZodDiscriminatedUnion))throw Error(`Expected object or discriminated union DTO`);let h=ee(i);J(h.documentType);let g=H(e,r.schema,f,h.documentType),b=S.parse(h),D=Object.freeze([...b.searchIndexes.map(e=>({...e,staged:!1})),...b.stagedSearchIndexes.map(e=>({...e,staged:!0}))].map(e=>Object.freeze({name:e.indexDescriptor,searchField:e.searchField,filterFields:Object.freeze([...e.filterFields].sort()),staged:e.staged})).sort((e,t)=>e.name.localeCompare(t.name))),A=b.indexes.map(e=>({name:e.indexDescriptor,fields:[...e.fields]})).sort((e,t)=>e.name.localeCompare(t.name));J(K(t(f))),x[e]=i;let j=Object.create(null),N=Object.create(null),I=Object.getOwnPropertyDescriptor(r,`fieldGroups`);if(!I&&`fieldGroups`in r||I&&!(`value`in I))throw Error(`Invalid field groups`);E(I?.value??{});let L=u.record(u.string(),u.array(u.string()).nonempty()).parse(I?.value??{}),R=/* @__PURE__ */ new Set,z=f instanceof u.ZodObject?[f]:f.options;for(let[e,t]of Object.entries(L)){if(!e||[`__proto__`,`constructor`,`prototype`].includes(e))throw Error(`Invalid field groups`);for(let e of t){if(!g.allFields.has(e)||e.startsWith(`_`)||R.has(e)||z.some(t=>!(t instanceof u.ZodObject)||Object.hasOwn(t.shape,e)))throw Error(`Conflicting or incompatible field groups`);let t=g.branches?Object.values(g.branches.options).map(t=>t.fields[e]).filter(e=>e!==void 0):[g.fields[e]];if(!t.every(e=>q(K(e))===q(K(t[0]))&&e.isOptional===t[0].isOptional))throw Error(`Conflicting or incompatible field groups`);R.add(e)}j[e]=Object.freeze([...t].sort());for(let[n,r]of g.branches?Object.entries(g.branches.options).map(([e,t])=>[e,t.fields]):[[null,g.fields]]){let i=Object.fromEntries(t.filter(e=>Object.hasOwn(r,e)).map(e=>[e,r[e]]));N[JSON.stringify([e,n])]=a(s(d.object(i)).strict())}}m[e]={...g,indexes:A,searchIndexes:D,dto:f,dtoRecipe:l,fieldGroups:Object.freeze(j),groupRecipes:Object.freeze(N)};let B=(t,n)=>{let r=Object.create(null);function i(t,r,a){let o={[p]:void 0,table:e,field:t,guard:n,forTable(e){if(n)throw Error(`forTable on branch-scoped fields is unsupported`);if(!P(r)?.includes(e))throw Error(`Invalid native ID member selection`);if(!Object.hasOwn(m,e))throw Error(`Native ID member table is not registered`);let a=Q(r)?d.union(d.id(e),d.null()):d.id(e);return i(t,r.isOptional===`optional`?d.optional(a):a,Object.freeze({table:e}))},through(e){if(a||v.has(e))throw Error(`forTable with through is unsupported`);let t=_.get(e);if(!C.has(e)||!t||!F(r,t))throw Error(`Invalid junction field or registry`);let n=Object.freeze({base:o,junction:e});return y.add(n),n}};return _.set(o,r),a&&v.set(o,a),C.add(o),Object.freeze(o)}for(let[e,n]of Object.entries(t))r[e]=i(e,n);return Object.freeze(r)};if(T[e]=B(g.fields),g.branches)for(let[t,n]of Object.entries(g.branches.options))w.set(JSON.stringify([e,t]),B(n.fields,Object.freeze({discriminator:g.branches.discriminator,tag:t})));O[e]=t=>M(e,`one`,t,C),k[e]=t=>M(e,`many`,t,C)}let N=r(Object.freeze({...T,one:Object.freeze(O),many:Object.freeze(k)}),((e,t)=>{let n=w.get(JSON.stringify([e,t]));if(!n)throw Error(`Unknown variant scope "${e}.${t}"`);return n})),I=Object.fromEntries(Object.entries(N).map(([e,t])=>[e,Object.freeze({...t})]));Object.freeze(I);for(let[e,t]of Object.entries(I)){if(!Object.hasOwn(m,e))throw Error(`Unknown source table "${e}"`);for(let[n,r]of Object.entries(t)){if(m[e].allFields.has(n)||m[e].branches&&[`variant`,`variants`].includes(n)||[`and`,`or`,`not`,`fields`,`then`,`__proto__`,`constructor`,`prototype`].includes(n))throw Error(`Relation name collision "${n}"`);if(!b.has(r)||!C.has(j(r.from))||!C.has(j(r.to))||r.source!==e)throw Error(`Relation source bucket mismatch`);L(r,m)}}let R={metadata:m,declarations:I},U={};for(let t of Object.keys(m))U[t]={filters(e){if(m[t].branches)throw Error(`Shared scalar contracts do not support variant tables`);for(let[n,r]of Object.entries(e.native)){let e=m[t].fields[n];if(!e||JSON.stringify(K(e))!==JSON.stringify(r.json)||e.isOptional===`optional`!==r.optional)throw Error(`Shared filter field mismatch "${n}"`)}return o(f).extend({filters:e.schema.optional(),order:u.enum([`asc`,`desc`]).optional()})},paginationOpts(n){return A(n),o(f).extend({filters:e(B(R,t,n)).optional(),order:u.enum([`asc`,`desc`]).optional()})},pageDto(e,n={}){return A(e),D(R,t,n),i(V(R,t,e,0,n)).result}};let W=JSON.stringify([2,Object.entries(m).sort(([e],[t])=>e.localeCompare(t)).map(([e,n])=>[e,Object.entries(n.fields).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,t.isOptional,K(t)]),n.branches?[n.branches.discriminator,Object.entries(n.branches.options).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,Object.entries(t.fields).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,t.isOptional,K(t)])])]:null,n.indexes,q(K(t(n.dto))),...Object.keys(n.fieldGroups).length?[n.fieldGroups]:[],...n.searchIndexes.length?[{searchIndexes:n.searchIndexes}]:[]]),Object.entries(I).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,Object.entries(t).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,t.cardinality,t.target,z(t.from),z(t.to)])])]),Y=Object.freeze({identity:W,version:1,tables:Object.freeze(U)});h.set(Y,ie(R));let X={};for(let[e,t]of Object.entries(m)){let n=l({});for(let e of t.indexes){let[t,...r]=e.fields;if(t===void 0)throw Error(`Invalid empty active index`);n.index(e.name,[t,...r])}let r=Object.getOwnPropertyDescriptor(n,`indexes`).value;for(let e of r)Object.freeze(e.fields),Object.freeze(e);Object.freeze(r),Object.freeze(n),X[e]=n}return g.set(Y,{internal:R,nativeTables:Object.freeze(x),streamSchema:c(Object.freeze(X))}),Y}function w(t){let n=g.get(t);if(!n)throw Error(`Unknown relation registry`);let i=e=>{let t=Object.keys(n.nativeTables);if(t.length!==Reflect.ownKeys(e).length||t.some(t=>{let r=Object.getOwnPropertyDescriptor(e,t);return!r||!(`value`in r)||r.value!==n.nativeTables[t]}))throw Error(`Native schema/table ownership disagrees with relation registry`)},a=/* @__PURE__ */ new WeakMap,c=/* @__PURE__ */ new WeakMap,l=/* @__PURE__ */ new WeakMap,p=/* @__PURE__ */ new Map,m=/* @__PURE__ */ new Map,h=/* @__PURE__ */ new WeakMap;function _(e,t){let r=n.internal.metadata[e];if(!r)throw Error(`Unknown query table`);if(!r.branches)return;let i=t[r.branches.discriminator],o=typeof i==`string`&&Object.hasOwn(r.branches.options,i)?r.branches.options[i]:void 0;if(!o)throw Error(`Invalid variant document`);let c=a.get(o),l=c?.fieldKeys??Object.keys(o.fields),u=[];for(let e of l)Object.hasOwn(t,e)&&u.push([e,void 0]);for(let e of u)e[1]=t[e[0]];let f=Object.fromEntries(u);c||(c={validator:s(d.object(o.fields)),fieldKeys:l},a.set(o,c)),c.validator.parse(f)}return Object.freeze({streamSchema:n.streamSchema,groups(e,t){return D(n.internal,e,t)},validateDocument:_,assertSchema:i,pagination(t){let i=n.internal;function a(e,t,n){let o=JSON.stringify([e,t,n??null]),s=m.get(o);if(s)return s;let c=i.metadata[e];if(!c)throw Error(`Unknown query table`);let l=JSON.stringify([e,n??null]),u=p.get(l);if(!u){u={};for(let[e,t]of Object.entries(n===void 0?c.fields:c.branches.options[n].fields))k(t)&&(u[e]=r(t).optional());p.set(l,u)}let d={fields:u,variants:c.branches&&n===void 0&&t<4?{discriminator:c.branches.discriminator,options:Object.fromEntries(Object.keys(c.branches.options).map(n=>[n,a(e,t+1,n)]))}:void 0,relations:t>=4?{}:Object.fromEntries(Object.entries(i.declarations[e]??{}).map(([e,n])=>[e,{cardinality:n.cardinality,target:a(n.target,t+1)}]))};return m.set(o,d),d}return o(f).extend({filters:e(a(t,0),h).optional(),order:u.enum([`asc`,`desc`]).optional()})},select(e,t){A(t);function r(e,t,i){if(!Object.hasOwn(n.internal.metadata,e))throw Error(`Unknown query table`);for(let[a,o]of Object.entries(t)){let t=n.internal.declarations[e]?.[a];if(!t||i>=4)throw Error(`Unknown or too deep relation "${e}.${a}"`);o!==!0&&r(t.target,o,i+1)}}r(e,t,0)},project(e,t,r,i=[]){if(!r())return null;let a=n.internal.metadata[e];if(!a)throw Error(`Unknown query table`);let o=a.branches?a.branches.options[String(t[a.branches.discriminator])]:void 0;if(a.branches&&!o)throw Error(`Invalid variant document`);let s=o?.dto??a.dto;if(!(s instanceof u.ZodObject))throw Error(`Invalid variant DTO`);if(i.length){let e=l.get(s);e||(e=/* @__PURE__ */ new Map,l.set(s,e));let n=JSON.stringify([...i].sort()),r=e.get(n);r||(r=s.extend(O(a,i,void 0,a.branches?String(t[a.branches.discriminator]):void 0)).strict(),e.set(n,r)),s=r}_(e,t);let d=c.get(s);return d||(d=Object.keys(s.shape),c.set(s,d)),s.parse(Object.fromEntries(d.filter(e=>Object.hasOwn(t,e)).map(e=>[e,t[e]])))}})}function T(e){let t=h.get(e);if(!t)throw Error(`Unknown relation registry`);return t}function E(e,t=0){if(t>16)throw Error(`Invalid field groups`);if(typeof e!=`object`||!e)return;let n=Object.getPrototypeOf(e);if(n!==Object.prototype&&n!==null&&n!==Array.prototype)throw Error(`Invalid field groups`);for(let n of Reflect.ownKeys(e)){let r=Object.getOwnPropertyDescriptor(e,n);if(!u.string().safeParse(n).success||!(`value`in r))throw Error(`Invalid field groups`);E(r.value,t+1)}}function D(e,t,n){E(n);function r(t,n,i){let a=u.object({fieldGroups:u.record(u.string(),u.enum([`required`,`if-permitted`])).optional(),relations:u.record(u.string(),u.unknown()).optional()}).strict().parse(n),o=e.metadata[t];if(!o)throw Error(`Unknown query table`);for(let e of Object.keys(a.fieldGroups??{}))if(!Object.hasOwn(o.fieldGroups,e))throw Error(`Unknown field group`);let s={};for(let[n,o]of Object.entries(a.relations??{})){let a=e.declarations[t]?.[n];if(!a||i>=4)throw Error(`Invalid field group relation`);s[n]=r(a.target,o,i+1)}return Object.freeze({fieldGroups:Object.freeze(a.fieldGroups??{}),relations:Object.freeze(s)})}return r(t,n,0)}function O(e,t,n,r){let i={};for(let a of t){let t=JSON.stringify([a,r??null]);if(!Object.hasOwn(e.groupRecipes,t))throw Error(`Unknown field group`);let s=o(e.groupRecipes[t]);if(!(s instanceof u.ZodObject))throw Error(`Invalid field group schema`);for(let[e,t]of Object.entries(s.shape))i[e]=n?.[a]===`if-permitted`?t.optional():t}return i}function k(e){return[`id`,`string`,`float64`,`int64`,`boolean`,`null`,`literal`].includes(e.kind)||e.kind===`union`&&e.members.every(k)}function A(e){let t=[{value:e,depth:0,ancestors:[]}],n=0;for(;t.length;){let{value:e,depth:r,ancestors:i}=t.pop();if(++n>256||r>4||i.includes(e))throw Error(`Selection cycle or depth/node budget exceeded`);let a=Object.getPrototypeOf(e);if(a!==Object.prototype&&a!==null)throw Error(`Invalid selection`);let o=Reflect.ownKeys(e);if(o.length+n+t.length>256)throw Error(`Selection node budget exceeded`);for(let a of o){let o=Object.getOwnPropertyDescriptor(e,a);if(!o.enumerable||!(`value`in o)||String(a)!==a)throw Error(`Invalid selection property`);if(o.value!==!0)t.push({value:o.value,depth:r+1,ancestors:[...i,e]});else if(++n>256)throw Error(`Selection node budget exceeded`)}}}function j(e){return`base`in e?e.base:e}function M(e,t,n,r){for(let e of[n.from,n.to])if(!r.has(j(e))||`base`in e&&(!y.has(e)||!r.has(e.junction)))throw Error(`Foreign registry or invalid field reference`);if(j(n.to).table!==e)throw Error(`Wrong relation target table`);let i=Object.freeze({[m]:!0,source:j(n.from).table,target:e,cardinality:t,from:n.from,to:n.to,sourceGuard:j(n.from).guard,targetGuard:j(n.to).guard,junctionGuard:N(n.from,n.to),sourceMember:v.get(j(n.from)),targetMember:v.get(j(n.to))});return b.add(i),i}function N(e,t){let n=`base`in e?e.junction.guard:void 0,r=`base`in t?t.junction.guard:void 0;if(n&&r&&(n.discriminator!==r.discriminator||n.tag!==r.tag))throw Error(`Contradictory junction scopes`);return n??r}function P(e){if(e.kind===`id`)return[e.tableName];if(e.kind===`null`)return[];if(e.kind!==`union`)return null;let t=e.members.map(P);return t.some(e=>e===null)?null:[...new Set(t.flatMap(e=>e))].sort()}function F(e,t){let n=I(e);return n.length>0&&JSON.stringify(n)===JSON.stringify(I(t))}function I(e){if(e.kind===`union`)return[...new Set(e.members.flatMap(I))].sort();if(e.kind===`null`)return[];if(![`id`,`string`,`float64`,`int64`,`boolean`,`literal`].includes(e.kind))throw Error(`Unsupported relation field kind`);return[JSON.stringify(K(e))]}function L(e,t){let n=e.from,r=e.to;if(`base`in n!=`base`in r)throw Error(`Both relation legs must use through`);if(`base`in n&&`base`in r){if(n.junction.table!==r.junction.table)throw Error(`Different junction tables`);R(t,n.junction.table,n.junction.field,e.junctionGuard),R(t,e.target,r.base.field,e.targetGuard);return}if(!F(_.get(j(n)),_.get(j(r))))throw Error(`Incompatible relation field types`);R(t,e.target,j(r).field,e.targetGuard)}function R(e,t,n,r){if(n!==`_id`&&!e[t].indexes.some(e=>{let t=e.fields.indexOf(n);return t>=0&&e.fields.slice(0,t).every(e=>e===r?.discriminator)}))throw Error(`No active index begins with or has a guarded prefix for "${t}.${n}"`)}function z(e){return`base`in e?[e.base.table,e.base.field,e.base.guard??null,e.junction.table,e.junction.field,e.junction.guard??null]:v.has(e)?[e.table,e.field,e.guard??null,v.get(e)]:[e.table,e.field,e.guard??null]}function B(e,t,n,i=0,a){let o={},s={},c=e.metadata[t],l={};for(let[u,d]of Object.entries(n)){if(u===`variants`&&d!==!0&&c.branches&&a===void 0){if(i>=4)throw Error(`Invalid variant selection`);for(let[r,a]of Object.entries(d)){if(!Object.hasOwn(c.branches.options,r)||a===!0)throw Error(`Unknown variant filter selection`);l[r]=B(e,t,{...Object.fromEntries(Object.entries(n).filter(([e])=>e!==`variants`)),...a},i+1,r)}continue}let f=(a===void 0?c.fields:c.branches.options[a].fields)[u],p=e.declarations[t]?.[u];if(d===!0&&f)o[u]=r(f).optional();else if(d!==!0&&p&&i<4)s[u]={cardinality:p.cardinality,target:B(e,p.target,d,i+1)};else throw Error(`Invalid relation filter selection "${t}.${u}"`)}return{fields:o,relations:s,variants:c.branches&&a===void 0?{discriminator:c.branches.discriminator,options:l}:void 0}}function V(e,t,n,r=0,a={}){let s={};for(let[o,c]of Object.entries(n)){let n=e.declarations[t]?.[o];if(!n||r>=4)throw Error(`Unknown or too deep relation "${t}.${o}"`);let l=V(e,n.target,c===!0?{}:c,r+1,a.relations?.[o]);if(n.targetGuard){if(!(l instanceof u.ZodDiscriminatedUnion))throw Error(`Invalid target scope`);l=l.options.filter(e=>e instanceof u.ZodObject).find(e=>e.shape[n.targetGuard.discriminator]instanceof u.ZodLiteral&&e.shape[n.targetGuard.discriminator].value===n.targetGuard.tag)}s[o]=n.cardinality===`one`?l.nullable():i(l).result}let c=e.metadata[t],l=o(c.dtoRecipe);function d(n,r){let i={...s};for(let n of Object.keys(i)){let a=e.declarations[t][n];a.sourceGuard&&r!==a.sourceGuard.tag&&a.cardinality===`one`&&(i[n]=u.null())}return n.extend({...O(c,Object.keys(a.fieldGroups??{}),a.fieldGroups,r),...i}).strict()}if(c.branches){if(!(l instanceof u.ZodDiscriminatedUnion))throw Error(`Invalid variant DTO`);let e=l.options.map(e=>{if(!(e instanceof u.ZodObject))throw Error(`Invalid variant DTO`);let t=e.shape[c.branches.discriminator];if(!(t instanceof u.ZodLiteral))throw Error(`Invalid variant tag`);return d(e,String(t.value))});return u.discriminatedUnion(c.branches.discriminator,[e[0],...e.slice(1)])}if(!(l instanceof u.ZodObject))throw Error(`Expected object DTO`);return d(l)}function H(e,n,r,i){if(n instanceof u.ZodObject&&r instanceof u.ZodObject){let r=t(n).fields;return Y(e,r,i),{fields:r,allFields:new Set(Object.keys(r))}}if(!(n instanceof u.ZodDiscriminatedUnion)||!(r instanceof u.ZodDiscriminatedUnion))throw Error(`Expected matching discriminated union boundaries "${e}"`);let a=n._zod.def.discriminator;if(r._zod.def.discriminator!==a)throw Error(`DTO discriminator mismatch`);function o(e){let t=Object.create(null);for(let n of e.options){if(!(n instanceof u.ZodObject))throw Error(`Variant branches must be objects`);let e=n.shape[a];if(!(e instanceof u.ZodLiteral)||e.values.size!==1)throw Error(`Variant tags must be unique required string literals`);let r=u.string().safeParse(e.value);if(!r.success||Object.hasOwn(t,r.data))throw Error(`Variant tags must be unique required string literals`);t[r.data]=n}if(Object.keys(t).length===0)throw Error(`Expected at least one variant branch`);return t}let s=o(n),c=o(r);if(Object.keys(s).sort().join(`\0`)!==Object.keys(c).sort().join(`\0`))throw Error(`DTO variant tags mismatch`);let l={discriminator:a,options:Object.create(null)},f=[];for(let[n,r]of Object.entries(s)){let i=t(r).fields,{_id:a,_creationTime:o,...s}=i;Y(e,i,K(d.object(s))),f.push(d.object(s)),l.options[n]={fields:i,dto:c[n]}}if(q(i)!==q(K(d.union(...f))))throw Error(`Native stored document disagrees with boundary "${e}"`);let p=Object.values(l.options).map(e=>e.fields),m={};for(let e of Object.keys(p[0])){if(!p.every(t=>Object.hasOwn(t,e))||e!==a&&!p.every(t=>U(t[e],p[0][e])))continue;let t=p.map(t=>t[e]),n=d.union(...t);m[e]=t.some(e=>e.isOptional===`optional`)?d.optional(n):n}return{fields:m,branches:l,allFields:new Set(p.flatMap(e=>Object.keys(e)))}}function U(e,t){try{return F(e,t)}catch{return q(K(e))===q(K(t))}}const W=/* @__PURE__ */ new Map;for(let e of[l(d.object({})),d.id(`sample`),d.null(),d.number(),d.int64(),d.commitTs(),d.boolean(),d.string(),d.bytes(),d.any(),d.object({}),d.literal(`sample`),d.array(d.string()),d.record(d.string(),d.string()),d.union(d.string(),d.null())]){let t=Object.getPrototypeOf(e);for(;t&&t!==Object.prototype;)W.has(t)||W.set(t,Object.getOwnPropertyDescriptors(t)),t=Object.getPrototypeOf(t)}function G(e){let t=/* @__PURE__ */ new Set,n=/* @__PURE__ */ new Set;function r(e,i,a=!1){if(n.has(e))throw Error(`Unsupported cyclic native schema`);if(t.has(e))return;if(i>64||t.size>=8192)throw Error(`Native schema graph budget exceeded`);t.add(e),n.add(e);let o=Object.getPrototypeOf(e),s=o&&W.get(o);if(o!==null&&o!==Object.prototype&&o!==Array.prototype&&!s)throw Error(`Unsupported native schema prototype`);if(Object.getOwnPropertySymbols(e).length)throw Error(`Unsupported native schema symbol`);let c=Object.getOwnPropertyNames(e).map(t=>Object.getOwnPropertyDescriptor(e,t));if(!a&&c.some(e=>!(`value`in e)||e.value instanceof Function))throw Error(`Unsupported native schema accessor or method`);if(s){let e=Object.getOwnPropertyNames(o);if(e.length!==Object.getOwnPropertyNames(s).length||e.some(e=>{let t=Object.getOwnPropertyDescriptor(o,e),n=Object.getOwnPropertyDescriptor(s,e)?.value;return!n||!Object.is(t.value,n.value)||t.get!==n.get||t.set!==n.set}))throw Error(`Unsupported native schema prototype mutation`);r(o,i+1,!0)}if(!a)for(let e of c)e.value!==null&&Object(e.value)===e.value&&r(e.value,i+1);n.delete(e)}r(e,0)}function ee(e){return e.export()}function K(e){return e.json}function q(e){if(Array.isArray(e))return`[${e.map(q).join(`,`)}]`;if(e!==null&&Object(e)===e){let t=e;return`{${Object.keys(t).sort().map(e=>`${JSON.stringify(e)}:${q(t[e])}`).join(`,`)}}`}return JSON.stringify(e)}function J(e){if(e===null||Object(e)!==e)return;let t=e;if(t.type===`any`)throw Error(`Unsupported native validation form`);for(let e of Object.values(t))J(e)}function Y(e,t,n){let{_id:r,_creationTime:i,...a}=t;if(!r||!i||q(K(r))!==q(K(d.id(e)))||q(K(i))!==q(K(d.number()))||r.isOptional!==`required`||i.isOptional!==`required`||q(n)!==q(K(d.object(a))))throw Error(`Native stored document disagrees with boundary "${e}"`)}const X=u.object({field:u.string()}),te=new Set([X,X.pick({field:!0}),X.omit({field:!0}),X.extend({other:u.string()}),X.safeExtend({other:u.string()}),X.merge(u.object({other:u.string()})),X.partial(),X.required()].flatMap(e=>{let t=Object.getOwnPropertyDescriptor(e._zod.def,`shape`)?.get;return t?[Function.prototype.toString.call(t)]:[]})),ne=Function.prototype.toString.call(Object.getOwnPropertyDescriptor(u.string().default(``)._zod.def,`defaultValue`).get),re=Function.prototype.toString.call(Object.getOwnPropertyDescriptor(u.string().prefault(``)._zod.def,`defaultValue`).get);function Z(e,t){let n=/* @__PURE__ */ new Set,r=/* @__PURE__ */ new Set,i=/* @__PURE__ */ new Set,a=/* @__PURE__ */ new Set;function o(e,s){if(i.has(e))throw Error(`Unsupported cyclic DTO schema`);if(!r.has(e)){if(s>32||r.size>=4096)throw Error(`DTO schema graph budget exceeded`);r.add(e),i.add(e);try{let r=Object.getOwnPropertyDescriptor(e,`_zod`);if(r){if(!(`value`in r))throw Error(`Unsupported DTO schema accessor`);let e=Object.getOwnPropertyDescriptor(r.value,`def`);if(!e||!(`value`in e))throw Error(`Unsupported DTO schema accessor`)}if(e instanceof u.core.$ZodCheck&&!(e instanceof u.core.$ZodType)){if(t===`dto`&&e._zod.def.check===`overwrite`)throw Error(`Unsupported DTO overwrite check`);o(e._zod.def,s+1);return}if(e instanceof u.core.$ZodType){let r=e._zod.def;if(t===`dto`&&(![`object`,`array`,`optional`,`nullable`,`nonoptional`,`union`,`intersection`,`tuple`,`record`,`string`,`number`,`boolean`,`bigint`,`null`,`never`,`custom`,`literal`,`enum`].includes(r.type)||`coerce`in r&&r.coerce))throw Error(`Unsupported DTO schema "${r.type}"`);if(t===`stored`&&(r.type==="default"||r.type===`prefault`)){let e=Object.getOwnPropertyDescriptor(r,`defaultValue`);if(e?.get){if(e.set||Function.prototype.toString.call(e.get)!==(r.type==="default"?ne:re))throw Error(`Unsupported stored schema accessor`);n.add(r)}}if(e instanceof u.ZodUnion&&o(e.options,s+1),r.type===`object`){let t=Object.getOwnPropertyDescriptor(r,`shape`);if(t?.get){if(t.set||!te.has(Function.prototype.toString.call(t.get)))throw Error(`Unsupported DTO schema accessor`);let e=r.shape;o(e,s+1),a.add(r)}if(e instanceof u.ZodObject){let t=Object.getOwnPropertyDescriptor(e,`shape`);if(t&&!(`value`in t))throw Error(`Unsupported DTO schema accessor`);o(e.shape,s+1)}}o(r,s+1);return}let i=Reflect.ownKeys(e),c=i.map(t=>Object.getOwnPropertyDescriptor(e,t));if(c.some((t,r)=>!(`value`in t)&&!(a.has(e)&&i[r]===`shape`)&&!(n.has(e)&&i[r]===`defaultValue`)))throw Error(`Unsupported DTO schema accessor`);for(let e of c)e.value!==null&&Object(e.value)===e.value&&!(e.value instanceof Function)&&o(e.value,s+1)}finally{i.delete(e)}}}o(e,0)}function ie(e){let t={};for(let[n,r]of Object.entries(e.metadata)){let e={};for(let[t,n]of Object.entries(r.fields))e[t]=Object.freeze({kind:n.kind,optional:n.isOptional===`optional`,nullable:Q(n),idTables:Object.freeze($(n)),native:ae(K(n))});t[n]=Object.freeze({fieldGroups:r.fieldGroups,searchIndexes:r.searchIndexes,fields:Object.freeze(e),variant:r.branches?Object.freeze({discriminator:r.branches.discriminator,tags:Object.freeze(Object.keys(r.branches.options))}):void 0,indexes:Object.freeze(r.indexes.map(e=>Object.freeze({name:e.name,fields:Object.freeze([...e.fields])})))})}return Object.freeze({tables:Object.freeze(t),declarations:e.declarations})}function Q(e){return e.kind===`null`||e.kind===`union`&&e.members.some(Q)}function $(e){return e.kind===`id`?[e.tableName]:e.kind===`union`?[...new Set(e.members.flatMap($))].sort():[]}function ae(e){let t=structuredClone(e),n=[t];for(;n.length;){let e=n.pop();if(Object(e)!==e)continue;let t=e;Object.freeze(t),n.push(...Object.values(t))}return t}export{C as defineRelations,w as getRelationExecutor,T as getRelationMetadata};
2
2
  //# sourceMappingURL=relations.mjs.map