@confect/server 6.0.0 → 8.0.0
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 +157 -1
- package/dist/ActionRunner.d.ts +3 -5
- package/dist/ActionRunner.d.ts.map +1 -1
- package/dist/ActionRunner.js.map +1 -1
- package/dist/DatabaseReader.d.ts +1 -1
- package/dist/DatabaseSchema.d.ts +5 -10
- package/dist/DatabaseSchema.d.ts.map +1 -1
- package/dist/DatabaseSchema.js +5 -6
- package/dist/DatabaseSchema.js.map +1 -1
- package/dist/Document.d.ts.map +1 -1
- package/dist/Document.js +35 -23
- package/dist/Document.js.map +1 -1
- package/dist/Handler.d.ts +1 -1
- package/dist/Handler.d.ts.map +1 -1
- package/dist/Handler.js.map +1 -1
- package/dist/MutationRunner.d.ts +5 -16
- package/dist/MutationRunner.d.ts.map +1 -1
- package/dist/MutationRunner.js +2 -12
- package/dist/MutationRunner.js.map +1 -1
- package/dist/QueryRunner.d.ts +3 -5
- package/dist/QueryRunner.d.ts.map +1 -1
- package/dist/QueryRunner.js.map +1 -1
- package/dist/RegisteredConvexFunction.d.ts +6 -6
- package/dist/RegisteredConvexFunction.d.ts.map +1 -1
- package/dist/RegisteredConvexFunction.js +36 -15
- package/dist/RegisteredConvexFunction.js.map +1 -1
- package/dist/RegisteredFunction.d.ts +24 -5
- package/dist/RegisteredFunction.d.ts.map +1 -1
- package/dist/RegisteredFunction.js +34 -5
- package/dist/RegisteredFunction.js.map +1 -1
- package/dist/RegisteredNodeFunction.js +3 -1
- package/dist/RegisteredNodeFunction.js.map +1 -1
- package/dist/SchemaToValidator.d.ts +8 -8
- package/dist/StorageActionWriter.d.ts +1 -1
- package/package.json +22 -18
- package/src/ActionRunner.ts +5 -1
- package/src/DatabaseSchema.ts +7 -10
- package/src/Document.ts +90 -58
- package/src/Handler.ts +5 -1
- package/src/MutationRunner.ts +6 -16
- package/src/QueryRunner.ts +5 -1
- package/src/RegisteredConvexFunction.ts +111 -94
- package/src/RegisteredFunction.ts +67 -22
- package/src/RegisteredNodeFunction.ts +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@confect/server",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "Backend bindings to the Convex platform",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -44,38 +44,38 @@
|
|
|
44
44
|
"license": "ISC",
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@ark/attest": "0.56.0",
|
|
47
|
-
"@effect/cluster": "0.
|
|
48
|
-
"@effect/experimental": "0.
|
|
49
|
-
"@effect/platform": "0.
|
|
50
|
-
"@effect/rpc": "0.
|
|
51
|
-
"@effect/sql": "0.
|
|
52
|
-
"@effect/vitest": "0.
|
|
53
|
-
"@effect/workflow": "0.
|
|
47
|
+
"@effect/cluster": "0.58.2",
|
|
48
|
+
"@effect/experimental": "0.60.0",
|
|
49
|
+
"@effect/platform": "0.96.1",
|
|
50
|
+
"@effect/rpc": "0.75.1",
|
|
51
|
+
"@effect/sql": "0.51.1",
|
|
52
|
+
"@effect/vitest": "0.29.0",
|
|
53
|
+
"@effect/workflow": "0.18.1",
|
|
54
54
|
"@eslint/js": "10.0.1",
|
|
55
55
|
"@swc/jest": "0.2.39",
|
|
56
56
|
"@types/node": "25.3.3",
|
|
57
57
|
"@vitest/coverage-v8": "3.2.4",
|
|
58
|
-
"convex-test": "0.0.
|
|
58
|
+
"convex-test": "0.0.50",
|
|
59
59
|
"dotenv": "17.3.1",
|
|
60
|
-
"effect": "3.
|
|
60
|
+
"effect": "3.21.2",
|
|
61
61
|
"eslint": "10.0.2",
|
|
62
62
|
"prettier": "3.8.1",
|
|
63
63
|
"tsdown": "0.20.3",
|
|
64
|
-
"tsx": "
|
|
64
|
+
"tsx": "4.21.0",
|
|
65
65
|
"typescript": "5.9.3",
|
|
66
66
|
"typescript-eslint": "8.56.1",
|
|
67
67
|
"vite": "7.3.1",
|
|
68
68
|
"vite-tsconfig-paths": "6.1.1",
|
|
69
69
|
"vitest": "3.2.4",
|
|
70
|
-
"@confect/cli": "
|
|
71
|
-
"@confect/test": "
|
|
70
|
+
"@confect/cli": "8.0.0",
|
|
71
|
+
"@confect/test": "8.0.0"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
|
-
"@effect/platform": "^0.
|
|
75
|
-
"@effect/platform-node": "^0.
|
|
74
|
+
"@effect/platform": "^0.96.1",
|
|
75
|
+
"@effect/platform-node": "^0.106.0",
|
|
76
76
|
"convex": "^1.30.0",
|
|
77
|
-
"effect": "^3.
|
|
78
|
-
"@confect/core": "
|
|
77
|
+
"effect": "^3.21.2",
|
|
78
|
+
"@confect/core": "^8.0.0"
|
|
79
79
|
},
|
|
80
80
|
"engines": {
|
|
81
81
|
"node": ">=22",
|
|
@@ -88,11 +88,15 @@
|
|
|
88
88
|
"build": "tsdown --config-loader unrun",
|
|
89
89
|
"dev": "tsdown --watch",
|
|
90
90
|
"test": "vitest run",
|
|
91
|
+
"test:mock-backend": "vitest run --config vitest.mock-backend.config.ts",
|
|
92
|
+
"test:local-backend": "vitest run --config vitest.local-backend.config.ts",
|
|
93
|
+
"codegen:mock-backend": "cd test/mock-backend/fixtures && pnpm confect codegen && CONVEX_AGENT_MODE=anonymous pnpm convex dev --once --typecheck=disable --tail-logs=disable",
|
|
94
|
+
"codegen:local-backend": "cd test/local-backend/fixtures && pnpm confect codegen && CONVEX_AGENT_MODE=anonymous pnpm convex dev --once --typecheck=disable --tail-logs=disable",
|
|
91
95
|
"typecheck": "tsc --noEmit --project tsconfig.json",
|
|
92
96
|
"fix": "prettier --write . && eslint --fix . --max-warnings=0",
|
|
93
97
|
"format": "prettier --check .",
|
|
94
98
|
"lint": "eslint . --max-warnings=0",
|
|
95
|
-
"bench": "tsx test/SchemaToValidator.bench.ts",
|
|
99
|
+
"bench": "tsx test/SchemaToValidator.bench.ts && tsx test/Document.bench.ts",
|
|
96
100
|
"clean": "rm -rf dist coverage node_modules"
|
|
97
101
|
}
|
|
98
102
|
}
|
package/src/ActionRunner.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as Ref from "@confect/core/Ref";
|
|
2
2
|
import { type GenericActionCtx } from "convex/server";
|
|
3
|
+
import type { ParseResult, Effect } from "effect";
|
|
3
4
|
import { Context, Layer } from "effect";
|
|
4
5
|
|
|
5
6
|
const make =
|
|
@@ -7,7 +8,10 @@ const make =
|
|
|
7
8
|
<Action extends Ref.AnyAction>(
|
|
8
9
|
action: Action,
|
|
9
10
|
...args: Ref.OptionalArgs<Action>
|
|
10
|
-
)
|
|
11
|
+
): Effect.Effect<
|
|
12
|
+
Ref.Returns<Action>,
|
|
13
|
+
Ref.Error<Action> | ParseResult.ParseError
|
|
14
|
+
> =>
|
|
11
15
|
Ref.runWithCodec(
|
|
12
16
|
action,
|
|
13
17
|
(args[0] ?? {}) as Ref.Args<Action>,
|
package/src/DatabaseSchema.ts
CHANGED
|
@@ -3,14 +3,15 @@ import {
|
|
|
3
3
|
defineSchema as defineConvexSchema,
|
|
4
4
|
type SchemaDefinition,
|
|
5
5
|
} from "convex/server";
|
|
6
|
-
import { Array, pipe,
|
|
6
|
+
import { Array, pipe, Record } from "effect";
|
|
7
7
|
import * as Table from "./Table";
|
|
8
|
+
import { TypeId } from "@confect/core/DatabaseSchema";
|
|
8
9
|
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
export {
|
|
11
|
+
type Any,
|
|
12
|
+
isDatabaseSchema,
|
|
13
|
+
TypeId,
|
|
14
|
+
} from "@confect/core/DatabaseSchema";
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* A schema definition tracks the schema and its Convex schema definition.
|
|
@@ -31,10 +32,6 @@ export interface DatabaseSchema<Tables_ extends Table.AnyWithProps = never> {
|
|
|
31
32
|
): DatabaseSchema<Tables_ | TableDef>;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
export interface Any {
|
|
35
|
-
readonly [TypeId]: TypeId;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
35
|
export interface AnyWithProps {
|
|
39
36
|
readonly [TypeId]: TypeId;
|
|
40
37
|
readonly tables: Record<string, Table.AnyWithProps>;
|
package/src/Document.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import * as SystemFields from "@confect/core/SystemFields";
|
|
1
2
|
import { Effect, Function, ParseResult, pipe, Schema } from "effect";
|
|
2
3
|
import type { ReadonlyRecord } from "effect/Record";
|
|
3
|
-
import * as SystemFields from "@confect/core/SystemFields";
|
|
4
4
|
import type * as DataModel from "./DataModel";
|
|
5
5
|
import type { ReadonlyValue } from "./SchemaToValidator";
|
|
6
6
|
import type * as TableInfo from "./TableInfo";
|
|
@@ -10,6 +10,37 @@ export type WithoutSystemFields<Doc> = Omit<Doc, "_creationTime" | "_id">;
|
|
|
10
10
|
export type Any = any;
|
|
11
11
|
export type AnyEncoded = ReadonlyRecord<string, ReadonlyValue>;
|
|
12
12
|
|
|
13
|
+
type Decode = (doc: unknown) => Effect.Effect<unknown, ParseResult.ParseError>;
|
|
14
|
+
|
|
15
|
+
const decoderCache = new WeakMap<
|
|
16
|
+
Schema.Schema.AnyNoContext,
|
|
17
|
+
Map<string, Decode>
|
|
18
|
+
>();
|
|
19
|
+
|
|
20
|
+
const getDecoder = (
|
|
21
|
+
tableName: string,
|
|
22
|
+
tableSchema: Schema.Schema.AnyNoContext,
|
|
23
|
+
): Decode => {
|
|
24
|
+
const byTable =
|
|
25
|
+
decoderCache.get(tableSchema) ??
|
|
26
|
+
(() => {
|
|
27
|
+
const map = new Map<string, Decode>();
|
|
28
|
+
decoderCache.set(tableSchema, map);
|
|
29
|
+
return map;
|
|
30
|
+
})();
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
byTable.get(tableName) ??
|
|
34
|
+
(() => {
|
|
35
|
+
const decoder = Schema.decode(
|
|
36
|
+
SystemFields.extendWithSystemFields(tableName, tableSchema),
|
|
37
|
+
) as Decode;
|
|
38
|
+
byTable.set(tableName, decoder);
|
|
39
|
+
return decoder;
|
|
40
|
+
})()
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
13
44
|
export const decode = Function.dual<
|
|
14
45
|
<
|
|
15
46
|
DataModel_ extends DataModel.AnyWithProps,
|
|
@@ -53,36 +84,43 @@ export const decode = Function.dual<
|
|
|
53
84
|
DataModel.TableInfoWithName_<DataModel_, TableName>["document"],
|
|
54
85
|
DocumentDecodeError
|
|
55
86
|
> =>
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
),
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
return decodedDoc;
|
|
83
|
-
}),
|
|
87
|
+
pipe(
|
|
88
|
+
self,
|
|
89
|
+
getDecoder(tableName, tableSchema),
|
|
90
|
+
Effect.catchIf(ParseResult.isParseError, (parseError) =>
|
|
91
|
+
Effect.gen(function* () {
|
|
92
|
+
const formattedParseError =
|
|
93
|
+
yield* ParseResult.TreeFormatter.formatError(parseError);
|
|
94
|
+
|
|
95
|
+
return yield* new DocumentDecodeError({
|
|
96
|
+
tableName,
|
|
97
|
+
id: self._id,
|
|
98
|
+
parseError: formattedParseError,
|
|
99
|
+
});
|
|
100
|
+
}),
|
|
101
|
+
),
|
|
102
|
+
Effect.map(
|
|
103
|
+
(decodedDoc) =>
|
|
104
|
+
decodedDoc as DataModel.TableInfoWithName_<
|
|
105
|
+
DataModel_,
|
|
106
|
+
TableName
|
|
107
|
+
>["document"],
|
|
108
|
+
),
|
|
109
|
+
),
|
|
84
110
|
);
|
|
85
111
|
|
|
112
|
+
type Encode = (doc: unknown) => Effect.Effect<unknown, ParseResult.ParseError>;
|
|
113
|
+
|
|
114
|
+
const encoderCache = new WeakMap<Schema.Schema.AnyNoContext, Encode>();
|
|
115
|
+
|
|
116
|
+
const getEncoder = (tableSchema: Schema.Schema.AnyNoContext): Encode =>
|
|
117
|
+
encoderCache.get(tableSchema) ??
|
|
118
|
+
(() => {
|
|
119
|
+
const encoder = Schema.encode(tableSchema) as Encode;
|
|
120
|
+
encoderCache.set(tableSchema, encoder);
|
|
121
|
+
return encoder;
|
|
122
|
+
})();
|
|
123
|
+
|
|
86
124
|
export const encode = Function.dual<
|
|
87
125
|
<
|
|
88
126
|
DataModel_ extends DataModel.AnyWithProps,
|
|
@@ -126,35 +164,29 @@ export const encode = Function.dual<
|
|
|
126
164
|
DataModel.TableInfoWithName_<DataModel_, TableName>["encodedDocument"],
|
|
127
165
|
DocumentEncodeError
|
|
128
166
|
> =>
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}),
|
|
153
|
-
),
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
return encodedDoc;
|
|
157
|
-
}),
|
|
167
|
+
pipe(
|
|
168
|
+
self,
|
|
169
|
+
getEncoder(tableSchema),
|
|
170
|
+
Effect.catchIf(ParseResult.isParseError, (parseError) =>
|
|
171
|
+
Effect.gen(function* () {
|
|
172
|
+
const formattedParseError =
|
|
173
|
+
yield* ParseResult.TreeFormatter.formatError(parseError);
|
|
174
|
+
|
|
175
|
+
return yield* new DocumentEncodeError({
|
|
176
|
+
tableName,
|
|
177
|
+
id: self._id,
|
|
178
|
+
parseError: formattedParseError,
|
|
179
|
+
});
|
|
180
|
+
}),
|
|
181
|
+
),
|
|
182
|
+
Effect.map(
|
|
183
|
+
(encodedDoc) =>
|
|
184
|
+
encodedDoc as DataModel.TableInfoWithName_<
|
|
185
|
+
DataModel_,
|
|
186
|
+
TableName
|
|
187
|
+
>["encodedDocument"],
|
|
188
|
+
),
|
|
189
|
+
),
|
|
158
190
|
);
|
|
159
191
|
|
|
160
192
|
export class DocumentDecodeError extends Schema.TaggedError<DocumentDecodeError>()(
|
package/src/Handler.ts
CHANGED
|
@@ -128,7 +128,11 @@ export type NodeRuntimeAction<
|
|
|
128
128
|
|
|
129
129
|
type Base<FunctionSpec_ extends FunctionSpec.AnyWithProps, R> = (
|
|
130
130
|
args: FunctionSpec.Args<FunctionSpec_>,
|
|
131
|
-
) => Effect.Effect<
|
|
131
|
+
) => Effect.Effect<
|
|
132
|
+
FunctionSpec.Returns<FunctionSpec_>,
|
|
133
|
+
FunctionSpec.Error<FunctionSpec_>,
|
|
134
|
+
R
|
|
135
|
+
>;
|
|
132
136
|
|
|
133
137
|
export type Any = AnyConfectProvenance | AnyConvexProvenance;
|
|
134
138
|
|
package/src/MutationRunner.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import * as Ref from "@confect/core/Ref";
|
|
2
2
|
import { type GenericMutationCtx } from "convex/server";
|
|
3
|
-
import {
|
|
3
|
+
import type { ParseResult, Effect } from "effect";
|
|
4
|
+
import { Context, Layer } from "effect";
|
|
4
5
|
|
|
5
6
|
const make =
|
|
6
7
|
(runMutation: GenericMutationCtx<any>["runMutation"]) =>
|
|
7
8
|
<Mutation extends Ref.AnyMutation>(
|
|
8
9
|
mutation: Mutation,
|
|
9
10
|
...args: Ref.OptionalArgs<Mutation>
|
|
10
|
-
)
|
|
11
|
+
): Effect.Effect<
|
|
12
|
+
Ref.Returns<Mutation>,
|
|
13
|
+
Ref.Error<Mutation> | ParseResult.ParseError
|
|
14
|
+
> =>
|
|
11
15
|
Ref.runWithCodec(
|
|
12
16
|
mutation,
|
|
13
17
|
(args[0] ?? {}) as Ref.Args<Mutation>,
|
|
@@ -22,17 +26,3 @@ export type MutationRunner = typeof MutationRunner.Identifier;
|
|
|
22
26
|
|
|
23
27
|
export const layer = (runMutation: GenericMutationCtx<any>["runMutation"]) =>
|
|
24
28
|
Layer.succeed(MutationRunner, make(runMutation));
|
|
25
|
-
|
|
26
|
-
export class MutationRollback extends Schema.TaggedError<MutationRollback>()(
|
|
27
|
-
"MutationRollback",
|
|
28
|
-
{
|
|
29
|
-
mutationName: Schema.String,
|
|
30
|
-
error: Schema.Unknown,
|
|
31
|
-
},
|
|
32
|
-
) {
|
|
33
|
-
/* v8 ignore start */
|
|
34
|
-
override get message(): string {
|
|
35
|
-
return `Mutation ${this.mutationName} failed and was rolled back.\n\n${this.error}`;
|
|
36
|
-
}
|
|
37
|
-
/* v8 ignore stop */
|
|
38
|
-
}
|
package/src/QueryRunner.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as Ref from "@confect/core/Ref";
|
|
2
2
|
import { type GenericQueryCtx } from "convex/server";
|
|
3
|
+
import type { ParseResult, Effect } from "effect";
|
|
3
4
|
import { Context, Layer } from "effect";
|
|
4
5
|
|
|
5
6
|
const make =
|
|
@@ -7,7 +8,10 @@ const make =
|
|
|
7
8
|
<Query extends Ref.AnyQuery>(
|
|
8
9
|
query: Query,
|
|
9
10
|
...args: Ref.OptionalArgs<Query>
|
|
10
|
-
)
|
|
11
|
+
): Effect.Effect<
|
|
12
|
+
Ref.Returns<Query>,
|
|
13
|
+
Ref.Error<Query> | ParseResult.ParseError
|
|
14
|
+
> =>
|
|
11
15
|
Ref.runWithCodec(
|
|
12
16
|
query,
|
|
13
17
|
(args[0] ?? {}) as Ref.Args<Query>,
|