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