@gaganref/confect-core 10.3.1-fork.75 → 10.3.1-fork.77

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.
@@ -8,6 +8,7 @@ import * as Ref from "./Ref.js";
8
8
  import type * as Refs from "./Refs.js";
9
9
  import type * as RuntimeAndFunctionType from "./RuntimeAndFunctionType.js";
10
10
  import * as Spec from "./Spec.js";
11
+ import type * as Table_ from "./Table.js";
11
12
  declare const EmptyComponentScopeError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
12
13
  readonly _tag: "EmptyComponentScopeError";
13
14
  } & Readonly<A>;
@@ -56,14 +57,60 @@ export type Api<Spec_ extends Spec.AnyWithProps, Name extends string | undefined
56
57
  interface Tree {
57
58
  readonly [key: string]: Tree | Ref.Any;
58
59
  }
59
- export interface Component<Spec_ extends Spec.AnyWithProps, Scope extends IdScope.IdScope, Tables extends string = string> {
60
+ /**
61
+ * Each grouped table's name, mapped to its id field and that id's table.
62
+ */
63
+ export interface GroupMap {
64
+ readonly [table: string]: {
65
+ readonly key: string;
66
+ readonly table: string;
67
+ };
68
+ }
69
+ export interface Component<Spec_ extends Spec.AnyWithProps, Scope extends IdScope.IdScope, Tables extends string = string, Groups_ extends GroupMap = GroupMap> {
60
70
  readonly [TypeId]: {
61
71
  readonly refs: Tree;
62
72
  readonly scope: Scope;
63
73
  readonly tables: ReadonlyArray<Tables>;
74
+ readonly groups: Groups_;
64
75
  };
65
76
  readonly "~Spec": Spec_;
66
77
  }
78
+ /**
79
+ * A component's tables as `contract` takes them: a table, or the name of a
80
+ * system table.
81
+ */
82
+ export type TableEntry = string | Table_.AnyWithProps;
83
+ type EntryName<Entry extends TableEntry> = Entry extends string ? Entry : Entry extends Table_.AnyWithProps ? Table_.Name<Entry> : never;
84
+ type Many<A, All = A> = string extends A ? true : number extends A ? true : A extends unknown ? [All] extends [A] ? never : true : never;
85
+ type Loose<Entries extends ReadonlyArray<TableEntry>> = true extends Many<Entries> | Many<Entries["length"]> | {
86
+ [Index in keyof Entries]: Many<Entries[Index]>;
87
+ }[number] ? "pass one table or one name per entry; a union may be absent at runtime" : never;
88
+ type StrayGroup<Entries extends ReadonlyArray<TableEntry>, Scope extends IdScope.IdScope> = [Loose<Entries>] extends [never] ? {
89
+ [Index in keyof Entries]: Entries[Index] extends {
90
+ readonly tableName: infer Name extends string;
91
+ readonly group: Table_.Group<infer Key, infer Target, infer GroupScope>;
92
+ } ? [Target, GroupScope] extends [EntryName<Entries[number]>, Scope] ? never : `${Name}.${Key} is not an id of a table of this component` : never;
93
+ }[number] : Loose<Entries>;
94
+ /**
95
+ * The group map `contract` publishes for these table entries.
96
+ */
97
+ export type Groups<Entries extends ReadonlyArray<TableEntry>> = {
98
+ readonly [Entry in Extract<Entries[number], {
99
+ readonly tableName: string;
100
+ readonly group: Table_.Group;
101
+ }> as Entry["tableName"]]: {
102
+ readonly key: Entry["group"]["key"];
103
+ readonly table: Entry["group"]["table"];
104
+ };
105
+ };
106
+ /**
107
+ * `unknown` when every entry is one table or name and every group's id names a
108
+ * table of this component in its scope, otherwise an object type naming the
109
+ * refused entry.
110
+ */
111
+ export type CheckGroups<Entries extends ReadonlyArray<TableEntry>, Scope extends IdScope.IdScope> = [StrayGroup<Entries, Scope>] extends [never] ? unknown : {
112
+ readonly "~StrayGroup": StrayGroup<Entries, Scope>;
113
+ };
67
114
  /**
68
115
  * An opaque identity: its string representation is not part of the API.
69
116
  */
@@ -87,8 +134,18 @@ export type Bound<Spec_ extends Spec.AnyWithProps, From extends IdScope.IdScope,
87
134
  };
88
135
  /**
89
136
  * Build a publishable contract containing only exported functions and codecs.
137
+ * `tables` lists the component's tables, each a table or a system table's name.
138
+ * A table grouped by an id must group by an id of one of these tables.
139
+ */
140
+ export declare function contract<Spec_ extends Spec.AnyWithProps, const Scope extends IdScope.IdScope, const Entries extends ReadonlyArray<TableEntry>>(spec: Spec_, scope: Scope, tables: Entries & CheckGroups<Entries, Scope>): Component<Spec_, Scope, EntryName<Entries[number]>, Groups<Entries>>;
141
+ /**
142
+ * Table names alone, as in an explicit third type argument, carry no groups.
143
+ */
144
+ export declare function contract<Spec_ extends Spec.AnyWithProps, const Scope extends IdScope.IdScope, const Tables extends string>(spec: Spec_, scope: Scope, tables: ReadonlyArray<Tables>): Component<Spec_, Scope, Tables, {}>;
145
+ /**
146
+ * Each grouped table's id field and the table that id names.
90
147
  */
