@effect/sql-d1 4.0.0-beta.102 → 4.0.0-beta.104
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/dist/D1Client.d.ts +22 -1
- package/dist/D1Client.d.ts.map +1 -1
- package/dist/D1Client.js +92 -5
- package/dist/D1Client.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -6
- package/src/D1Client.ts +144 -9
package/dist/D1Client.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ import * as Layer from "effect/Layer";
|
|
|
19
19
|
import type * as Scope from "effect/Scope";
|
|
20
20
|
import * as Reactivity from "effect/unstable/reactivity/Reactivity";
|
|
21
21
|
import * as Client from "effect/unstable/sql/SqlClient";
|
|
22
|
+
import { SqlError } from "effect/unstable/sql/SqlError";
|
|
23
|
+
import * as Statement from "effect/unstable/sql/Statement";
|
|
22
24
|
/**
|
|
23
25
|
* Unique runtime identifier used to tag `D1Client` values.
|
|
24
26
|
*
|
|
@@ -36,12 +38,31 @@ export type TypeId = "~@effect/sql-d1/D1Client";
|
|
|
36
38
|
/**
|
|
37
39
|
* Cloudflare D1 SQL client service, extending `SqlClient` with its D1 configuration and no `updateValues` support.
|
|
38
40
|
*
|
|
39
|
-
* @category
|
|
41
|
+
* @category services
|
|
40
42
|
* @since 4.0.0
|
|
41
43
|
*/
|
|
42
44
|
export interface D1Client extends Client.SqlClient {
|
|
43
45
|
readonly [TypeId]: TypeId;
|
|
44
46
|
readonly config: D1ClientConfig;
|
|
47
|
+
/**
|
|
48
|
+
* Executes SQL statements as a single atomic D1 batch and returns their row results in order.
|
|
49
|
+
*
|
|
50
|
+
* **When to use**
|
|
51
|
+
*
|
|
52
|
+
* Use when you have a fixed collection of statements that should run in one
|
|
53
|
+
* request and roll back together if any statement fails.
|
|
54
|
+
*
|
|
55
|
+
* **Gotchas**
|
|
56
|
+
*
|
|
57
|
+
* Each statement uses the query and result name transformations from the
|
|
58
|
+
* client that created it. Mixing clients can produce differently shaped row
|
|
59
|
+
* results within the same batch.
|
|
60
|
+
*
|
|
61
|
+
* @since 4.0.0
|
|
62
|
+
*/
|
|
63
|
+
readonly batch: <const Statements extends ReadonlyArray<Statement.Statement<any>>>(statements: Statements) => Effect.Effect<{
|
|
64
|
+
readonly [K in keyof Statements]: Effect.Success<Statements[K]>;
|
|
65
|
+
}, SqlError>;
|
|
45
66
|
/** Not supported in d1 */
|
|
46
67
|
readonly updateValues: never;
|
|
47
68
|
}
|
package/dist/D1Client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"D1Client.d.ts","sourceRoot":"","sources":["../src/D1Client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,UAAU,EAAuB,MAAM,2BAA2B,CAAA;AAEhF,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAA;AAE1C,OAAO,KAAK,UAAU,MAAM,uCAAuC,CAAA;AACnE,OAAO,KAAK,MAAM,MAAM,+BAA+B,CAAA;
|
|
1
|
+
{"version":3,"file":"D1Client.d.ts","sourceRoot":"","sources":["../src/D1Client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,UAAU,EAAuB,MAAM,2BAA2B,CAAA;AAEhF,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAA;AAE1C,OAAO,KAAK,UAAU,MAAM,uCAAuC,CAAA;AACnE,OAAO,KAAK,MAAM,MAAM,+BAA+B,CAAA;AAEvD,OAAO,EAAE,QAAQ,EAAgB,MAAM,8BAA8B,CAAA;AACrE,OAAO,KAAK,SAAS,MAAM,+BAA+B,CAAA;AAS1D;;;;;GAKG;AACH,eAAO,MAAM,MAAM,EAAE,MAAmC,CAAA;AAExD;;;;;GAKG;AACH,MAAM,MAAM,MAAM,GAAG,0BAA0B,CAAA;AAE/C;;;;;GAKG;AACH,MAAM,WAAW,QAAS,SAAQ,MAAM,CAAC,SAAS;IAChD,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAE/B;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,UAAU,SAAS,aAAa,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAC/E,UAAU,EAAE,UAAU,KACnB,MAAM,CAAC,MAAM,CAChB;QACE,QAAQ,EAAE,CAAC,IAAI,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;KAChE,EACD,QAAQ,CACT,CAAA;IAED,0BAA0B;IAC1B,QAAQ,CAAC,YAAY,EAAE,KAAK,CAAA;CAC7B;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,QAAQ,qCAAuD,CAAA;AAE5E;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAA;IACvB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9C,QAAQ,CAAC,eAAe,CAAC,EAAE,QAAQ,CAAC,KAAK,GAAG,SAAS,CAAA;IACrD,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAA;IAE7D,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAA;IACrE,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAA;CACrE;AA0ED;;;;;GAKG;AACH,eAAO,MAAM,IAAI,YACN,cAAc,KACtB,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,UAAU,CAsKjE,CAAA;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,WAAW,WACd,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,KAClC,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,CAUrB,CAAA;AAEzC;;;;;GAKG;AACH,eAAO,MAAM,KAAK,WACR,cAAc,KACrB,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,CAMrB,CAAA"}
|
package/dist/D1Client.js
CHANGED
|
@@ -11,6 +11,8 @@ import * as Client from "effect/unstable/sql/SqlClient";
|
|
|
11
11
|
import { SqlError, UnknownError } from "effect/unstable/sql/SqlError";
|
|
12
12
|
import * as Statement from "effect/unstable/sql/Statement";
|
|
13
13
|
const ATTR_DB_SYSTEM_NAME = "db.system.name";
|
|
14
|
+
const ATTR_DB_OPERATION_NAME = "db.operation.name";
|
|
15
|
+
const ATTR_DB_QUERY_TEXT = "db.query.text";
|
|
14
16
|
const classifyError = (cause, message, operation) => new UnknownError({
|
|
15
17
|
cause,
|
|
16
18
|
message,
|
|
@@ -35,6 +37,51 @@ export const TypeId = "~@effect/sql-d1/D1Client";
|
|
|
35
37
|
* @since 4.0.0
|
|
36
38
|
*/
|
|
37
39
|
export const D1Client = /*#__PURE__*/Context.Service("@effect/sql-d1/D1Client");
|
|
40
|
+
const makeBatch = options => statements => {
|
|
41
|
+
if (statements.length === 0) {
|
|
42
|
+
return Effect.succeed([]);
|
|
43
|
+
}
|
|
44
|
+
return Effect.useSpan("sql.execute", {
|
|
45
|
+
kind: "client"
|
|
46
|
+
}, span => Effect.withFiber(Effect.fnUntraced(function* (fiber) {
|
|
47
|
+
const transformer = fiber.getRef(Statement.CurrentTransformer);
|
|
48
|
+
const prepared = [];
|
|
49
|
+
const transforms = [];
|
|
50
|
+
const queryTexts = [];
|
|
51
|
+
for (const original of statements) {
|
|
52
|
+
const statement = transformer === undefined ? original : yield* transformer(original, options.getClient(), fiber, span);
|
|
53
|
+
const [sql, params] = statement.compile();
|
|
54
|
+
queryTexts.push(sql);
|
|
55
|
+
transforms.push(statement.transformRows);
|
|
56
|
+
prepared.push((yield* Cache.get(options.prepareCache, sql)).bind(...params));
|
|
57
|
+
}
|
|
58
|
+
for (const [key, value] of options.spanAttributes) {
|
|
59
|
+
span.attribute(key, value);
|
|
60
|
+
}
|
|
61
|
+
span.attribute(ATTR_DB_OPERATION_NAME, "batch");
|
|
62
|
+
span.attribute(ATTR_DB_QUERY_TEXT, queryTexts.join("; "));
|
|
63
|
+
// D1 batches execute on the binding directly and intentionally cannot participate in SqlClient transactions.
|
|
64
|
+
const responses = yield* Effect.tryPromise({
|
|
65
|
+
try: () => options.db.batch(prepared).then(responses => {
|
|
66
|
+
for (const response of responses) {
|
|
67
|
+
if (response.error) {
|
|
68
|
+
throw response.error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return responses;
|
|
72
|
+
}),
|
|
73
|
+
catch: cause => new SqlError({
|
|
74
|
+
reason: classifyError(cause, "Failed to execute batch", "execute")
|
|
75
|
+
})
|
|
76
|
+
});
|
|
77
|
+
const results = responses.map((response, index) => {
|
|
78
|
+
const rows = response.results || [];
|
|
79
|
+
const transformRows = transforms[index];
|
|
80
|
+
return transformRows ? transformRows(rows) : rows;
|
|
81
|
+
});
|
|
82
|
+
return results;
|
|
83
|
+
})));
|
|
84
|
+
};
|
|
38
85
|
/**
|
|
39
86
|
* Creates a scoped Cloudflare D1 SQL client. Prepared statements are cached, while transactions and streaming queries are not supported by this driver.
|
|
40
87
|
*
|
|
@@ -44,6 +91,7 @@ export const D1Client = /*#__PURE__*/Context.Service("@effect/sql-d1/D1Client");
|
|
|
44
91
|
export const make = options => Effect.gen(function* () {
|
|
45
92
|
const compiler = Statement.makeCompilerSqlite(options.transformQueryNames);
|
|
46
93
|
const transformRows = options.transformResultNames ? Statement.defaultTransforms(options.transformResultNames).array : undefined;
|
|
94
|
+
const spanAttributes = [...(options.spanAttributes ? Object.entries(options.spanAttributes) : []), [ATTR_DB_SYSTEM_NAME, "sqlite"]];
|
|
47
95
|
const makeConnection = Effect.gen(function* () {
|
|
48
96
|
const db = options.db;
|
|
49
97
|
const prepareCache = yield* Cache.make({
|
|
@@ -87,7 +135,7 @@ export const make = options => Effect.gen(function* () {
|
|
|
87
135
|
reason: classifyError(cause, "Failed to execute statement", "execute")
|
|
88
136
|
})
|
|
89
137
|
});
|
|
90
|
-
|
|
138
|
+
const connection = identity({
|
|
91
139
|
execute(sql, params, transformRows) {
|
|
92
140
|
return transformRows ? Effect.map(runCached(sql, params), transformRows) : runCached(sql, params);
|
|
93
141
|
},
|
|
@@ -107,20 +155,59 @@ export const make = options => Effect.gen(function* () {
|
|
|
107
155
|
return Stream.die("executeStream not implemented");
|
|
108
156
|
}
|
|
109
157
|
});
|
|
158
|
+
return {
|
|
159
|
+
connection,
|
|
160
|
+
prepareCache
|
|
161
|
+
};
|
|
110
162
|
});
|
|
111
|
-
const
|
|
163
|
+
const {
|
|
164
|
+
connection,
|
|
165
|
+
prepareCache
|
|
166
|
+
} = yield* makeConnection;
|
|
112
167
|
const acquirer = Effect.succeed(connection);
|
|
113
168
|
const transactionAcquirer = Effect.die("transactions are not supported in D1");
|
|
114
|
-
|
|
169
|
+
let client;
|
|
170
|
+
client = Object.assign(yield* Client.make({
|
|
115
171
|
acquirer,
|
|
116
172
|
compiler,
|
|
117
173
|
transactionAcquirer,
|
|
118
|
-
spanAttributes
|
|
174
|
+
spanAttributes,
|
|
119
175
|
transformRows
|
|
120
176
|
}), {
|
|
121
177
|
[TypeId]: TypeId,
|
|
122
|
-
config: options
|
|
178
|
+
config: options,
|
|
179
|
+
batch: makeBatch({
|
|
180
|
+
db: options.db,
|
|
181
|
+
prepareCache,
|
|
182
|
+
spanAttributes,
|
|
183
|
+
getClient: () => client
|
|
184
|
+
})
|
|
123
185
|
});
|
|
186
|
+
if (options.transformQueryNames !== undefined || transformRows !== undefined) {
|
|
187
|
+
const clientWithoutTransformsBase = yield* Client.make({
|
|
188
|
+
acquirer: Effect.succeed(connection),
|
|
189
|
+
compiler: compiler.withoutTransform,
|
|
190
|
+
transactionAcquirer,
|
|
191
|
+
spanAttributes,
|
|
192
|
+
transformRows: undefined
|
|
193
|
+
});
|
|
194
|
+
let clientWithoutTransforms;
|
|
195
|
+
clientWithoutTransforms = Object.assign(clientWithoutTransformsBase, {
|
|
196
|
+
[TypeId]: TypeId,
|
|
197
|
+
config: options,
|
|
198
|
+
batch: makeBatch({
|
|
199
|
+
db: options.db,
|
|
200
|
+
prepareCache,
|
|
201
|
+
spanAttributes,
|
|
202
|
+
getClient: () => clientWithoutTransforms
|
|
203
|
+
}),
|
|
204
|
+
withoutTransforms: () => clientWithoutTransforms
|
|
205
|
+
});
|
|
206
|
+
Object.assign(client, {
|
|
207
|
+
withoutTransforms: () => clientWithoutTransforms
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
return client;
|
|
124
211
|
});
|
|
125
212
|
/**
|
|
126
213
|
* Creates a layer from a `Config`-wrapped D1 client configuration, providing both `D1Client` and `SqlClient`.
|
package/dist/D1Client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"D1Client.js","names":[
|
|
1
|
+
{"version":3,"file":"D1Client.js","names":[],"sources":["../src/D1Client.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":[null],"mappings":"AAAA;;;AAIA;AAEA;;;AAGA,OAAO,KAAK,QAAQ,MAAM,eAAe","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect/sql-d1",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.104",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "A Cloudflare D1 integration for Effect",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
".": "./dist/index.js",
|
|
34
34
|
"./*": "./dist/*.js",
|
|
35
35
|
"./internal/*": null,
|
|
36
|
+
"./index": null,
|
|
36
37
|
"./*/index": null
|
|
37
38
|
},
|
|
38
39
|
"files": [
|
|
@@ -48,10 +49,10 @@
|
|
|
48
49
|
},
|
|
49
50
|
"devDependencies": {
|
|
50
51
|
"miniflare": "^4.20260706.0",
|
|
51
|
-
"effect": "^4.0.0-beta.
|
|
52
|
+
"effect": "^4.0.0-beta.104"
|
|
52
53
|
},
|
|
53
54
|
"peerDependencies": {
|
|
54
|
-
"effect": "^4.0.0-beta.
|
|
55
|
+
"effect": "^4.0.0-beta.104"
|
|
55
56
|
},
|
|
56
57
|
"dependencies": {
|
|
57
58
|
"@cloudflare/workers-types": "^5.20260708.1"
|
|
@@ -60,8 +61,6 @@
|
|
|
60
61
|
"codegen": "effect-utils codegen",
|
|
61
62
|
"build": "tsc -b tsconfig.json && pnpm babel",
|
|
62
63
|
"babel": "babel dist --plugins annotate-pure-calls --out-dir dist --source-maps",
|
|
63
|
-
"check": "tsc -b tsconfig.json"
|
|
64
|
-
"test": "vitest",
|
|
65
|
-
"coverage": "vitest --coverage"
|
|
64
|
+
"check": "tsc -b tsconfig.json"
|
|
66
65
|
}
|
|
67
66
|
}
|
package/src/D1Client.ts
CHANGED
|
@@ -27,6 +27,8 @@ import { SqlError, UnknownError } from "effect/unstable/sql/SqlError"
|
|
|
27
27
|
import * as Statement from "effect/unstable/sql/Statement"
|
|
28
28
|
|
|
29
29
|
const ATTR_DB_SYSTEM_NAME = "db.system.name"
|
|
30
|
+
const ATTR_DB_OPERATION_NAME = "db.operation.name"
|
|
31
|
+
const ATTR_DB_QUERY_TEXT = "db.query.text"
|
|
30
32
|
|
|
31
33
|
const classifyError = (cause: unknown, message: string, operation: string) =>
|
|
32
34
|
new UnknownError({ cause, message, operation })
|
|
@@ -50,13 +52,38 @@ export type TypeId = "~@effect/sql-d1/D1Client"
|
|
|
50
52
|
/**
|
|
51
53
|
* Cloudflare D1 SQL client service, extending `SqlClient` with its D1 configuration and no `updateValues` support.
|
|
52
54
|
*
|
|
53
|
-
* @category
|
|
55
|
+
* @category services
|
|
54
56
|
* @since 4.0.0
|
|
55
57
|
*/
|
|
56
58
|
export interface D1Client extends Client.SqlClient {
|
|
57
59
|
readonly [TypeId]: TypeId
|
|
58
60
|
readonly config: D1ClientConfig
|
|
59
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Executes SQL statements as a single atomic D1 batch and returns their row results in order.
|
|
64
|
+
*
|
|
65
|
+
* **When to use**
|
|
66
|
+
*
|
|
67
|
+
* Use when you have a fixed collection of statements that should run in one
|
|
68
|
+
* request and roll back together if any statement fails.
|
|
69
|
+
*
|
|
70
|
+
* **Gotchas**
|
|
71
|
+
*
|
|
72
|
+
* Each statement uses the query and result name transformations from the
|
|
73
|
+
* client that created it. Mixing clients can produce differently shaped row
|
|
74
|
+
* results within the same batch.
|
|
75
|
+
*
|
|
76
|
+
* @since 4.0.0
|
|
77
|
+
*/
|
|
78
|
+
readonly batch: <const Statements extends ReadonlyArray<Statement.Statement<any>>>(
|
|
79
|
+
statements: Statements
|
|
80
|
+
) => Effect.Effect<
|
|
81
|
+
{
|
|
82
|
+
readonly [K in keyof Statements]: Effect.Success<Statements[K]>
|
|
83
|
+
},
|
|
84
|
+
SqlError
|
|
85
|
+
>
|
|
86
|
+
|
|
60
87
|
/** Not supported in d1 */
|
|
61
88
|
readonly updateValues: never
|
|
62
89
|
}
|
|
@@ -90,6 +117,78 @@ export interface D1ClientConfig {
|
|
|
90
117
|
readonly transformQueryNames?: ((str: string) => string) | undefined
|
|
91
118
|
}
|
|
92
119
|
|
|
120
|
+
type TransformRows = <A extends object>(rows: ReadonlyArray<A>) => ReadonlyArray<A>
|
|
121
|
+
|
|
122
|
+
type BatchResults<Statements extends ReadonlyArray<Statement.Statement<any>>> = {
|
|
123
|
+
readonly [K in keyof Statements]: Effect.Success<Statements[K]>
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
interface StatementWithTransformRows extends Statement.Statement<any> {
|
|
127
|
+
readonly transformRows: TransformRows | undefined
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const makeBatch = (options: {
|
|
131
|
+
readonly db: D1Database
|
|
132
|
+
readonly prepareCache: Cache.Cache<string, D1PreparedStatement, SqlError>
|
|
133
|
+
readonly spanAttributes: ReadonlyArray<readonly [string, unknown]>
|
|
134
|
+
readonly getClient: () => D1Client
|
|
135
|
+
}): D1Client["batch"] =>
|
|
136
|
+
<const Statements extends ReadonlyArray<Statement.Statement<any>>>(
|
|
137
|
+
statements: Statements
|
|
138
|
+
) => {
|
|
139
|
+
if (statements.length === 0) {
|
|
140
|
+
return Effect.succeed([] as unknown as BatchResults<Statements>)
|
|
141
|
+
}
|
|
142
|
+
return Effect.useSpan(
|
|
143
|
+
"sql.execute",
|
|
144
|
+
{ kind: "client" },
|
|
145
|
+
(span) =>
|
|
146
|
+
Effect.withFiber(Effect.fnUntraced(function*(fiber) {
|
|
147
|
+
const transformer = fiber.getRef(Statement.CurrentTransformer)
|
|
148
|
+
const prepared: Array<D1PreparedStatement> = []
|
|
149
|
+
const transforms: Array<TransformRows | undefined> = []
|
|
150
|
+
const queryTexts: Array<string> = []
|
|
151
|
+
|
|
152
|
+
for (const original of statements) {
|
|
153
|
+
const statement = transformer === undefined
|
|
154
|
+
? original
|
|
155
|
+
: yield* transformer(original, options.getClient(), fiber, span)
|
|
156
|
+
const [sql, params] = statement.compile()
|
|
157
|
+
queryTexts.push(sql)
|
|
158
|
+
transforms.push((statement as StatementWithTransformRows).transformRows)
|
|
159
|
+
prepared.push((yield* Cache.get(options.prepareCache, sql)).bind(...params))
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
for (const [key, value] of options.spanAttributes) {
|
|
163
|
+
span.attribute(key, value)
|
|
164
|
+
}
|
|
165
|
+
span.attribute(ATTR_DB_OPERATION_NAME, "batch")
|
|
166
|
+
span.attribute(ATTR_DB_QUERY_TEXT, queryTexts.join("; "))
|
|
167
|
+
|
|
168
|
+
// D1 batches execute on the binding directly and intentionally cannot participate in SqlClient transactions.
|
|
169
|
+
const responses = yield* Effect.tryPromise({
|
|
170
|
+
try: () =>
|
|
171
|
+
options.db.batch<Record<string, unknown>>(prepared).then((responses) => {
|
|
172
|
+
for (const response of responses) {
|
|
173
|
+
if (response.error) {
|
|
174
|
+
throw response.error
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return responses
|
|
178
|
+
}),
|
|
179
|
+
catch: (cause) => new SqlError({ reason: classifyError(cause, "Failed to execute batch", "execute") })
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
const results = responses.map((response, index) => {
|
|
183
|
+
const rows = response.results || []
|
|
184
|
+
const transformRows = transforms[index]
|
|
185
|
+
return transformRows ? transformRows(rows) : rows
|
|
186
|
+
})
|
|
187
|
+
return results as BatchResults<Statements>
|
|
188
|
+
}))
|
|
189
|
+
)
|
|
190
|
+
}
|
|
191
|
+
|
|
93
192
|
/**
|
|
94
193
|
* Creates a scoped Cloudflare D1 SQL client. Prepared statements are cached, while transactions and streaming queries are not supported by this driver.
|
|
95
194
|
*
|
|
@@ -104,6 +203,10 @@ export const make = (
|
|
|
104
203
|
const transformRows = options.transformResultNames ?
|
|
105
204
|
Statement.defaultTransforms(options.transformResultNames).array :
|
|
106
205
|
undefined
|
|
206
|
+
const spanAttributes: Array<readonly [string, unknown]> = [
|
|
207
|
+
...(options.spanAttributes ? Object.entries(options.spanAttributes) : []),
|
|
208
|
+
[ATTR_DB_SYSTEM_NAME, "sqlite"]
|
|
209
|
+
]
|
|
107
210
|
|
|
108
211
|
const makeConnection = Effect.gen(function*() {
|
|
109
212
|
const db = options.db
|
|
@@ -182,7 +285,7 @@ export const make = (
|
|
|
182
285
|
catch: (cause) => new SqlError({ reason: classifyError(cause, "Failed to execute statement", "execute") })
|
|
183
286
|
})
|
|
184
287
|
|
|
185
|
-
|
|
288
|
+
const connection = identity<Connection>({
|
|
186
289
|
execute(sql, params, transformRows) {
|
|
187
290
|
return transformRows
|
|
188
291
|
? Effect.map(runCached(sql, params), transformRows)
|
|
@@ -206,28 +309,60 @@ export const make = (
|
|
|
206
309
|
return Stream.die("executeStream not implemented")
|
|
207
310
|
}
|
|
208
311
|
})
|
|
312
|
+
return { connection, prepareCache } as const
|
|
209
313
|
})
|
|
210
314
|
|
|
211
|
-
const connection = yield* makeConnection
|
|
315
|
+
const { connection, prepareCache } = yield* makeConnection
|
|
212
316
|
const acquirer = Effect.succeed(connection)
|
|
213
317
|
const transactionAcquirer = Effect.die("transactions are not supported in D1")
|
|
214
318
|
|
|
215
|
-
|
|
319
|
+
let client!: D1Client
|
|
320
|
+
client = Object.assign(
|
|
216
321
|
(yield* Client.make({
|
|
217
322
|
acquirer,
|
|
218
323
|
compiler,
|
|
219
324
|
transactionAcquirer,
|
|
220
|
-
spanAttributes
|
|
221
|
-
...(options.spanAttributes ? Object.entries(options.spanAttributes) : []),
|
|
222
|
-
[ATTR_DB_SYSTEM_NAME, "sqlite"]
|
|
223
|
-
],
|
|
325
|
+
spanAttributes,
|
|
224
326
|
transformRows
|
|
225
327
|
})) as D1Client,
|
|
226
328
|
{
|
|
227
329
|
[TypeId]: TypeId as TypeId,
|
|
228
|
-
config: options
|
|
330
|
+
config: options,
|
|
331
|
+
batch: makeBatch({
|
|
332
|
+
db: options.db,
|
|
333
|
+
prepareCache,
|
|
334
|
+
spanAttributes,
|
|
335
|
+
getClient: () => client
|
|
336
|
+
})
|
|
229
337
|
}
|
|
230
338
|
)
|
|
339
|
+
|
|
340
|
+
if (options.transformQueryNames !== undefined || transformRows !== undefined) {
|
|
341
|
+
const clientWithoutTransformsBase = yield* Client.make({
|
|
342
|
+
acquirer: Effect.succeed(connection),
|
|
343
|
+
compiler: compiler.withoutTransform,
|
|
344
|
+
transactionAcquirer,
|
|
345
|
+
spanAttributes,
|
|
346
|
+
transformRows: undefined
|
|
347
|
+
})
|
|
348
|
+
let clientWithoutTransforms!: D1Client
|
|
349
|
+
clientWithoutTransforms = Object.assign(clientWithoutTransformsBase as D1Client, {
|
|
350
|
+
[TypeId]: TypeId as TypeId,
|
|
351
|
+
config: options,
|
|
352
|
+
batch: makeBatch({
|
|
353
|
+
db: options.db,
|
|
354
|
+
prepareCache,
|
|
355
|
+
spanAttributes,
|
|
356
|
+
getClient: () => clientWithoutTransforms
|
|
357
|
+
}),
|
|
358
|
+
withoutTransforms: () => clientWithoutTransforms
|
|
359
|
+
})
|
|
360
|
+
Object.assign(client, {
|
|
361
|
+
withoutTransforms: () => clientWithoutTransforms
|
|
362
|
+
})
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return client
|
|
231
366
|
})
|
|
232
367
|
|
|
233
368
|
/**
|