@confect/server 9.0.0-next.5 → 9.0.0-next.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/CHANGELOG.md +156 -0
  2. package/dist/Auth.d.ts +1 -1
  3. package/dist/DatabaseReader.d.ts +4299 -26
  4. package/dist/DatabaseReader.d.ts.map +1 -1
  5. package/dist/DatabaseReader.js +5 -6
  6. package/dist/DatabaseReader.js.map +1 -1
  7. package/dist/DatabaseSchema.d.ts +25 -112
  8. package/dist/DatabaseSchema.d.ts.map +1 -1
  9. package/dist/DatabaseSchema.js +20 -30
  10. package/dist/DatabaseSchema.js.map +1 -1
  11. package/dist/DatabaseWriter.d.ts +4 -4
  12. package/dist/DatabaseWriter.d.ts.map +1 -1
  13. package/dist/DatabaseWriter.js +3 -4
  14. package/dist/DatabaseWriter.js.map +1 -1
  15. package/dist/FunctionImpl.d.ts +26 -17
  16. package/dist/FunctionImpl.d.ts.map +1 -1
  17. package/dist/FunctionImpl.js +22 -14
  18. package/dist/FunctionImpl.js.map +1 -1
  19. package/dist/GroupImpl.d.ts +22 -13
  20. package/dist/GroupImpl.d.ts.map +1 -1
  21. package/dist/GroupImpl.js +34 -35
  22. package/dist/GroupImpl.js.map +1 -1
  23. package/dist/Handler.d.ts +1 -1
  24. package/dist/QueryInitializer.d.ts +1 -1
  25. package/dist/QueryInitializer.d.ts.map +1 -1
  26. package/dist/QueryInitializer.js.map +1 -1
  27. package/dist/RegisteredConvexFunction.d.ts +1084 -17
  28. package/dist/RegisteredConvexFunction.d.ts.map +1 -1
  29. package/dist/RegisteredConvexFunction.js +4 -4
  30. package/dist/RegisteredConvexFunction.js.map +1 -1
  31. package/dist/RegisteredFunction.d.ts +3 -3
  32. package/dist/RegisteredFunction.d.ts.map +1 -1
  33. package/dist/RegisteredFunctions.d.ts +36 -12
  34. package/dist/RegisteredFunctions.d.ts.map +1 -1
  35. package/dist/RegisteredFunctions.js +21 -9
  36. package/dist/RegisteredFunctions.js.map +1 -1
  37. package/dist/RegisteredNodeFunction.d.ts +4 -4
  38. package/dist/RegisteredNodeFunction.d.ts.map +1 -1
  39. package/dist/RegisteredNodeFunction.js +2 -2
  40. package/dist/RegisteredNodeFunction.js.map +1 -1
  41. package/dist/StorageActionWriter.d.ts +1 -1
  42. package/dist/Table.d.ts +35 -27
  43. package/dist/Table.d.ts.map +1 -1
  44. package/dist/Table.js +69 -60
  45. package/dist/Table.js.map +1 -1
  46. package/dist/index.d.ts +4 -5
  47. package/dist/index.js +4 -5
  48. package/package.json +51 -52
  49. package/src/DatabaseReader.ts +17 -21
  50. package/src/DatabaseSchema.ts +38 -98
  51. package/src/DatabaseWriter.ts +8 -5
  52. package/src/FunctionImpl.ts +33 -43
  53. package/src/GroupImpl.ts +45 -69
  54. package/src/QueryInitializer.ts +10 -2
  55. package/src/RegisteredConvexFunction.ts +5 -6
  56. package/src/RegisteredFunctions.ts +67 -93
  57. package/src/RegisteredNodeFunction.ts +3 -4
  58. package/src/Table.ts +251 -131
  59. package/src/index.ts +0 -1
  60. package/dist/Api.d.ts +0 -43
  61. package/dist/Api.d.ts.map +0 -1
  62. package/dist/Api.js +0 -43
  63. package/dist/Api.js.map +0 -1
  64. package/src/Api.ts +0 -102
