@confect/server 9.0.0-next.4 → 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.
- package/CHANGELOG.md +162 -0
- package/dist/Auth.d.ts +1 -1
- package/dist/DatabaseReader.d.ts +4299 -26
- package/dist/DatabaseReader.d.ts.map +1 -1
- package/dist/DatabaseReader.js +5 -6
- package/dist/DatabaseReader.js.map +1 -1
- package/dist/DatabaseSchema.d.ts +25 -112
- package/dist/DatabaseSchema.d.ts.map +1 -1
- package/dist/DatabaseSchema.js +20 -30
- package/dist/DatabaseSchema.js.map +1 -1
- package/dist/DatabaseWriter.d.ts +4 -4
- package/dist/DatabaseWriter.d.ts.map +1 -1
- package/dist/DatabaseWriter.js +3 -4
- package/dist/DatabaseWriter.js.map +1 -1
- package/dist/FunctionImpl.d.ts +26 -17
- package/dist/FunctionImpl.d.ts.map +1 -1
- package/dist/FunctionImpl.js +22 -14
- package/dist/FunctionImpl.js.map +1 -1
- package/dist/GroupImpl.d.ts +22 -13
- package/dist/GroupImpl.d.ts.map +1 -1
- package/dist/GroupImpl.js +34 -35
- package/dist/GroupImpl.js.map +1 -1
- package/dist/Handler.d.ts +1 -1
- package/dist/QueryInitializer.d.ts +1 -1
- package/dist/QueryInitializer.d.ts.map +1 -1
- package/dist/QueryInitializer.js.map +1 -1
- package/dist/RegisteredConvexFunction.d.ts +1085 -18
- package/dist/RegisteredConvexFunction.d.ts.map +1 -1
- package/dist/RegisteredConvexFunction.js +4 -4
- package/dist/RegisteredConvexFunction.js.map +1 -1
- package/dist/RegisteredFunction.d.ts +4 -4
- package/dist/RegisteredFunction.d.ts.map +1 -1
- package/dist/RegisteredFunctions.d.ts +36 -12
- package/dist/RegisteredFunctions.d.ts.map +1 -1
- package/dist/RegisteredFunctions.js +21 -9
- package/dist/RegisteredFunctions.js.map +1 -1
- package/dist/RegisteredNodeFunction.d.ts +4 -4
- package/dist/RegisteredNodeFunction.d.ts.map +1 -1
- package/dist/RegisteredNodeFunction.js +2 -2
- package/dist/RegisteredNodeFunction.js.map +1 -1
- package/dist/StorageActionWriter.d.ts +1 -1
- package/dist/Table.d.ts +27 -19
- package/dist/Table.d.ts.map +1 -1
- package/dist/Table.js +69 -60
- package/dist/Table.js.map +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.js +4 -5
- package/package.json +51 -52
- package/src/DatabaseReader.ts +17 -21
- package/src/DatabaseSchema.ts +38 -98
- package/src/DatabaseWriter.ts +8 -5
- package/src/FunctionImpl.ts +33 -43
- package/src/GroupImpl.ts +45 -69
- package/src/QueryInitializer.ts +10 -2
- package/src/RegisteredConvexFunction.ts +5 -6
- package/src/RegisteredFunctions.ts +67 -93
- package/src/RegisteredNodeFunction.ts +3 -4
- package/src/Table.ts +251 -131
- package/src/index.ts +0 -1
- package/dist/Api.d.ts +0 -43
- package/dist/Api.d.ts.map +0 -1
- package/dist/Api.js +0 -43
- package/dist/Api.js.map +0 -1
- package/src/Api.ts +0 -102
package/src/DatabaseSchema.ts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import
|
|
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
|
|
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:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
|
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
|
-
*
|
|
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 =
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
+
});
|
package/src/DatabaseWriter.ts
CHANGED
|
@@ -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
|
-
|
|
32
|
-
|
|
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
|
-
|
|
106
|
+
tableDef.Fields,
|
|
104
107
|
);
|
|
105
108
|
|
|
106
109
|
yield* Effect.promise(() =>
|
package/src/FunctionImpl.ts
CHANGED
|
@@ -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
|
|
5
|
-
import * as
|
|
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<
|
|
29
|
-
`@confect/server/FunctionImpl/${
|
|
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
|
-
|
|
40
|
+
DatabaseSchema_ extends DatabaseSchema.AnyWithProps,
|
|
34
41
|
Group extends GroupSpec.AnyWithProps,
|
|
35
42
|
const FunctionName extends FunctionSpec.Name<GroupSpec.Functions<Group>>,
|
|
36
43
|
>(
|
|
37
|
-
|
|
44
|
+
_databaseSchema: DatabaseSchema_,
|
|
38
45
|
group: Group,
|
|
39
46
|
functionName: FunctionName,
|
|
40
47
|
handler: Handler.WithName<
|
|
41
|
-
|
|
48
|
+
DatabaseSchema_,
|
|
42
49
|
GroupSpec.Functions<Group>,
|
|
43
50
|
FunctionName
|
|
44
51
|
>,
|
|
45
|
-
): Layer.Layer<FunctionImpl<
|
|
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<
|
|
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
|
-
[
|
|
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
|
|
77
|
+
* Get the function implementation service type for a specific function name.
|
|
78
78
|
*/
|
|
79
|
-
export type
|
|
80
|
-
|
|
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<
|
|
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
|
|
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<
|
|
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<
|
|
45
|
-
export interface AnyUnfinalized extends GroupImpl<
|
|
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 `
|
|
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<
|
|
71
|
-
`@confect/server/GroupImpl/${finalizationStatus}
|
|
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
|
-
|
|
79
|
+
DatabaseSchema_ extends DatabaseSchema.AnyWithProps,
|
|
76
80
|
Group extends GroupSpec.AnyWithProps,
|
|
77
81
|
>(
|
|
78
|
-
|
|
79
|
-
|
|
82
|
+
_databaseSchema: DatabaseSchema_,
|
|
83
|
+
_group: Group,
|
|
80
84
|
): Layer.Layer<
|
|
81
|
-
GroupImpl<
|
|
85
|
+
GroupImpl<"Unfinalized">,
|
|
82
86
|
never,
|
|
83
87
|
FunctionImpl.FromGroupSpec<Group>
|
|
84
|
-
> =>
|
|
85
|
-
|
|
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<
|
|
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
|
-
*
|
|
110
|
-
*
|
|
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
|
|
111
|
+
const collectFunctionNames = (
|
|
113
112
|
items: Registry.RegistryItems,
|
|
114
|
-
groupPath: string,
|
|
115
113
|
): ReadonlyArray<string> =>
|
|
116
114
|
pipe(
|
|
117
|
-
|
|
118
|
-
Array.
|
|
119
|
-
|
|
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 =
|
|
155
|
-
group: Layer.Layer<GroupImpl<
|
|
156
|
-
): Layer.Layer<GroupImpl<
|
|
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<
|
|
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: (
|
|
169
|
-
|
|
170
|
-
|
|
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:
|
|
183
|
-
items,
|
|
184
|
-
groupPath,
|
|
185
|
-
),
|
|
162
|
+
registeredFunctionNames: collectFunctionNames(items),
|
|
186
163
|
};
|
|
187
164
|
}),
|
|
188
|
-
)
|
|
189
|
-
},
|
|
165
|
+
),
|
|
190
166
|
}),
|
|
191
167
|
),
|
|
192
168
|
);
|
package/src/QueryInitializer.ts
CHANGED
|
@@ -238,7 +238,13 @@ export const make = <
|
|
|
238
238
|
return OrderedQuery.make<
|
|
239
239
|
DataModel.TableInfoWithName_<DataModel_, TableName>,
|
|
240
240
|
TableName
|
|
241
|
-
>(
|
|
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 =
|
|
35
|
-
|
|
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
|
|
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
|
|
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(
|
|
86
|
+
convexActionFunction(databaseSchema, {
|
|
88
87
|
args: functionProvenance.args,
|
|
89
88
|
returns: functionProvenance.returns,
|
|
90
89
|
error: functionProvenance.error,
|