@prisma/adapter-d1 6.11.0-dev.43 → 6.11.0-dev.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/dist/index.d.mts +6 -9
- package/dist/index.d.ts +6 -9
- package/dist/index.js +164 -189
- package/dist/index.mjs +164 -189
- package/package.json +3 -7
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D1Database as D1Database_2 } from '@cloudflare/workers-types';
|
|
1
|
+
import type { D1Database as D1Database_2 } from '@cloudflare/workers-types';
|
|
2
2
|
import { SqlDriverAdapter } from '@prisma/driver-adapter-utils';
|
|
3
3
|
import { SqlDriverAdapterFactory } from '@prisma/driver-adapter-utils';
|
|
4
4
|
import { SqlMigrationAwareDriverAdapterFactory } from '@prisma/driver-adapter-utils';
|
|
@@ -10,15 +10,14 @@ declare type D1HTTPParams = {
|
|
|
10
10
|
CLOUDFLARE_SHADOW_DATABASE_ID?: string;
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
export declare class PrismaD1
|
|
13
|
+
export declare class PrismaD1 implements SqlDriverAdapterFactory {
|
|
14
|
+
private client;
|
|
14
15
|
readonly provider = "sqlite";
|
|
15
16
|
readonly adapterName: string;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
constructor(params: Args);
|
|
17
|
+
constructor(client: StdClient);
|
|
18
|
+
connect(): Promise<SqlDriverAdapter>;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
/** @deprecated Use PrismaD1 instead */
|
|
22
21
|
export declare class PrismaD1HTTP implements SqlMigrationAwareDriverAdapterFactory {
|
|
23
22
|
private params;
|
|
24
23
|
readonly provider = "sqlite";
|
|
@@ -28,8 +27,6 @@ export declare class PrismaD1HTTP implements SqlMigrationAwareDriverAdapterFacto
|
|
|
28
27
|
connectToShadowDb(): Promise<SqlDriverAdapter>;
|
|
29
28
|
}
|
|
30
29
|
|
|
31
|
-
declare type
|
|
32
|
-
connectToShadowDb: Params extends D1HTTPParams ? () => Promise<SqlDriverAdapter> : undefined;
|
|
33
|
-
};
|
|
30
|
+
declare type StdClient = D1Database_2;
|
|
34
31
|
|
|
35
32
|
export { }
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D1Database as D1Database_2 } from '@cloudflare/workers-types';
|
|
1
|
+
import type { D1Database as D1Database_2 } from '@cloudflare/workers-types';
|
|
2
2
|
import { SqlDriverAdapter } from '@prisma/driver-adapter-utils';
|
|
3
3
|
import { SqlDriverAdapterFactory } from '@prisma/driver-adapter-utils';
|
|
4
4
|
import { SqlMigrationAwareDriverAdapterFactory } from '@prisma/driver-adapter-utils';
|
|
@@ -10,15 +10,14 @@ declare type D1HTTPParams = {
|
|
|
10
10
|
CLOUDFLARE_SHADOW_DATABASE_ID?: string;
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
export declare class PrismaD1
|
|
13
|
+
export declare class PrismaD1 implements SqlDriverAdapterFactory {
|
|
14
|
+
private client;
|
|
14
15
|
readonly provider = "sqlite";
|
|
15
16
|
readonly adapterName: string;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
constructor(params: Args);
|
|
17
|
+
constructor(client: StdClient);
|
|
18
|
+
connect(): Promise<SqlDriverAdapter>;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
/** @deprecated Use PrismaD1 instead */
|
|
22
21
|
export declare class PrismaD1HTTP implements SqlMigrationAwareDriverAdapterFactory {
|
|
23
22
|
private params;
|
|
24
23
|
readonly provider = "sqlite";
|
|
@@ -28,8 +27,6 @@ export declare class PrismaD1HTTP implements SqlMigrationAwareDriverAdapterFacto
|
|
|
28
27
|
connectToShadowDb(): Promise<SqlDriverAdapter>;
|
|
29
28
|
}
|
|
30
29
|
|
|
31
|
-
declare type
|
|
32
|
-
connectToShadowDb: Params extends D1HTTPParams ? () => Promise<SqlDriverAdapter> : undefined;
|
|
33
|
-
};
|
|
30
|
+
declare type StdClient = D1Database_2;
|
|
34
31
|
|
|
35
32
|
export { }
|
package/dist/index.js
CHANGED
|
@@ -30,15 +30,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
-
PrismaD1: () =>
|
|
33
|
+
PrismaD1: () => PrismaD1AdapterFactory,
|
|
34
34
|
PrismaD1HTTP: () => PrismaD1HTTPAdapterFactory
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(index_exports);
|
|
37
37
|
|
|
38
|
-
//
|
|
39
|
-
var name = "@prisma/adapter-d1";
|
|
40
|
-
|
|
41
|
-
// src/d1-http.ts
|
|
38
|
+
// src/d1.ts
|
|
42
39
|
var import_driver_adapter_utils2 = require("@prisma/driver-adapter-utils");
|
|
43
40
|
|
|
44
41
|
// ../../node_modules/.pnpm/kleur@4.1.5/node_modules/kleur/colors.mjs
|
|
@@ -89,8 +86,8 @@ var bgMagenta = init(45, 49);
|
|
|
89
86
|
var bgCyan = init(46, 49);
|
|
90
87
|
var bgWhite = init(47, 49);
|
|
91
88
|
|
|
92
|
-
//
|
|
93
|
-
var
|
|
89
|
+
// package.json
|
|
90
|
+
var name = "@prisma/adapter-d1";
|
|
94
91
|
|
|
95
92
|
// src/constants.ts
|
|
96
93
|
var MAX_BIND_VALUES = 98;
|
|
@@ -266,48 +263,14 @@ function cleanArg(arg, argType) {
|
|
|
266
263
|
return arg;
|
|
267
264
|
}
|
|
268
265
|
|
|
269
|
-
// src/d1
|
|
270
|
-
var debug = (0, import_driver_adapter_utils2.Debug)("prisma:driver-adapter:d1
|
|
271
|
-
|
|
272
|
-
debug("D1 HTTP Errors: %O", errors);
|
|
273
|
-
const error = errors.at(0) ?? { message: "Unknown error", code: GENERIC_SQLITE_ERROR };
|
|
274
|
-
throw new import_driver_adapter_utils2.DriverAdapterError(convertDriverError(error));
|
|
275
|
-
}
|
|
276
|
-
function onGenericD1HTTPError(error) {
|
|
277
|
-
debug("HTTP Error: %O", error);
|
|
278
|
-
throw new import_driver_adapter_utils2.DriverAdapterError(convertDriverError(error));
|
|
279
|
-
}
|
|
280
|
-
function onError(error) {
|
|
281
|
-
console.error("Error in performIO: %O", error);
|
|
282
|
-
throw new import_driver_adapter_utils2.DriverAdapterError(convertDriverError(error));
|
|
283
|
-
}
|
|
284
|
-
async function performRawQuery(client, options) {
|
|
285
|
-
try {
|
|
286
|
-
const response = await client.post("raw", options).json();
|
|
287
|
-
const tag = "[js::performRawQuery]";
|
|
288
|
-
debug(`${tag} %O`, {
|
|
289
|
-
success: response.success,
|
|
290
|
-
errors: response.errors,
|
|
291
|
-
messages: response.messages,
|
|
292
|
-
result: response.result
|
|
293
|
-
});
|
|
294
|
-
if (!response.success) {
|
|
295
|
-
onUnsuccessfulD1HTTPResponse(response);
|
|
296
|
-
}
|
|
297
|
-
return response.result;
|
|
298
|
-
} catch (e) {
|
|
299
|
-
onGenericD1HTTPError(e);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
function isD1HTTPParams(params) {
|
|
303
|
-
return typeof params === "object" && params !== null && "CLOUDFLARE_D1_TOKEN" in params && "CLOUDFLARE_ACCOUNT_ID" in params && "CLOUDFLARE_DATABASE_ID" in params;
|
|
304
|
-
}
|
|
305
|
-
var D1HTTPQueryable = class {
|
|
266
|
+
// src/d1.ts
|
|
267
|
+
var debug = (0, import_driver_adapter_utils2.Debug)("prisma:driver-adapter:d1");
|
|
268
|
+
var D1Queryable = class {
|
|
306
269
|
constructor(client) {
|
|
307
270
|
this.client = client;
|
|
308
271
|
}
|
|
309
272
|
provider = "sqlite";
|
|
310
|
-
adapterName =
|
|
273
|
+
adapterName = name;
|
|
311
274
|
/**
|
|
312
275
|
* Execute a query given as SQL, interpolating the given parameters.
|
|
313
276
|
*/
|
|
@@ -318,7 +281,9 @@ var D1HTTPQueryable = class {
|
|
|
318
281
|
const convertedData = this.convertData(data);
|
|
319
282
|
return convertedData;
|
|
320
283
|
}
|
|
321
|
-
convertData(
|
|
284
|
+
convertData(ioResult) {
|
|
285
|
+
const columnNames = ioResult[0];
|
|
286
|
+
const results = ioResult[1];
|
|
322
287
|
if (results.length === 0) {
|
|
323
288
|
return {
|
|
324
289
|
columnNames: [],
|
|
@@ -326,10 +291,14 @@ var D1HTTPQueryable = class {
|
|
|
326
291
|
rows: []
|
|
327
292
|
};
|
|
328
293
|
}
|
|
329
|
-
const columnTypes = getColumnTypes(columnNames, results);
|
|
294
|
+
const columnTypes = Object.values(getColumnTypes(columnNames, results));
|
|
330
295
|
const rows = results.map((value) => mapRow(value, columnTypes));
|
|
331
296
|
return {
|
|
332
297
|
columnNames,
|
|
298
|
+
// * Note: without Object.values the array looks like
|
|
299
|
+
// * columnTypes: [ id: 128 ],
|
|
300
|
+
// * and errors with:
|
|
301
|
+
// * ✘ [ERROR] A hanging Promise was canceled. This happens when the worker runtime is waiting for a Promise from JavaScript to resolve, but has detected that the Promise cannot possibly ever resolve because all code and events related to the Promise's I/O context have already finished.
|
|
333
302
|
columnTypes,
|
|
334
303
|
rows
|
|
335
304
|
};
|
|
@@ -342,34 +311,25 @@ var D1HTTPQueryable = class {
|
|
|
342
311
|
async executeRaw(query) {
|
|
343
312
|
const tag = "[js::execute_raw]";
|
|
344
313
|
debug(`${tag} %O`, query);
|
|
345
|
-
const result = await this.performIO(query);
|
|
346
|
-
return result.
|
|
314
|
+
const result = await this.performIO(query, true);
|
|
315
|
+
return result.meta.changes ?? 0;
|
|
347
316
|
}
|
|
348
|
-
async performIO(query) {
|
|
317
|
+
async performIO(query, executeRaw = false) {
|
|
349
318
|
try {
|
|
350
319
|
query.args = query.args.map((arg, i) => cleanArg(arg, query.argTypes[i]));
|
|
351
|
-
const
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
const tag = "[js::perform_io]";
|
|
358
|
-
debug(`${tag} %O`, body);
|
|
359
|
-
const results = await performRawQuery(this.client, body);
|
|
360
|
-
if (results.length !== 1) {
|
|
361
|
-
throw new Error("Expected exactly one result");
|
|
320
|
+
const stmt = this.client.prepare(query.sql).bind(...query.args);
|
|
321
|
+
if (executeRaw) {
|
|
322
|
+
return await stmt.run();
|
|
323
|
+
} else {
|
|
324
|
+
const [columnNames, ...rows] = await stmt.raw({ columnNames: true });
|
|
325
|
+
return [columnNames, rows];
|
|
362
326
|
}
|
|
363
|
-
const result = results[0];
|
|
364
|
-
const { columns: columnNames = [], rows = [] } = result.results ?? {};
|
|
365
|
-
const affectedRows = result.meta?.changes;
|
|
366
|
-
return { rows, columnNames, affectedRows };
|
|
367
327
|
} catch (e) {
|
|
368
328
|
onError(e);
|
|
369
329
|
}
|
|
370
330
|
}
|
|
371
331
|
};
|
|
372
|
-
var
|
|
332
|
+
var D1Transaction = class extends D1Queryable {
|
|
373
333
|
constructor(client, options) {
|
|
374
334
|
super(client);
|
|
375
335
|
this.options = options;
|
|
@@ -381,17 +341,8 @@ var D1HTTPTransaction = class extends D1HTTPQueryable {
|
|
|
381
341
|
debug(`[js::rollback]`);
|
|
382
342
|
}
|
|
383
343
|
};
|
|
384
|
-
var
|
|
385
|
-
constructor(
|
|
386
|
-
const D1_API_BASE_URL = `https://api.cloudflare.com/client/v4/accounts/${params.CLOUDFLARE_ACCOUNT_ID}/d1/database/${params.CLOUDFLARE_DATABASE_ID}`;
|
|
387
|
-
const client = import_ky.default.create({
|
|
388
|
-
prefixUrl: D1_API_BASE_URL,
|
|
389
|
-
headers: {
|
|
390
|
-
Authorization: `Bearer ${params.CLOUDFLARE_D1_TOKEN}`
|
|
391
|
-
},
|
|
392
|
-
// Don't automatically throw on non-2xx status codes
|
|
393
|
-
throwHttpErrors: false
|
|
394
|
-
});
|
|
344
|
+
var PrismaD1Adapter = class extends D1Queryable {
|
|
345
|
+
constructor(client, release) {
|
|
395
346
|
super(client);
|
|
396
347
|
this.release = release;
|
|
397
348
|
}
|
|
@@ -420,11 +371,7 @@ var PrismaD1HTTPAdapter = class extends D1HTTPQueryable {
|
|
|
420
371
|
};
|
|
421
372
|
async executeScript(script) {
|
|
422
373
|
try {
|
|
423
|
-
await
|
|
424
|
-
json: {
|
|
425
|
-
sql: script
|
|
426
|
-
}
|
|
427
|
-
});
|
|
374
|
+
await this.client.exec(script);
|
|
428
375
|
} catch (error) {
|
|
429
376
|
onError(error);
|
|
430
377
|
}
|
|
@@ -451,80 +398,69 @@ var PrismaD1HTTPAdapter = class extends D1HTTPQueryable {
|
|
|
451
398
|
};
|
|
452
399
|
const tag = "[js::startTransaction]";
|
|
453
400
|
debug("%s options: %O", tag, options);
|
|
454
|
-
return new
|
|
401
|
+
return new D1Transaction(this.client, options);
|
|
455
402
|
}
|
|
456
403
|
async dispose() {
|
|
457
404
|
await this.release?.();
|
|
458
405
|
}
|
|
459
406
|
};
|
|
460
|
-
var
|
|
461
|
-
constructor(
|
|
462
|
-
this.
|
|
407
|
+
var PrismaD1AdapterFactory = class {
|
|
408
|
+
constructor(client) {
|
|
409
|
+
this.client = client;
|
|
463
410
|
}
|
|
464
411
|
provider = "sqlite";
|
|
465
|
-
adapterName =
|
|
412
|
+
adapterName = name;
|
|
466
413
|
async connect() {
|
|
467
|
-
return new
|
|
414
|
+
return new PrismaD1Adapter(this.client, async () => {
|
|
468
415
|
});
|
|
469
416
|
}
|
|
470
|
-
async connectToShadowDb() {
|
|
471
|
-
const D1_API_BASE_URL = `https://api.cloudflare.com/client/v4/accounts/${this.params.CLOUDFLARE_ACCOUNT_ID}/d1/database`;
|
|
472
|
-
const client = import_ky.default.create({
|
|
473
|
-
headers: {
|
|
474
|
-
Authorization: `Bearer ${this.params.CLOUDFLARE_D1_TOKEN}`
|
|
475
|
-
},
|
|
476
|
-
// Don't throw on non-2xx status codes
|
|
477
|
-
throwHttpErrors: false
|
|
478
|
-
});
|
|
479
|
-
const createShadowDatabase = async () => {
|
|
480
|
-
const tag = "[js::connectToShadowDb::createShadowDatabase]";
|
|
481
|
-
const SHADOW_DATABASE_PREFIX = "_prisma_shadow_";
|
|
482
|
-
const CLOUDFLARE_SHADOW_DATABASE_NAME = `${SHADOW_DATABASE_PREFIX}${globalThis.crypto.randomUUID()}`;
|
|
483
|
-
debug(`${tag} creating database %s`, CLOUDFLARE_SHADOW_DATABASE_NAME);
|
|
484
|
-
try {
|
|
485
|
-
const response = await client.post(D1_API_BASE_URL, {
|
|
486
|
-
json: {
|
|
487
|
-
name: CLOUDFLARE_SHADOW_DATABASE_NAME
|
|
488
|
-
}
|
|
489
|
-
}).json();
|
|
490
|
-
debug(`${tag} %O`, response);
|
|
491
|
-
if (!response.success) {
|
|
492
|
-
onUnsuccessfulD1HTTPResponse(response);
|
|
493
|
-
}
|
|
494
|
-
const { uuid: CLOUDFLARE_SHADOW_DATABASE_ID2 } = response.result;
|
|
495
|
-
debug(`${tag} created database %s with ID %s`, CLOUDFLARE_SHADOW_DATABASE_NAME, CLOUDFLARE_SHADOW_DATABASE_ID2);
|
|
496
|
-
return CLOUDFLARE_SHADOW_DATABASE_ID2;
|
|
497
|
-
} catch (e) {
|
|
498
|
-
onGenericD1HTTPError(e);
|
|
499
|
-
}
|
|
500
|
-
};
|
|
501
|
-
const CLOUDFLARE_SHADOW_DATABASE_ID = this.params.CLOUDFLARE_SHADOW_DATABASE_ID ?? await createShadowDatabase();
|
|
502
|
-
const dispose = async () => {
|
|
503
|
-
const tag = "[js::connectToShadowDb::dispose]";
|
|
504
|
-
try {
|
|
505
|
-
debug(`${tag} deleting database %s`, CLOUDFLARE_SHADOW_DATABASE_ID);
|
|
506
|
-
const response = await client.delete(`${D1_API_BASE_URL}/${CLOUDFLARE_SHADOW_DATABASE_ID}`).json();
|
|
507
|
-
debug(`${tag} %O`, response);
|
|
508
|
-
if (!response.success) {
|
|
509
|
-
onUnsuccessfulD1HTTPResponse(response);
|
|
510
|
-
}
|
|
511
|
-
} catch (e) {
|
|
512
|
-
onGenericD1HTTPError(e);
|
|
513
|
-
}
|
|
514
|
-
};
|
|
515
|
-
return new PrismaD1HTTPAdapter(this.params, dispose);
|
|
516
|
-
}
|
|
517
417
|
};
|
|
418
|
+
function onError(error) {
|
|
419
|
+
console.error("Error in performIO: %O", error);
|
|
420
|
+
throw new import_driver_adapter_utils2.DriverAdapterError(convertDriverError(error));
|
|
421
|
+
}
|
|
518
422
|
|
|
519
|
-
// src/d1-
|
|
423
|
+
// src/d1-http.ts
|
|
520
424
|
var import_driver_adapter_utils3 = require("@prisma/driver-adapter-utils");
|
|
521
|
-
var
|
|
522
|
-
var
|
|
425
|
+
var import_ky = __toESM(require("ky"));
|
|
426
|
+
var debug2 = (0, import_driver_adapter_utils3.Debug)("prisma:driver-adapter:d1-http");
|
|
427
|
+
function onUnsuccessfulD1HTTPResponse({ errors }) {
|
|
428
|
+
debug2("D1 HTTP Errors: %O", errors);
|
|
429
|
+
const error = errors.at(0) ?? { message: "Unknown error", code: GENERIC_SQLITE_ERROR };
|
|
430
|
+
throw new import_driver_adapter_utils3.DriverAdapterError(convertDriverError(error));
|
|
431
|
+
}
|
|
432
|
+
function onGenericD1HTTPError(error) {
|
|
433
|
+
debug2("HTTP Error: %O", error);
|
|
434
|
+
throw new import_driver_adapter_utils3.DriverAdapterError(convertDriverError(error));
|
|
435
|
+
}
|
|
436
|
+
function onError2(error) {
|
|
437
|
+
console.error("Error in performIO: %O", error);
|
|
438
|
+
throw new import_driver_adapter_utils3.DriverAdapterError(convertDriverError(error));
|
|
439
|
+
}
|
|
440
|
+
async function performRawQuery(client, options) {
|
|
441
|
+
try {
|
|
442
|
+
const response = await client.post("raw", options).json();
|
|
443
|
+
const tag = "[js::performRawQuery]";
|
|
444
|
+
debug2(`${tag} %O`, {
|
|
445
|
+
success: response.success,
|
|
446
|
+
errors: response.errors,
|
|
447
|
+
messages: response.messages,
|
|
448
|
+
result: response.result
|
|
449
|
+
});
|
|
450
|
+
if (!response.success) {
|
|
451
|
+
onUnsuccessfulD1HTTPResponse(response);
|
|
452
|
+
}
|
|
453
|
+
return response.result;
|
|
454
|
+
} catch (e) {
|
|
455
|
+
onGenericD1HTTPError(e);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
var D1HTTPQueryable = class {
|
|
523
459
|
constructor(client) {
|
|
524
460
|
this.client = client;
|
|
525
461
|
}
|
|
526
462
|
provider = "sqlite";
|
|
527
|
-
adapterName = name
|
|
463
|
+
adapterName = `${name}-http`;
|
|
528
464
|
/**
|
|
529
465
|
* Execute a query given as SQL, interpolating the given parameters.
|
|
530
466
|
*/
|
|
@@ -535,9 +471,7 @@ var D1WorkerQueryable = class {
|
|
|
535
471
|
const convertedData = this.convertData(data);
|
|
536
472
|
return convertedData;
|
|
537
473
|
}
|
|
538
|
-
convertData(
|
|
539
|
-
const columnNames = ioResult[0];
|
|
540
|
-
const results = ioResult[1];
|
|
474
|
+
convertData({ columnNames, rows: results }) {
|
|
541
475
|
if (results.length === 0) {
|
|
542
476
|
return {
|
|
543
477
|
columnNames: [],
|
|
@@ -545,14 +479,10 @@ var D1WorkerQueryable = class {
|
|
|
545
479
|
rows: []
|
|
546
480
|
};
|
|
547
481
|
}
|
|
548
|
-
const columnTypes =
|
|
482
|
+
const columnTypes = getColumnTypes(columnNames, results);
|
|
549
483
|
const rows = results.map((value) => mapRow(value, columnTypes));
|
|
550
484
|
return {
|
|
551
485
|
columnNames,
|
|
552
|
-
// * Note: without Object.values the array looks like
|
|
553
|
-
// * columnTypes: [ id: 128 ],
|
|
554
|
-
// * and errors with:
|
|
555
|
-
// * ✘ [ERROR] A hanging Promise was canceled. This happens when the worker runtime is waiting for a Promise from JavaScript to resolve, but has detected that the Promise cannot possibly ever resolve because all code and events related to the Promise's I/O context have already finished.
|
|
556
486
|
columnTypes,
|
|
557
487
|
rows
|
|
558
488
|
};
|
|
@@ -565,25 +495,34 @@ var D1WorkerQueryable = class {
|
|
|
565
495
|
async executeRaw(query) {
|
|
566
496
|
const tag = "[js::execute_raw]";
|
|
567
497
|
debug2(`${tag} %O`, query);
|
|
568
|
-
const result = await this.performIO(query
|
|
569
|
-
return result.
|
|
498
|
+
const result = await this.performIO(query);
|
|
499
|
+
return result.affectedRows ?? 0;
|
|
570
500
|
}
|
|
571
|
-
async performIO(query
|
|
501
|
+
async performIO(query) {
|
|
572
502
|
try {
|
|
573
503
|
query.args = query.args.map((arg, i) => cleanArg(arg, query.argTypes[i]));
|
|
574
|
-
const
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
504
|
+
const body = {
|
|
505
|
+
json: {
|
|
506
|
+
sql: query.sql,
|
|
507
|
+
params: query.args
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
const tag = "[js::perform_io]";
|
|
511
|
+
debug2(`${tag} %O`, body);
|
|
512
|
+
const results = await performRawQuery(this.client, body);
|
|
513
|
+
if (results.length !== 1) {
|
|
514
|
+
throw new Error("Expected exactly one result");
|
|
580
515
|
}
|
|
516
|
+
const result = results[0];
|
|
517
|
+
const { columns: columnNames = [], rows = [] } = result.results ?? {};
|
|
518
|
+
const affectedRows = result.meta?.changes;
|
|
519
|
+
return { rows, columnNames, affectedRows };
|
|
581
520
|
} catch (e) {
|
|
582
521
|
onError2(e);
|
|
583
522
|
}
|
|
584
523
|
}
|
|
585
524
|
};
|
|
586
|
-
var
|
|
525
|
+
var D1HTTPTransaction = class extends D1HTTPQueryable {
|
|
587
526
|
constructor(client, options) {
|
|
588
527
|
super(client);
|
|
589
528
|
this.options = options;
|
|
@@ -595,8 +534,17 @@ var D1WorkerTransaction = class extends D1WorkerQueryable {
|
|
|
595
534
|
debug2(`[js::rollback]`);
|
|
596
535
|
}
|
|
597
536
|
};
|
|
598
|
-
var
|
|
599
|
-
constructor(
|
|
537
|
+
var PrismaD1HTTPAdapter = class extends D1HTTPQueryable {
|
|
538
|
+
constructor(params, release) {
|
|
539
|
+
const D1_API_BASE_URL = `https://api.cloudflare.com/client/v4/accounts/${params.CLOUDFLARE_ACCOUNT_ID}/d1/database/${params.CLOUDFLARE_DATABASE_ID}`;
|
|
540
|
+
const client = import_ky.default.create({
|
|
541
|
+
prefixUrl: D1_API_BASE_URL,
|
|
542
|
+
headers: {
|
|
543
|
+
Authorization: `Bearer ${params.CLOUDFLARE_D1_TOKEN}`
|
|
544
|
+
},
|
|
545
|
+
// Don't automatically throw on non-2xx status codes
|
|
546
|
+
throwHttpErrors: false
|
|
547
|
+
});
|
|
600
548
|
super(client);
|
|
601
549
|
this.release = release;
|
|
602
550
|
}
|
|
@@ -625,7 +573,11 @@ var PrismaD1WorkerAdapter = class extends D1WorkerQueryable {
|
|
|
625
573
|
};
|
|
626
574
|
async executeScript(script) {
|
|
627
575
|
try {
|
|
628
|
-
await this.client
|
|
576
|
+
await performRawQuery(this.client, {
|
|
577
|
+
json: {
|
|
578
|
+
sql: script
|
|
579
|
+
}
|
|
580
|
+
});
|
|
629
581
|
} catch (error) {
|
|
630
582
|
onError2(error);
|
|
631
583
|
}
|
|
@@ -652,45 +604,68 @@ var PrismaD1WorkerAdapter = class extends D1WorkerQueryable {
|
|
|
652
604
|
};
|
|
653
605
|
const tag = "[js::startTransaction]";
|
|
654
606
|
debug2("%s options: %O", tag, options);
|
|
655
|
-
return new
|
|
607
|
+
return new D1HTTPTransaction(this.client, options);
|
|
656
608
|
}
|
|
657
609
|
async dispose() {
|
|
658
610
|
await this.release?.();
|
|
659
611
|
}
|
|
660
612
|
};
|
|
661
|
-
var
|
|
662
|
-
constructor(
|
|
663
|
-
this.
|
|
613
|
+
var PrismaD1HTTPAdapterFactory = class {
|
|
614
|
+
constructor(params) {
|
|
615
|
+
this.params = params;
|
|
664
616
|
}
|
|
665
617
|
provider = "sqlite";
|
|
666
|
-
adapterName = name
|
|
618
|
+
adapterName = `${name}-http`;
|
|
667
619
|
async connect() {
|
|
668
|
-
return new
|
|
620
|
+
return new PrismaD1HTTPAdapter(this.params, async () => {
|
|
669
621
|
});
|
|
670
622
|
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
//
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
623
|
+
async connectToShadowDb() {
|
|
624
|
+
const D1_API_BASE_URL = `https://api.cloudflare.com/client/v4/accounts/${this.params.CLOUDFLARE_ACCOUNT_ID}/d1/database`;
|
|
625
|
+
const client = import_ky.default.create({
|
|
626
|
+
headers: {
|
|
627
|
+
Authorization: `Bearer ${this.params.CLOUDFLARE_D1_TOKEN}`
|
|
628
|
+
},
|
|
629
|
+
// Don't throw on non-2xx status codes
|
|
630
|
+
throwHttpErrors: false
|
|
631
|
+
});
|
|
632
|
+
const createShadowDatabase = async () => {
|
|
633
|
+
const tag = "[js::connectToShadowDb::createShadowDatabase]";
|
|
634
|
+
const SHADOW_DATABASE_PREFIX = "_prisma_shadow_";
|
|
635
|
+
const CLOUDFLARE_SHADOW_DATABASE_NAME = `${SHADOW_DATABASE_PREFIX}${globalThis.crypto.randomUUID()}`;
|
|
636
|
+
debug2(`${tag} creating database %s`, CLOUDFLARE_SHADOW_DATABASE_NAME);
|
|
637
|
+
try {
|
|
638
|
+
const response = await client.post(D1_API_BASE_URL, {
|
|
639
|
+
json: {
|
|
640
|
+
name: CLOUDFLARE_SHADOW_DATABASE_NAME
|
|
641
|
+
}
|
|
642
|
+
}).json();
|
|
643
|
+
debug2(`${tag} %O`, response);
|
|
644
|
+
if (!response.success) {
|
|
645
|
+
onUnsuccessfulD1HTTPResponse(response);
|
|
646
|
+
}
|
|
647
|
+
const { uuid: CLOUDFLARE_SHADOW_DATABASE_ID2 } = response.result;
|
|
648
|
+
debug2(`${tag} created database %s with ID %s`, CLOUDFLARE_SHADOW_DATABASE_NAME, CLOUDFLARE_SHADOW_DATABASE_ID2);
|
|
649
|
+
return CLOUDFLARE_SHADOW_DATABASE_ID2;
|
|
650
|
+
} catch (e) {
|
|
651
|
+
onGenericD1HTTPError(e);
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
const CLOUDFLARE_SHADOW_DATABASE_ID = this.params.CLOUDFLARE_SHADOW_DATABASE_ID ?? await createShadowDatabase();
|
|
655
|
+
const dispose = async () => {
|
|
656
|
+
const tag = "[js::connectToShadowDb::dispose]";
|
|
657
|
+
try {
|
|
658
|
+
debug2(`${tag} deleting database %s`, CLOUDFLARE_SHADOW_DATABASE_ID);
|
|
659
|
+
const response = await client.delete(`${D1_API_BASE_URL}/${CLOUDFLARE_SHADOW_DATABASE_ID}`).json();
|
|
660
|
+
debug2(`${tag} %O`, response);
|
|
661
|
+
if (!response.success) {
|
|
662
|
+
onUnsuccessfulD1HTTPResponse(response);
|
|
663
|
+
}
|
|
664
|
+
} catch (e) {
|
|
665
|
+
onGenericD1HTTPError(e);
|
|
666
|
+
}
|
|
667
|
+
};
|
|
668
|
+
return new PrismaD1HTTPAdapter(this.params, dispose);
|
|
694
669
|
}
|
|
695
670
|
};
|
|
696
671
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
//
|
|
2
|
-
var name = "@prisma/adapter-d1";
|
|
3
|
-
|
|
4
|
-
// src/d1-http.ts
|
|
1
|
+
// src/d1.ts
|
|
5
2
|
import {
|
|
6
3
|
Debug,
|
|
7
4
|
DriverAdapterError
|
|
@@ -55,8 +52,8 @@ var bgMagenta = init(45, 49);
|
|
|
55
52
|
var bgCyan = init(46, 49);
|
|
56
53
|
var bgWhite = init(47, 49);
|
|
57
54
|
|
|
58
|
-
//
|
|
59
|
-
|
|
55
|
+
// package.json
|
|
56
|
+
var name = "@prisma/adapter-d1";
|
|
60
57
|
|
|
61
58
|
// src/constants.ts
|
|
62
59
|
var MAX_BIND_VALUES = 98;
|
|
@@ -232,48 +229,14 @@ function cleanArg(arg, argType) {
|
|
|
232
229
|
return arg;
|
|
233
230
|
}
|
|
234
231
|
|
|
235
|
-
// src/d1
|
|
236
|
-
var debug = Debug("prisma:driver-adapter:d1
|
|
237
|
-
|
|
238
|
-
debug("D1 HTTP Errors: %O", errors);
|
|
239
|
-
const error = errors.at(0) ?? { message: "Unknown error", code: GENERIC_SQLITE_ERROR };
|
|
240
|
-
throw new DriverAdapterError(convertDriverError(error));
|
|
241
|
-
}
|
|
242
|
-
function onGenericD1HTTPError(error) {
|
|
243
|
-
debug("HTTP Error: %O", error);
|
|
244
|
-
throw new DriverAdapterError(convertDriverError(error));
|
|
245
|
-
}
|
|
246
|
-
function onError(error) {
|
|
247
|
-
console.error("Error in performIO: %O", error);
|
|
248
|
-
throw new DriverAdapterError(convertDriverError(error));
|
|
249
|
-
}
|
|
250
|
-
async function performRawQuery(client, options) {
|
|
251
|
-
try {
|
|
252
|
-
const response = await client.post("raw", options).json();
|
|
253
|
-
const tag = "[js::performRawQuery]";
|
|
254
|
-
debug(`${tag} %O`, {
|
|
255
|
-
success: response.success,
|
|
256
|
-
errors: response.errors,
|
|
257
|
-
messages: response.messages,
|
|
258
|
-
result: response.result
|
|
259
|
-
});
|
|
260
|
-
if (!response.success) {
|
|
261
|
-
onUnsuccessfulD1HTTPResponse(response);
|
|
262
|
-
}
|
|
263
|
-
return response.result;
|
|
264
|
-
} catch (e) {
|
|
265
|
-
onGenericD1HTTPError(e);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
function isD1HTTPParams(params) {
|
|
269
|
-
return typeof params === "object" && params !== null && "CLOUDFLARE_D1_TOKEN" in params && "CLOUDFLARE_ACCOUNT_ID" in params && "CLOUDFLARE_DATABASE_ID" in params;
|
|
270
|
-
}
|
|
271
|
-
var D1HTTPQueryable = class {
|
|
232
|
+
// src/d1.ts
|
|
233
|
+
var debug = Debug("prisma:driver-adapter:d1");
|
|
234
|
+
var D1Queryable = class {
|
|
272
235
|
constructor(client) {
|
|
273
236
|
this.client = client;
|
|
274
237
|
}
|
|
275
238
|
provider = "sqlite";
|
|
276
|
-
adapterName =
|
|
239
|
+
adapterName = name;
|
|
277
240
|
/**
|
|
278
241
|
* Execute a query given as SQL, interpolating the given parameters.
|
|
279
242
|
*/
|
|
@@ -284,7 +247,9 @@ var D1HTTPQueryable = class {
|
|
|
284
247
|
const convertedData = this.convertData(data);
|
|
285
248
|
return convertedData;
|
|
286
249
|
}
|
|
287
|
-
convertData(
|
|
250
|
+
convertData(ioResult) {
|
|
251
|
+
const columnNames = ioResult[0];
|
|
252
|
+
const results = ioResult[1];
|
|
288
253
|
if (results.length === 0) {
|
|
289
254
|
return {
|
|
290
255
|
columnNames: [],
|
|
@@ -292,10 +257,14 @@ var D1HTTPQueryable = class {
|
|
|
292
257
|
rows: []
|
|
293
258
|
};
|
|
294
259
|
}
|
|
295
|
-
const columnTypes = getColumnTypes(columnNames, results);
|
|
260
|
+
const columnTypes = Object.values(getColumnTypes(columnNames, results));
|
|
296
261
|
const rows = results.map((value) => mapRow(value, columnTypes));
|
|
297
262
|
return {
|
|
298
263
|
columnNames,
|
|
264
|
+
// * Note: without Object.values the array looks like
|
|
265
|
+
// * columnTypes: [ id: 128 ],
|
|
266
|
+
// * and errors with:
|
|
267
|
+
// * ✘ [ERROR] A hanging Promise was canceled. This happens when the worker runtime is waiting for a Promise from JavaScript to resolve, but has detected that the Promise cannot possibly ever resolve because all code and events related to the Promise's I/O context have already finished.
|
|
299
268
|
columnTypes,
|
|
300
269
|
rows
|
|
301
270
|
};
|
|
@@ -308,34 +277,25 @@ var D1HTTPQueryable = class {
|
|
|
308
277
|
async executeRaw(query) {
|
|
309
278
|
const tag = "[js::execute_raw]";
|
|
310
279
|
debug(`${tag} %O`, query);
|
|
311
|
-
const result = await this.performIO(query);
|
|
312
|
-
return result.
|
|
280
|
+
const result = await this.performIO(query, true);
|
|
281
|
+
return result.meta.changes ?? 0;
|
|
313
282
|
}
|
|
314
|
-
async performIO(query) {
|
|
283
|
+
async performIO(query, executeRaw = false) {
|
|
315
284
|
try {
|
|
316
285
|
query.args = query.args.map((arg, i) => cleanArg(arg, query.argTypes[i]));
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
const tag = "[js::perform_io]";
|
|
324
|
-
debug(`${tag} %O`, body);
|
|
325
|
-
const results = await performRawQuery(this.client, body);
|
|
326
|
-
if (results.length !== 1) {
|
|
327
|
-
throw new Error("Expected exactly one result");
|
|
286
|
+
const stmt = this.client.prepare(query.sql).bind(...query.args);
|
|
287
|
+
if (executeRaw) {
|
|
288
|
+
return await stmt.run();
|
|
289
|
+
} else {
|
|
290
|
+
const [columnNames, ...rows] = await stmt.raw({ columnNames: true });
|
|
291
|
+
return [columnNames, rows];
|
|
328
292
|
}
|
|
329
|
-
const result = results[0];
|
|
330
|
-
const { columns: columnNames = [], rows = [] } = result.results ?? {};
|
|
331
|
-
const affectedRows = result.meta?.changes;
|
|
332
|
-
return { rows, columnNames, affectedRows };
|
|
333
293
|
} catch (e) {
|
|
334
294
|
onError(e);
|
|
335
295
|
}
|
|
336
296
|
}
|
|
337
297
|
};
|
|
338
|
-
var
|
|
298
|
+
var D1Transaction = class extends D1Queryable {
|
|
339
299
|
constructor(client, options) {
|
|
340
300
|
super(client);
|
|
341
301
|
this.options = options;
|
|
@@ -347,17 +307,8 @@ var D1HTTPTransaction = class extends D1HTTPQueryable {
|
|
|
347
307
|
debug(`[js::rollback]`);
|
|
348
308
|
}
|
|
349
309
|
};
|
|
350
|
-
var
|
|
351
|
-
constructor(
|
|
352
|
-
const D1_API_BASE_URL = `https://api.cloudflare.com/client/v4/accounts/${params.CLOUDFLARE_ACCOUNT_ID}/d1/database/${params.CLOUDFLARE_DATABASE_ID}`;
|
|
353
|
-
const client = ky.create({
|
|
354
|
-
prefixUrl: D1_API_BASE_URL,
|
|
355
|
-
headers: {
|
|
356
|
-
Authorization: `Bearer ${params.CLOUDFLARE_D1_TOKEN}`
|
|
357
|
-
},
|
|
358
|
-
// Don't automatically throw on non-2xx status codes
|
|
359
|
-
throwHttpErrors: false
|
|
360
|
-
});
|
|
310
|
+
var PrismaD1Adapter = class extends D1Queryable {
|
|
311
|
+
constructor(client, release) {
|
|
361
312
|
super(client);
|
|
362
313
|
this.release = release;
|
|
363
314
|
}
|
|
@@ -386,11 +337,7 @@ var PrismaD1HTTPAdapter = class extends D1HTTPQueryable {
|
|
|
386
337
|
};
|
|
387
338
|
async executeScript(script) {
|
|
388
339
|
try {
|
|
389
|
-
await
|
|
390
|
-
json: {
|
|
391
|
-
sql: script
|
|
392
|
-
}
|
|
393
|
-
});
|
|
340
|
+
await this.client.exec(script);
|
|
394
341
|
} catch (error) {
|
|
395
342
|
onError(error);
|
|
396
343
|
}
|
|
@@ -417,83 +364,72 @@ var PrismaD1HTTPAdapter = class extends D1HTTPQueryable {
|
|
|
417
364
|
};
|
|
418
365
|
const tag = "[js::startTransaction]";
|
|
419
366
|
debug("%s options: %O", tag, options);
|
|
420
|
-
return new
|
|
367
|
+
return new D1Transaction(this.client, options);
|
|
421
368
|
}
|
|
422
369
|
async dispose() {
|
|
423
370
|
await this.release?.();
|
|
424
371
|
}
|
|
425
372
|
};
|
|
426
|
-
var
|
|
427
|
-
constructor(
|
|
428
|
-
this.
|
|
373
|
+
var PrismaD1AdapterFactory = class {
|
|
374
|
+
constructor(client) {
|
|
375
|
+
this.client = client;
|
|
429
376
|
}
|
|
430
377
|
provider = "sqlite";
|
|
431
|
-
adapterName =
|
|
378
|
+
adapterName = name;
|
|
432
379
|
async connect() {
|
|
433
|
-
return new
|
|
380
|
+
return new PrismaD1Adapter(this.client, async () => {
|
|
434
381
|
});
|
|
435
382
|
}
|
|
436
|
-
async connectToShadowDb() {
|
|
437
|
-
const D1_API_BASE_URL = `https://api.cloudflare.com/client/v4/accounts/${this.params.CLOUDFLARE_ACCOUNT_ID}/d1/database`;
|
|
438
|
-
const client = ky.create({
|
|
439
|
-
headers: {
|
|
440
|
-
Authorization: `Bearer ${this.params.CLOUDFLARE_D1_TOKEN}`
|
|
441
|
-
},
|
|
442
|
-
// Don't throw on non-2xx status codes
|
|
443
|
-
throwHttpErrors: false
|
|
444
|
-
});
|
|
445
|
-
const createShadowDatabase = async () => {
|
|
446
|
-
const tag = "[js::connectToShadowDb::createShadowDatabase]";
|
|
447
|
-
const SHADOW_DATABASE_PREFIX = "_prisma_shadow_";
|
|
448
|
-
const CLOUDFLARE_SHADOW_DATABASE_NAME = `${SHADOW_DATABASE_PREFIX}${globalThis.crypto.randomUUID()}`;
|
|
449
|
-
debug(`${tag} creating database %s`, CLOUDFLARE_SHADOW_DATABASE_NAME);
|
|
450
|
-
try {
|
|
451
|
-
const response = await client.post(D1_API_BASE_URL, {
|
|
452
|
-
json: {
|
|
453
|
-
name: CLOUDFLARE_SHADOW_DATABASE_NAME
|
|
454
|
-
}
|
|
455
|
-
}).json();
|
|
456
|
-
debug(`${tag} %O`, response);
|
|
457
|
-
if (!response.success) {
|
|
458
|
-
onUnsuccessfulD1HTTPResponse(response);
|
|
459
|
-
}
|
|
460
|
-
const { uuid: CLOUDFLARE_SHADOW_DATABASE_ID2 } = response.result;
|
|
461
|
-
debug(`${tag} created database %s with ID %s`, CLOUDFLARE_SHADOW_DATABASE_NAME, CLOUDFLARE_SHADOW_DATABASE_ID2);
|
|
462
|
-
return CLOUDFLARE_SHADOW_DATABASE_ID2;
|
|
463
|
-
} catch (e) {
|
|
464
|
-
onGenericD1HTTPError(e);
|
|
465
|
-
}
|
|
466
|
-
};
|
|
467
|
-
const CLOUDFLARE_SHADOW_DATABASE_ID = this.params.CLOUDFLARE_SHADOW_DATABASE_ID ?? await createShadowDatabase();
|
|
468
|
-
const dispose = async () => {
|
|
469
|
-
const tag = "[js::connectToShadowDb::dispose]";
|
|
470
|
-
try {
|
|
471
|
-
debug(`${tag} deleting database %s`, CLOUDFLARE_SHADOW_DATABASE_ID);
|
|
472
|
-
const response = await client.delete(`${D1_API_BASE_URL}/${CLOUDFLARE_SHADOW_DATABASE_ID}`).json();
|
|
473
|
-
debug(`${tag} %O`, response);
|
|
474
|
-
if (!response.success) {
|
|
475
|
-
onUnsuccessfulD1HTTPResponse(response);
|
|
476
|
-
}
|
|
477
|
-
} catch (e) {
|
|
478
|
-
onGenericD1HTTPError(e);
|
|
479
|
-
}
|
|
480
|
-
};
|
|
481
|
-
return new PrismaD1HTTPAdapter(this.params, dispose);
|
|
482
|
-
}
|
|
483
383
|
};
|
|
384
|
+
function onError(error) {
|
|
385
|
+
console.error("Error in performIO: %O", error);
|
|
386
|
+
throw new DriverAdapterError(convertDriverError(error));
|
|
387
|
+
}
|
|
484
388
|
|
|
485
|
-
// src/d1-
|
|
389
|
+
// src/d1-http.ts
|
|
486
390
|
import {
|
|
487
391
|
Debug as Debug2,
|
|
488
392
|
DriverAdapterError as DriverAdapterError2
|
|
489
393
|
} from "@prisma/driver-adapter-utils";
|
|
490
|
-
|
|
491
|
-
var
|
|
394
|
+
import ky from "ky";
|
|
395
|
+
var debug2 = Debug2("prisma:driver-adapter:d1-http");
|
|
396
|
+
function onUnsuccessfulD1HTTPResponse({ errors }) {
|
|
397
|
+
debug2("D1 HTTP Errors: %O", errors);
|
|
398
|
+
const error = errors.at(0) ?? { message: "Unknown error", code: GENERIC_SQLITE_ERROR };
|
|
399
|
+
throw new DriverAdapterError2(convertDriverError(error));
|
|
400
|
+
}
|
|
401
|
+
function onGenericD1HTTPError(error) {
|
|
402
|
+
debug2("HTTP Error: %O", error);
|
|
403
|
+
throw new DriverAdapterError2(convertDriverError(error));
|
|
404
|
+
}
|
|
405
|
+
function onError2(error) {
|
|
406
|
+
console.error("Error in performIO: %O", error);
|
|
407
|
+
throw new DriverAdapterError2(convertDriverError(error));
|
|
408
|
+
}
|
|
409
|
+
async function performRawQuery(client, options) {
|
|
410
|
+
try {
|
|
411
|
+
const response = await client.post("raw", options).json();
|
|
412
|
+
const tag = "[js::performRawQuery]";
|
|
413
|
+
debug2(`${tag} %O`, {
|
|
414
|
+
success: response.success,
|
|
415
|
+
errors: response.errors,
|
|
416
|
+
messages: response.messages,
|
|
417
|
+
result: response.result
|
|
418
|
+
});
|
|
419
|
+
if (!response.success) {
|
|
420
|
+
onUnsuccessfulD1HTTPResponse(response);
|
|
421
|
+
}
|
|
422
|
+
return response.result;
|
|
423
|
+
} catch (e) {
|
|
424
|
+
onGenericD1HTTPError(e);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
var D1HTTPQueryable = class {
|
|
492
428
|
constructor(client) {
|
|
493
429
|
this.client = client;
|
|
494
430
|
}
|
|
495
431
|
provider = "sqlite";
|
|
496
|
-
adapterName = name
|
|
432
|
+
adapterName = `${name}-http`;
|
|
497
433
|
/**
|
|
498
434
|
* Execute a query given as SQL, interpolating the given parameters.
|
|
499
435
|
*/
|
|
@@ -504,9 +440,7 @@ var D1WorkerQueryable = class {
|
|
|
504
440
|
const convertedData = this.convertData(data);
|
|
505
441
|
return convertedData;
|
|
506
442
|
}
|
|
507
|
-
convertData(
|
|
508
|
-
const columnNames = ioResult[0];
|
|
509
|
-
const results = ioResult[1];
|
|
443
|
+
convertData({ columnNames, rows: results }) {
|
|
510
444
|
if (results.length === 0) {
|
|
511
445
|
return {
|
|
512
446
|
columnNames: [],
|
|
@@ -514,14 +448,10 @@ var D1WorkerQueryable = class {
|
|
|
514
448
|
rows: []
|
|
515
449
|
};
|
|
516
450
|
}
|
|
517
|
-
const columnTypes =
|
|
451
|
+
const columnTypes = getColumnTypes(columnNames, results);
|
|
518
452
|
const rows = results.map((value) => mapRow(value, columnTypes));
|
|
519
453
|
return {
|
|
520
454
|
columnNames,
|
|
521
|
-
// * Note: without Object.values the array looks like
|
|
522
|
-
// * columnTypes: [ id: 128 ],
|
|
523
|
-
// * and errors with:
|
|
524
|
-
// * ✘ [ERROR] A hanging Promise was canceled. This happens when the worker runtime is waiting for a Promise from JavaScript to resolve, but has detected that the Promise cannot possibly ever resolve because all code and events related to the Promise's I/O context have already finished.
|
|
525
455
|
columnTypes,
|
|
526
456
|
rows
|
|
527
457
|
};
|
|
@@ -534,25 +464,34 @@ var D1WorkerQueryable = class {
|
|
|
534
464
|
async executeRaw(query) {
|
|
535
465
|
const tag = "[js::execute_raw]";
|
|
536
466
|
debug2(`${tag} %O`, query);
|
|
537
|
-
const result = await this.performIO(query
|
|
538
|
-
return result.
|
|
467
|
+
const result = await this.performIO(query);
|
|
468
|
+
return result.affectedRows ?? 0;
|
|
539
469
|
}
|
|
540
|
-
async performIO(query
|
|
470
|
+
async performIO(query) {
|
|
541
471
|
try {
|
|
542
472
|
query.args = query.args.map((arg, i) => cleanArg(arg, query.argTypes[i]));
|
|
543
|
-
const
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
473
|
+
const body = {
|
|
474
|
+
json: {
|
|
475
|
+
sql: query.sql,
|
|
476
|
+
params: query.args
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
const tag = "[js::perform_io]";
|
|
480
|
+
debug2(`${tag} %O`, body);
|
|
481
|
+
const results = await performRawQuery(this.client, body);
|
|
482
|
+
if (results.length !== 1) {
|
|
483
|
+
throw new Error("Expected exactly one result");
|
|
549
484
|
}
|
|
485
|
+
const result = results[0];
|
|
486
|
+
const { columns: columnNames = [], rows = [] } = result.results ?? {};
|
|
487
|
+
const affectedRows = result.meta?.changes;
|
|
488
|
+
return { rows, columnNames, affectedRows };
|
|
550
489
|
} catch (e) {
|
|
551
490
|
onError2(e);
|
|
552
491
|
}
|
|
553
492
|
}
|
|
554
493
|
};
|
|
555
|
-
var
|
|
494
|
+
var D1HTTPTransaction = class extends D1HTTPQueryable {
|
|
556
495
|
constructor(client, options) {
|
|
557
496
|
super(client);
|
|
558
497
|
this.options = options;
|
|
@@ -564,8 +503,17 @@ var D1WorkerTransaction = class extends D1WorkerQueryable {
|
|
|
564
503
|
debug2(`[js::rollback]`);
|
|
565
504
|
}
|
|
566
505
|
};
|
|
567
|
-
var
|
|
568
|
-
constructor(
|
|
506
|
+
var PrismaD1HTTPAdapter = class extends D1HTTPQueryable {
|
|
507
|
+
constructor(params, release) {
|
|
508
|
+
const D1_API_BASE_URL = `https://api.cloudflare.com/client/v4/accounts/${params.CLOUDFLARE_ACCOUNT_ID}/d1/database/${params.CLOUDFLARE_DATABASE_ID}`;
|
|
509
|
+
const client = ky.create({
|
|
510
|
+
prefixUrl: D1_API_BASE_URL,
|
|
511
|
+
headers: {
|
|
512
|
+
Authorization: `Bearer ${params.CLOUDFLARE_D1_TOKEN}`
|
|
513
|
+
},
|
|
514
|
+
// Don't automatically throw on non-2xx status codes
|
|
515
|
+
throwHttpErrors: false
|
|
516
|
+
});
|
|
569
517
|
super(client);
|
|
570
518
|
this.release = release;
|
|
571
519
|
}
|
|
@@ -594,7 +542,11 @@ var PrismaD1WorkerAdapter = class extends D1WorkerQueryable {
|
|
|
594
542
|
};
|
|
595
543
|
async executeScript(script) {
|
|
596
544
|
try {
|
|
597
|
-
await this.client
|
|
545
|
+
await performRawQuery(this.client, {
|
|
546
|
+
json: {
|
|
547
|
+
sql: script
|
|
548
|
+
}
|
|
549
|
+
});
|
|
598
550
|
} catch (error) {
|
|
599
551
|
onError2(error);
|
|
600
552
|
}
|
|
@@ -621,48 +573,71 @@ var PrismaD1WorkerAdapter = class extends D1WorkerQueryable {
|
|
|
621
573
|
};
|
|
622
574
|
const tag = "[js::startTransaction]";
|
|
623
575
|
debug2("%s options: %O", tag, options);
|
|
624
|
-
return new
|
|
576
|
+
return new D1HTTPTransaction(this.client, options);
|
|
625
577
|
}
|
|
626
578
|
async dispose() {
|
|
627
579
|
await this.release?.();
|
|
628
580
|
}
|
|
629
581
|
};
|
|
630
|
-
var
|
|
631
|
-
constructor(
|
|
632
|
-
this.
|
|
582
|
+
var PrismaD1HTTPAdapterFactory = class {
|
|
583
|
+
constructor(params) {
|
|
584
|
+
this.params = params;
|
|
633
585
|
}
|
|
634
586
|
provider = "sqlite";
|
|
635
|
-
adapterName = name
|
|
587
|
+
adapterName = `${name}-http`;
|
|
636
588
|
async connect() {
|
|
637
|
-
return new
|
|
589
|
+
return new PrismaD1HTTPAdapter(this.params, async () => {
|
|
638
590
|
});
|
|
639
591
|
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
//
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
592
|
+
async connectToShadowDb() {
|
|
593
|
+
const D1_API_BASE_URL = `https://api.cloudflare.com/client/v4/accounts/${this.params.CLOUDFLARE_ACCOUNT_ID}/d1/database`;
|
|
594
|
+
const client = ky.create({
|
|
595
|
+
headers: {
|
|
596
|
+
Authorization: `Bearer ${this.params.CLOUDFLARE_D1_TOKEN}`
|
|
597
|
+
},
|
|
598
|
+
// Don't throw on non-2xx status codes
|
|
599
|
+
throwHttpErrors: false
|
|
600
|
+
});
|
|
601
|
+
const createShadowDatabase = async () => {
|
|
602
|
+
const tag = "[js::connectToShadowDb::createShadowDatabase]";
|
|
603
|
+
const SHADOW_DATABASE_PREFIX = "_prisma_shadow_";
|
|
604
|
+
const CLOUDFLARE_SHADOW_DATABASE_NAME = `${SHADOW_DATABASE_PREFIX}${globalThis.crypto.randomUUID()}`;
|
|
605
|
+
debug2(`${tag} creating database %s`, CLOUDFLARE_SHADOW_DATABASE_NAME);
|
|
606
|
+
try {
|
|
607
|
+
const response = await client.post(D1_API_BASE_URL, {
|
|
608
|
+
json: {
|
|
609
|
+
name: CLOUDFLARE_SHADOW_DATABASE_NAME
|
|
610
|
+
}
|
|
611
|
+
}).json();
|
|
612
|
+
debug2(`${tag} %O`, response);
|
|
613
|
+
if (!response.success) {
|
|
614
|
+
onUnsuccessfulD1HTTPResponse(response);
|
|
615
|
+
}
|
|
616
|
+
const { uuid: CLOUDFLARE_SHADOW_DATABASE_ID2 } = response.result;
|
|
617
|
+
debug2(`${tag} created database %s with ID %s`, CLOUDFLARE_SHADOW_DATABASE_NAME, CLOUDFLARE_SHADOW_DATABASE_ID2);
|
|
618
|
+
return CLOUDFLARE_SHADOW_DATABASE_ID2;
|
|
619
|
+
} catch (e) {
|
|
620
|
+
onGenericD1HTTPError(e);
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
const CLOUDFLARE_SHADOW_DATABASE_ID = this.params.CLOUDFLARE_SHADOW_DATABASE_ID ?? await createShadowDatabase();
|
|
624
|
+
const dispose = async () => {
|
|
625
|
+
const tag = "[js::connectToShadowDb::dispose]";
|
|
626
|
+
try {
|
|
627
|
+
debug2(`${tag} deleting database %s`, CLOUDFLARE_SHADOW_DATABASE_ID);
|
|
628
|
+
const response = await client.delete(`${D1_API_BASE_URL}/${CLOUDFLARE_SHADOW_DATABASE_ID}`).json();
|
|
629
|
+
debug2(`${tag} %O`, response);
|
|
630
|
+
if (!response.success) {
|
|
631
|
+
onUnsuccessfulD1HTTPResponse(response);
|
|
632
|
+
}
|
|
633
|
+
} catch (e) {
|
|
634
|
+
onGenericD1HTTPError(e);
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
return new PrismaD1HTTPAdapter(this.params, dispose);
|
|
663
638
|
}
|
|
664
639
|
};
|
|
665
640
|
export {
|
|
666
|
-
PrismaD1,
|
|
641
|
+
PrismaD1AdapterFactory as PrismaD1,
|
|
667
642
|
PrismaD1HTTPAdapterFactory as PrismaD1HTTP
|
|
668
643
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/adapter-d1",
|
|
3
|
-
"version": "6.11.0-dev.
|
|
3
|
+
"version": "6.11.0-dev.6",
|
|
4
4
|
"description": "Prisma's driver adapter for Cloudflare D1",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -37,14 +37,10 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@cloudflare/workers-types": "4.20250214.0",
|
|
39
39
|
"ky": "1.7.5",
|
|
40
|
-
"@prisma/driver-adapter-utils": "6.11.0-dev.
|
|
41
|
-
},
|
|
42
|
-
"devDependencies": {
|
|
43
|
-
"vitest": "3.0.9"
|
|
40
|
+
"@prisma/driver-adapter-utils": "6.11.0-dev.6"
|
|
44
41
|
},
|
|
45
42
|
"scripts": {
|
|
46
43
|
"dev": "DEV=true tsx helpers/build.ts",
|
|
47
|
-
"build": "tsx helpers/build.ts"
|
|
48
|
-
"test": "vitest run"
|
|
44
|
+
"build": "tsx helpers/build.ts"
|
|
49
45
|
}
|
|
50
46
|
}
|