@@ -1,10 +1,5 @@
1
- import type { Expand, GenericSchema } from "convex/server";
2
- import {
3
- defineSchema as defineConvexSchema,
4
- type SchemaDefinition,
5
- } from "convex/server";
6
- import { Array, pipe, Predicate, Record } from "effect";
7
- import * as Table from "./Table";
1
+ import { Predicate } from "effect";
2
+ import type * as Table from "./Table";
8
3
 
9
4
  export const TypeId = "@confect/server/DatabaseSchema";
10
5
  export type TypeId = typeof TypeId;
@@ -17,29 +12,25 @@ export const isDatabaseSchema = (u: unknown): u is Any =>
17
12
  Predicate.hasProperty(u, TypeId);
18
13
 
19
14
  /**
20
- * A schema definition tracks the schema and its Convex schema definition.
15
+ * A schema definition holding a record of bound `Table`s keyed by table
16
+ * name. Codegen emits a single static `DatabaseSchema.make({ ... })` call;
17
+ * laziness now lives entirely on each `Table` (its `Fields`, `Doc`, and
18
+ * `tableDefinition` are lazy memoised getters), so this layer is a plain
19
+ * record indirection with no module-loading or async machinery.
21
20
  */
22
21
  export interface DatabaseSchema<Tables_ extends Table.AnyWithProps = never> {
23
22
  readonly [TypeId]: TypeId;
24
- readonly tables: Table.TablesRecord<Tables_>;
25
- readonly convexSchemaDefinition: SchemaDefinition<
26
- ConvexDatabaseSchemaFromTables<Tables_>,
27
- true
28
- >;
29
-
30
- /**
31
- * Add a table definition to the schema.
32
- */
33
- addTable<TableDef extends Table.AnyWithProps>(
34
- table: TableDef,
35
- ): DatabaseSchema<Tables_ | TableDef>;
23
+ readonly tables: {
24
+ readonly [TableName in Table.Name<Tables_>]: Table.WithName<
25
+ Tables_,
26
+ TableName
27
+ >;
28
+ };
36
29
  }
37
30
 
38
31
  export interface AnyWithProps {
39
32
  readonly [TypeId]: TypeId;
40
33
  readonly tables: Record<string, Table.AnyWithProps>;
41
- readonly convexSchemaDefinition: SchemaDefinition<GenericSchema, true>;
42
- addTable<TableDef extends Table.AnyWithProps>(table: TableDef): AnyWithProps;
43
34
  }
44
35
 
45
36
  export type Tables<DatabaseSchema_ extends AnyWithProps> =
@@ -53,82 +44,31 @@ export type TableNames<DatabaseSchema_ extends AnyWithProps> = Table.Name<
53
44
  export type TableWithName<
54
45
  DatabaseSchema_ extends AnyWithProps,
55
46
  TableName extends TableNames<DatabaseSchema_>,
56
- > = Extract<Tables<DatabaseSchema_>, { readonly name: TableName }>;
57
-
58
- const Proto = {
59
- [TypeId]: TypeId,
60
-
61
- addTable<TableDef extends Table.AnyWithProps>(
62
- this: DatabaseSchema<Table.AnyWithProps>,
63
- table: TableDef,
64
- ) {
65
- const tablesArray = Object.values(this.tables) as Table.AnyWithProps[];
66
- const newTablesArray = [...tablesArray, table];
67
-
68
- return makeProto({
69
- tables: Record.set(this.tables, table.name, table),
70
- convexSchemaDefinition: pipe(
71
- newTablesArray,
72
- Array.map(
73
- ({ name, tableDefinition }) => [name, tableDefinition] as const,
74
- ),
75
- Record.fromEntries,
76
- defineConvexSchema,
77
- ),
78
- });
79
- },
80
- };
81
-
82
- const makeProto = <Tables_ extends Table.AnyWithProps>({
83
- tables,
84
- convexSchemaDefinition,
85
- }: {
86
- tables: Record.ReadonlyRecord<string, Tables_>;
87
- convexSchemaDefinition: SchemaDefinition<GenericSchema, true>;
88
- }): DatabaseSchema<Tables_> =>
89
- Object.assign(Object.create(Proto), {
90
- tables,
91
- convexSchemaDefinition,
92
- });
47
+ > = Extract<Tables<DatabaseSchema_>, { readonly tableName: TableName }>;
93
48
 