91
- export declare const contract: <Spec_ extends Spec.AnyWithProps, const Scope extends IdScope.IdScope, const Tables extends string>(spec: Spec_, scope: Scope, tables: ReadonlyArray<Tables>) => Component<Spec_, Scope, Tables>;
148
+ export declare const groups: <Groups_ extends GroupMap>(component: Component<Spec.AnyWithProps, IdScope.IdScope, string, Groups_>) => Groups_;
92
149
  /**
93
150
  * Bind the published contract to an actual installed component reference.
94
151
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Component.d.ts","sourceRoot":"","sources":["../src/Component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Component.d.ts","sourceRoot":"","sources":["../src/Component.ts"],"names":[],"mappings":"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"}
package/dist/Component.js CHANGED
@@ -3,7 +3,7 @@ import { defineProperty } from "./Lazy.js";
3
3
  import { app, instance } from "./IdScope.js";
4
4
  import { GenericId, rebase } from "./GenericId.js";
5
5
  import { fromProvenance, isRef, make as make$1 } from "./Ref.js";
6
- import { groups } from "./Spec.js";
6
+ import { groups as groups$1 } from "./Spec.js";
7
7
  import * as Schema from "effect/Schema";
8
8
  import * as Data from "effect/Data";
9
9
  import { getFunctionAddress } from "convex/server";
@@ -19,6 +19,7 @@ var Component_exports = /* @__PURE__ */ __exportAll({
19
19
  UninstalledComponentReferenceError: () => UninstalledComponentReferenceError,
20
20
  bind: () => bind,
21
21
  contract: () => contract,
22
+ groups: () => groups,
22
23
  id: () => id,
23
24
  make: () => make,
24
25
  schema: () => schema
@@ -53,11 +54,8 @@ const validateNames = (groups, prefix = "") => {
53
54
  const validateContract = (scope, groups) => scope === "" ? Result.fail(new EmptyComponentScopeError({ definitionScope: scope })) : validateNames(groups);
54
55
  const TypeId = "~@confect/core/Component";
55
56
  const BoundTypeId = "~@confect/core/BoundComponent";
56
- /**
57
- * Build a publishable contract containing only exported functions and codecs.
58
- */
59
- const contract = (spec, scope, tables) => {
60
- const specGroups = groups(spec);
57
+ function contract(spec, scope, tables) {
58
+ const specGroups = groups$1(spec);
61
59
  Result.getOrThrow(validateContract(scope, specGroups));
62
60
  const collect = (groups, prefix = "") => pipe(groups, Record.map((group, name) => {
63
61
  const path = prefix === "" ? name : `${prefix}/${name}`;
@@ -69,12 +67,22 @@ const contract = (spec, scope, tables) => {
69
67
  ...functions
70
68
  };
71
69
  }), Record.filter((children) => !Record.isEmptyRecord(children)));
72
- return { [TypeId]: {
70
+ const grouped = pipe(tables, Array.flatMap((entry) => typeof entry !== "string" && entry.group !== void 0 ? [[entry.tableName, entry.group]] : []), Record.fromEntries);
71
+ const published = {
73
72
  refs: collect(specGroups),
74
73
  scope,
75
- tables
76
- } };
77
- };
74
+ tables: Array.map(tables, (entry) => typeof entry === "string" ? entry : entry.tableName),
75
+ groups: grouped
76
+ };
77
+ return { [TypeId]: published };
78
+ }
79
+ /**
80
+ * Each grouped table's id field and the table that id names.
81
+ */
82
+ const groups = (component) => Record.map(component[TypeId].groups, ({ key, table }) => ({
83
+ key,
84
+ table
85
+ }));
78
86
  /**
79
87
  * Bind the published contract to an actual installed component reference.
80
88
  */
@@ -159,6 +167,6 @@ const make = (name, options) => ({
159
167
  name
160
168
  });
161
169
  //#endregion
162
- export { ComponentNameCollisionError, Component_exports, EmptyComponentScopeError, UninstalledComponentReferenceError, bind, contract, id, make, schema };
170
+ export { ComponentNameCollisionError, Component_exports, EmptyComponentScopeError, UninstalledComponentReferenceError, bind, contract, groups, id, make, schema };
163
171
 
164
172
  //# sourceMappingURL=Component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Component.js","names":["Spec.groups","Ref.make","IdScope.instance","IdScope.app","rebase","GenericId.rebase","Ref.isRef","Ref.fromProvenance","GenericId.GenericId"],"sources":["../src/Component.ts"],"sourcesContent":["import type { DefaultFunctionArgs, FunctionReference } from \"convex/server\";\nimport { getFunctionAddress } from \"convex/server\";\nimport * as Array from \"effect/Array\";\nimport * as Data from \"effect/Data\";\nimport * as Result from \"effect/Result\";\nimport { memoize, pipe } from \"effect/Function\";\nimport * as Match from \"effect/Match\";\nimport * as Record from \"effect/Record\";\nimport * as Schema from \"effect/Schema\";\nimport type * as FunctionProvenance from \"./FunctionProvenance.js\";\nimport type * as FunctionSpec from \"./FunctionSpec.js\";\nimport * as GenericId from \"./GenericId.js\";\nimport type * as GroupSpec from \"./GroupSpec.js\";\nimport * as IdScope from \"./IdScope.js\";\nimport * as Lazy from \"./Lazy.js\";\nimport type * as MiddlewareSpec from \"./MiddlewareSpec.js\";\nimport * as Ref from \"./Ref.js\";\nimport type * as Refs from \"./Refs.js\";\nimport type * as RuntimeAndFunctionType from \"./RuntimeAndFunctionType.js\";\nimport * as Spec from \"./Spec.js\";\n\nexport class EmptyComponentScopeError extends Data.TaggedError(\n \"EmptyComponentScopeError\",\n)<{\n readonly definitionScope: IdScope.IdScope;\n}> {\n override get message(): string {\n return \"A component contract requires a nonempty definition scope.\";\n }\n}\n\nexport class ComponentNameCollisionError extends Data.TaggedError(\n \"ComponentNameCollisionError\",\n)<{\n readonly groupPath: string;\n readonly functionName: string;\n}> {\n override get message(): string {\n return `Group and function at same level have same name ('${this.groupPath}:${this.functionName}')`;\n }\n}\n\nexport class UninstalledComponentReferenceError extends Data.TaggedError(\n \"UninstalledComponentReferenceError\",\n)<{\n readonly definitionScope: IdScope.IdScope;\n}> {\n override get message(): string {\n return \"Component.bind expects an installed component from the generated components registry.\";\n }\n}\n\nconst validateNames = (\n groups: Readonly<Record<string, GroupSpec.AnyWithProps>>,\n prefix = \"\",\n): Result.Result<void, ComponentNameCollisionError> => {\n for (const [name, group] of Record.toEntries(groups)) {\n const path = prefix === \"\" ? name : `${prefix}/${name}`;\n for (const functionSpec of Record.values(group.functions)) {\n if (Record.has(group.groups, functionSpec.name)) {\n return Result.fail(\n new ComponentNameCollisionError({\n groupPath: path,\n functionName: functionSpec.name,\n }),\n );\n }\n }\n const nested = validateNames(group.groups, path);\n if (Result.isFailure(nested)) return nested;\n }\n return Result.succeed(undefined);\n};\n\nconst validateContract = (\n scope: IdScope.IdScope,\n groups: Readonly<Record<string, GroupSpec.AnyWithProps>>,\n): Result.Result<\n void,\n EmptyComponentScopeError | ComponentNameCollisionError\n> =>\n scope === \"\"\n ? Result.fail(new EmptyComponentScopeError({ definitionScope: scope }))\n : validateNames(groups);\n\nconst TypeId = \"~@confect/core/Component\";\nconst BoundTypeId = \"~@confect/core/BoundComponent\";\n\n/**\n * Convex's generated ComponentApi erases database ID brands at the boundary.\n */\ntype Wire<A> = A extends { readonly __tableName: string }\n ? string\n : A extends\n | string\n | number\n | bigint\n | boolean\n | null\n | undefined\n | ArrayBuffer\n ? A\n : { [K in keyof A]: Wire<A[K]> };\n\ntype OmitEmpty<A> = {\n [K in keyof A as keyof A[K] extends never ? never : K]: A[K];\n};\ntype ApiGroups<\n GroupSpec_ extends GroupSpec.AnyWithProps,\n Name extends string | undefined,\n> = OmitEmpty<{\n [GroupName in GroupSpec.Name<GroupSpec_>]: ApiGroup<\n GroupSpec.WithName<GroupSpec_, GroupName>,\n Name\n >;\n}>;\ntype ApiGroup<\n GroupSpec_ extends GroupSpec.AnyWithProps,\n Name extends string | undefined,\n> = ApiGroups<GroupSpec.Groups<GroupSpec_>, Name> & {\n [\n FunctionSpec_ in GroupSpec.Functions<GroupSpec_> as FunctionSpec.GetFunctionVisibility<FunctionSpec_> extends \"public\"\n ? FunctionSpec.Name<FunctionSpec_>\n : never\n ]: FunctionReference<\n RuntimeAndFunctionType.GetFunctionType<\n FunctionSpec_[\"runtimeAndFunctionType\"]\n >,\n \"internal\",\n Extract<Wire<FunctionSpec.EncodedArgs<FunctionSpec_>>, DefaultFunctionArgs>,\n Wire<FunctionSpec.EncodedReturns<FunctionSpec_>>,\n Name\n >;\n};\n\nexport type Api<\n Spec_ extends Spec.AnyWithProps,\n Name extends string | undefined = string | undefined,\n> = ApiGroups<Spec.Groups<Spec_>, Name>;\n\ninterface Tree {\n readonly [key: string]: Tree | Ref.Any;\n}\n\nexport interface Component<\n Spec_ extends Spec.AnyWithProps,\n Scope extends IdScope.IdScope,\n Tables extends string = string,\n> {\n readonly [TypeId]: {\n readonly refs: Tree;\n readonly scope: Scope;\n readonly tables: ReadonlyArray<Tables>;\n };\n readonly \"~Spec\": Spec_;\n}\n\n/**\n * An opaque identity: its string representation is not part of the API.\n */\nexport type MountScope<\n Parent extends IdScope.IdScope,\n Name extends string | undefined,\n> = IdScope.Mount<Parent, Name>;\n\ntype MountName<ComponentApi> =\n ComponentApi extends FunctionReference<any, any, any, any, infer Name>\n ? Name\n : ComponentApi extends object\n ? {\n [Key in keyof ComponentApi]: MountName<ComponentApi[Key]>;\n }[keyof ComponentApi]\n : never;\n\ntype BindRefs<\n RefTree,\n From extends IdScope.IdScope,\n To extends IdScope.IdScope,\n> = RefTree extends Ref.Any\n ? RefTree extends { readonly _tag: \"Convex\" }\n ? Ref.ConvexRef<\n Ref.GetRuntimeAndFunctionType<RefTree>,\n \"internal\",\n Extract<Wire<Ref.Args<RefTree>>, DefaultFunctionArgs>,\n Wire<Ref.Returns<RefTree>>\n >\n : Extract<\n Ref.Ref<\n Ref.GetRuntimeAndFunctionType<RefTree>,\n \"internal\",\n Extract<\n GenericId.Rebase<Ref.Args<RefTree>, From, To>,\n DefaultFunctionArgs\n >,\n GenericId.Rebase<Ref.Returns<RefTree>, From, To>,\n GenericId.Rebase<Ref.Error<RefTree>, From, To>\n >,\n { readonly _tag: RefTree[\"_tag\"] }\n >\n : { [Key in keyof RefTree]: BindRefs<RefTree[Key], From, To> };\n\nexport type Bound<\n Spec_ extends Spec.AnyWithProps,\n From extends IdScope.IdScope,\n To extends IdScope.IdScope,\n Tables extends string,\n> = BindRefs<Refs.Refs<Spec_, Ref.AnyPublic>, From, To> & {\n readonly [BoundTypeId]: {\n readonly from: From;\n readonly scope: To;\n readonly tables: ReadonlyArray<Tables>;\n };\n};\n\n/**\n * Build a publishable contract containing only exported functions and codecs.\n */\nexport const contract = <\n Spec_ extends Spec.AnyWithProps,\n const Scope extends IdScope.IdScope,\n const Tables extends string,\n>(\n spec: Spec_,\n scope: Scope,\n tables: ReadonlyArray<Tables>,\n): Component<Spec_, Scope, Tables> => {\n const specGroups = Spec.groups(spec);\n Result.getOrThrow(validateContract(scope, specGroups));\n const collect = (\n groups: Readonly<Record<string, GroupSpec.AnyWithProps>>,\n prefix = \"\",\n ): Tree =>\n pipe(\n groups,\n Record.map((group, name) => {\n const path = prefix === \"\" ? name : `${prefix}/${name}`;\n const functions = pipe(\n group.functions,\n Record.filter((functionSpec) => {\n return Match.value(functionSpec.functionVisibility).pipe(\n Match.when(\"public\", () => true),\n Match.when(\"internal\", () => false),\n Match.exhaustive,\n );\n }),\n Record.map((functionSpec) =>\n Ref.make(path, functionSpec, group.middlewareAttachments),\n ),\n );\n return { ...collect(group.groups, path), ...functions };\n }),\n Record.filter((children) => !Record.isEmptyRecord(children)),\n );\n return {\n [TypeId]: { refs: collect(specGroups), scope, tables },\n } as Component<Spec_, Scope, Tables>;\n};\n\n/**\n * Bind the published contract to an actual installed component reference.\n */\nexport const bind = <\n Spec_ extends Spec.AnyWithProps,\n From extends IdScope.IdScope,\n Tables extends string,\n Native extends Api<NoInfer<Spec_>>,\n const Parent extends IdScope.IdScope = IdScope.App,\n>(\n component: Component<Spec_, From, Tables>,\n native: Native,\n options?: { readonly parentScope: Parent },\n): Bound<\n Spec_,\n From,\n MountScope<Parent, Extract<MountName<Native>, string | undefined>>,\n Tables\n> => {\n const published = component[TypeId];\n const address = getFunctionAddress(native);\n const installedReference = Result.getOrThrow(\n Result.fromNullishOr(\n address.reference,\n () =>\n new UninstalledComponentReferenceError({\n definitionScope: published.scope,\n }),\n ),\n );\n // Preserve the opaque address as an identity only. Calls retain the native\n // references; no component address is constructed or parsed for routing.\n const scope = IdScope.instance(\n options?.parentScope ?? IdScope.app,\n installedReference,\n );\n const rebase = (schema: Schema.ConstraintCodec<any, any, never, never>) =>\n GenericId.rebase(schema, published.scope, scope);\n const rebaseMiddleware = memoize(\n (middleware: MiddlewareSpec.AnyMiddlewareSpec) => {\n if (!(\"error\" in middleware)) return middleware;\n const boundMiddleware = Object.create(\n middleware,\n ) as MiddlewareSpec.AnyMiddlewareSpec;\n Lazy.defineProperty(boundMiddleware, \"error\", () => {\n const error = middleware.error;\n return error === undefined ? undefined : rebase(error);\n });\n return boundMiddleware;\n },\n );\n const visit = (tree: Tree, references: unknown): Tree =>\n Record.map(tree, (child, key) => {\n const reference = (references as Record<string, unknown>)[key];\n if (Ref.isRef(child)) {\n const nativeRef = reference as FunctionReference<any, any>;\n return Match.value(child).pipe(\n Match.tag(\"Convex\", (ref) => ({\n ...ref,\n functionReference: nativeRef,\n })),\n Match.tag(\"Confect\", (ref) => {\n const provenance = {\n _tag: \"Confect\" as const,\n kind: Match.value(ref.kind).pipe(\n Match.tag(\"Standard\", (kind) => kind),\n Match.tag(\"Paginated\", (kind) => {\n const boundKind = { _tag: \"Paginated\" as const };\n Lazy.defineProperty(boundKind, \"userArgs\", () =>\n Schema.Struct(Record.map(kind.userArgs.fields, rebase)),\n );\n Lazy.defineProperty(boundKind, \"item\", () =>\n rebase(kind.item),\n );\n Lazy.defineProperty(boundKind, \"page\", () =>\n rebase(kind.page),\n );\n return boundKind as FunctionProvenance.Paginated;\n }),\n Match.exhaustive,\n ),\n };\n Lazy.defineProperty(provenance, \"args\", () =>\n Schema.Struct(Record.map(ref.args.fields, rebase)),\n );\n Lazy.defineProperty(provenance, \"returns\", () =>\n rebase(ref.returns),\n );\n if (\"error\" in ref) {\n Lazy.defineProperty(provenance, \"error\", () => {\n const error = ref.error;\n return error === undefined ? undefined : rebase(error);\n });\n }\n return Ref.fromProvenance(\n ref.convexFunctionName,\n provenance as FunctionProvenance.AnyConfect,\n Array.map(ref.middlewareAttachments, (attachment) => ({\n ...attachment,\n spec: rebaseMiddleware(attachment.spec),\n })),\n nativeRef,\n ref.functionType,\n ref.reservedArgument,\n );\n }),\n Match.exhaustive,\n );\n } else {\n return visit(child, reference);\n }\n });\n const refs = visit(published.refs, native);\n Object.defineProperty(refs, BoundTypeId, {\n value: { from: published.scope, scope, tables: published.tables },\n });\n return refs as Bound<\n Spec_,\n From,\n MountScope<Parent, Extract<MountName<Native>, string | undefined>>,\n Tables\n >;\n};\n\n/**\n * Reference an installed component's table ID in host schemas.\n */\nexport const id = <\n From extends IdScope.IdScope,\n To extends IdScope.IdScope,\n Tables extends string,\n const Table extends Tables,\n>(\n component: {\n readonly [BoundTypeId]: {\n readonly from: From;\n readonly scope: To;\n readonly tables: ReadonlyArray<Tables>;\n };\n },\n table: Table,\n) => GenericId.GenericId(table, component[BoundTypeId].scope);\n\n/**\n * Reuse a component's codec in a host function or table without losing its\n * scope.\n */\nexport const schema = <\n From extends IdScope.IdScope,\n To extends IdScope.IdScope,\n Schema_ extends Schema.Codec<any, any>,\n>(\n component: {\n readonly [BoundTypeId]: { readonly from: From; readonly scope: To };\n },\n codec: Schema_,\n) =>\n GenericId.rebase(\n codec,\n component[BoundTypeId].from,\n component[BoundTypeId].scope,\n );\n\n/**\n * A component's `init`: an internal Confect mutation whose args are the install\n * args each mount passes.\n */\nexport type Init = Ref.AnyConfect & {\n readonly \"~RuntimeAndFunctionType\": RuntimeAndFunctionType.ConvexMutation;\n readonly \"~FunctionVisibility\": \"internal\";\n};\n\nexport interface DescriptorOptions {\n readonly init?: Init;\n /**\n * The component's `_generated/component` contract. A mount of a descriptor\n * with one rebases a callback slot's args with `callbackArgs`.\n */\n readonly contract?: Component<Spec.AnyWithProps, IdScope.IdScope, string>;\n readonly env?: Readonly<Record<string, Schema.Top>>;\n /**\n * Builds the component's client from its native mount, then the mount's\n * `options` when the client takes any.\n */\n readonly client: (...args: never) => unknown;\n}\n\nexport type Descriptor<\n Name extends string = string,\n Options extends DescriptorOptions = DescriptorOptions,\n> = Options & { readonly name: Name };\n\n/**\n * Describe a Convex component for `Mount.make`, as `defineComponent` does for\n * Convex. A component with `init` takes install `args` at each mount, and one\n * with `env` takes `env`. Export it from the package's `./client` entry.\n *\n * ```ts\n * export default Component.make(\"email\", {\n * init: refs.internal.install.init,\n * env: { RESEND_API_KEY: Schema.String },\n * client: Client.make,\n * });\n * ```\n */\nexport const make = <\n const Name extends string,\n const Options extends DescriptorOptions,\n>(\n name: Name,\n options: Options,\n): Descriptor<Name, Options> => ({ ...options, name });\n"],"mappings":"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"}
1
+ {"version":3,"file":"Component.js","names":["Spec.groups","Ref.make","IdScope.instance","IdScope.app","rebase","GenericId.rebase","Ref.isRef","Ref.fromProvenance","GenericId.GenericId"],"sources":["../src/Component.ts"],"sourcesContent":["import type { DefaultFunctionArgs, FunctionReference } from \"convex/server\";\nimport { getFunctionAddress } from \"convex/server\";\nimport * as Array from \"effect/Array\";\nimport * as Data from \"effect/Data\";\nimport * as Result from \"effect/Result\";\nimport { memoize, pipe } from \"effect/Function\";\nimport * as Match from \"effect/Match\";\nimport * as Record from \"effect/Record\";\nimport * as Schema from \"effect/Schema\";\nimport type * as FunctionProvenance from \"./FunctionProvenance.js\";\nimport type * as FunctionSpec from \"./FunctionSpec.js\";\nimport * as GenericId from \"./GenericId.js\";\nimport type * as GroupSpec from \"./GroupSpec.js\";\nimport * as IdScope from \"./IdScope.js\";\nimport * as Lazy from \"./Lazy.js\";\nimport type * as MiddlewareSpec from \"./MiddlewareSpec.js\";\nimport * as Ref from \"./Ref.js\";\nimport type * as Refs from \"./Refs.js\";\nimport type * as RuntimeAndFunctionType from \"./RuntimeAndFunctionType.js\";\nimport * as Spec from \"./Spec.js\";\nimport type * as Table_ from \"./Table.js\";\n\nexport class EmptyComponentScopeError extends Data.TaggedError(\n \"EmptyComponentScopeError\",\n)<{\n readonly definitionScope: IdScope.IdScope;\n}> {\n override get message(): string {\n return \"A component contract requires a nonempty definition scope.\";\n }\n}\n\nexport class ComponentNameCollisionError extends Data.TaggedError(\n \"ComponentNameCollisionError\",\n)<{\n readonly groupPath: string;\n readonly functionName: string;\n}> {\n override get message(): string {\n return `Group and function at same level have same name ('${this.groupPath}:${this.functionName}')`;\n }\n}\n\nexport class UninstalledComponentReferenceError extends Data.TaggedError(\n \"UninstalledComponentReferenceError\",\n)<{\n readonly definitionScope: IdScope.IdScope;\n}> {\n override get message(): string {\n return \"Component.bind expects an installed component from the generated components registry.\";\n }\n}\n\nconst validateNames = (\n groups: Readonly<Record<string, GroupSpec.AnyWithProps>>,\n prefix = \"\",\n): Result.Result<void, ComponentNameCollisionError> => {\n for (const [name, group] of Record.toEntries(groups)) {\n const path = prefix === \"\" ? name : `${prefix}/${name}`;\n for (const functionSpec of Record.values(group.functions)) {\n if (Record.has(group.groups, functionSpec.name)) {\n return Result.fail(\n new ComponentNameCollisionError({\n groupPath: path,\n functionName: functionSpec.name,\n }),\n );\n }\n }\n const nested = validateNames(group.groups, path);\n if (Result.isFailure(nested)) return nested;\n }\n return Result.succeed(undefined);\n};\n\nconst validateContract = (\n scope: IdScope.IdScope,\n groups: Readonly<Record<string, GroupSpec.AnyWithProps>>,\n): Result.Result<\n void,\n EmptyComponentScopeError | ComponentNameCollisionError\n> =>\n scope === \"\"\n ? Result.fail(new EmptyComponentScopeError({ definitionScope: scope }))\n : validateNames(groups);\n\nconst TypeId = \"~@confect/core/Component\";\nconst BoundTypeId = \"~@confect/core/BoundComponent\";\n\n/**\n * Convex's generated ComponentApi erases database ID brands at the boundary.\n */\ntype Wire<A> = A extends { readonly __tableName: string }\n ? string\n : A extends\n | string\n | number\n | bigint\n | boolean\n | null\n | undefined\n | ArrayBuffer\n ? A\n : { [K in keyof A]: Wire<A[K]> };\n\ntype OmitEmpty<A> = {\n [K in keyof A as keyof A[K] extends never ? never : K]: A[K];\n};\ntype ApiGroups<\n GroupSpec_ extends GroupSpec.AnyWithProps,\n Name extends string | undefined,\n> = OmitEmpty<{\n [GroupName in GroupSpec.Name<GroupSpec_>]: ApiGroup<\n GroupSpec.WithName<GroupSpec_, GroupName>,\n Name\n >;\n}>;\ntype ApiGroup<\n GroupSpec_ extends GroupSpec.AnyWithProps,\n Name extends string | undefined,\n> = ApiGroups<GroupSpec.Groups<GroupSpec_>, Name> & {\n [\n FunctionSpec_ in GroupSpec.Functions<GroupSpec_> as FunctionSpec.GetFunctionVisibility<FunctionSpec_> extends \"public\"\n ? FunctionSpec.Name<FunctionSpec_>\n : never\n ]: FunctionReference<\n RuntimeAndFunctionType.GetFunctionType<\n FunctionSpec_[\"runtimeAndFunctionType\"]\n >,\n \"internal\",\n Extract<Wire<FunctionSpec.EncodedArgs<FunctionSpec_>>, DefaultFunctionArgs>,\n Wire<FunctionSpec.EncodedReturns<FunctionSpec_>>,\n Name\n >;\n};\n\nexport type Api<\n Spec_ extends Spec.AnyWithProps,\n Name extends string | undefined = string | undefined,\n> = ApiGroups<Spec.Groups<Spec_>, Name>;\n\ninterface Tree {\n readonly [key: string]: Tree | Ref.Any;\n}\n\n/**\n * Each grouped table's name, mapped to its id field and that id's table.\n */\nexport interface GroupMap {\n readonly [table: string]: { readonly key: string; readonly table: string };\n}\n\nexport interface Component<\n Spec_ extends Spec.AnyWithProps,\n Scope extends IdScope.IdScope,\n Tables extends string = string,\n Groups_ extends GroupMap = GroupMap,\n> {\n readonly [TypeId]: {\n readonly refs: Tree;\n readonly scope: Scope;\n readonly tables: ReadonlyArray<Tables>;\n readonly groups: Groups_;\n };\n readonly \"~Spec\": Spec_;\n}\n\n/**\n * A component's tables as `contract` takes them: a table, or the name of a\n * system table.\n */\nexport type TableEntry = string | Table_.AnyWithProps;\n\ntype EntryName<Entry extends TableEntry> = Entry extends string\n ? Entry\n : Entry extends Table_.AnyWithProps\n ? Table_.Name<Entry>\n : never;\n\ntype Many<A, All = A> = string extends A\n ? true\n : number extends A\n ? true\n : A extends unknown\n ? [All] extends [A]\n ? never\n : true\n : never;\n\ntype Loose<Entries extends ReadonlyArray<TableEntry>> = true extends\n | Many<Entries>\n | Many<Entries[\"length\"]>\n | { [Index in keyof Entries]: Many<Entries[Index]> }[number]\n ? \"pass one table or one name per entry; a union may be absent at runtime\"\n : never;\n\ntype StrayGroup<\n Entries extends ReadonlyArray<TableEntry>,\n Scope extends IdScope.IdScope,\n> = [Loose<Entries>] extends [never]\n ? {\n [Index in keyof Entries]: Entries[Index] extends {\n readonly tableName: infer Name extends string;\n readonly group: Table_.Group<infer Key, infer Target, infer GroupScope>;\n }\n ? [Target, GroupScope] extends [EntryName<Entries[number]>, Scope]\n ? never\n : `${Name}.${Key} is not an id of a table of this component`\n : never;\n }[number]\n : Loose<Entries>;\n\n/**\n * The group map `contract` publishes for these table entries.\n */\nexport type Groups<Entries extends ReadonlyArray<TableEntry>> = {\n readonly [\n Entry in Extract<\n Entries[number],\n { readonly tableName: string; readonly group: Table_.Group }\n > as Entry[\"tableName\"]\n ]: {\n readonly key: Entry[\"group\"][\"key\"];\n readonly table: Entry[\"group\"][\"table\"];\n };\n};\n\n/**\n * `unknown` when every entry is one table or name and every group's id names a\n * table of this component in its scope, otherwise an object type naming the\n * refused entry.\n */\nexport type CheckGroups<\n Entries extends ReadonlyArray<TableEntry>,\n Scope extends IdScope.IdScope,\n> = [StrayGroup<Entries, Scope>] extends [never]\n ? unknown\n : { readonly \"~StrayGroup\": StrayGroup<Entries, Scope> };\n\n/**\n * An opaque identity: its string representation is not part of the API.\n */\nexport type MountScope<\n Parent extends IdScope.IdScope,\n Name extends string | undefined,\n> = IdScope.Mount<Parent, Name>;\n\ntype MountName<ComponentApi> =\n ComponentApi extends FunctionReference<any, any, any, any, infer Name>\n ? Name\n : ComponentApi extends object\n ? {\n [Key in keyof ComponentApi]: MountName<ComponentApi[Key]>;\n }[keyof ComponentApi]\n : never;\n\ntype BindRefs<\n RefTree,\n From extends IdScope.IdScope,\n To extends IdScope.IdScope,\n> = RefTree extends Ref.Any\n ? RefTree extends { readonly _tag: \"Convex\" }\n ? Ref.ConvexRef<\n Ref.GetRuntimeAndFunctionType<RefTree>,\n \"internal\",\n Extract<Wire<Ref.Args<RefTree>>, DefaultFunctionArgs>,\n Wire<Ref.Returns<RefTree>>\n >\n : Extract<\n Ref.Ref<\n Ref.GetRuntimeAndFunctionType<RefTree>,\n \"internal\",\n Extract<\n GenericId.Rebase<Ref.Args<RefTree>, From, To>,\n DefaultFunctionArgs\n >,\n GenericId.Rebase<Ref.Returns<RefTree>, From, To>,\n GenericId.Rebase<Ref.Error<RefTree>, From, To>\n >,\n { readonly _tag: RefTree[\"_tag\"] }\n >\n : { [Key in keyof RefTree]: BindRefs<RefTree[Key], From, To> };\n\nexport type Bound<\n Spec_ extends Spec.AnyWithProps,\n From extends IdScope.IdScope,\n To extends IdScope.IdScope,\n Tables extends string,\n> = BindRefs<Refs.Refs<Spec_, Ref.AnyPublic>, From, To> & {\n readonly [BoundTypeId]: {\n readonly from: From;\n readonly scope: To;\n readonly tables: ReadonlyArray<Tables>;\n };\n};\n\n/**\n * Build a publishable contract containing only exported functions and codecs.\n * `tables` lists the component's tables, each a table or a system table's name.\n * A table grouped by an id must group by an id of one of these tables.\n */\nexport function contract<\n Spec_ extends Spec.AnyWithProps,\n const Scope extends IdScope.IdScope,\n const Entries extends ReadonlyArray<TableEntry>,\n>(\n spec: Spec_,\n scope: Scope,\n tables: Entries & CheckGroups<Entries, Scope>,\n): Component<Spec_, Scope, EntryName<Entries[number]>, Groups<Entries>>;\n/**\n * Table names alone, as in an explicit third type argument, carry no groups.\n */\nexport function contract<\n Spec_ extends Spec.AnyWithProps,\n const Scope extends IdScope.IdScope,\n const Tables extends string,\n>(\n spec: Spec_,\n scope: Scope,\n tables: ReadonlyArray<Tables>,\n): Component<Spec_, Scope, Tables, {}>;\nexport function contract(\n spec: Spec.AnyWithProps,\n scope: IdScope.IdScope,\n tables: ReadonlyArray<TableEntry>,\n): Component<Spec.AnyWithProps, IdScope.IdScope> {\n const specGroups = Spec.groups(spec);\n Result.getOrThrow(validateContract(scope, specGroups));\n const collect = (\n groups: Readonly<Record<string, GroupSpec.AnyWithProps>>,\n prefix = \"\",\n ): Tree =>\n pipe(\n groups,\n Record.map((group, name) => {\n const path = prefix === \"\" ? name : `${prefix}/${name}`;\n const functions = pipe(\n group.functions,\n Record.filter((functionSpec) => {\n return Match.value(functionSpec.functionVisibility).pipe(\n Match.when(\"public\", () => true),\n Match.when(\"internal\", () => false),\n Match.exhaustive,\n );\n }),\n Record.map((functionSpec) =>\n Ref.make(path, functionSpec, group.middlewareAttachments),\n ),\n );\n return { ...collect(group.groups, path), ...functions };\n }),\n Record.filter((children) => !Record.isEmptyRecord(children)),\n );\n const grouped: GroupMap = pipe(\n tables,\n Array.flatMap((entry) =>\n typeof entry !== \"string\" && entry.group !== undefined\n ? [[entry.tableName, entry.group] as const]\n : [],\n ),\n Record.fromEntries,\n );\n const published: Component<\n Spec.AnyWithProps,\n IdScope.IdScope\n >[typeof TypeId] = {\n refs: collect(specGroups),\n scope,\n tables: Array.map(tables, (entry) =>\n typeof entry === \"string\" ? entry : entry.tableName,\n ),\n groups: grouped,\n };\n return { [TypeId]: published } as Component<\n Spec.AnyWithProps,\n IdScope.IdScope\n >;\n}\n\n/**\n * Each grouped table's id field and the table that id names.\n */\nexport const groups = <Groups_ extends GroupMap>(\n component: Component<Spec.AnyWithProps, IdScope.IdScope, string, Groups_>,\n): Groups_ =>\n Record.map(component[TypeId].groups, ({ key, table }) => ({\n key,\n table,\n })) as Groups_;\n\n/**\n * Bind the published contract to an actual installed component reference.\n */\nexport const bind = <\n Spec_ extends Spec.AnyWithProps,\n From extends IdScope.IdScope,\n Tables extends string,\n Native extends Api<NoInfer<Spec_>>,\n const Parent extends IdScope.IdScope = IdScope.App,\n>(\n component: Component<Spec_, From, Tables>,\n native: Native,\n options?: { readonly parentScope: Parent },\n): Bound<\n Spec_,\n From,\n MountScope<Parent, Extract<MountName<Native>, string | undefined>>,\n Tables\n> => {\n const published = component[TypeId];\n const address = getFunctionAddress(native);\n const installedReference = Result.getOrThrow(\n Result.fromNullishOr(\n address.reference,\n () =>\n new UninstalledComponentReferenceError({\n definitionScope: published.scope,\n }),\n ),\n );\n // Preserve the opaque address as an identity only. Calls retain the native\n // references; no component address is constructed or parsed for routing.\n const scope = IdScope.instance(\n options?.parentScope ?? IdScope.app,\n installedReference,\n );\n const rebase = (schema: Schema.ConstraintCodec<any, any, never, never>) =>\n GenericId.rebase(schema, published.scope, scope);\n const rebaseMiddleware = memoize(\n (middleware: MiddlewareSpec.AnyMiddlewareSpec) => {\n if (!(\"error\" in middleware)) return middleware;\n const boundMiddleware = Object.create(\n middleware,\n ) as MiddlewareSpec.AnyMiddlewareSpec;\n Lazy.defineProperty(boundMiddleware, \"error\", () => {\n const error = middleware.error;\n return error === undefined ? undefined : rebase(error);\n });\n return boundMiddleware;\n },\n );\n const visit = (tree: Tree, references: unknown): Tree =>\n Record.map(tree, (child, key) => {\n const reference = (references as Record<string, unknown>)[key];\n if (Ref.isRef(child)) {\n const nativeRef = reference as FunctionReference<any, any>;\n return Match.value(child).pipe(\n Match.tag(\"Convex\", (ref) => ({\n ...ref,\n functionReference: nativeRef,\n })),\n Match.tag(\"Confect\", (ref) => {\n const provenance = {\n _tag: \"Confect\" as const,\n kind: Match.value(ref.kind).pipe(\n Match.tag(\"Standard\", (kind) => kind),\n Match.tag(\"Paginated\", (kind) => {\n const boundKind = { _tag: \"Paginated\" as const };\n Lazy.defineProperty(boundKind, \"userArgs\", () =>\n Schema.Struct(Record.map(kind.userArgs.fields, rebase)),\n );\n Lazy.defineProperty(boundKind, \"item\", () =>\n rebase(kind.item),\n );\n Lazy.defineProperty(boundKind, \"page\", () =>\n rebase(kind.page),\n );\n return boundKind as FunctionProvenance.Paginated;\n }),\n Match.exhaustive,\n ),\n };\n Lazy.defineProperty(provenance, \"args\", () =>\n Schema.Struct(Record.map(ref.args.fields, rebase)),\n );\n Lazy.defineProperty(provenance, \"returns\", () =>\n rebase(ref.returns),\n );\n if (\"error\" in ref) {\n Lazy.defineProperty(provenance, \"error\", () => {\n const error = ref.error;\n return error === undefined ? undefined : rebase(error);\n });\n }\n return Ref.fromProvenance(\n ref.convexFunctionName,\n provenance as FunctionProvenance.AnyConfect,\n Array.map(ref.middlewareAttachments, (attachment) => ({\n ...attachment,\n spec: rebaseMiddleware(attachment.spec),\n })),\n nativeRef,\n ref.functionType,\n ref.reservedArgument,\n );\n }),\n Match.exhaustive,\n );\n } else {\n return visit(child, reference);\n }\n });\n const refs = visit(published.refs, native);\n Object.defineProperty(refs, BoundTypeId, {\n value: { from: published.scope, scope, tables: published.tables },\n });\n return refs as Bound<\n Spec_,\n From,\n MountScope<Parent, Extract<MountName<Native>, string | undefined>>,\n Tables\n >;\n};\n\n/**\n * Reference an installed component's table ID in host schemas.\n */\nexport const id = <\n From extends IdScope.IdScope,\n To extends IdScope.IdScope,\n Tables extends string,\n const Table extends Tables,\n>(\n component: {\n readonly [BoundTypeId]: {\n readonly from: From;\n readonly scope: To;\n readonly tables: ReadonlyArray<Tables>;\n };\n },\n table: Table,\n) => GenericId.GenericId(table, component[BoundTypeId].scope);\n\n/**\n * Reuse a component's codec in a host function or table without losing its\n * scope.\n */\nexport const schema = <\n From extends IdScope.IdScope,\n To extends IdScope.IdScope,\n Schema_ extends Schema.Codec<any, any>,\n>(\n component: {\n readonly [BoundTypeId]: { readonly from: From; readonly scope: To };\n },\n codec: Schema_,\n) =>\n GenericId.rebase(\n codec,\n component[BoundTypeId].from,\n component[BoundTypeId].scope,\n );\n\n/**\n * A component's `init`: an internal Confect mutation whose args are the install\n * args each mount passes.\n */\nexport type Init = Ref.AnyConfect & {\n readonly \"~RuntimeAndFunctionType\": RuntimeAndFunctionType.ConvexMutation;\n readonly \"~FunctionVisibility\": \"internal\";\n};\n\nexport interface DescriptorOptions {\n readonly init?: Init;\n /**\n * The component's `_generated/component` contract. A mount of a descriptor\n * with one rebases a callback slot's args with `callbackArgs`.\n */\n readonly contract?: Component<Spec.AnyWithProps, IdScope.IdScope, string>;\n readonly env?: Readonly<Record<string, Schema.Top>>;\n /**\n * Builds the component's client from its native mount, then the mount's\n * `options` when the client takes any.\n */\n readonly client: (...args: never) => unknown;\n}\n\nexport type Descriptor<\n Name extends string = string,\n Options extends DescriptorOptions = DescriptorOptions,\n> = Options & { readonly name: Name };\n\n/**\n * Describe a Convex component for `Mount.make`, as `defineComponent` does for\n * Convex. A component with `init` takes install `args` at each mount, and one\n * with `env` takes `env`. Export it from the package's `./client` entry.\n *\n * ```ts\n * export default Component.make(\"email\", {\n * init: refs.internal.install.init,\n * env: { RESEND_API_KEY: Schema.String },\n * client: Client.make,\n * });\n * ```\n */\nexport const make = <\n const Name extends string,\n const Options extends DescriptorOptions,\n>(\n name: Name,\n options: Options,\n): Descriptor<Name, Options> => ({ ...options, name });\n"],"mappings":"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"}
package/dist/Table.d.ts CHANGED
@@ -2,16 +2,50 @@ import * as IdScope from "./IdScope.js";
2
2
  import * as SystemFields from "./SystemFields.js";
3
3
  import type { TableSchemaToTableValidator } from "./SchemaToValidator.js";
4
4
  import type { SystemFields as ConvexSystemFields, Expand, GenericTableIndexes, GenericTableSearchIndexes, GenericTableVectorIndexes, IndexTiebreakerField, SearchIndexConfig, VectorIndexConfig } from "convex/server";
5
- import type { GenericValidator, Validator } from "convex/values";
5
+ import type { GenericId as ConvexGenericId, GenericValidator, Validator } from "convex/values";
6
6
  import type * as Schema from "effect/Schema";
7
7
  export declare const TypeId = "~@confect/core/Table";
8
8
  export type TypeId = typeof TypeId;
9
9
  export declare const isTable: (u: unknown) => u is Any;
10
10
  export declare const isUnnamedTable: (u: unknown) => u is UnnamedAny;
11
- export interface Table<Name_ extends string, TableSchema_ extends Schema.Codec<any, any>, TableValidator_ extends GenericValidator = TableSchemaToTableValidator<TableSchema_>, Indexes_ extends GenericTableIndexes = {}, SearchIndexes_ extends GenericTableSearchIndexes = {}, VectorIndexes_ extends GenericTableVectorIndexes = {}, Scope_ extends IdScope.IdScope = IdScope.App> {
11
+ export interface Group<Key extends string = string, Table_ extends string = string, Scope_ extends IdScope.IdScope = IdScope.IdScope> {
12
+ readonly key: Key;
13
+ readonly table: Table_;
14
+ readonly scope: Scope_;
15
+ }
16
+ declare const GroupFieldError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
17
+ readonly _tag: "GroupFieldError";
18
+ } & Readonly<A>;
19
+ export declare class GroupFieldError extends GroupFieldError_base<{
20
+ readonly tableName: string;
21
+ readonly key: string;
22
+ }> {
23
+ get message(): string;
24
+ }
25
+ type FieldsOf<TableSchema_> = TableSchema_ extends {
26
+ readonly fields: infer StructFields extends Schema.Struct.Fields;
27
+ } ? StructFields : never;
28
+ type GroupKeys<TableSchema_> = {
29
+ [Key in keyof FieldsOf<TableSchema_> & string]: FieldsOf<TableSchema_>[Key] extends {
30
+ readonly Type: ConvexGenericId<string>;
31
+ } ? [FieldsOf<TableSchema_>[Key]["~type.optionality"]] extends ["optional"] ? never : Key : never;
32
+ }[keyof FieldsOf<TableSchema_> & string];
33
+ type IdTableName<Id> = Id extends {
34
+ readonly "~@confect/core/ScopedId": {
35
+ readonly table: infer TableName extends string;
36
+ };
37
+ } ? TableName : Id extends ConvexGenericId<infer TableName> ? TableName : never;
38
+ type IdScopeOf<Id> = Id extends {
39
+ readonly "~@confect/core/ScopedId": {
40
+ readonly scope: infer Scope_ extends IdScope.IdScope;
41
+ };
42
+ } ? Scope_ : IdScope.App;
43
+ type GroupOf<TableSchema_, Key extends string> = Group<Key, IdTableName<FieldsOf<TableSchema_>[Key & keyof FieldsOf<TableSchema_>]["Type"]>, IdScopeOf<FieldsOf<TableSchema_>[Key & keyof FieldsOf<TableSchema_>]["Type"]>>;
44
+ export interface Table<Name_ extends string, TableSchema_ extends Schema.Codec<any, any>, TableValidator_ extends GenericValidator = TableSchemaToTableValidator<TableSchema_>, Indexes_ extends GenericTableIndexes = {}, SearchIndexes_ extends GenericTableSearchIndexes = {}, VectorIndexes_ extends GenericTableVectorIndexes = {}, Scope_ extends IdScope.IdScope = IdScope.App, Group_ extends Group | undefined = undefined> {
12
45
  readonly [TypeId]: TypeId;
13
46
  readonly tableName: Name_;
14
47
  readonly scope: Scope_;
48
+ readonly group: Group_;
15
49
  readonly Fields: TableSchema_;
16
50
  readonly Doc: SystemFields.ExtendWithSystemFields<Name_, TableSchema_, Scope_>;
17
51
  readonly indexes: Indexes_;
@@ -23,9 +57,9 @@ export interface Any {
23
57
  readonly [TypeId]: TypeId;
24
58
  readonly tableName: string;
25
59
  }
26
- export type AnyWithProps = Table<any, Schema.Codec<any, any>, GenericValidator, GenericTableIndexes, GenericTableSearchIndexes, GenericTableVectorIndexes, IdScope.IdScope>;
27
- export interface UnnamedTable<TableSchema_ extends Schema.Codec<any, any>, TableValidator_ extends GenericValidator = TableSchemaToTableValidator<TableSchema_>, Indexes_ extends GenericTableIndexes = {}, SearchIndexes_ extends GenericTableSearchIndexes = {}, VectorIndexes_ extends GenericTableVectorIndexes = {}> {
28
- <const Name_ extends string, const Scope_ extends IdScope.IdScope = IdScope.App>(tableName: Name_, scope?: Scope_): Table<Name_, TableSchema_, TableValidator_, Indexes_, SearchIndexes_, VectorIndexes_, Scope_>;
60
+ export type AnyWithProps = Table<any, Schema.Codec<any, any>, GenericValidator, GenericTableIndexes, GenericTableSearchIndexes, GenericTableVectorIndexes, IdScope.IdScope, Group | undefined>;
61
+ export interface UnnamedTable<TableSchema_ extends Schema.Codec<any, any>, TableValidator_ extends GenericValidator = TableSchemaToTableValidator<TableSchema_>, Indexes_ extends GenericTableIndexes = {}, SearchIndexes_ extends GenericTableSearchIndexes = {}, VectorIndexes_ extends GenericTableVectorIndexes = {}, Group_ extends Group | undefined = undefined> {
62
+ <const Name_ extends string, const Scope_ extends IdScope.IdScope = IdScope.App>(tableName: Name_, scope?: Scope_): Table<Name_, TableSchema_, TableValidator_, Indexes_, SearchIndexes_, VectorIndexes_, Scope_, Group_>;
29
63
  readonly [TypeId]: TypeId;
30
64
  readonly indexes: Indexes_;
31
65
  readonly searchIndexes: SearchIndexes_;
@@ -35,21 +69,26 @@ export interface UnnamedTable<TableSchema_ extends Schema.Codec<any, any>, Table
35
69
  FirstFieldPath,
36
70
  ...RestFieldPaths,
37
71
  IndexTiebreakerField
38
- ]>>, SearchIndexes_, VectorIndexes_>;
72
+ ]>>, SearchIndexes_, VectorIndexes_, Group_>;
39
73
  searchIndex<IndexName extends string, SearchField extends ExtractFieldPaths<TableValidator_>, FilterFields extends ExtractFieldPaths<TableValidator_> = never>(name: IndexName, indexConfig: Expand<SearchIndexConfig<SearchField, FilterFields>>): UnnamedTable<TableSchema_, TableValidator_, Indexes_, Expand<SearchIndexes_ & Record<IndexName, {
40
74
  searchField: SearchField;
41
75
  filterFields: FilterFields;
42
- }>>, VectorIndexes_>;
76
+ }>>, VectorIndexes_, Group_>;
43
77
  vectorIndex<IndexName extends string, VectorField extends ExtractFieldPaths<TableValidator_>, FilterFields extends ExtractFieldPaths<TableValidator_> = never>(name: IndexName, indexConfig: Expand<VectorIndexConfig<VectorField, FilterFields>>): UnnamedTable<TableSchema_, TableValidator_, Indexes_, SearchIndexes_, Expand<VectorIndexes_ & Record<IndexName, {
44
78
  vectorField: VectorField;
45
79
  dimensions: number;
46
80
  filterFields: FilterFields;
47
- }>>>;
81
+ }>>, Group_>;
82
+ /**
83
+ * Name the required id field that groups this table's rows. The field's table
84
+ * is the one whose rows own these rows.
85
+ */
86
+ group<const Key extends GroupKeys<TableSchema_>>(key: Key): UnnamedTable<TableSchema_, TableValidator_, Indexes_, SearchIndexes_, VectorIndexes_, GroupOf<TableSchema_, Key>>;
48
87
  }
49
88
  export interface UnnamedAny {
50
89
  readonly [TypeId]: TypeId;
51
90
  }
52
- export type UnnamedAnyWithProps = UnnamedTable<Schema.Codec<any, any>, GenericValidator, GenericTableIndexes, GenericTableSearchIndexes, GenericTableVectorIndexes>;
91
+ export type UnnamedAnyWithProps = UnnamedTable<Schema.Codec<any, any>, GenericValidator, GenericTableIndexes, GenericTableSearchIndexes, GenericTableVectorIndexes, Group | undefined>;
53
92
  export type Name<TableDef extends AnyWithProps> = TableDef["tableName"] & string;
54
93
  export type TableSchema<TableDef extends AnyWithProps> = TableDef["Fields"];
55
94
  export type TableValidator<TableDef extends AnyWithProps> = TableDef["~TableValidator"];
@@ -1 +1 @@
1
- {"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../src/Table.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../src/Table.ts"],"names":[],"mappings":"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"}
package/dist/Table.js CHANGED
@@ -1,10 +1,14 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.js";
2
2
  import { defineProperty } from "./Lazy.js";
