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.
- package/README.md +50 -2
- package/dist/errors.d.mts +3 -2
- package/dist/errors.mjs +1 -1
- package/dist/errors.mjs.map +1 -1
- package/dist/filters.d.mts +4 -0
- package/dist/filters.mjs +1 -0
- package/dist/index.d.mts +3 -3
- package/dist/modules/contracts/errors.d.mts +218 -0
- package/dist/modules/contracts/errors.mjs +1 -1
- package/dist/modules/contracts/errors.mjs.map +1 -1
- package/dist/modules/effect/crud.d.mts +28 -0
- package/dist/querying/cursors.d.mts +30 -4
- package/dist/querying/cursors.mjs +1 -1
- package/dist/querying/cursors.mjs.map +1 -1
- package/dist/querying/execution.d.mts +14 -3
- package/dist/querying/execution.mjs +1 -1
- package/dist/querying/execution.mjs.map +1 -1
- package/dist/querying/failures.d.mts +13 -0
- package/dist/querying/failures.mjs +2 -0
- package/dist/querying/failures.mjs.map +1 -0
- package/dist/querying/filters.d.mts +43 -44
- package/dist/querying/filters.mjs +1 -1
- package/dist/querying/filters.mjs.map +1 -1
- package/dist/querying/planner.d.mts +13 -16
- package/dist/querying/planner.mjs +1 -1
- package/dist/querying/planner.mjs.map +1 -1
- package/dist/querying/relationships.d.mts +24 -7
- package/dist/querying/relationships.mjs +1 -1
- package/dist/querying/relationships.mjs.map +1 -1
- package/dist/querying/schema-snapshot.d.mts +29 -0
- package/dist/querying/schema-snapshot.mjs +2 -0
- package/dist/querying/schema-snapshot.mjs.map +1 -0
- package/dist/querying/search.d.mts +69 -0
- package/dist/querying/search.mjs +2 -0
- package/dist/querying/search.mjs.map +1 -0
- package/dist/querying/security.d.mts +19 -2
- package/dist/querying/security.mjs +1 -1
- package/dist/querying/security.mjs.map +1 -1
- package/dist/querying/shared/ast.d.mts +28 -0
- package/dist/querying/shared/ast.mjs +2 -0
- package/dist/querying/shared/ast.mjs.map +1 -0
- package/dist/querying/shared/contract.d.mts +104 -0
- package/dist/querying/shared/contract.mjs +2 -0
- package/dist/querying/shared/contract.mjs.map +1 -0
- package/dist/querying/shared/evaluate.d.mts +7 -0
- package/dist/querying/shared/evaluate.mjs +2 -0
- package/dist/querying/shared/evaluate.mjs.map +1 -0
- package/dist/querying/shared/filters.d.mts +31 -0
- package/dist/querying/shared/filters.mjs +2 -0
- package/dist/querying/shared/filters.mjs.map +1 -0
- package/dist/querying.d.mts +47 -16
- package/dist/querying.mjs +1 -1
- package/dist/querying.mjs.map +1 -1
- package/dist/react/failures.d.mts +23 -0
- package/dist/react/failures.mjs +2 -0
- package/dist/react/failures.mjs.map +1 -0
- package/dist/react/optimistic.d.mts +47 -0
- package/dist/react/optimistic.mjs +2 -0
- package/dist/react/optimistic.mjs.map +1 -0
- package/dist/react/pagination-state.d.mts +40 -0
- package/dist/react/pagination-state.mjs +2 -0
- package/dist/react/pagination-state.mjs.map +1 -0
- package/dist/react/use-command.d.mts +23 -0
- package/dist/react/use-command.mjs +2 -0
- package/dist/react/use-command.mjs.map +1 -0
- package/dist/react/use-paginated-list.d.mts +32 -0
- package/dist/react/use-paginated-list.mjs +2 -0
- package/dist/react/use-paginated-list.mjs.map +1 -0
- package/dist/react.d.mts +6 -0
- package/dist/react.mjs +1 -0
- package/dist/relations-public.d.mts +2 -2
- package/dist/relations.d.mts +65 -22
- package/dist/relations.mjs +1 -1
- package/dist/relations.mjs.map +1 -1
- package/dist/zod-convex.mjs +1 -1
- package/dist/zod-convex.mjs.map +1 -1
- package/dist/zod-table.d.mts +15 -1
- package/dist/zod-table.mjs +1 -1
- package/dist/zod-table.mjs.map +1 -1
- 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"}
|
package/dist/react.d.mts
ADDED
|
@@ -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 };
|
package/dist/relations.d.mts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import {
|
|
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 {
|
|
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 :
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
198
|
-
|
|
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;
|
package/dist/relations.mjs
CHANGED
|
@@ -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
|