94
49
  /**
95
- * Create an empty schema definition. Add tables incrementally via `addTable`.
50
+ * Construct a `DatabaseSchema` from a record of bound `Table`s. The empty
51
+ * case is `DatabaseSchema.make({})`. The `Tables_` union is inferred from
52
+ * the value record's values, so codegen-emitted calls of the form
53
+ * `DatabaseSchema.make({ notes, tags, users })` do not need an explicit
54
+ * type argument.
55
+ *
56
+ * Invariant: each record **key must equal its value's `tableName`**. The
57
+ * record is stored verbatim and later read by key (`databaseSchema.tables[
58
+ * tableName]` in `DatabaseReader`/`DatabaseWriter`), so a key that diverges
59
+ * from the bound table's name would make those lookups silently miss. The
60
+ * type signature does not enforce this — codegen upholds it by deriving both
61
+ * the key and the table name from the same filename (and the shorthand
62
+ * `{ notes, tags, users }` form it emits makes them identical by
63
+ * construction). Hand-written calls must preserve it.
96
64
  */
97
- export const make = (): DatabaseSchema<never> =>
98
- makeProto({
99
- tables: Record.empty(),
100
- convexSchemaDefinition: defineConvexSchema({}),
101
- });
102
-
103
- export type ConvexDatabaseSchemaFromTables<Tables_ extends Table.AnyWithProps> =
104
- Expand<{
105
- [TableName in Table.Name<Tables_> & string]: Table.WithName<
106
- Tables_,
107
- TableName
108
- >["tableDefinition"];
109
- }>;
110
-
111
- // System tables
112
-
113
- export const systemSchema = make()
114
- .addTable(Table.scheduledFunctionsTable)
115
- .addTable(Table.storageTable);
116
-
117
- export const extendWithSystemTables = <Tables_ extends Table.AnyWithProps>(
118
- tables: Table.TablesRecord<Tables_>,
119
- ): ExtendWithSystemTables<Tables_> =>
120
- ({
121
- ...tables,
122
- ...Table.systemTables,
123
- }) as ExtendWithSystemTables<Tables_>;
124
-
125
- export type ExtendWithSystemTables<Tables_ extends Table.AnyWithProps> =
126
- Table.TablesRecord<Tables_ | Table.SystemTables>;
127
-
128
- export type IncludeSystemTables<Tables_ extends Table.AnyWithProps> =
129
- | Tables_
130
- | Table.SystemTables extends infer T
131
- ? T extends Table.AnyWithProps
132
- ? T
133
- : never
134
- : never;
65
+ export const make = <
66
+ const TablesRecord extends Record<string, Table.AnyWithProps>,
67
+ >(
68
+ tables: TablesRecord,
69
+ ): DatabaseSchema<TablesRecord[keyof TablesRecord]> => ({
70
+ [TypeId]: TypeId,
71
+ tables: tables as unknown as DatabaseSchema<
72
+ TablesRecord[keyof TablesRecord]
73
+ >["tables"],
74
+ });
@@ -22,14 +22,13 @@ export const make = <DatabaseSchema_ extends DatabaseSchema.AnyWithProps>(
22
22
  >,
23
23
  ) => {
24
24
  type DataModel_ = DataModel.FromSchema<DatabaseSchema_>;
25
- const tables = databaseSchema.tables as Record<string, Table.AnyWithProps>;
26
25
 
27
26
  const table = <const TableName extends DataModel.TableNames<DataModel_>>(
28
27
  tableName: TableName,
29
28
  ) => {
30
- const tableDef = tables[tableName]!;
31
- const tableSchema = tableDef.Fields as TableInfo.TableSchema<
32
- DataModel.TableInfoWithName_<DataModel_, TableName>
29
+ const tableDef = databaseSchema.tables[tableName] as Table.WithName<
30
+ DatabaseSchema.Tables<DatabaseSchema_>,
31
+ TableName
33
32
  >;
34
33
 
35
34
  const insert = (
@@ -63,6 +62,10 @@ export const make = <DatabaseSchema_ extends DatabaseSchema.AnyWithProps>(
63
62
  >,
64
63
  ) =>
65
64
  Effect.gen(function* () {
65
+ const tableSchema = tableDef.Fields as TableInfo.TableSchema<
66
+ DataModel.TableInfoWithName_<DataModel_, TableName>
67
+ >;
68
+
66
69
  const originalDecodedDoc = yield* QueryInitializer.getById(
67
70
  tableName,
68
71
  convexDatabaseWriter as any,
@@ -100,7 +103,7 @@ export const make = <DatabaseSchema_ extends DatabaseSchema.AnyWithProps>(
100
103
  const updatedEncodedDoc = yield* Document.encode(
101
104
  value,
102
105
  tableName,
103
- tableSchema,
106
+ tableDef.Fields,
104
107
  );
105
108
 
106
109
  yield* Effect.promise(() =>
@@ -1,63 +1,66 @@
1
1
  import type * as FunctionSpec from "@confect/core/FunctionSpec";
2
2
  import type * as GroupSpec from "@confect/core/GroupSpec";
3
3
  import * as Registry from "@confect/core/Registry";
4
- import { Context, Effect, Layer, Ref, String } from "effect";
5
- import * as Api from "./Api";
4
+ import { Context, Effect, Layer, Ref } from "effect";
5
+ import type * as DatabaseSchema from "./DatabaseSchema";
6
6
  import type * as Handler from "./Handler";
7
7
  import { setNestedProperty } from "./internal/utils";
8
8
  import * as RegistryItem from "./RegistryItem";
9
9
 
10
- export interface FunctionImpl<
11
- GroupPath_ extends string,
12
- FunctionName extends string,
13
- > {
14
- readonly groupPath: GroupPath_;
10
+ export interface FunctionImpl<FunctionName extends string> {
15
11
  readonly functionName: FunctionName;
16
12
  }
17
13
 
18
- export const FunctionImpl = <
19
- GroupPath_ extends string,
20
- FunctionName extends string,
21
- >({
22
- groupPath,
14
+ export const FunctionImpl = <FunctionName extends string>({
23
15
  functionName,
24
16
  }: {
25
- groupPath: GroupPath_;
26
17
  functionName: FunctionName;
27
18
  }) =>
28
- Context.GenericTag<FunctionImpl<GroupPath_, FunctionName>>(
29
- `@confect/server/FunctionImpl/${groupPath}/${functionName}`,
19
+ Context.GenericTag<FunctionImpl<FunctionName>>(
20
+ `@confect/server/FunctionImpl/${functionName}`,
30
21
  );
31
22
 
23
+ /**
24
+ * Register a single function's implementation into the group's `Registry`.
25
+ *
26
+ * The function is registered under a flat, single-segment key (its own
27
+ * `functionName`), not a project-wide dot-path. Each group's impl layer is
28
+ * built in isolation — `RegisteredFunctions.buildForGroup` (and the CLI's
29
+ * `validateImpl`) provide a fresh `Registry` per group — so function names
30
+ * only need to be unique within their own group.
31
+ *
32
+ * `databaseSchema` is retained purely as a type-level carrier: the handler's
33
+ * ctx-service requirements (`DatabaseReader`, `QueryCtx<DataModel>`, …) are
34
+ * derived from it via `Handler.WithName`. It is not read at runtime — the
35
+ * generated per-group registry forwards the schema value to the function
36
+ * builders — so impls depend on `_generated/schema` (table schemas) rather than
37
+ * `_generated/api` (which transitively imports every function spec).
38
+ */
32
39
  export const make = <
33
- Api_ extends Api.AnyWithProps,
40
+ DatabaseSchema_ extends DatabaseSchema.AnyWithProps,
34
41
  Group extends GroupSpec.AnyWithProps,
35
42
  const FunctionName extends FunctionSpec.Name<GroupSpec.Functions<Group>>,
36
43
  >(
37
- api: Api_,
44
+ _databaseSchema: DatabaseSchema_,
38
45
  group: Group,
39
46
  functionName: FunctionName,
40
47
  handler: Handler.WithName<
41
- Api.Schema<Api_>,
48
+ DatabaseSchema_,
42
49
  GroupSpec.Functions<Group>,
43
50
  FunctionName
44
51
  >,
45
- ): Layer.Layer<FunctionImpl<string, FunctionName>> => {
46
- const groupPath = Api.resolveGroupPathUnsafe(api, group);
52
+ ): Layer.Layer<FunctionImpl<FunctionName>> => {
47
53
  const functionSpec = group.functions[functionName]!;
48
54
 
49
55
  return Layer.effect(
50
- FunctionImpl<string, FunctionName>({
51
- groupPath,
52
- functionName,
53
- }),
56
+ FunctionImpl<FunctionName>({ functionName }),
54
57
  Effect.gen(function* () {
55
58
  const registry = yield* Registry.Registry;
56
59
 
57
60
  yield* Ref.update(registry, (registryItems) =>
58
61
  setNestedProperty(
59
62
  registryItems,
60
- [...String.split(groupPath, "."), functionName],
63
+ [functionName],
61
64
  RegistryItem.make({
62
65
  functionSpec,
63
66
  handler,
@@ -65,21 +68,16 @@ export const make = <
65
68
  ),
66
69
  );
67
70
 
68
- return {
69
- groupPath,
70
- functionName,
71
- };
71
+ return { functionName };
72
72
  }),
73
73
  );
74
74
  };
75
75
 
76
76
  /**
77
- * Get the function implementation service type for a specific group path and function name.
77
+ * Get the function implementation service type for a specific function name.
78
78
  */
79
- export type ForGroupPathAndFunction<
80
- GroupPath_ extends string,
81
- FunctionName extends string,
82
- > = FunctionImpl<GroupPath_, FunctionName>;
79
+ export type ForFunction<FunctionName extends string> =
80
+ FunctionImpl<FunctionName>;
83
81
 
84
82
  /**
85
83
  * Get all function implementation services required for a group spec.
@@ -89,14 +87,6 @@ export type FromGroupSpec<Group extends GroupSpec.AnyWithProps> =
89
87
  GroupSpec.Functions<Group>
90
88
  > extends infer FunctionNames extends string
91
89
  ? FunctionNames extends string
92
- ? FunctionImpl<string, FunctionNames>
90
+ ? FunctionImpl<FunctionNames>
93
91
  : never
94
92
  : never;
95
-
96
- /**
97
- * @deprecated Use {@link FromGroupSpec} instead.
98
- */
99
- export type FromGroupAtPath<
100
- _GroupPath extends string,
101
- Group extends GroupSpec.AnyWithProps,
102
- > = FromGroupSpec<Group>;
package/src/GroupImpl.ts CHANGED
@@ -10,9 +10,8 @@ import {
10
10
  Predicate,
11
11
  Record,
12
12
  Ref,
13
- String,
14
13
  } from "effect";
15
- import * as Api from "./Api";
14
+ import type * as DatabaseSchema from "./DatabaseSchema";
16
15
  import type * as FunctionImpl from "./FunctionImpl";
17
16
 
18
17
  export const TypeId = "@confect/server/GroupImpl";
@@ -21,11 +20,9 @@ export type TypeId = typeof TypeId;
21
20
  export type FinalizationStatus = "Unfinalized" | "Finalized";
22
21
 
23
22
  export interface GroupImpl<
24
- GroupPath_ extends string,
25
23
  FinalizationStatus_ extends FinalizationStatus = "Unfinalized",
26
24
  > {
27
25
  readonly [TypeId]: TypeId;
28
- readonly groupPath: GroupPath_;
29
26
  readonly finalizationStatus: FinalizationStatus_;
30
27
  /**
31
28
  * Names of every function registered into this group's layer scope by
@@ -36,13 +33,13 @@ export interface GroupImpl<
36
33
  readonly registeredFunctionNames: ReadonlyArray<string>;
37
34
  }
38
35
 
39
- export interface Any extends GroupImpl<string, FinalizationStatus> {}
36
+ export interface Any extends GroupImpl<FinalizationStatus> {}
40
37
 
41
38
  export const isGroupImpl = (u: unknown): u is Any =>
42
39
  Predicate.hasProperty(u, TypeId);
43
40
 
44
- export interface AnyFinalized extends GroupImpl<string, "Finalized"> {}
45
- export interface AnyUnfinalized extends GroupImpl<string, "Unfinalized"> {}
41
+ export interface AnyFinalized extends GroupImpl<"Finalized"> {}
42
+ export interface AnyUnfinalized extends GroupImpl<"Unfinalized"> {}
46
43
 
47
44
  export const isFinalizedGroupImpl = (u: unknown): u is AnyFinalized =>
48
45
  isGroupImpl(u) && u.finalizationStatus === "Finalized";
@@ -54,83 +51,71 @@ export const isUnfinalizedGroupImpl = (u: unknown): u is AnyUnfinalized =>
54
51
  * Build the runtime tag for a `GroupImpl` service. The finalization status is
55
52
  * embedded in the tag string so that `Unfinalized` and `Finalized` are distinct
56
53
  * services at runtime; consumers of a finalized layer (the server's
57
- * `RegisteredFunctions.buildForGroup` and the CLI's `implValidation`) retrieve
54
+ * `RegisteredFunctions.buildForGroup` and the CLI's `validateImpl`) retrieve
58
55
  * the typed `Finalized` service directly rather than scanning the context.
56
+ *
57
+ * The tag is keyed only by finalization status — no group path — because each
58
+ * group's impl layer is built in its own isolated scope (`buildForGroup` /
59
+ * `validateImpl` each provide a fresh `Registry`), so at most one `GroupImpl`
60
+ * service of each status exists per build.
59
61
  */
60
- export const GroupImpl = <
61
- GroupPath_ extends string,
62
- FinalizationStatus_ extends FinalizationStatus,
63
- >({
64
- groupPath,
62
+ export const GroupImpl = <FinalizationStatus_ extends FinalizationStatus>({
65
63
  finalizationStatus,
66
64
  }: {
67
- groupPath: GroupPath_;
68
65
  finalizationStatus: FinalizationStatus_;
69
66
  }) =>
70
- Context.GenericTag<GroupImpl<GroupPath_, FinalizationStatus_>>(
71
- `@confect/server/GroupImpl/${finalizationStatus}/${groupPath}`,
67
+ Context.GenericTag<GroupImpl<FinalizationStatus_>>(
68
+ `@confect/server/GroupImpl/${finalizationStatus}`,
72
69
  );
73
70
 
71
+ /**
72
+ * Begin a group's impl layer. `databaseSchema` and `group` are retained only as
73
+ * type-level carriers (`group` drives the required `FunctionImpl` services via
74
+ * `FromGroupSpec<Group>`; `databaseSchema` keeps the impl's dependency on
75
+ * `_generated/schema` symmetric with `FunctionImpl.make`). Neither is read at
76
+ * runtime.
77
+ */
74
78
  export const make = <
75
- Api_ extends Api.AnyWithProps,
79
+ DatabaseSchema_ extends DatabaseSchema.AnyWithProps,
76
80
  Group extends GroupSpec.AnyWithProps,
77
81
  >(
78
- api: Api_,
79
- group: Group,
82
+ _databaseSchema: DatabaseSchema_,
83
+ _group: Group,
80
84
  ): Layer.Layer<
81
- GroupImpl<string, "Unfinalized">,
85
+ GroupImpl<"Unfinalized">,
82
86
  never,
83
87
  FunctionImpl.FromGroupSpec<Group>
84
- > => {
85
- const groupPath = Api.resolveGroupPathUnsafe(api, group);
86
-
87
- return Layer.succeed(
88
- GroupImpl<string, "Unfinalized">({
89
- groupPath,
90
- finalizationStatus: "Unfinalized",
91
- }),
88
+ > =>
89
+ Layer.succeed(
90
+ GroupImpl<"Unfinalized">({ finalizationStatus: "Unfinalized" }),
92
91
  {
93
92
  [TypeId]: TypeId,
94
- groupPath,
95
93
  finalizationStatus: "Unfinalized" as const,
96
94
  registeredFunctionNames: [],
97
95
  },
98
96
  ) as Layer.Layer<
99
- GroupImpl<string, "Unfinalized">,
97
+ GroupImpl<"Unfinalized">,
100
98
  never,
101
99
  FunctionImpl.FromGroupSpec<Group>
102
100
  >;
103
- };
104
101
 
105
102
  const isFunctionShaped = (value: unknown): boolean =>
106
103
  Predicate.isRecord(value) && "functionSpec" in value;
107
104
 
108
105
  /**
109
- * Walk a `RegistryItems` tree to the entries at `groupPath` and return the
110
- * names of the function-shaped leaves directly underneath.
106
+ * Return the names of the function-shaped entries in a group's (flat,
107
+ * isolated) registry. `FunctionImpl.make` registers each function under a
108
+ * single-segment key, so the registry built for one group contains exactly
109
+ * that group's functions at the top level.
111
110
  */
112
- const collectFunctionNamesAtPath = (
111
+ const collectFunctionNames = (
113
112
  items: Registry.RegistryItems,
114
- groupPath: string,
115
113
  ): ReadonlyArray<string> =>
116
114
  pipe(
117
- String.split(groupPath, "."),
118
- Array.reduce(Option.some<unknown>(items), (acc, segment) =>
119
- acc.pipe(
120
- Option.filter(Predicate.isRecord),
121
- Option.flatMap((node) =>
122
- segment in node ? Option.some(node[segment]) : Option.none(),
123
- ),
124
- ),
115
+ Record.toEntries(items),
116
+ Array.filterMap(([name, value]) =>
117
+ isFunctionShaped(value) ? Option.some(name) : Option.none(),
125
118
  ),
126
- Option.filter(Predicate.isRecord),
127
- Option.map(Record.toEntries),
128
- Option.map(
129
- Array.filterMap(([name, value]) =>
130
- isFunctionShaped(value) ? Option.some(name) : Option.none(),
131
- ),
132
- ),
133
- Option.getOrElse((): ReadonlyArray<string> => []),
134
119
  );
135
120
 
136
121
  const findUnfinalizedGroupImpl = <S>(
@@ -151,12 +136,12 @@ const findUnfinalizedGroupImpl = <S>(
151
136
  * impl completeness against a `GroupSpec`'s expected functions without
152
137
  * having to inspect the `Registry` themselves.
153
138
  */
154
- export const finalize = <GroupPath_ extends string>(
155
- group: Layer.Layer<GroupImpl<GroupPath_, "Unfinalized">>,
156
- ): Layer.Layer<GroupImpl<GroupPath_, "Finalized">> =>
139
+ export const finalize = (
140
+ group: Layer.Layer<GroupImpl<"Unfinalized">>,
141
+ ): Layer.Layer<GroupImpl<"Finalized">> =>
157
142
  Layer.flatMap(
158
143
  group,
159
- (context): Layer.Layer<GroupImpl<GroupPath_, "Finalized">> =>
144
+ (context): Layer.Layer<GroupImpl<"Finalized">> =>
160
145
  findUnfinalizedGroupImpl(context).pipe(
161
146
  Option.match({
162
147
  onNone: () =>
@@ -165,28 +150,19 @@ export const finalize = <GroupPath_ extends string>(
165
150
  "GroupImpl.finalize: no Unfinalized GroupImpl service was found in the layer's context.",
166
151
  ),
167
152
  ),
168
- onSome: (unfinalized) => {
169
- const groupPath = unfinalized.groupPath as GroupPath_;
170
- return Layer.effect(
171
- GroupImpl<GroupPath_, "Finalized">({
172
- groupPath,
173
- finalizationStatus: "Finalized",
174
- }),
153
+ onSome: () =>
154
+ Layer.effect(
155
+ GroupImpl<"Finalized">({ finalizationStatus: "Finalized" }),
175
156
  Effect.gen(function* () {
176
157
  const registry = yield* Registry.Registry;
177
158
  const items = yield* Ref.get(registry);
178
159
  return {
179
160
  [TypeId]: TypeId,
180
- groupPath,
181
161
  finalizationStatus: "Finalized" as const,
182
- registeredFunctionNames: collectFunctionNamesAtPath(
183
- items,
184
- groupPath,
185
- ),
162
+ registeredFunctionNames: collectFunctionNames(items),
186
163
  };
187
164
  }),
188
- );
189
- },
165
+ ),
190
166
  }),
191
167
  ),
192
168
  );
@@ -238,7 +238,13 @@ export const make = <
238
238
  return OrderedQuery.make<
239
239
  DataModel.TableInfoWithName_<DataModel_, TableName>,
240
240
  TableName
241
- >(orderedQuery, tableName, table.Fields);
241
+ >(
242
+ orderedQuery,
243
+ tableName,
244
+ table.Fields as TableInfo.TableSchema<
245
+ DataModel.TableInfoWithName_<DataModel_, TableName>
246
+ >,
247
+ );
242
248
  };
243
249
 
244
250
  const search: QueryInitializerFunction<"search"> = (
@@ -253,7 +259,9 @@ export const make = <
253
259
  .query(tableName)
254
260
  .withSearchIndex(indexName, searchFilter),
255
261
  tableName,
256
- table.Fields,
262
+ table.Fields as TableInfo.TableSchema<
263
+ DataModel.TableInfoWithName_<DataModel_, TableName>
264
+ >,
257
265
  );
258
266
 
259
267
  return {
@@ -12,7 +12,6 @@ import {
12
12
  } from "convex/server";
13
13
  import type { Value } from "convex/values";
14
14
  import { Clock, Effect, Layer, Match, pipe, Schema } from "effect";
15
- import type * as Api from "./Api";
16
15
  import * as Auth from "./Auth";
17
16
  import * as ConvexConfigProvider from "./ConvexConfigProvider";
18
17
  import * as DatabaseReader from "./DatabaseReader";
@@ -31,8 +30,8 @@ import * as SchemaToValidator from "./SchemaToValidator";
31
30
  import { StorageReader } from "./StorageReader";
32
31
  import { StorageWriter } from "./StorageWriter";
33
32
 
34
- export const make = <Api_ extends Api.AnyWithPropsWithRuntime<"Convex">>(
35
- api: Api_,
33
+ export const make = (
34
+ databaseSchema: DatabaseSchema.AnyWithProps,
36
35
  { functionSpec, handler }: RegistryItem.AnyWithProps,
37
36
  ): RegisteredFunction.Any =>
38
37
  Match.value(functionSpec.functionProvenance).pipe(
@@ -51,7 +50,7 @@ export const make = <Api_ extends Api.AnyWithPropsWithRuntime<"Convex">>(
51
50
 
52
51
  return genericFunction(
53
52
  queryFunction({
54
- databaseSchema: api.databaseSchema,
53
+ databaseSchema,
55
54
  args: functionProvenance.args,
56
55
  returns: functionProvenance.returns,
57
56
  error: functionProvenance.error,
@@ -68,7 +67,7 @@ export const make = <Api_ extends Api.AnyWithPropsWithRuntime<"Convex">>(
68
67
 
69
68
  return genericFunction(
70
69
  mutationFunction({
71
- databaseSchema: api.databaseSchema,
70
+ databaseSchema,
72
71
  args: functionProvenance.args,
73
72
  returns: functionProvenance.returns,
74
73
  error: functionProvenance.error,
@@ -84,7 +83,7 @@ export const make = <Api_ extends Api.AnyWithPropsWithRuntime<"Convex">>(
84
83
  );
85
84
 
86
85
  return genericFunction(
87
- convexActionFunction(api.databaseSchema, {
86
+ convexActionFunction(databaseSchema, {
88
87
  args: functionProvenance.args,
89
88
  returns: functionProvenance.returns,
90
89
  error: functionProvenance.error,