3
3
  import { app } from "./IdScope.js";
4
+ import { scope, tableName } from "./GenericId.js";
4
5
  import { extendWithSystemFields } from "./SystemFields.js";
5
6
  import * as Predicate from "effect/Predicate";
7
+ import * as Data from "effect/Data";
8
+ import * as Option from "effect/Option";
6
9
  //#region src/Table.ts
7
10
  var Table_exports = /* @__PURE__ */ __exportAll({
11
+ GroupFieldError: () => GroupFieldError,
8
12
  TypeId: () => TypeId,
9
13
  isTable: () => isTable,
10
14
  isUnnamedTable: () => isUnnamedTable,
@@ -13,11 +17,35 @@ var Table_exports = /* @__PURE__ */ __exportAll({
13
17
  const TypeId = "~@confect/core/Table";
14
18
  const isTable = (u) => Predicate.hasProperty(u, "~@confect/core/Table") && Predicate.hasProperty(u, "tableName");
15
19
  const isUnnamedTable = (u) => Predicate.hasProperty(u, "~@confect/core/Table") && !Predicate.hasProperty(u, "tableName");
20
+ var GroupFieldError = class extends Data.TaggedError("GroupFieldError") {
21
+ get message() {
22
+ return `Table '${this.tableName}' cannot be grouped by '${this.key}': it is not a field holding an id.`;
23
+ }
24
+ };
25
+ const makeGroup = (tableName$1, key, fields) => {
26
+ const idField = () => {
27
+ const ast = fields().fields?.[key]?.ast;
28
+ const table = ast === void 0 ? Option.none() : tableName(ast);
29
+ if (ast === void 0 || Option.isNone(table)) throw new GroupFieldError({
30
+ tableName: tableName$1,
31
+ key
32
+ });
33
+ return {
34
+ table: table.value,
35
+ scope: scope(ast)
36
+ };
37
+ };
38
+ const group = { key };
39
+ defineProperty(group, "table", () => idField().table);
40
+ defineProperty(group, "scope", () => idField().scope);
41
+ return group;
42
+ };
16
43
  const makeBound = (tableName, state, scope) => {
17
44
  const bound = {
18
45
  [TypeId]: TypeId,
19
46
  tableName,
20
47
  scope,
48
+ group: state.groupKey === void 0 ? void 0 : makeGroup(tableName, state.groupKey, () => bound.Fields),
21
49
  indexes: state.indexes,
22
50
  searchIndexes: state.searchIndexes,
23
51
  vectorIndexes: state.vectorIndexes
@@ -29,32 +57,30 @@ const makeBound = (tableName, state, scope) => {
29
57
  const makeUnnamed = (state) => {
30
58
  const bind = (tableName, scope) => makeBound(tableName, state, scope ?? app);
31
59
  const index = (name, fields) => makeUnnamed({
32
- lazyFields: state.lazyFields,
60
+ ...state,
33
61
  indexes: {
34
62
  ...state.indexes,
35
63
  [name]: fields
36
- },
37
- searchIndexes: state.searchIndexes,
38
- vectorIndexes: state.vectorIndexes
64
+ }
39
65
  });
40
66
  const searchIndex = (name, indexConfig) => makeUnnamed({
41
- lazyFields: state.lazyFields,
42
- indexes: state.indexes,
67
+ ...state,
43
68
  searchIndexes: {
44
69
  ...state.searchIndexes,
45
70
  [name]: indexConfig
46
- },
47
- vectorIndexes: state.vectorIndexes
71
+ }
48
72
  });
49
73
  const vectorIndex = (name, indexConfig) => makeUnnamed({
50
- lazyFields: state.lazyFields,
51
- indexes: state.indexes,
52
- searchIndexes: state.searchIndexes,
74
+ ...state,
53
75
  vectorIndexes: {
54
76
  ...state.vectorIndexes,
55
77
  [name]: indexConfig
56
78
  }
57
79
  });
80
+ const group = (key) => makeUnnamed({
81
+ ...state,
82
+ groupKey: key
83
+ });
58
84
  return Object.assign(bind, {
59
85
  [TypeId]: TypeId,
60
86
  indexes: state.indexes,
@@ -62,18 +88,20 @@ const makeUnnamed = (state) => {
62
88
  vectorIndexes: state.vectorIndexes,
63
89
  index,
64
90
  searchIndex,
65
- vectorIndex
91
+ vectorIndex,
92
+ group
66
93
  });
67
94
  };
68
95
  const make = (lazyFields) => {
69
96
  return makeUnnamed({
70
97
  lazyFields,
98
+ groupKey: void 0,
71
99
  indexes: {},
72
100
  searchIndexes: {},
73
101
  vectorIndexes: {}
74
102
  });
75
103
  };
76
104
  //#endregion
77
- export { Table_exports, TypeId, isTable, isUnnamedTable, make };
105
+ export { GroupFieldError, Table_exports, TypeId, isTable, isUnnamedTable, make };
78
106
 
79
107
  //# sourceMappingURL=Table.js.map
package/dist/Table.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Table.js","names":["SystemFields.extendWithSystemFields","IdScope.app"],"sources":["../src/Table.ts"],"sourcesContent":["import * as IdScope from \"./IdScope.js\";\nimport * as Lazy from \"./Lazy.js\";\nimport * as SystemFields from \"./SystemFields.js\";\nimport type { TableSchemaToTableValidator } from \"./SchemaToValidator.js\";\nimport type {\n SystemFields as ConvexSystemFields,\n Expand,\n GenericTableIndexes,\n GenericTableSearchIndexes,\n GenericTableVectorIndexes,\n IndexTiebreakerField,\n SearchIndexConfig,\n VectorIndexConfig,\n} from \"convex/server\";\nimport type { GenericValidator, Validator } from \"convex/values\";\nimport * as Predicate from \"effect/Predicate\";\nimport type * as Schema from \"effect/Schema\";\n\nexport const TypeId = \"~@confect/core/Table\";\nexport type TypeId = typeof TypeId;\n\n// -----------------------------------------------------------------------------\n// Predicates\n// -----------------------------------------------------------------------------\n//\n// Both bound `Table`s and `UnnamedTable` callables share the same `[TypeId]`\n// brand. They disambiguate by whether a `tableName` property is set: bound\n// tables have one, unnamed callables do not.\n//\n// The discriminator is `tableName` (not `name`) so it does not collide with\n// the built-in `Function.prototype.name` that every JS function carries.\n\nexport const isTable = (u: unknown): u is Any =>\n Predicate.hasProperty(u, TypeId) && Predicate.hasProperty(u, \"tableName\");\n\nexport const isUnnamedTable = (u: unknown): u is UnnamedAny =>\n Predicate.hasProperty(u, TypeId) && !Predicate.hasProperty(u, \"tableName\");\n\n// -----------------------------------------------------------------------------\n// Bound Table\n// -----------------------------------------------------------------------------\n//\n// A bound `Table` is the client-safe document schema: `Fields`, `Doc`, and\n// the index metadata records. The Convex deploy `tableDefinition` (which\n// value-imports `convex/server`) is produced separately by\n// `@confect/server/Table.tableDefinition`.\n\nexport interface Table<\n Name_ extends string,\n TableSchema_ extends Schema.Codec<any, any>,\n TableValidator_ extends GenericValidator =\n TableSchemaToTableValidator<TableSchema_>,\n Indexes_ extends GenericTableIndexes = {},\n SearchIndexes_ extends GenericTableSearchIndexes = {},\n VectorIndexes_ extends GenericTableVectorIndexes = {},\n Scope_ extends IdScope.IdScope = IdScope.App,\n> {\n readonly [TypeId]: TypeId;\n readonly tableName: Name_;\n readonly scope: Scope_;\n readonly Fields: TableSchema_;\n readonly Doc: SystemFields.ExtendWithSystemFields<\n Name_,\n TableSchema_,\n Scope_\n >;\n readonly indexes: Indexes_;\n readonly searchIndexes: SearchIndexes_;\n readonly vectorIndexes: VectorIndexes_;\n readonly \"~TableValidator\": TableValidator_;\n}\n\nexport interface Any {\n readonly [TypeId]: TypeId;\n readonly tableName: string;\n}\n\nexport type AnyWithProps = Table<\n any,\n Schema.Codec<any, any>,\n GenericValidator,\n GenericTableIndexes,\n GenericTableSearchIndexes,\n GenericTableVectorIndexes,\n IdScope.IdScope\n>;\n\n// -----------------------------------------------------------------------------\n// UnnamedTable (callable)\n// -----------------------------------------------------------------------------\n//\n// `Table.make(lazyFields)` returns an `UnnamedTable`: a callable that\n// produces a fully bound `Table` when invoked with a name. Chaining methods\n// (`.index`, `.searchIndex`, `.vectorIndex`) live here and return new\n// `UnnamedTable`s, accumulating plain index metadata records. The\n// user-supplied `lazyFields` callback is just carried through until first\n// access of `Fields`/`Doc` on a bound table. The codegen pipeline emits a\n// wrapper file per user-authored table that simply invokes the unnamed\n// callable with the filename basename.\n\nexport interface UnnamedTable<\n TableSchema_ extends Schema.Codec<any, any>,\n TableValidator_ extends GenericValidator =\n TableSchemaToTableValidator<TableSchema_>,\n Indexes_ extends GenericTableIndexes = {},\n SearchIndexes_ extends GenericTableSearchIndexes = {},\n VectorIndexes_ extends GenericTableVectorIndexes = {},\n> {\n <\n const Name_ extends string,\n const Scope_ extends IdScope.IdScope = IdScope.App,\n >(\n tableName: Name_,\n scope?: Scope_,\n ): Table<\n Name_,\n TableSchema_,\n TableValidator_,\n Indexes_,\n SearchIndexes_,\n VectorIndexes_,\n Scope_\n >;\n\n readonly [TypeId]: TypeId;\n readonly indexes: Indexes_;\n readonly searchIndexes: SearchIndexes_;\n readonly vectorIndexes: VectorIndexes_;\n readonly \"~TableValidator\": TableValidator_;\n\n index<\n IndexName extends string,\n FirstFieldPath extends ExtractFieldPaths<TableValidator_>,\n RestFieldPaths extends ExtractFieldPaths<TableValidator_>[],\n >(\n name: IndexName,\n fields: [FirstFieldPath, ...RestFieldPaths],\n ): UnnamedTable<\n TableSchema_,\n TableValidator_,\n Expand<\n Indexes_ &\n Record<\n IndexName,\n [FirstFieldPath, ...RestFieldPaths, IndexTiebreakerField]\n >\n >,\n SearchIndexes_,\n VectorIndexes_\n >;\n\n searchIndex<\n IndexName extends string,\n SearchField extends ExtractFieldPaths<TableValidator_>,\n FilterFields extends ExtractFieldPaths<TableValidator_> = never,\n >(\n name: IndexName,\n indexConfig: Expand<SearchIndexConfig<SearchField, FilterFields>>,\n ): UnnamedTable<\n TableSchema_,\n TableValidator_,\n Indexes_,\n Expand<\n SearchIndexes_ &\n Record<\n IndexName,\n {\n searchField: SearchField;\n filterFields: FilterFields;\n }\n >\n >,\n VectorIndexes_\n >;\n\n vectorIndex<\n IndexName extends string,\n VectorField extends ExtractFieldPaths<TableValidator_>,\n FilterFields extends ExtractFieldPaths<TableValidator_> = never,\n >(\n name: IndexName,\n indexConfig: Expand<VectorIndexConfig<VectorField, FilterFields>>,\n ): UnnamedTable<\n TableSchema_,\n TableValidator_,\n Indexes_,\n SearchIndexes_,\n Expand<\n VectorIndexes_ &\n Record<\n IndexName,\n {\n vectorField: VectorField;\n dimensions: number;\n filterFields: FilterFields;\n }\n >\n >\n >;\n}\n\nexport interface UnnamedAny {\n readonly [TypeId]: TypeId;\n}\n\nexport type UnnamedAnyWithProps = UnnamedTable<\n Schema.Codec<any, any>,\n GenericValidator,\n GenericTableIndexes,\n GenericTableSearchIndexes,\n GenericTableVectorIndexes\n>;\n\n// -----------------------------------------------------------------------------\n// Type extractors\n// -----------------------------------------------------------------------------\n\nexport type Name<TableDef extends AnyWithProps> = TableDef[\"tableName\"] &\n string;\n\nexport type TableSchema<TableDef extends AnyWithProps> = TableDef[\"Fields\"];\n\nexport type TableValidator<TableDef extends AnyWithProps> =\n TableDef[\"~TableValidator\"];\n\nexport type Indexes<TableDef extends AnyWithProps> = TableDef[\"indexes\"];\n\nexport type SearchIndexes<TableDef extends AnyWithProps> =\n TableDef[\"searchIndexes\"];\n\nexport type VectorIndexes<TableDef extends AnyWithProps> =\n TableDef[\"vectorIndexes\"];\n\nexport type Doc<TableDef extends AnyWithProps> = TableDef[\"Doc\"];\n\nexport type Fields<TableDef extends AnyWithProps> = TableDef[\"Fields\"];\nexport type Scope<TableDef extends AnyWithProps> = TableDef[\"scope\"];\n\nexport type WithName<\n TableDef extends AnyWithProps,\n Name_ extends string,\n> = TableDef extends { readonly tableName: Name_ } ? TableDef : never;\n\nexport type TablesRecord<Tables extends AnyWithProps> = {\n readonly [TableName_ in Name<Tables>]: WithName<Tables, TableName_>;\n};\n\n// -----------------------------------------------------------------------------\n// Construction\n// -----------------------------------------------------------------------------\n//\n// `make` only stores the user-supplied `lazyFields` callback alongside any\n// chained index metadata. Neither `Fields` nor `Doc` is constructed until\n// first access on a bound `Table`. Each chain step is O(1) (plain object\n// spread of the metadata records) and never invokes the callback. Binding\n// via `unnamed(tableName)` installs lazy memoised getters for `Fields` and\n// `Doc` via `Lazy.defineProperty`, so the first access materialises the\n// value and replaces the getter with a plain data property—second-and-\n// subsequent accesses are observably indistinguishable from a plain\n// property and avoid all function-call overhead.\n\ninterface UnnamedState<\n TableSchema_ extends Schema.Codec<any, any>,\n Indexes_ extends GenericTableIndexes,\n SearchIndexes_ extends GenericTableSearchIndexes,\n VectorIndexes_ extends GenericTableVectorIndexes,\n> {\n readonly lazyFields: () => TableSchema_;\n readonly indexes: Indexes_;\n readonly searchIndexes: SearchIndexes_;\n readonly vectorIndexes: VectorIndexes_;\n}\n\nconst makeBound = <\n Name_ extends string,\n TableSchema_ extends Schema.Codec<any, any>,\n TableValidator_ extends Validator<any, any, any>,\n Indexes_ extends GenericTableIndexes,\n SearchIndexes_ extends GenericTableSearchIndexes,\n VectorIndexes_ extends GenericTableVectorIndexes,\n Scope_ extends IdScope.IdScope,\n>(\n tableName: Name_,\n state: UnnamedState<TableSchema_, Indexes_, SearchIndexes_, VectorIndexes_>,\n scope: Scope_,\n): Table<\n Name_,\n TableSchema_,\n TableValidator_,\n Indexes_,\n SearchIndexes_,\n VectorIndexes_,\n Scope_\n> => {\n const bound = {\n [TypeId]: TypeId as TypeId,\n tableName,\n scope,\n indexes: state.indexes,\n searchIndexes: state.searchIndexes,\n vectorIndexes: state.vectorIndexes,\n } as Table<\n Name_,\n TableSchema_,\n TableValidator_,\n Indexes_,\n SearchIndexes_,\n VectorIndexes_,\n Scope_\n >;\n\n Lazy.defineProperty(bound, \"Fields\", () => state.lazyFields());\n\n Lazy.defineProperty(bound, \"Doc\", () =>\n SystemFields.extendWithSystemFields(\n tableName,\n (bound as { Fields: TableSchema_ }).Fields,\n scope,\n ),\n );\n\n return bound;\n};\n\nconst makeUnnamed = <\n TableSchema_ extends Schema.Codec<any, any>,\n TableValidator_ extends Validator<any, any, any>,\n Indexes_ extends GenericTableIndexes,\n SearchIndexes_ extends GenericTableSearchIndexes,\n VectorIndexes_ extends GenericTableVectorIndexes,\n>(\n state: UnnamedState<TableSchema_, Indexes_, SearchIndexes_, VectorIndexes_>,\n): UnnamedTable<\n TableSchema_,\n TableValidator_,\n Indexes_,\n SearchIndexes_,\n VectorIndexes_\n> => {\n type UnnamedTable_ = UnnamedTable<\n TableSchema_,\n TableValidator_,\n Indexes_,\n SearchIndexes_,\n VectorIndexes_\n >;\n\n type UnnamedTableFunction<FunctionName extends keyof UnnamedTable_> =\n UnnamedTable_[FunctionName];\n\n const bind = <\n const Name_ extends string,\n const Scope_ extends IdScope.IdScope = IdScope.App,\n >(\n tableName: Name_,\n scope?: Scope_,\n ): Table<\n Name_,\n TableSchema_,\n TableValidator_,\n Indexes_,\n SearchIndexes_,\n VectorIndexes_,\n Scope_\n > =>\n makeBound<\n Name_,\n TableSchema_,\n TableValidator_,\n Indexes_,\n SearchIndexes_,\n VectorIndexes_,\n Scope_\n >(tableName, state, (scope ?? IdScope.app) as Scope_);\n\n const index: UnnamedTableFunction<\"index\"> = (name, fields) =>\n makeUnnamed({\n lazyFields: state.lazyFields,\n indexes: {\n ...state.indexes,\n [name]: fields,\n } as any,\n searchIndexes: state.searchIndexes,\n vectorIndexes: state.vectorIndexes,\n });\n\n const searchIndex: UnnamedTableFunction<\"searchIndex\"> = (\n name,\n indexConfig,\n ) =>\n makeUnnamed({\n lazyFields: state.lazyFields,\n indexes: state.indexes,\n searchIndexes: {\n ...state.searchIndexes,\n [name]: indexConfig,\n } as any,\n vectorIndexes: state.vectorIndexes,\n });\n\n const vectorIndex: UnnamedTableFunction<\"vectorIndex\"> = (\n name,\n indexConfig,\n ) =>\n makeUnnamed({\n lazyFields: state.lazyFields,\n indexes: state.indexes,\n searchIndexes: state.searchIndexes,\n vectorIndexes: {\n ...state.vectorIndexes,\n [name]: indexConfig,\n } as any,\n });\n\n return Object.assign(bind, {\n [TypeId]: TypeId as TypeId,\n indexes: state.indexes,\n searchIndexes: state.searchIndexes,\n vectorIndexes: state.vectorIndexes,\n index,\n searchIndex,\n vectorIndex,\n }) as UnnamedTable_;\n};\n\nexport const make = <const TableSchema_ extends Schema.Codec<any, any>>(\n lazyFields: () => TableSchema_,\n): UnnamedTable<TableSchema_, TableSchemaToTableValidator<TableSchema_>> => {\n type TableValidator_ = TableSchemaToTableValidator<TableSchema_>;\n type UnnamedTable_ = UnnamedTable<TableSchema_, TableValidator_>;\n\n return makeUnnamed<TableSchema_, TableValidator_, {}, {}, {}>({\n lazyFields,\n indexes: {},\n searchIndexes: {},\n vectorIndexes: {},\n }) as UnnamedTable_;\n};\n\n// Vendored types from convex-js, partially modified. Ideally we could use these directly. See https://github.com/get-convex/convex-js/pull/14\n\n/**\n * Extract all of the index field paths within a Convex `Validator`.\n *\n * This is used when declaring table indexes.\n *\n * @public\n */\ntype ExtractFieldPaths<TableValidator_ extends Validator<any, any, any>> =\n // Add in the system fields available in index definitions.\n // This should be everything except for `_id` because thats added to indexes\n // automatically.\n TableValidator_[\"fieldPaths\"] | keyof ConvexSystemFields;\n"],"mappings":";;;;;;;;;;;;AAkBA,MAAa,SAAS;AActB,MAAa,WAAW,MACtB,UAAU,YAAY,GAAA,sBAAS,KAAK,UAAU,YAAY,GAAG,WAAW;AAE1E,MAAa,kBAAkB,MAC7B,UAAU,YAAY,GAAA,sBAAS,KAAK,CAAC,UAAU,YAAY,GAAG,WAAW;AA6O3E,MAAM,aASJ,WACA,OACA,UASG;CACH,MAAM,QAAQ;GACX,SAAS;EACV;EACA;EACA,SAAS,MAAM;EACf,eAAe,MAAM;EACrB,eAAe,MAAM;CACvB;CAUA,eAAoB,OAAO,gBAAgB,MAAM,WAAW,CAAC;CAE7D,eAAoB,OAAO,aACzBA,uBACE,WACC,MAAmC,QACpC,KACF,CACF;CAEA,OAAO;AACT;AAEA,MAAM,eAOJ,UAOG;CAYH,MAAM,QAIJ,WACA,UAUA,UAQE,WAAW,OAAQ,SAASC,GAAsB;CAEtD,MAAM,SAAwC,MAAM,WAClD,YAAY;EACV,YAAY,MAAM;EAClB,SAAS;GACP,GAAG,MAAM;IACR,OAAO;EACV;EACA,eAAe,MAAM;EACrB,eAAe,MAAM;CACvB,CAAC;CAEH,MAAM,eACJ,MACA,gBAEA,YAAY;EACV,YAAY,MAAM;EAClB,SAAS,MAAM;EACf,eAAe;GACb,GAAG,MAAM;IACR,OAAO;EACV;EACA,eAAe,MAAM;CACvB,CAAC;CAEH,MAAM,eACJ,MACA,gBAEA,YAAY;EACV,YAAY,MAAM;EAClB,SAAS,MAAM;EACf,eAAe,MAAM;EACrB,eAAe;GACb,GAAG,MAAM;IACR,OAAO;EACV;CACF,CAAC;CAEH,OAAO,OAAO,OAAO,MAAM;GACxB,SAAS;EACV,SAAS,MAAM;EACf,eAAe,MAAM;EACrB,eAAe,MAAM;EACrB;EACA;EACA;CACF,CAAC;AACH;AAEA,MAAa,QACX,eAC0E;CAI1E,OAAO,YAAuD;EAC5D;EACA,SAAS,CAAC;EACV,eAAe,CAAC;EAChB,eAAe,CAAC;CAClB,CAAC;AACH"}
1
+ {"version":3,"file":"Table.js","names":["GenericId.tableName","GenericId.scope","SystemFields.extendWithSystemFields","IdScope.app"],"sources":["../src/Table.ts"],"sourcesContent":["import * as GenericId from \"./GenericId.js\";\nimport * as IdScope from \"./IdScope.js\";\nimport * as Lazy from \"./Lazy.js\";\nimport * as SystemFields from \"./SystemFields.js\";\nimport type { TableSchemaToTableValidator } from \"./SchemaToValidator.js\";\nimport type {\n SystemFields as ConvexSystemFields,\n Expand,\n GenericTableIndexes,\n GenericTableSearchIndexes,\n GenericTableVectorIndexes,\n IndexTiebreakerField,\n SearchIndexConfig,\n VectorIndexConfig,\n} from \"convex/server\";\nimport type {\n GenericId as ConvexGenericId,\n GenericValidator,\n Validator,\n} from \"convex/values\";\nimport * as Data from \"effect/Data\";\nimport * as Option from \"effect/Option\";\nimport * as Predicate from \"effect/Predicate\";\nimport type * as Schema from \"effect/Schema\";\n\nexport const TypeId = \"~@confect/core/Table\";\nexport type TypeId = typeof TypeId;\n\n// -----------------------------------------------------------------------------\n// Predicates\n// -----------------------------------------------------------------------------\n//\n// Both bound `Table`s and `UnnamedTable` callables share the same `[TypeId]`\n// brand. They disambiguate by whether a `tableName` property is set: bound\n// tables have one, unnamed callables do not.\n//\n// The discriminator is `tableName` (not `name`) so it does not collide with\n// the built-in `Function.prototype.name` that every JS function carries.\n\nexport const isTable = (u: unknown): u is Any =>\n Predicate.hasProperty(u, TypeId) && Predicate.hasProperty(u, \"tableName\");\n\nexport const isUnnamedTable = (u: unknown): u is UnnamedAny =>\n Predicate.hasProperty(u, TypeId) && !Predicate.hasProperty(u, \"tableName\");\n\n// -----------------------------------------------------------------------------\n// Group\n// -----------------------------------------------------------------------------\n//\n// A table is grouped by one of its required id fields, and the id's table owns\n// its rows. `table` and `scope` come from the id's schema on first read, so\n// binding a table never builds its `Fields`.\n\nexport interface Group<\n Key extends string = string,\n Table_ extends string = string,\n Scope_ extends IdScope.IdScope = IdScope.IdScope,\n> {\n readonly key: Key;\n readonly table: Table_;\n readonly scope: Scope_;\n}\n\nexport class GroupFieldError extends Data.TaggedError(\"GroupFieldError\")<{\n readonly tableName: string;\n readonly key: string;\n}> {\n override get message(): string {\n return `Table '${this.tableName}' cannot be grouped by '${this.key}': it is not a field holding an id.`;\n }\n}\n\ntype FieldsOf<TableSchema_> = TableSchema_ extends {\n readonly fields: infer StructFields extends Schema.Struct.Fields;\n}\n ? StructFields\n : never;\n\ntype GroupKeys<TableSchema_> = {\n [\n Key in keyof FieldsOf<TableSchema_> & string\n ]: FieldsOf<TableSchema_>[Key] extends {\n readonly Type: ConvexGenericId<string>;\n }\n ? [FieldsOf<TableSchema_>[Key][\"~type.optionality\"]] extends [\"optional\"]\n ? never\n : Key\n : never;\n}[keyof FieldsOf<TableSchema_> & string];\n\ntype IdTableName<Id> = Id extends {\n readonly \"~@confect/core/ScopedId\": {\n readonly table: infer TableName extends string;\n };\n}\n ? TableName\n : Id extends ConvexGenericId<infer TableName>\n ? TableName\n : never;\n\ntype IdScopeOf<Id> = Id extends {\n readonly \"~@confect/core/ScopedId\": {\n readonly scope: infer Scope_ extends IdScope.IdScope;\n };\n}\n ? Scope_\n : IdScope.App;\n\ntype GroupOf<TableSchema_, Key extends string> = Group<\n Key,\n IdTableName<\n FieldsOf<TableSchema_>[Key & keyof FieldsOf<TableSchema_>][\"Type\"]\n >,\n IdScopeOf<FieldsOf<TableSchema_>[Key & keyof FieldsOf<TableSchema_>][\"Type\"]>\n>;\n\nconst makeGroup = (\n tableName: string,\n key: string,\n fields: () => Schema.Codec<any, any>,\n): Group => {\n const idField = () => {\n const ast = (fields() as { readonly fields?: Schema.Struct.Fields })\n .fields?.[key]?.ast;\n const table =\n ast === undefined ? Option.none() : GenericId.tableName<string>(ast);\n if (ast === undefined || Option.isNone(table))\n throw new GroupFieldError({ tableName, key });\n return { table: table.value, scope: GenericId.scope(ast) };\n };\n const group = { key };\n Lazy.defineProperty(group, \"table\", () => idField().table);\n Lazy.defineProperty(group, \"scope\", () => idField().scope);\n return group as Group;\n};\n\n// -----------------------------------------------------------------------------\n// Bound Table\n// -----------------------------------------------------------------------------\n//\n// A bound `Table` is the client-safe document schema: `Fields`, `Doc`, and\n// the index metadata records. The Convex deploy `tableDefinition` (which\n// value-imports `convex/server`) is produced separately by\n// `@confect/server/Table.tableDefinition`.\n\nexport interface Table<\n Name_ extends string,\n TableSchema_ extends Schema.Codec<any, any>,\n TableValidator_ extends GenericValidator =\n TableSchemaToTableValidator<TableSchema_>,\n Indexes_ extends GenericTableIndexes = {},\n SearchIndexes_ extends GenericTableSearchIndexes = {},\n VectorIndexes_ extends GenericTableVectorIndexes = {},\n Scope_ extends IdScope.IdScope = IdScope.App,\n Group_ extends Group | undefined = undefined,\n> {\n readonly [TypeId]: TypeId;\n readonly tableName: Name_;\n readonly scope: Scope_;\n readonly group: Group_;\n readonly Fields: TableSchema_;\n readonly Doc: SystemFields.ExtendWithSystemFields<\n Name_,\n TableSchema_,\n Scope_\n >;\n readonly indexes: Indexes_;\n readonly searchIndexes: SearchIndexes_;\n readonly vectorIndexes: VectorIndexes_;\n readonly \"~TableValidator\": TableValidator_;\n}\n\nexport interface Any {\n readonly [TypeId]: TypeId;\n readonly tableName: string;\n}\n\nexport type AnyWithProps = Table<\n any,\n Schema.Codec<any, any>,\n GenericValidator,\n GenericTableIndexes,\n GenericTableSearchIndexes,\n GenericTableVectorIndexes,\n IdScope.IdScope,\n Group | undefined\n>;\n\n// -----------------------------------------------------------------------------\n// UnnamedTable (callable)\n// -----------------------------------------------------------------------------\n//\n// `Table.make(lazyFields)` returns an `UnnamedTable`: a callable that\n// produces a fully bound `Table` when invoked with a name. Chaining methods\n// (`.index`, `.searchIndex`, `.vectorIndex`) live here and return new\n// `UnnamedTable`s, accumulating plain index metadata records. The\n// user-supplied `lazyFields` callback is just carried through until first\n// access of `Fields`/`Doc` on a bound table. The codegen pipeline emits a\n// wrapper file per user-authored table that simply invokes the unnamed\n// callable with the filename basename.\n\nexport interface UnnamedTable<\n TableSchema_ extends Schema.Codec<any, any>,\n TableValidator_ extends GenericValidator =\n TableSchemaToTableValidator<TableSchema_>,\n Indexes_ extends GenericTableIndexes = {},\n SearchIndexes_ extends GenericTableSearchIndexes = {},\n VectorIndexes_ extends GenericTableVectorIndexes = {},\n Group_ extends Group | undefined = undefined,\n> {\n <\n const Name_ extends string,\n const Scope_ extends IdScope.IdScope = IdScope.App,\n >(\n tableName: Name_,\n scope?: Scope_,\n ): Table<\n Name_,\n TableSchema_,\n TableValidator_,\n Indexes_,\n SearchIndexes_,\n VectorIndexes_,\n Scope_,\n Group_\n >;\n\n readonly [TypeId]: TypeId;\n readonly indexes: Indexes_;\n readonly searchIndexes: SearchIndexes_;\n readonly vectorIndexes: VectorIndexes_;\n readonly \"~TableValidator\": TableValidator_;\n\n index<\n IndexName extends string,\n FirstFieldPath extends ExtractFieldPaths<TableValidator_>,\n RestFieldPaths extends ExtractFieldPaths<TableValidator_>[],\n >(\n name: IndexName,\n fields: [FirstFieldPath, ...RestFieldPaths],\n ): UnnamedTable<\n TableSchema_,\n TableValidator_,\n Expand<\n Indexes_ &\n Record<\n IndexName,\n [FirstFieldPath, ...RestFieldPaths, IndexTiebreakerField]\n >\n >,\n SearchIndexes_,\n VectorIndexes_,\n Group_\n >;\n\n searchIndex<\n IndexName extends string,\n SearchField extends ExtractFieldPaths<TableValidator_>,\n FilterFields extends ExtractFieldPaths<TableValidator_> = never,\n >(\n name: IndexName,\n indexConfig: Expand<SearchIndexConfig<SearchField, FilterFields>>,\n ): UnnamedTable<\n TableSchema_,\n TableValidator_,\n Indexes_,\n Expand<\n SearchIndexes_ &\n Record<\n IndexName,\n {\n searchField: SearchField;\n filterFields: FilterFields;\n }\n >\n >,\n VectorIndexes_,\n Group_\n >;\n\n vectorIndex<\n IndexName extends string,\n VectorField extends ExtractFieldPaths<TableValidator_>,\n FilterFields extends ExtractFieldPaths<TableValidator_> = never,\n >(\n name: IndexName,\n indexConfig: Expand<VectorIndexConfig<VectorField, FilterFields>>,\n ): UnnamedTable<\n TableSchema_,\n TableValidator_,\n Indexes_,\n SearchIndexes_,\n Expand<\n VectorIndexes_ &\n Record<\n IndexName,\n {\n vectorField: VectorField;\n dimensions: number;\n filterFields: FilterFields;\n }\n >\n >,\n Group_\n >;\n\n /**\n * Name the required id field that groups this table's rows. The field's table\n * is the one whose rows own these rows.\n */\n group<const Key extends GroupKeys<TableSchema_>>(\n key: Key,\n ): UnnamedTable<\n TableSchema_,\n TableValidator_,\n Indexes_,\n SearchIndexes_,\n VectorIndexes_,\n GroupOf<TableSchema_, Key>\n >;\n}\n\nexport interface UnnamedAny {\n readonly [TypeId]: TypeId;\n}\n\nexport type UnnamedAnyWithProps = UnnamedTable<\n Schema.Codec<any, any>,\n GenericValidator,\n GenericTableIndexes,\n GenericTableSearchIndexes,\n GenericTableVectorIndexes,\n Group | undefined\n>;\n\n// -----------------------------------------------------------------------------\n// Type extractors\n// -----------------------------------------------------------------------------\n\nexport type Name<TableDef extends AnyWithProps> = TableDef[\"tableName\"] &\n string;\n\nexport type TableSchema<TableDef extends AnyWithProps> = TableDef[\"Fields\"];\n\nexport type TableValidator<TableDef extends AnyWithProps> =\n TableDef[\"~TableValidator\"];\n\nexport type Indexes<TableDef extends AnyWithProps> = TableDef[\"indexes\"];\n\nexport type SearchIndexes<TableDef extends AnyWithProps> =\n TableDef[\"searchIndexes\"];\n\nexport type VectorIndexes<TableDef extends AnyWithProps> =\n TableDef[\"vectorIndexes\"];\n\nexport type Doc<TableDef extends AnyWithProps> = TableDef[\"Doc\"];\n\nexport type Fields<TableDef extends AnyWithProps> = TableDef[\"Fields\"];\nexport type Scope<TableDef extends AnyWithProps> = TableDef[\"scope\"];\n\nexport type WithName<\n TableDef extends AnyWithProps,\n Name_ extends string,\n> = TableDef extends { readonly tableName: Name_ } ? TableDef : never;\n\nexport type TablesRecord<Tables extends AnyWithProps> = {\n readonly [TableName_ in Name<Tables>]: WithName<Tables, TableName_>;\n};\n\n// -----------------------------------------------------------------------------\n// Construction\n// -----------------------------------------------------------------------------\n//\n// `make` only stores the user-supplied `lazyFields` callback alongside any\n// chained index metadata. Neither `Fields` nor `Doc` is constructed until\n// first access on a bound `Table`. Each chain step is O(1) (plain object\n// spread of the metadata records) and never invokes the callback. Binding\n// via `unnamed(tableName)` installs lazy memoised getters for `Fields` and\n// `Doc` via `Lazy.defineProperty`, so the first access materialises the\n// value and replaces the getter with a plain data property—second-and-\n// subsequent accesses are observably indistinguishable from a plain\n// property and avoid all function-call overhead.\n\ninterface UnnamedState<\n TableSchema_ extends Schema.Codec<any, any>,\n Indexes_ extends GenericTableIndexes,\n SearchIndexes_ extends GenericTableSearchIndexes,\n VectorIndexes_ extends GenericTableVectorIndexes,\n> {\n readonly lazyFields: () => TableSchema_;\n readonly groupKey: string | undefined;\n readonly indexes: Indexes_;\n readonly searchIndexes: SearchIndexes_;\n readonly vectorIndexes: VectorIndexes_;\n}\n\nconst makeBound = <\n Name_ extends string,\n TableSchema_ extends Schema.Codec<any, any>,\n TableValidator_ extends Validator<any, any, any>,\n Indexes_ extends GenericTableIndexes,\n SearchIndexes_ extends GenericTableSearchIndexes,\n VectorIndexes_ extends GenericTableVectorIndexes,\n Scope_ extends IdScope.IdScope,\n Group_ extends Group | undefined,\n>(\n tableName: Name_,\n state: UnnamedState<TableSchema_, Indexes_, SearchIndexes_, VectorIndexes_>,\n scope: Scope_,\n): Table<\n Name_,\n TableSchema_,\n TableValidator_,\n Indexes_,\n SearchIndexes_,\n VectorIndexes_,\n Scope_,\n Group_\n> => {\n const bound = {\n [TypeId]: TypeId as TypeId,\n tableName,\n scope,\n group:\n state.groupKey === undefined\n ? undefined\n : makeGroup(tableName, state.groupKey, () => bound.Fields),\n indexes: state.indexes,\n searchIndexes: state.searchIndexes,\n vectorIndexes: state.vectorIndexes,\n } as Table<\n Name_,\n TableSchema_,\n TableValidator_,\n Indexes_,\n SearchIndexes_,\n VectorIndexes_,\n Scope_,\n Group_\n >;\n\n Lazy.defineProperty(bound, \"Fields\", () => state.lazyFields());\n\n Lazy.defineProperty(bound, \"Doc\", () =>\n SystemFields.extendWithSystemFields(\n tableName,\n (bound as { Fields: TableSchema_ }).Fields,\n scope,\n ),\n );\n\n return bound;\n};\n\nconst makeUnnamed = <\n TableSchema_ extends Schema.Codec<any, any>,\n TableValidator_ extends Validator<any, any, any>,\n Indexes_ extends GenericTableIndexes,\n SearchIndexes_ extends GenericTableSearchIndexes,\n VectorIndexes_ extends GenericTableVectorIndexes,\n Group_ extends Group | undefined,\n>(\n state: UnnamedState<TableSchema_, Indexes_, SearchIndexes_, VectorIndexes_>,\n): UnnamedTable<\n TableSchema_,\n TableValidator_,\n Indexes_,\n SearchIndexes_,\n VectorIndexes_,\n Group_\n> => {\n type UnnamedTable_ = UnnamedTable<\n TableSchema_,\n TableValidator_,\n Indexes_,\n SearchIndexes_,\n VectorIndexes_,\n Group_\n >;\n\n type UnnamedTableFunction<FunctionName extends keyof UnnamedTable_> =\n UnnamedTable_[FunctionName];\n\n const bind = <\n const Name_ extends string,\n const Scope_ extends IdScope.IdScope = IdScope.App,\n >(\n tableName: Name_,\n scope?: Scope_,\n ): Table<\n Name_,\n TableSchema_,\n TableValidator_,\n Indexes_,\n SearchIndexes_,\n VectorIndexes_,\n Scope_,\n Group_\n > =>\n makeBound<\n Name_,\n TableSchema_,\n TableValidator_,\n Indexes_,\n SearchIndexes_,\n VectorIndexes_,\n Scope_,\n Group_\n >(tableName, state, (scope ?? IdScope.app) as Scope_);\n\n const index: UnnamedTableFunction<\"index\"> = (name, fields) =>\n makeUnnamed({\n ...state,\n indexes: {\n ...state.indexes,\n [name]: fields,\n } as any,\n });\n\n const searchIndex: UnnamedTableFunction<\"searchIndex\"> = (\n name,\n indexConfig,\n ) =>\n makeUnnamed({\n ...state,\n searchIndexes: {\n ...state.searchIndexes,\n [name]: indexConfig,\n } as any,\n });\n\n const vectorIndex: UnnamedTableFunction<\"vectorIndex\"> = (\n name,\n indexConfig,\n ) =>\n makeUnnamed({\n ...state,\n vectorIndexes: {\n ...state.vectorIndexes,\n [name]: indexConfig,\n } as any,\n });\n\n const group: UnnamedTableFunction<\"group\"> = (key) =>\n makeUnnamed({ ...state, groupKey: key });\n\n return Object.assign(bind, {\n [TypeId]: TypeId as TypeId,\n indexes: state.indexes,\n searchIndexes: state.searchIndexes,\n vectorIndexes: state.vectorIndexes,\n index,\n searchIndex,\n vectorIndex,\n group,\n }) as UnnamedTable_;\n};\n\nexport const make = <const TableSchema_ extends Schema.Codec<any, any>>(\n lazyFields: () => TableSchema_,\n): UnnamedTable<TableSchema_, TableSchemaToTableValidator<TableSchema_>> => {\n type TableValidator_ = TableSchemaToTableValidator<TableSchema_>;\n type UnnamedTable_ = UnnamedTable<TableSchema_, TableValidator_>;\n\n return makeUnnamed<TableSchema_, TableValidator_, {}, {}, {}, undefined>({\n lazyFields,\n groupKey: undefined,\n indexes: {},\n searchIndexes: {},\n vectorIndexes: {},\n }) as UnnamedTable_;\n};\n\n// Vendored types from convex-js, partially modified. Ideally we could use these directly. See https://github.com/get-convex/convex-js/pull/14\n\n/**\n * Extract all of the index field paths within a Convex `Validator`.\n *\n * This is used when declaring table indexes.\n *\n * @public\n */\ntype ExtractFieldPaths<TableValidator_ extends Validator<any, any, any>> =\n // Add in the system fields available in index definitions.\n // This should be everything except for `_id` because thats added to indexes\n // automatically.\n TableValidator_[\"fieldPaths\"] | keyof ConvexSystemFields;\n"],"mappings":";;;;;;;;;;;;;;;;AAyBA,MAAa,SAAS;AActB,MAAa,WAAW,MACtB,UAAU,YAAY,GAAA,sBAAS,KAAK,UAAU,YAAY,GAAG,WAAW;AAE1E,MAAa,kBAAkB,MAC7B,UAAU,YAAY,GAAA,sBAAS,KAAK,CAAC,UAAU,YAAY,GAAG,WAAW;AAoB3E,IAAa,kBAAb,cAAqC,KAAK,YAAY,iBAAiB,CAAC,CAGrE;CACD,IAAa,UAAkB;EAC7B,OAAO,UAAU,KAAK,UAAU,0BAA0B,KAAK,IAAI;CACrE;AACF;AA8CA,MAAM,aACJ,aACA,KACA,WACU;CACV,MAAM,gBAAgB;EACpB,MAAM,MAAO,OAAO,CAAC,CAClB,SAAS,IAAI,EAAE;EAClB,MAAM,QACJ,QAAQ,KAAA,IAAY,OAAO,KAAK,IAAIA,UAA4B,GAAG;EACrE,IAAI,QAAQ,KAAA,KAAa,OAAO,OAAO,KAAK,GAC1C,MAAM,IAAI,gBAAgB;GAAE,WAAA;GAAW;EAAI,CAAC;EAC9C,OAAO;GAAE,OAAO,MAAM;GAAO,OAAOC,MAAgB,GAAG;EAAE;CAC3D;CACA,MAAM,QAAQ,EAAE,IAAI;CACpB,eAAoB,OAAO,eAAe,QAAQ,CAAC,CAAC,KAAK;CACzD,eAAoB,OAAO,eAAe,QAAQ,CAAC,CAAC,KAAK;CACzD,OAAO;AACT;AAsQA,MAAM,aAUJ,WACA,OACA,UAUG;CACH,MAAM,QAAQ;GACX,SAAS;EACV;EACA;EACA,OACE,MAAM,aAAa,KAAA,IACf,KAAA,IACA,UAAU,WAAW,MAAM,gBAAgB,MAAM,MAAM;EAC7D,SAAS,MAAM;EACf,eAAe,MAAM;EACrB,eAAe,MAAM;CACvB;CAWA,eAAoB,OAAO,gBAAgB,MAAM,WAAW,CAAC;CAE7D,eAAoB,OAAO,aACzBC,uBACE,WACC,MAAmC,QACpC,KACF,CACF;CAEA,OAAO;AACT;AAEA,MAAM,eAQJ,UAQG;CAaH,MAAM,QAIJ,WACA,UAWA,UASE,WAAW,OAAQ,SAASC,GAAsB;CAEtD,MAAM,SAAwC,MAAM,WAClD,YAAY;EACV,GAAG;EACH,SAAS;GACP,GAAG,MAAM;IACR,OAAO;EACV;CACF,CAAC;CAEH,MAAM,eACJ,MACA,gBAEA,YAAY;EACV,GAAG;EACH,eAAe;GACb,GAAG,MAAM;IACR,OAAO;EACV;CACF,CAAC;CAEH,MAAM,eACJ,MACA,gBAEA,YAAY;EACV,GAAG;EACH,eAAe;GACb,GAAG,MAAM;IACR,OAAO;EACV;CACF,CAAC;CAEH,MAAM,SAAwC,QAC5C,YAAY;EAAE,GAAG;EAAO,UAAU;CAAI,CAAC;CAEzC,OAAO,OAAO,OAAO,MAAM;GACxB,SAAS;EACV,SAAS,MAAM;EACf,eAAe,MAAM;EACrB,eAAe,MAAM;EACrB;EACA;EACA;EACA;CACF,CAAC;AACH;AAEA,MAAa,QACX,eAC0E;CAI1E,OAAO,YAAkE;EACvE;EACA,UAAU,KAAA;EACV,SAAS,CAAC;EACV,eAAe,CAAC;EAChB,eAAe,CAAC;CAClB,CAAC;AACH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gaganref/confect-core",
3
- "version": "10.3.1-fork.75",
3
+ "version": "10.3.1-fork.77",
4
4
  "peerDependencies": {
5
5
  "convex": "^1.49.0",
6
6
  "effect": ">=4.0.0 <4.1.0"
package/src/Component.ts CHANGED
@@ -18,6 +18,7 @@ import * as Ref from "./Ref.js";
18
18
  import type * as Refs from "./Refs.js";
19
19
  import type * as RuntimeAndFunctionType from "./RuntimeAndFunctionType.js";
20
20
  import * as Spec from "./Spec.js";
21
+ import type * as Table_ from "./Table.js";
21
22
 
22
23
  export class EmptyComponentScopeError extends Data.TaggedError(
23
24
  "EmptyComponentScopeError",
@@ -142,19 +143,100 @@ interface Tree {
142
143
  readonly [key: string]: Tree | Ref.Any;
143
144
  }
144
145
 
146
+ /**
147
+ * Each grouped table's name, mapped to its id field and that id's table.
148
+ */
149
+ export interface GroupMap {
150
+ readonly [table: string]: { readonly key: string; readonly table: string };
151
+ }
152
+
145
153
  export interface Component<
146
154
  Spec_ extends Spec.AnyWithProps,
147
155
  Scope extends IdScope.IdScope,
148
156
  Tables extends string = string,
157
+ Groups_ extends GroupMap = GroupMap,
149
158
  > {
150
159
  readonly [TypeId]: {
151
160
  readonly refs: Tree;
152
161
  readonly scope: Scope;
153
162
  readonly tables: ReadonlyArray<Tables>;
163
+ readonly groups: Groups_;
154
164
  };
155
165
  readonly "~Spec": Spec_;
156
166
  }
157
167
 
168
+ /**
169
+ * A component's tables as `contract` takes them: a table, or the name of a
170
+ * system table.
171
+ */
172
+ export type TableEntry = string | Table_.AnyWithProps;
173
+
174
+ type EntryName<Entry extends TableEntry> = Entry extends string
175
+ ? Entry
176
+ : Entry extends Table_.AnyWithProps
177
+ ? Table_.Name<Entry>
178
+ : never;
179
+
180
+ type Many<A, All = A> = string extends A
181
+ ? true
182
+ : number extends A
183
+ ? true
184
+ : A extends unknown
185
+ ? [All] extends [A]
186
+ ? never
187
+ : true
188
+ : never;
189
+
190
+ type Loose<Entries extends ReadonlyArray<TableEntry>> = true extends
191
+ | Many<Entries>
192
+ | Many<Entries["length"]>
193
+ | { [Index in keyof Entries]: Many<Entries[Index]> }[number]
194
+ ? "pass one table or one name per entry; a union may be absent at runtime"
195
+ : never;
196
+
197
+ type StrayGroup<
198
+ Entries extends ReadonlyArray<TableEntry>,
199
+ Scope extends IdScope.IdScope,
200
+ > = [Loose<Entries>] extends [never]
201
+ ? {
202
+ [Index in keyof Entries]: Entries[Index] extends {
203
+ readonly tableName: infer Name extends string;
204
+ readonly group: Table_.Group<infer Key, infer Target, infer GroupScope>;
205
+ }
206
+ ? [Target, GroupScope] extends [EntryName<Entries[number]>, Scope]
207
+ ? never
208
+ : `${Name}.${Key} is not an id of a table of this component`
209
+ : never;
210
+ }[number]
211
+ : Loose<Entries>;
212
+
213
+ /**
214
+ * The group map `contract` publishes for these table entries.
215
+ */
216
+ export type Groups<Entries extends ReadonlyArray<TableEntry>> = {
217
+ readonly [
218
+ Entry in Extract<
219
+ Entries[number],
220
+ { readonly tableName: string; readonly group: Table_.Group }
221
+ > as Entry["tableName"]
222
+ ]: {
223
+ readonly key: Entry["group"]["key"];
224
+ readonly table: Entry["group"]["table"];
225
+ };
226
+ };
227
+
228
+ /**
229
+ * `unknown` when every entry is one table or name and every group's id names a
230
+ * table of this component in its scope, otherwise an object type naming the
231
+ * refused entry.
232
+ */
233
+ export type CheckGroups<
234
+ Entries extends ReadonlyArray<TableEntry>,
235
+ Scope extends IdScope.IdScope,
236
+ > = [StrayGroup<Entries, Scope>] extends [never]
237
+ ? unknown
238
+ : { readonly "~StrayGroup": StrayGroup<Entries, Scope> };
239
+
158
240
  /**
159
241
  * An opaque identity: its string representation is not part of the API.
160
242
  */
@@ -214,8 +296,22 @@ export type Bound<
214
296
 
215
297
  /**
216
298
  * Build a publishable contract containing only exported functions and codecs.
299
+ * `tables` lists the component's tables, each a table or a system table's name.
300
+ * A table grouped by an id must group by an id of one of these tables.
301
+ */
302
+ export function contract<
303
+ Spec_ extends Spec.AnyWithProps,
304
+ const Scope extends IdScope.IdScope,
305
+ const Entries extends ReadonlyArray<TableEntry>,
306
+ >(
307
+ spec: Spec_,
308
+ scope: Scope,
309
+ tables: Entries & CheckGroups<Entries, Scope>,
310
+ ): Component<Spec_, Scope, EntryName<Entries[number]>, Groups<Entries>>;
311
+ /**
312
+ * Table names alone, as in an explicit third type argument, carry no groups.
217
313
  */
218
- export const contract = <
314
+ export function contract<
219
315
  Spec_ extends Spec.AnyWithProps,
220
316
  const Scope extends IdScope.IdScope,
221
317
  const Tables extends string,
@@ -223,7 +319,12 @@ export const contract = <
223
319
  spec: Spec_,
224
320
  scope: Scope,
225
321
  tables: ReadonlyArray<Tables>,
226
- ): Component<Spec_, Scope, Tables> => {
322
+ ): Component<Spec_, Scope, Tables, {}>;
323
+ export function contract(
324
+ spec: Spec.AnyWithProps,
325
+ scope: IdScope.IdScope,
326
+ tables: ReadonlyArray<TableEntry>,
327
+ ): Component<Spec.AnyWithProps, IdScope.IdScope> {
227
328
  const specGroups = Spec.groups(spec);
228
329
  Result.getOrThrow(validateContract(scope, specGroups));
229
330
  const collect = (
@@ -251,10 +352,42 @@ export const contract = <
251
352
  }),
252
353
  Record.filter((children) => !Record.isEmptyRecord(children)),
253
354
  );
254
- return {
255
- [TypeId]: { refs: collect(specGroups), scope, tables },
256
- } as Component<Spec_, Scope, Tables>;
257
- };
355
+ const grouped: GroupMap = pipe(
356
+ tables,
357
+ Array.flatMap((entry) =>
358
+ typeof entry !== "string" && entry.group !== undefined
359
+ ? [[entry.tableName, entry.group] as const]
360
+ : [],
361
+ ),
362
+ Record.fromEntries,
363
+ );
364
+ const published: Component<
365
+ Spec.AnyWithProps,
366
+ IdScope.IdScope
367
+ >[typeof TypeId] = {
368
+ refs: collect(specGroups),
369
+ scope,
370
+ tables: Array.map(tables, (entry) =>
371
+ typeof entry === "string" ? entry : entry.tableName,
372
+ ),
373
+ groups: grouped,
374
+ };
375
+ return { [TypeId]: published } as Component<
376
+ Spec.AnyWithProps,
377
+ IdScope.IdScope
378
+ >;
379
+ }
380
+
381
+ /**
382
+ * Each grouped table's id field and the table that id names.
383
+ */
384
+ export const groups = <Groups_ extends GroupMap>(
385
+ component: Component<Spec.AnyWithProps, IdScope.IdScope, string, Groups_>,
386
+ ): Groups_ =>
387
+ Record.map(component[TypeId].groups, ({ key, table }) => ({
388
+ key,
389
+ table,
390
+ })) as Groups_;
258
391
 
259
392
  /**
260
393
  * Bind the published contract to an actual installed component reference.
package/src/Table.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import * as GenericId from "./GenericId.js";
1
2
  import * as IdScope from "./IdScope.js";
2
3
  import * as Lazy from "./Lazy.js";
3
4
  import * as SystemFields from "./SystemFields.js";
@@ -12,7 +13,13 @@ import type {
12
13
  SearchIndexConfig,
13
14
  VectorIndexConfig,
14
15
  } from "convex/server";
15
- import type { GenericValidator, Validator } from "convex/values";
16
+ import type {
17
+ GenericId as ConvexGenericId,
18
+ GenericValidator,
19
+ Validator,
20
+ } from "convex/values";
21
+ import * as Data from "effect/Data";
22
+ import * as Option from "effect/Option";
16
23
  import * as Predicate from "effect/Predicate";
17
24
  import type * as Schema from "effect/Schema";
18
25
 
@@ -36,6 +43,97 @@ export const isTable = (u: unknown): u is Any =>
36
43
  export const isUnnamedTable = (u: unknown): u is UnnamedAny =>
37
44
  Predicate.hasProperty(u, TypeId) && !Predicate.hasProperty(u, "tableName");
38
45
 
46
+ // -----------------------------------------------------------------------------
47
+ // Group
48
+ // -----------------------------------------------------------------------------
49
+ //
50
+ // A table is grouped by one of its required id fields, and the id's table owns
51
+ // its rows. `table` and `scope` come from the id's schema on first read, so
52
+ // binding a table never builds its `Fields`.
53
+
54
+ export interface Group<
55
+ Key extends string = string,
56
+ Table_ extends string = string,
57
+ Scope_ extends IdScope.IdScope = IdScope.IdScope,
58
+ > {
59
+ readonly key: Key;
60
+ readonly table: Table_;
61
+ readonly scope: Scope_;
62
+ }
63
+
64
+ export class GroupFieldError extends Data.TaggedError("GroupFieldError")<{
65
+ readonly tableName: string;
66
+ readonly key: string;
67
+ }> {
68
+ override get message(): string {
69
+ return `Table '${this.tableName}' cannot be grouped by '${this.key}': it is not a field holding an id.`;
70
+ }
71
+ }
72
+
73
+ type FieldsOf<TableSchema_> = TableSchema_ extends {
74
+ readonly fields: infer StructFields extends Schema.Struct.Fields;
75
+ }
76
+ ? StructFields
77
+ : never;
78
+
79
+ type GroupKeys<TableSchema_> = {
80
+ [
81
+ Key in keyof FieldsOf<TableSchema_> & string
82
+ ]: FieldsOf<TableSchema_>[Key] extends {
83
+ readonly Type: ConvexGenericId<string>;
84
+ }
85
+ ? [FieldsOf<TableSchema_>[Key]["~type.optionality"]] extends ["optional"]
86
+ ? never
87
+ : Key
88
+ : never;
89
+ }[keyof FieldsOf<TableSchema_> & string];
90
+
91
+ type IdTableName<Id> = Id extends {
92
+ readonly "~@confect/core/ScopedId": {
93
+ readonly table: infer TableName extends string;
94
+ };
95
+ }
96
+ ? TableName
97
+ : Id extends ConvexGenericId<infer TableName>
98
+ ? TableName
99
+ : never;
100
+
101
+ type IdScopeOf<Id> = Id extends {
102
+ readonly "~@confect/core/ScopedId": {
103
+ readonly scope: infer Scope_ extends IdScope.IdScope;
104
+ };
105
+ }
106
+ ? Scope_
107
+ : IdScope.App;
108
+
109
+ type GroupOf<TableSchema_, Key extends string> = Group<
110
+ Key,
111
+ IdTableName<
112
+ FieldsOf<TableSchema_>[Key & keyof FieldsOf<TableSchema_>]["Type"]
113
+ >,
114
+ IdScopeOf<FieldsOf<TableSchema_>[Key & keyof FieldsOf<TableSchema_>]["Type"]>
115
+ >;
116
+
117
+ const makeGroup = (
118
+ tableName: string,
119
+ key: string,
120
+ fields: () => Schema.Codec<any, any>,
121
+ ): Group => {
122
+ const idField = () => {
123
+ const ast = (fields() as { readonly fields?: Schema.Struct.Fields })
124
+ .fields?.[key]?.ast;
125
+ const table =
126
+ ast === undefined ? Option.none() : GenericId.tableName<string>(ast);
127
+ if (ast === undefined || Option.isNone(table))
128
+ throw new GroupFieldError({ tableName, key });
129
+ return { table: table.value, scope: GenericId.scope(ast) };
130
+ };
131
+ const group = { key };
132
+ Lazy.defineProperty(group, "table", () => idField().table);
133
+ Lazy.defineProperty(group, "scope", () => idField().scope);
134
+ return group as Group;
135
+ };
136
+
39
137
  // -----------------------------------------------------------------------------
40
138
  // Bound Table
41
139
  // -----------------------------------------------------------------------------
@@ -54,10 +152,12 @@ export interface Table<
54
152
  SearchIndexes_ extends GenericTableSearchIndexes = {},
55
153
  VectorIndexes_ extends GenericTableVectorIndexes = {},
56
154
  Scope_ extends IdScope.IdScope = IdScope.App,
155
+ Group_ extends Group | undefined = undefined,
57
156
  > {
58
157
  readonly [TypeId]: TypeId;
59
158
  readonly tableName: Name_;
60
159
  readonly scope: Scope_;
160
+ readonly group: Group_;
61
161
  readonly Fields: TableSchema_;
62
162
  readonly Doc: SystemFields.ExtendWithSystemFields<
63
163
  Name_,
@@ -82,7 +182,8 @@ export type AnyWithProps = Table<
82
182
  GenericTableIndexes,
83
183
  GenericTableSearchIndexes,
84
184
  GenericTableVectorIndexes,
85
- IdScope.IdScope
185
+ IdScope.IdScope,
186
+ Group | undefined
86
187
  >;
87
188
 
88
189
  // -----------------------------------------------------------------------------
@@ -105,6 +206,7 @@ export interface UnnamedTable<
105
206
  Indexes_ extends GenericTableIndexes = {},
106
207
  SearchIndexes_ extends GenericTableSearchIndexes = {},
107
208
  VectorIndexes_ extends GenericTableVectorIndexes = {},
209
+ Group_ extends Group | undefined = undefined,
108
210
  > {
109
211
  <
110
212
  const Name_ extends string,
@@ -119,7 +221,8 @@ export interface UnnamedTable<
119
221
  Indexes_,
120
222
  SearchIndexes_,
121
223
  VectorIndexes_,
122
- Scope_
224
+ Scope_,
225
+ Group_
123
226
  >;
124
227
 
125
228
  readonly [TypeId]: TypeId;
@@ -146,7 +249,8 @@ export interface UnnamedTable<
146
249
  >
147
250
  >,
148
251
  SearchIndexes_,
149
- VectorIndexes_
252
+ VectorIndexes_,
253
+ Group_
150
254
  >;
151
255
 
152
256
  searchIndex<
@@ -170,7 +274,8 @@ export interface UnnamedTable<
170
274
  }
171
275
  >
172
276
  >,
173
- VectorIndexes_
277
+ VectorIndexes_,
278
+ Group_
174
279
  >;
175
280
 
176
281
  vectorIndex<
@@ -195,7 +300,23 @@ export interface UnnamedTable<
195
300
  filterFields: FilterFields;
196
301
  }
197
302
  >
198
- >
303
+ >,
304
+ Group_
305
+ >;
306
+
307
+ /**
308
+ * Name the required id field that groups this table's rows. The field's table
309
+ * is the one whose rows own these rows.
310
+ */
311
+ group<const Key extends GroupKeys<TableSchema_>>(
312
+ key: Key,
313
+ ): UnnamedTable<
314
+ TableSchema_,
315
+ TableValidator_,
316
+ Indexes_,
317
+ SearchIndexes_,
318
+ VectorIndexes_,
319
+ GroupOf<TableSchema_, Key>
199
320
  >;
200
321
  }
201
322
 
@@ -208,7 +329,8 @@ export type UnnamedAnyWithProps = UnnamedTable<
208
329
  GenericValidator,
209
330
  GenericTableIndexes,
210
331
  GenericTableSearchIndexes,
211
- GenericTableVectorIndexes
332
+ GenericTableVectorIndexes,
333
+ Group | undefined
212
334
  >;
213
335
 
214
336
  // -----------------------------------------------------------------------------
@@ -266,6 +388,7 @@ interface UnnamedState<
266
388
  VectorIndexes_ extends GenericTableVectorIndexes,
267
389
  > {
268
390
  readonly lazyFields: () => TableSchema_;
391
+ readonly groupKey: string | undefined;
269
392
  readonly indexes: Indexes_;
270
393
  readonly searchIndexes: SearchIndexes_;
271
394
  readonly vectorIndexes: VectorIndexes_;
@@ -279,6 +402,7 @@ const makeBound = <
279
402
  SearchIndexes_ extends GenericTableSearchIndexes,
280
403
  VectorIndexes_ extends GenericTableVectorIndexes,
281
404
  Scope_ extends IdScope.IdScope,
405
+ Group_ extends Group | undefined,
282
406
  >(
283
407
  tableName: Name_,
284
408
  state: UnnamedState<TableSchema_, Indexes_, SearchIndexes_, VectorIndexes_>,
@@ -290,12 +414,17 @@ const makeBound = <
290
414
  Indexes_,
291
415
  SearchIndexes_,
292
416
  VectorIndexes_,
293
- Scope_
417
+ Scope_,
418
+ Group_
294
419
  > => {
295
420
  const bound = {
296
421
  [TypeId]: TypeId as TypeId,
297
422
  tableName,
298
423
  scope,
424
+ group:
425
+ state.groupKey === undefined
426
+ ? undefined
427
+ : makeGroup(tableName, state.groupKey, () => bound.Fields),
299
428
  indexes: state.indexes,
300
429
  searchIndexes: state.searchIndexes,
301
430
  vectorIndexes: state.vectorIndexes,
@@ -306,7 +435,8 @@ const makeBound = <
306
435
  Indexes_,
307
436
  SearchIndexes_,
308
437
  VectorIndexes_,
309
- Scope_
438
+ Scope_,
439
+ Group_
310
440
  >;
311
441
 
312
442
  Lazy.defineProperty(bound, "Fields", () => state.lazyFields());
@@ -328,6 +458,7 @@ const makeUnnamed = <
328
458
  Indexes_ extends GenericTableIndexes,
329
459
  SearchIndexes_ extends GenericTableSearchIndexes,
330
460
  VectorIndexes_ extends GenericTableVectorIndexes,
461
+ Group_ extends Group | undefined,
331
462
  >(
332
463
  state: UnnamedState<TableSchema_, Indexes_, SearchIndexes_, VectorIndexes_>,
333
464
  ): UnnamedTable<
@@ -335,14 +466,16 @@ const makeUnnamed = <
335
466
  TableValidator_,
336
467
  Indexes_,
337
468
  SearchIndexes_,
338
- VectorIndexes_
469
+ VectorIndexes_,
470
+ Group_
339
471
  > => {
340
472
  type UnnamedTable_ = UnnamedTable<
341
473
  TableSchema_,
342
474
  TableValidator_,
343
475
  Indexes_,
344
476
  SearchIndexes_,
345
- VectorIndexes_
477
+ VectorIndexes_,
478
+ Group_
346
479
  >;
347
480
 
348
481
  type UnnamedTableFunction<FunctionName extends keyof UnnamedTable_> =
@@ -361,7 +494,8 @@ const makeUnnamed = <
361
494
  Indexes_,
362
495
  SearchIndexes_,
363
496
  VectorIndexes_,
364
- Scope_
497
+ Scope_,
498
+ Group_
365
499
  > =>
366
500
  makeBound<
367
501
  Name_,
@@ -370,18 +504,17 @@ const makeUnnamed = <
370
504
  Indexes_,
371
505
  SearchIndexes_,
372
506
  VectorIndexes_,
373
- Scope_
507
+ Scope_,
508
+ Group_
374
509
  >(tableName, state, (scope ?? IdScope.app) as Scope_);
375
510
 
376
511
  const index: UnnamedTableFunction<"index"> = (name, fields) =>
377
512
  makeUnnamed({
378
- lazyFields: state.lazyFields,
513
+ ...state,
379
514
  indexes: {
380
515
  ...state.indexes,
381
516
  [name]: fields,
382
517
  } as any,
383
- searchIndexes: state.searchIndexes,
384
- vectorIndexes: state.vectorIndexes,
385
518
  });
386
519
 
387
520
  const searchIndex: UnnamedTableFunction<"searchIndex"> = (
@@ -389,13 +522,11 @@ const makeUnnamed = <
389
522
  indexConfig,
390
523
  ) =>
391
524
  makeUnnamed({
392
- lazyFields: state.lazyFields,
393
- indexes: state.indexes,
525
+ ...state,
394
526
  searchIndexes: {
395
527
  ...state.searchIndexes,
396
528
  [name]: indexConfig,
397
529
  } as any,
398
- vectorIndexes: state.vectorIndexes,
399
530
  });
400
531
 
401
532
  const vectorIndex: UnnamedTableFunction<"vectorIndex"> = (
@@ -403,15 +534,16 @@ const makeUnnamed = <
403
534
  indexConfig,
404
535
  ) =>
405
536
  makeUnnamed({
406
- lazyFields: state.lazyFields,
407
- indexes: state.indexes,
408
- searchIndexes: state.searchIndexes,
537
+ ...state,
409
538
  vectorIndexes: {
410
539
  ...state.vectorIndexes,
411
540
  [name]: indexConfig,
412
541
  } as any,
413
542
  });
414
543
 
544
+ const group: UnnamedTableFunction<"group"> = (key) =>
545
+ makeUnnamed({ ...state, groupKey: key });
546
+
415
547
  return Object.assign(bind, {
416
548
  [TypeId]: TypeId as TypeId,
417
549
  indexes: state.indexes,
@@ -420,6 +552,7 @@ const makeUnnamed = <
420
552
  index,
421
553
  searchIndex,
422
554
  vectorIndex,
555
+ group,
423
556
  }) as UnnamedTable_;
424
557
  };
425
558
 
@@ -429,8 +562,9 @@ export const make = <const TableSchema_ extends Schema.Codec<any, any>>(
429
562
  type TableValidator_ = TableSchemaToTableValidator<TableSchema_>;
430
563
  type UnnamedTable_ = UnnamedTable<TableSchema_, TableValidator_>;
431
564
 
432
- return makeUnnamed<TableSchema_, TableValidator_, {}, {}, {}>({
565
+ return makeUnnamed<TableSchema_, TableValidator_, {}, {}, {}, undefined>({
433
566
  lazyFields,
567
+ groupKey: undefined,
434
568
  indexes: {},
435
569
  searchIndexes: {},
436
570
  vectorIndexes: {},