@deox/drizzle-d1-utils 0.0.1 → 0.0.2
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.cjs +36 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +23 -7
- package/dist/index.js.map +1 -1
- package/package.json +15 -8
package/dist/index.cjs
CHANGED
|
@@ -1,17 +1,26 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// ../../node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.47.6_@types+node@24.5.2__postcss@8.5.6_tsx@4.20.5_typescript@5.9.3_yaml@2.4.2/node_modules/tsup/assets/cjs_shims.js
|
|
2
|
+
var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
|
|
2
3
|
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
4
|
+
|
|
5
|
+
// src/index.ts
|
|
6
|
+
var _child_process = require('child_process');
|
|
7
|
+
var _crypto = require('crypto');
|
|
8
|
+
var _fs = require('fs');
|
|
9
|
+
var _module = require('module');
|
|
10
|
+
var _path = require('path');
|
|
11
|
+
var _promptsync = require('prompt-sync'); var _promptsync2 = _interopRequireDefault(_promptsync);
|
|
8
12
|
var _cli = require('wrangler/wrangler-dist/cli');
|
|
9
13
|
function durableObjectNamespaceIdFromName(uniqueKey, name) {
|
|
10
|
-
const key =
|
|
11
|
-
const nameHmac =
|
|
12
|
-
const hmac =
|
|
14
|
+
const key = _crypto.createHash.call(void 0, "sha256").update(uniqueKey).digest();
|
|
15
|
+
const nameHmac = _crypto.createHmac.call(void 0, "sha256", key).update(name).digest().subarray(0, 16);
|
|
16
|
+
const hmac = _crypto.createHmac.call(void 0, "sha256", key).update(nameHmac).digest().subarray(0, 16);
|
|
13
17
|
return Buffer.concat([nameHmac, hmac]).toString("hex");
|
|
14
18
|
}
|
|
19
|
+
function confirmSync(message) {
|
|
20
|
+
const prompt = _promptsync2.default.call(void 0, );
|
|
21
|
+
const answer = prompt(`${message} (y/N): `);
|
|
22
|
+
return _optionalChain([answer, 'optionalAccess', _2 => _2.toLowerCase, 'call', _3 => _3()]) === "y";
|
|
23
|
+
}
|
|
15
24
|
function getD1BindingInfo({
|
|
16
25
|
binding,
|
|
17
26
|
environment,
|
|
@@ -19,7 +28,10 @@ function getD1BindingInfo({
|
|
|
19
28
|
configPath: wranglerConfigPath
|
|
20
29
|
} = {}) {
|
|
21
30
|
const { d1_databases, configPath } = _cli.unstable_readConfig.call(void 0, { env: environment, config: wranglerConfigPath });
|
|
22
|
-
if (
|
|
31
|
+
if (typeof configPath !== "string") {
|
|
32
|
+
throw new Error("Failed to get wrangler config path");
|
|
33
|
+
}
|
|
34
|
+
if (!d1_databases || d1_databases.length === 0) {
|
|
23
35
|
throw new Error("No D1 binding exists in the config");
|
|
24
36
|
}
|
|
25
37
|
if (d1_databases.length > 1 && !binding) {
|
|
@@ -37,8 +49,8 @@ function getD1BindingInfo({
|
|
|
37
49
|
if (!bindingConfig.database_id && !bindingConfig.preview_database_id) {
|
|
38
50
|
throw new Error(`Neither 'database_id' nor 'preview_database_id' is set for D1 binding '${bindingConfig.binding}'`);
|
|
39
51
|
}
|
|
40
|
-
const wranglerConfigDir = configPath ?
|
|
41
|
-
const wranglerStateDir = _nullishCoalesce(persistTo, () => (
|
|
52
|
+
const wranglerConfigDir = configPath ? _path.dirname.call(void 0, configPath) : void 0;
|
|
53
|
+
const wranglerStateDir = _nullishCoalesce(persistTo, () => ( _path.relative.call(void 0, ".", _path.join.call(void 0, _nullishCoalesce(wranglerConfigDir, () => ( "")), ".wrangler/state/v3"))));
|
|
42
54
|
const [database, previewDatabase] = [bindingConfig.database_id, bindingConfig.preview_database_id].map((databaseId) => {
|
|
43
55
|
if (!databaseId) {
|
|
44
56
|
return null;
|
|
@@ -46,11 +58,11 @@ function getD1BindingInfo({
|
|
|
46
58
|
const uniqueKey = "miniflare-D1DatabaseObject";
|
|
47
59
|
const miniflarePath = `${wranglerStateDir}/d1/${uniqueKey}`;
|
|
48
60
|
const hash = durableObjectNamespaceIdFromName(uniqueKey, databaseId);
|
|
49
|
-
const filename =
|
|
61
|
+
const filename = _path.join.call(void 0, miniflarePath, `${hash}.sqlite`);
|
|
50
62
|
return {
|
|
51
63
|
id: databaseId,
|
|
52
64
|
filename,
|
|
53
|
-
exists:
|
|
65
|
+
exists: _fs.existsSync.call(void 0, filename)
|
|
54
66
|
};
|
|
55
67
|
});
|
|
56
68
|
return {
|
|
@@ -83,7 +95,7 @@ function drizzleD1Config(config, options = {}) {
|
|
|
83
95
|
if (binding.databaseName) {
|
|
84
96
|
let bin;
|
|
85
97
|
try {
|
|
86
|
-
bin =
|
|
98
|
+
bin = _module.createRequire.call(void 0, importMetaUrl).resolve("wrangler/bin/wrangler");
|
|
87
99
|
} catch (_) {
|
|
88
100
|
}
|
|
89
101
|
if (bin) {
|
|
@@ -98,15 +110,21 @@ function drizzleD1Config(config, options = {}) {
|
|
|
98
110
|
args.push(`--persist-to=${options.persistTo}`);
|
|
99
111
|
}
|
|
100
112
|
const command = ["wrangler", ...args].join(" ");
|
|
101
|
-
console.log(`[!] SQLite file for D1 binding '${binding.binding}' does not exist
|
|
113
|
+
console.log(`[!] SQLite file for D1 binding '${binding.binding}' does not exist.`);
|
|
114
|
+
console.log("[!] The file can be created by executing the following command:");
|
|
102
115
|
console.log(` ${command}`);
|
|
116
|
+
const confirmed = confirmSync("[!] Run this command to create it?");
|
|
117
|
+
if (!confirmed) {
|
|
118
|
+
throw new Error("Aborted by user.");
|
|
119
|
+
}
|
|
120
|
+
console.log("[!] Command is being executed. Please wait...");
|
|
103
121
|
try {
|
|
104
|
-
|
|
122
|
+
_child_process.execFileSync.call(void 0, bin, args, {
|
|
105
123
|
stdio: "ignore"
|
|
106
124
|
});
|
|
107
125
|
} catch (_) {
|
|
108
126
|
}
|
|
109
|
-
if (
|
|
127
|
+
if (_fs.existsSync.call(void 0, database.filename)) {
|
|
110
128
|
database.exists = true;
|
|
111
129
|
console.log("[\u2713] Command success! SQLite file has been successfully created.");
|
|
112
130
|
} else {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.5.0_@microsoft+api-extractor@7.47.6_@types+node@24.5.2__postcss@8.4.38_tsx@4.20.5_typescript@5.9.2_yaml@2.4.2/node_modules/tsup/assets/cjs_shims.js","../src/index.ts","/home/runner/work/deox/deox/packages/drizzle-d1-utils/dist/index.cjs"],"names":[],"mappings":"AAKA,iLAAM,iBAAA,EAAmB,CAAA,EAAA,GACvB,OAAO,SAAA,IAAa,YAAA,EAChB,IAAI,GAAA,CAAI,CAAA,KAAA,EAAQ,UAAU,CAAA,CAAA;AAI8B;ACXjC;AACU;AACZ;AACG;AACU;AAEJ;AAEuC;AAUf,EAAA;AACqB,EAAA;AACA,EAAA;AAC1B,EAAA;AACvD;AAE0B;AACxB,EAAA;AACA,EAAA;AACA,EAAA;AACY,EAAA;AAMN;AAC+E,EAAA;AACtD,EAAA;AACuB,IAAA;AACtD,EAAA;AACyC,EAAA;AACvB,IAAA;AAClB,EAAA;AACI,EAAA;AACS,EAAA;AACqD,IAAA;AAC5C,IAAA;AACgD,MAAA;AACpE,IAAA;AACK,EAAA;AACyB,IAAA;AAChC,EAAA;AAEsE,EAAA;AACpD,IAAA;AAClB,EAAA;AAE6D,EAAA;AACqB,EAAA;AAEJ,EAAA;AAC3D,IAAA;AACR,MAAA;AACT,IAAA;AACkB,IAAA;AACuC,IAAA;AACU,IAAA;AACd,IAAA;AAC9C,IAAA;AACD,MAAA;AACJ,MAAA;AAC2B,MAAA;AAC7B,IAAA;AACD,EAAA;AAEM,EAAA;AACL,IAAA;AACuB,IAAA;AACK,IAAA;AAC5B,IAAA;AACA,IAAA;AACF,EAAA;AACF;AAasI;AAChH,EAAA;AAC0D,IAAA;AACN,IAAA;AACvC,IAAA;AACwB,MAAA;AACvD,IAAA;AACF,EAAA;AAEiC,EAAA;AACd,IAAA;AACI,IAAA;AACD,IAAA;AACD,IAAA;AACpB,EAAA;AAEoE,EAAA;AAEtD,EAAA;AAC8D,IAAA;AAC7E,EAAA;AAEyC,EAAA;AACb,IAAA;AACpB,MAAA;AACA,MAAA;AACkE,QAAA;AAC1D,MAAA;AAAC,MAAA;AAEJ,MAAA;AACgF,QAAA;AAC9D,QAAA;AACiB,UAAA;AAC1C,QAAA;AACwB,QAAA;AACoB,UAAA;AAC5C,QAAA;AACuB,QAAA;AACwB,UAAA;AAC/C,QAAA;AAE8C,QAAA;AACgB,QAAA;AAClC,QAAA;AAExB,QAAA;AACsB,UAAA;AACf,YAAA;AACR,UAAA;AACS,QAAA;AAAC,QAAA;AAEsB,QAAA;AACf,UAAA;AAEN,UAAA;AACP,QAAA;AAC0D,UAAA;AACjD,UAAA;AAChB,QAAA;AACF,MAAA;AACF,IAAA;AACsB,IAAA;AAC4D,MAAA;AAClF,IAAA;AACF,EAAA;AAEwE,EAAA;AAC5B,EAAA;AAC4B,EAAA;AACrB,EAAA;AACoB,EAAA;AACxB,EAAA;AAC3B,EAAA;AACqB,IAAA;AAC+B,IAAA;AACjE,EAAA;AACiC,IAAA;AACwB,IAAA;AACT,IAAA;AACvD,EAAA;AACwE,EAAA;AAE/C,EAAA;AACT,IAAA;AACf,EAAA;AAEM,EAAA;AACF,IAAA;AACM,IAAA;AAEL,IAAA;AACU,MAAA;AACO,MAAA;AACQ,QAAA;AACF,QAAA;AACJ,QAAA;AACjB,MAAA;AAEF,IAAA;AACiB,MAAA;AACiB,QAAA;AAChC,MAAA;AACF,IAAA;AACN,EAAA;AACF;AC1C0F;AACA;AACA","file":"/home/runner/work/deox/deox/packages/drizzle-d1-utils/dist/index.cjs","sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () =>\n typeof document === 'undefined'\n ? new URL(`file:${__filename}`).href\n : (document.currentScript && document.currentScript.src) ||\n new URL('main.js', document.baseURI).href\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import { execFileSync } from 'node:child_process';\nimport { createHash, createHmac } from 'node:crypto';\nimport { existsSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join, relative } from 'node:path';\nimport type { Config } from 'drizzle-kit';\nimport { unstable_readConfig } from 'wrangler/wrangler-dist/cli';\n\nfunction durableObjectNamespaceIdFromName(uniqueKey: string, name: string) {\n /**\n * In v3.2, miniflare uses durable object to implement D1 and hashes the local sqlite filename.\n *\n * See the following for more context:\n * https://github.com/cloudflare/workers-sdk/issues/4548 (understand the hash of the local D1 filename)\n * https://github.com/cloudflare/miniflare/releases/tag/v3.20230918.0\n *\n * This function is copied from these links\n */\n const key = createHash('sha256').update(uniqueKey).digest();\n const nameHmac = createHmac('sha256', key).update(name).digest().subarray(0, 16);\n const hmac = createHmac('sha256', key).update(nameHmac).digest().subarray(0, 16);\n return Buffer.concat([nameHmac, hmac]).toString('hex');\n}\n\nfunction getD1BindingInfo({\n binding,\n environment,\n persistTo,\n configPath: wranglerConfigPath,\n}: {\n binding?: string;\n configPath?: string;\n persistTo?: string;\n environment?: string;\n} = {}) {\n const { d1_databases, configPath } = unstable_readConfig({ env: environment, config: wranglerConfigPath });\n if (d1_databases.length === 0) {\n throw new Error('No D1 binding exists in the config');\n }\n if (d1_databases.length > 1 && !binding) {\n throw new Error(\"Argument 'binding' is required when more than one D1 bindings exist in the config\");\n }\n let bindingConfig: (typeof d1_databases)[number] | undefined;\n if (binding) {\n bindingConfig = d1_databases.find((d1) => d1.binding === binding);\n if (!bindingConfig) {\n throw new Error(`Could not find D1 binding '${binding}' in config`);\n }\n } else {\n bindingConfig = d1_databases[0];\n }\n\n if (!bindingConfig.database_id && !bindingConfig.preview_database_id) {\n throw new Error(`Neither 'database_id' nor 'preview_database_id' is set for D1 binding '${bindingConfig.binding}'`);\n }\n\n const wranglerConfigDir = configPath ? dirname(configPath) : undefined;\n const wranglerStateDir = persistTo ?? relative('.', join(wranglerConfigDir ?? '', '.wrangler/state/v3'));\n\n const [database, previewDatabase] = [bindingConfig.database_id, bindingConfig.preview_database_id].map((databaseId) => {\n if (!databaseId) {\n return null;\n }\n const uniqueKey = 'miniflare-D1DatabaseObject';\n const miniflarePath = `${wranglerStateDir}/d1/${uniqueKey}`;\n const hash = durableObjectNamespaceIdFromName(uniqueKey, databaseId);\n const filename = join(miniflarePath, `${hash}.sqlite`);\n return {\n id: databaseId,\n filename,\n exists: existsSync(filename),\n };\n });\n\n return {\n configPath,\n binding: bindingConfig.binding,\n databaseName: bindingConfig.database_name,\n database,\n previewDatabase,\n };\n}\n\nexport interface DrizzleD1Options {\n configPath?: string;\n persistTo?: string;\n environment?: string;\n binding?: string;\n remote?: boolean;\n preview?: boolean;\n accountId?: string;\n apiToken?: string;\n}\n\nexport function drizzleD1Config(config: Omit<Config, 'dialect' | 'driver' | 'dbCredentials'>, options: DrizzleD1Options = {}): Config {\n if (options.remote) {\n const requiredOptions: (keyof DrizzleD1Options)[] = ['accountId', 'apiToken'];\n const missingOptions = requiredOptions.filter((name) => !options[name]);\n if (missingOptions.length > 0) {\n throw new Error(`Options ${requiredOptions.join(', ')} are required when using remote database. Missing: ${missingOptions.join(', ')}`);\n }\n }\n\n const binding = getD1BindingInfo({\n binding: options.binding,\n environment: options.environment,\n configPath: options.configPath,\n persistTo: options.persistTo,\n });\n\n const database = options.preview ? binding.previewDatabase : binding.database;\n\n if (!database) {\n throw new Error(`'${options.preview ? 'preview_database_id' : 'database_id'} is not set for D1 binding '${binding.binding}'`);\n }\n\n if (!options.remote && !database.exists) {\n if (binding.databaseName) {\n let bin: string | undefined;\n try {\n bin = createRequire(import.meta.url).resolve('wrangler/bin/wrangler');\n } catch (_) {}\n\n if (bin) {\n const args: string[] = ['d1', 'execute', binding.databaseName, \"--command='SELECT 1'\", '--local'];\n if (options.environment) {\n args.push(`--env=${options.environment}`);\n }\n if (options.configPath) {\n args.push(`--config=${options.configPath}`);\n }\n if (options.persistTo) {\n args.push(`--persist-to=${options.persistTo}`);\n }\n\n const command = ['wrangler', ...args].join(' ');\n console.log(`[!] SQLite file for D1 binding '${binding.binding}' does not exist. Trying to create one by executing the following command:`);\n console.log(` ${command}`);\n\n try {\n execFileSync(bin, args, {\n stdio: 'ignore',\n });\n } catch (_) {}\n\n if (existsSync(database.filename)) {\n database.exists = true;\n\n console.log('[✓] Command success! SQLite file has been successfully created.');\n } else {\n console.log('[×] Command failed! Unable to create SQLite file.');\n process.exit(1);\n }\n }\n }\n if (!database.exists) {\n throw new Error(`Could not find SQLite file for D1 binding '${binding.binding}'`);\n }\n }\n\n console.log('----------------------------------------------------------');\n console.log(' Using following D1 Database:');\n console.log('----------------------------------------------------------');\n console.log(` Binding : ${binding.binding}`);\n console.log(` Database name : ${binding.databaseName ?? '(not set)'}`);\n console.log(` Database Id : ${database.id}`);\n if (options.remote) {\n console.log(' Mode : REMOTE');\n console.log(' (using remote Cloudflare D1 database)');\n } else {\n console.log(' Mode : LOCAL');\n console.log(' (using local SQLite database)');\n console.log(` SQLite file : ${database.filename}`);\n }\n console.log('----------------------------------------------------------');\n\n process.on('exit', () => {\n console.log('');\n });\n\n return {\n ...config,\n dialect: 'sqlite',\n ...(options.remote\n ? {\n driver: 'd1-http',\n dbCredentials: {\n databaseId: database.id,\n accountId: options.accountId,\n token: options.apiToken,\n },\n }\n : {\n dbCredentials: {\n url: `file:${database.filename}`,\n },\n }),\n };\n}\n",null]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/deox/deox/packages/drizzle-d1-utils/dist/index.cjs","../../../node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.47.6_@types+node@24.5.2__postcss@8.5.6_tsx@4.20.5_typescript@5.9.3_yaml@2.4.2/node_modules/tsup/assets/cjs_shims.js","../src/index.ts"],"names":[],"mappings":"AAAA;ACKA,IAAM,iBAAA,EAAmB,CAAA,EAAA,GACvB,OAAO,SAAA,IAAa,YAAA,EAChB,IAAI,GAAA,CAAI,CAAA,KAAA,EAAQ,UAAU,CAAA,CAAA;AAK8B;ADT4B;AACA;AEJ7D;AACU;AACZ;AACG;AACU;AAEjB;AACa;AAEuC;AAUf,EAAA;AACqB,EAAA;AACA,EAAA;AAC1B,EAAA;AACvD;AAE+C;AACnB,EAAA;AACgB,EAAA;AACT,EAAA;AACnC;AAc0B;AACxB,EAAA;AACA,EAAA;AACA,EAAA;AACY,EAAA;AAMN;AAC+E,EAAA;AACjD,EAAA;AACkB,IAAA;AACtD,EAAA;AACgD,EAAA;AACM,IAAA;AACtD,EAAA;AACyC,EAAA;AACvB,IAAA;AAClB,EAAA;AACI,EAAA;AACS,EAAA;AACqD,IAAA;AAC5C,IAAA;AACgD,MAAA;AACpE,IAAA;AACK,EAAA;AACyB,IAAA;AAChC,EAAA;AAEsE,EAAA;AACpD,IAAA;AAClB,EAAA;AAE6D,EAAA;AACqB,EAAA;AAEJ,EAAA;AAC3D,IAAA;AACR,MAAA;AACT,IAAA;AACkB,IAAA;AACuC,IAAA;AACU,IAAA;AACd,IAAA;AAC9C,IAAA;AACD,MAAA;AACJ,MAAA;AAC2B,MAAA;AAC7B,IAAA;AACD,EAAA;AAEM,EAAA;AACL,IAAA;AACuB,IAAA;AACK,IAAA;AAC5B,IAAA;AACA,IAAA;AACF,EAAA;AACF;AAasI;AAChH,EAAA;AAC0D,IAAA;AACN,IAAA;AACvC,IAAA;AACwB,MAAA;AACvD,IAAA;AACF,EAAA;AAEiC,EAAA;AACd,IAAA;AACI,IAAA;AACD,IAAA;AACD,IAAA;AACpB,EAAA;AAEoE,EAAA;AAEtD,EAAA;AAC8D,IAAA;AAC7E,EAAA;AAEyC,EAAA;AACb,IAAA;AACpB,MAAA;AACA,MAAA;AACkE,QAAA;AAC1D,MAAA;AAAC,MAAA;AAEJ,MAAA;AACgF,QAAA;AAC9D,QAAA;AACiB,UAAA;AAC1C,QAAA;AACwB,QAAA;AACoB,UAAA;AAC5C,QAAA;AACuB,QAAA;AACwB,UAAA;AAC/C,QAAA;AAE8C,QAAA;AACmC,QAAA;AACJ,QAAA;AACjD,QAAA;AAEsC,QAAA;AAClD,QAAA;AACoB,UAAA;AACpC,QAAA;AAE2D,QAAA;AAEvD,QAAA;AACsB,UAAA;AACf,YAAA;AACR,UAAA;AACS,QAAA;AAAC,QAAA;AAEsB,QAAA;AACf,UAAA;AAEN,UAAA;AACP,QAAA;AAC0D,UAAA;AACjD,UAAA;AAChB,QAAA;AACF,MAAA;AACF,IAAA;AACsB,IAAA;AAC4D,MAAA;AAClF,IAAA;AACF,EAAA;AAEwE,EAAA;AAC5B,EAAA;AAC4B,EAAA;AACrB,EAAA;AACoB,EAAA;AACxB,EAAA;AAC3B,EAAA;AACqB,IAAA;AAC+B,IAAA;AACjE,EAAA;AACiC,IAAA;AACwB,IAAA;AACT,IAAA;AACvD,EAAA;AACwE,EAAA;AAE/C,EAAA;AACT,IAAA;AACf,EAAA;AAEM,EAAA;AACF,IAAA;AACM,IAAA;AAEL,IAAA;AACU,MAAA;AACO,MAAA;AACQ,QAAA;AACF,QAAA;AACJ,QAAA;AACjB,MAAA;AAEF,IAAA;AACiB,MAAA;AACiB,QAAA;AAChC,MAAA;AACF,IAAA;AACN,EAAA;AACF;AFtD0F;AACA;AACA","file":"/home/runner/work/deox/deox/packages/drizzle-d1-utils/dist/index.cjs","sourcesContent":[null,"// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import { execFileSync } from 'node:child_process';\nimport { createHash, createHmac } from 'node:crypto';\nimport { existsSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join, relative } from 'node:path';\nimport type { Config } from 'drizzle-kit';\nimport promptSync from 'prompt-sync';\nimport { unstable_readConfig } from 'wrangler/wrangler-dist/cli';\n\nfunction durableObjectNamespaceIdFromName(uniqueKey: string, name: string) {\n /**\n * In v3.2, miniflare uses durable object to implement D1 and hashes the local sqlite filename.\n *\n * See the following for more context:\n * https://github.com/cloudflare/workers-sdk/issues/4548 (understand the hash of the local D1 filename)\n * https://github.com/cloudflare/miniflare/releases/tag/v3.20230918.0\n *\n * This function is copied from these links\n */\n const key = createHash('sha256').update(uniqueKey).digest();\n const nameHmac = createHmac('sha256', key).update(name).digest().subarray(0, 16);\n const hmac = createHmac('sha256', key).update(nameHmac).digest().subarray(0, 16);\n return Buffer.concat([nameHmac, hmac]).toString('hex');\n}\n\nfunction confirmSync(message: string): boolean {\n const prompt = promptSync();\n const answer = prompt(`${message} (y/N): `);\n return answer?.toLowerCase() === 'y';\n}\n\ninterface MinimalD1Database {\n binding?: string;\n database_id?: string;\n preview_database_id?: string;\n database_name?: string;\n}\n\ninterface WranglerMinimalConfig {\n d1_databases?: MinimalD1Database[];\n configPath?: string;\n}\n\nfunction getD1BindingInfo({\n binding,\n environment,\n persistTo,\n configPath: wranglerConfigPath,\n}: {\n binding?: string;\n configPath?: string;\n persistTo?: string;\n environment?: string;\n} = {}) {\n const { d1_databases, configPath } = unstable_readConfig({ env: environment, config: wranglerConfigPath }) as WranglerMinimalConfig;\n if (typeof configPath !== 'string') {\n throw new Error('Failed to get wrangler config path');\n }\n if (!d1_databases || d1_databases.length === 0) {\n throw new Error('No D1 binding exists in the config');\n }\n if (d1_databases.length > 1 && !binding) {\n throw new Error(\"Argument 'binding' is required when more than one D1 bindings exist in the config\");\n }\n let bindingConfig: MinimalD1Database | undefined;\n if (binding) {\n bindingConfig = d1_databases.find((d1) => d1.binding === binding);\n if (!bindingConfig) {\n throw new Error(`Could not find D1 binding '${binding}' in config`);\n }\n } else {\n bindingConfig = d1_databases[0];\n }\n\n if (!bindingConfig.database_id && !bindingConfig.preview_database_id) {\n throw new Error(`Neither 'database_id' nor 'preview_database_id' is set for D1 binding '${bindingConfig.binding}'`);\n }\n\n const wranglerConfigDir = configPath ? dirname(configPath) : undefined;\n const wranglerStateDir = persistTo ?? relative('.', join(wranglerConfigDir ?? '', '.wrangler/state/v3'));\n\n const [database, previewDatabase] = [bindingConfig.database_id, bindingConfig.preview_database_id].map((databaseId) => {\n if (!databaseId) {\n return null;\n }\n const uniqueKey = 'miniflare-D1DatabaseObject';\n const miniflarePath = `${wranglerStateDir}/d1/${uniqueKey}`;\n const hash = durableObjectNamespaceIdFromName(uniqueKey, databaseId);\n const filename = join(miniflarePath, `${hash}.sqlite`);\n return {\n id: databaseId,\n filename,\n exists: existsSync(filename),\n };\n });\n\n return {\n configPath,\n binding: bindingConfig.binding,\n databaseName: bindingConfig.database_name,\n database,\n previewDatabase,\n };\n}\n\nexport interface DrizzleD1Options {\n configPath?: string;\n persistTo?: string;\n environment?: string;\n binding?: string;\n remote?: boolean;\n preview?: boolean;\n accountId?: string;\n apiToken?: string;\n}\n\nexport function drizzleD1Config(config: Omit<Config, 'dialect' | 'driver' | 'dbCredentials'>, options: DrizzleD1Options = {}): Config {\n if (options.remote) {\n const requiredOptions: (keyof DrizzleD1Options)[] = ['accountId', 'apiToken'];\n const missingOptions = requiredOptions.filter((name) => !options[name]);\n if (missingOptions.length > 0) {\n throw new Error(`Options ${requiredOptions.join(', ')} are required when using remote database. Missing: ${missingOptions.join(', ')}`);\n }\n }\n\n const binding = getD1BindingInfo({\n binding: options.binding,\n environment: options.environment,\n configPath: options.configPath,\n persistTo: options.persistTo,\n });\n\n const database = options.preview ? binding.previewDatabase : binding.database;\n\n if (!database) {\n throw new Error(`'${options.preview ? 'preview_database_id' : 'database_id'} is not set for D1 binding '${binding.binding}'`);\n }\n\n if (!options.remote && !database.exists) {\n if (binding.databaseName) {\n let bin: string | undefined;\n try {\n bin = createRequire(import.meta.url).resolve('wrangler/bin/wrangler');\n } catch (_) {}\n\n if (bin) {\n const args: string[] = ['d1', 'execute', binding.databaseName, \"--command='SELECT 1'\", '--local'];\n if (options.environment) {\n args.push(`--env=${options.environment}`);\n }\n if (options.configPath) {\n args.push(`--config=${options.configPath}`);\n }\n if (options.persistTo) {\n args.push(`--persist-to=${options.persistTo}`);\n }\n\n const command = ['wrangler', ...args].join(' ');\n console.log(`[!] SQLite file for D1 binding '${binding.binding}' does not exist.`);\n console.log('[!] The file can be created by executing the following command:');\n console.log(` ${command}`);\n\n const confirmed = confirmSync('[!] Run this command to create it?');\n if (!confirmed) {\n throw new Error('Aborted by user.');\n }\n\n console.log('[!] Command is being executed. Please wait...');\n\n try {\n execFileSync(bin, args, {\n stdio: 'ignore',\n });\n } catch (_) {}\n\n if (existsSync(database.filename)) {\n database.exists = true;\n\n console.log('[✓] Command success! SQLite file has been successfully created.');\n } else {\n console.log('[×] Command failed! Unable to create SQLite file.');\n process.exit(1);\n }\n }\n }\n if (!database.exists) {\n throw new Error(`Could not find SQLite file for D1 binding '${binding.binding}'`);\n }\n }\n\n console.log('----------------------------------------------------------');\n console.log(' Using following D1 Database:');\n console.log('----------------------------------------------------------');\n console.log(` Binding : ${binding.binding}`);\n console.log(` Database name : ${binding.databaseName ?? '(not set)'}`);\n console.log(` Database Id : ${database.id}`);\n if (options.remote) {\n console.log(' Mode : REMOTE');\n console.log(' (using remote Cloudflare D1 database)');\n } else {\n console.log(' Mode : LOCAL');\n console.log(' (using local SQLite database)');\n console.log(` SQLite file : ${database.filename}`);\n }\n console.log('----------------------------------------------------------');\n\n process.on('exit', () => {\n console.log('');\n });\n\n return {\n ...config,\n dialect: 'sqlite',\n ...(options.remote\n ? {\n driver: 'd1-http',\n dbCredentials: {\n databaseId: database.id,\n accountId: options.accountId,\n token: options.apiToken,\n },\n }\n : {\n dbCredentials: {\n url: `file:${database.filename}`,\n },\n }),\n };\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { execFileSync } from "child_process";
|
|
3
|
+
import { createHash, createHmac } from "crypto";
|
|
4
|
+
import { existsSync } from "fs";
|
|
5
|
+
import { createRequire } from "module";
|
|
6
|
+
import { dirname, join, relative } from "path";
|
|
7
|
+
import promptSync from "prompt-sync";
|
|
6
8
|
import { unstable_readConfig } from "wrangler/wrangler-dist/cli";
|
|
7
9
|
function durableObjectNamespaceIdFromName(uniqueKey, name) {
|
|
8
10
|
const key = createHash("sha256").update(uniqueKey).digest();
|
|
@@ -10,6 +12,11 @@ function durableObjectNamespaceIdFromName(uniqueKey, name) {
|
|
|
10
12
|
const hmac = createHmac("sha256", key).update(nameHmac).digest().subarray(0, 16);
|
|
11
13
|
return Buffer.concat([nameHmac, hmac]).toString("hex");
|
|
12
14
|
}
|
|
15
|
+
function confirmSync(message) {
|
|
16
|
+
const prompt = promptSync();
|
|
17
|
+
const answer = prompt(`${message} (y/N): `);
|
|
18
|
+
return answer?.toLowerCase() === "y";
|
|
19
|
+
}
|
|
13
20
|
function getD1BindingInfo({
|
|
14
21
|
binding,
|
|
15
22
|
environment,
|
|
@@ -17,7 +24,10 @@ function getD1BindingInfo({
|
|
|
17
24
|
configPath: wranglerConfigPath
|
|
18
25
|
} = {}) {
|
|
19
26
|
const { d1_databases, configPath } = unstable_readConfig({ env: environment, config: wranglerConfigPath });
|
|
20
|
-
if (
|
|
27
|
+
if (typeof configPath !== "string") {
|
|
28
|
+
throw new Error("Failed to get wrangler config path");
|
|
29
|
+
}
|
|
30
|
+
if (!d1_databases || d1_databases.length === 0) {
|
|
21
31
|
throw new Error("No D1 binding exists in the config");
|
|
22
32
|
}
|
|
23
33
|
if (d1_databases.length > 1 && !binding) {
|
|
@@ -96,8 +106,14 @@ function drizzleD1Config(config, options = {}) {
|
|
|
96
106
|
args.push(`--persist-to=${options.persistTo}`);
|
|
97
107
|
}
|
|
98
108
|
const command = ["wrangler", ...args].join(" ");
|
|
99
|
-
console.log(`[!] SQLite file for D1 binding '${binding.binding}' does not exist
|
|
109
|
+
console.log(`[!] SQLite file for D1 binding '${binding.binding}' does not exist.`);
|
|
110
|
+
console.log("[!] The file can be created by executing the following command:");
|
|
100
111
|
console.log(` ${command}`);
|
|
112
|
+
const confirmed = confirmSync("[!] Run this command to create it?");
|
|
113
|
+
if (!confirmed) {
|
|
114
|
+
throw new Error("Aborted by user.");
|
|
115
|
+
}
|
|
116
|
+
console.log("[!] Command is being executed. Please wait...");
|
|
101
117
|
try {
|
|
102
118
|
execFileSync(bin, args, {
|
|
103
119
|
stdio: "ignore"
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { execFileSync } from 'node:child_process';\nimport { createHash, createHmac } from 'node:crypto';\nimport { existsSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join, relative } from 'node:path';\nimport type { Config } from 'drizzle-kit';\nimport { unstable_readConfig } from 'wrangler/wrangler-dist/cli';\n\nfunction durableObjectNamespaceIdFromName(uniqueKey: string, name: string) {\n /**\n * In v3.2, miniflare uses durable object to implement D1 and hashes the local sqlite filename.\n *\n * See the following for more context:\n * https://github.com/cloudflare/workers-sdk/issues/4548 (understand the hash of the local D1 filename)\n * https://github.com/cloudflare/miniflare/releases/tag/v3.20230918.0\n *\n * This function is copied from these links\n */\n const key = createHash('sha256').update(uniqueKey).digest();\n const nameHmac = createHmac('sha256', key).update(name).digest().subarray(0, 16);\n const hmac = createHmac('sha256', key).update(nameHmac).digest().subarray(0, 16);\n return Buffer.concat([nameHmac, hmac]).toString('hex');\n}\n\nfunction getD1BindingInfo({\n binding,\n environment,\n persistTo,\n configPath: wranglerConfigPath,\n}: {\n binding?: string;\n configPath?: string;\n persistTo?: string;\n environment?: string;\n} = {}) {\n const { d1_databases, configPath } = unstable_readConfig({ env: environment, config: wranglerConfigPath });\n if (d1_databases.length === 0) {\n throw new Error('No D1 binding exists in the config');\n }\n if (d1_databases.length > 1 && !binding) {\n throw new Error(\"Argument 'binding' is required when more than one D1 bindings exist in the config\");\n }\n let bindingConfig: (typeof d1_databases)[number] | undefined;\n if (binding) {\n bindingConfig = d1_databases.find((d1) => d1.binding === binding);\n if (!bindingConfig) {\n throw new Error(`Could not find D1 binding '${binding}' in config`);\n }\n } else {\n bindingConfig = d1_databases[0];\n }\n\n if (!bindingConfig.database_id && !bindingConfig.preview_database_id) {\n throw new Error(`Neither 'database_id' nor 'preview_database_id' is set for D1 binding '${bindingConfig.binding}'`);\n }\n\n const wranglerConfigDir = configPath ? dirname(configPath) : undefined;\n const wranglerStateDir = persistTo ?? relative('.', join(wranglerConfigDir ?? '', '.wrangler/state/v3'));\n\n const [database, previewDatabase] = [bindingConfig.database_id, bindingConfig.preview_database_id].map((databaseId) => {\n if (!databaseId) {\n return null;\n }\n const uniqueKey = 'miniflare-D1DatabaseObject';\n const miniflarePath = `${wranglerStateDir}/d1/${uniqueKey}`;\n const hash = durableObjectNamespaceIdFromName(uniqueKey, databaseId);\n const filename = join(miniflarePath, `${hash}.sqlite`);\n return {\n id: databaseId,\n filename,\n exists: existsSync(filename),\n };\n });\n\n return {\n configPath,\n binding: bindingConfig.binding,\n databaseName: bindingConfig.database_name,\n database,\n previewDatabase,\n };\n}\n\nexport interface DrizzleD1Options {\n configPath?: string;\n persistTo?: string;\n environment?: string;\n binding?: string;\n remote?: boolean;\n preview?: boolean;\n accountId?: string;\n apiToken?: string;\n}\n\nexport function drizzleD1Config(config: Omit<Config, 'dialect' | 'driver' | 'dbCredentials'>, options: DrizzleD1Options = {}): Config {\n if (options.remote) {\n const requiredOptions: (keyof DrizzleD1Options)[] = ['accountId', 'apiToken'];\n const missingOptions = requiredOptions.filter((name) => !options[name]);\n if (missingOptions.length > 0) {\n throw new Error(`Options ${requiredOptions.join(', ')} are required when using remote database. Missing: ${missingOptions.join(', ')}`);\n }\n }\n\n const binding = getD1BindingInfo({\n binding: options.binding,\n environment: options.environment,\n configPath: options.configPath,\n persistTo: options.persistTo,\n });\n\n const database = options.preview ? binding.previewDatabase : binding.database;\n\n if (!database) {\n throw new Error(`'${options.preview ? 'preview_database_id' : 'database_id'} is not set for D1 binding '${binding.binding}'`);\n }\n\n if (!options.remote && !database.exists) {\n if (binding.databaseName) {\n let bin: string | undefined;\n try {\n bin = createRequire(import.meta.url).resolve('wrangler/bin/wrangler');\n } catch (_) {}\n\n if (bin) {\n const args: string[] = ['d1', 'execute', binding.databaseName, \"--command='SELECT 1'\", '--local'];\n if (options.environment) {\n args.push(`--env=${options.environment}`);\n }\n if (options.configPath) {\n args.push(`--config=${options.configPath}`);\n }\n if (options.persistTo) {\n args.push(`--persist-to=${options.persistTo}`);\n }\n\n const command = ['wrangler', ...args].join(' ');\n console.log(`[!] SQLite file for D1 binding '${binding.binding}' does not exist. Trying to create one by executing the following command:`);\n console.log(` ${command}`);\n\n try {\n execFileSync(bin, args, {\n stdio: 'ignore',\n });\n } catch (_) {}\n\n if (existsSync(database.filename)) {\n database.exists = true;\n\n console.log('[✓] Command success! SQLite file has been successfully created.');\n } else {\n console.log('[×] Command failed! Unable to create SQLite file.');\n process.exit(1);\n }\n }\n }\n if (!database.exists) {\n throw new Error(`Could not find SQLite file for D1 binding '${binding.binding}'`);\n }\n }\n\n console.log('----------------------------------------------------------');\n console.log(' Using following D1 Database:');\n console.log('----------------------------------------------------------');\n console.log(` Binding : ${binding.binding}`);\n console.log(` Database name : ${binding.databaseName ?? '(not set)'}`);\n console.log(` Database Id : ${database.id}`);\n if (options.remote) {\n console.log(' Mode : REMOTE');\n console.log(' (using remote Cloudflare D1 database)');\n } else {\n console.log(' Mode : LOCAL');\n console.log(' (using local SQLite database)');\n console.log(` SQLite file : ${database.filename}`);\n }\n console.log('----------------------------------------------------------');\n\n process.on('exit', () => {\n console.log('');\n });\n\n return {\n ...config,\n dialect: 'sqlite',\n ...(options.remote\n ? {\n driver: 'd1-http',\n dbCredentials: {\n databaseId: database.id,\n accountId: options.accountId,\n token: options.apiToken,\n },\n }\n : {\n dbCredentials: {\n url: `file:${database.filename}`,\n },\n }),\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { execFileSync } from 'node:child_process';\nimport { createHash, createHmac } from 'node:crypto';\nimport { existsSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join, relative } from 'node:path';\nimport type { Config } from 'drizzle-kit';\nimport promptSync from 'prompt-sync';\nimport { unstable_readConfig } from 'wrangler/wrangler-dist/cli';\n\nfunction durableObjectNamespaceIdFromName(uniqueKey: string, name: string) {\n /**\n * In v3.2, miniflare uses durable object to implement D1 and hashes the local sqlite filename.\n *\n * See the following for more context:\n * https://github.com/cloudflare/workers-sdk/issues/4548 (understand the hash of the local D1 filename)\n * https://github.com/cloudflare/miniflare/releases/tag/v3.20230918.0\n *\n * This function is copied from these links\n */\n const key = createHash('sha256').update(uniqueKey).digest();\n const nameHmac = createHmac('sha256', key).update(name).digest().subarray(0, 16);\n const hmac = createHmac('sha256', key).update(nameHmac).digest().subarray(0, 16);\n return Buffer.concat([nameHmac, hmac]).toString('hex');\n}\n\nfunction confirmSync(message: string): boolean {\n const prompt = promptSync();\n const answer = prompt(`${message} (y/N): `);\n return answer?.toLowerCase() === 'y';\n}\n\ninterface MinimalD1Database {\n binding?: string;\n database_id?: string;\n preview_database_id?: string;\n database_name?: string;\n}\n\ninterface WranglerMinimalConfig {\n d1_databases?: MinimalD1Database[];\n configPath?: string;\n}\n\nfunction getD1BindingInfo({\n binding,\n environment,\n persistTo,\n configPath: wranglerConfigPath,\n}: {\n binding?: string;\n configPath?: string;\n persistTo?: string;\n environment?: string;\n} = {}) {\n const { d1_databases, configPath } = unstable_readConfig({ env: environment, config: wranglerConfigPath }) as WranglerMinimalConfig;\n if (typeof configPath !== 'string') {\n throw new Error('Failed to get wrangler config path');\n }\n if (!d1_databases || d1_databases.length === 0) {\n throw new Error('No D1 binding exists in the config');\n }\n if (d1_databases.length > 1 && !binding) {\n throw new Error(\"Argument 'binding' is required when more than one D1 bindings exist in the config\");\n }\n let bindingConfig: MinimalD1Database | undefined;\n if (binding) {\n bindingConfig = d1_databases.find((d1) => d1.binding === binding);\n if (!bindingConfig) {\n throw new Error(`Could not find D1 binding '${binding}' in config`);\n }\n } else {\n bindingConfig = d1_databases[0];\n }\n\n if (!bindingConfig.database_id && !bindingConfig.preview_database_id) {\n throw new Error(`Neither 'database_id' nor 'preview_database_id' is set for D1 binding '${bindingConfig.binding}'`);\n }\n\n const wranglerConfigDir = configPath ? dirname(configPath) : undefined;\n const wranglerStateDir = persistTo ?? relative('.', join(wranglerConfigDir ?? '', '.wrangler/state/v3'));\n\n const [database, previewDatabase] = [bindingConfig.database_id, bindingConfig.preview_database_id].map((databaseId) => {\n if (!databaseId) {\n return null;\n }\n const uniqueKey = 'miniflare-D1DatabaseObject';\n const miniflarePath = `${wranglerStateDir}/d1/${uniqueKey}`;\n const hash = durableObjectNamespaceIdFromName(uniqueKey, databaseId);\n const filename = join(miniflarePath, `${hash}.sqlite`);\n return {\n id: databaseId,\n filename,\n exists: existsSync(filename),\n };\n });\n\n return {\n configPath,\n binding: bindingConfig.binding,\n databaseName: bindingConfig.database_name,\n database,\n previewDatabase,\n };\n}\n\nexport interface DrizzleD1Options {\n configPath?: string;\n persistTo?: string;\n environment?: string;\n binding?: string;\n remote?: boolean;\n preview?: boolean;\n accountId?: string;\n apiToken?: string;\n}\n\nexport function drizzleD1Config(config: Omit<Config, 'dialect' | 'driver' | 'dbCredentials'>, options: DrizzleD1Options = {}): Config {\n if (options.remote) {\n const requiredOptions: (keyof DrizzleD1Options)[] = ['accountId', 'apiToken'];\n const missingOptions = requiredOptions.filter((name) => !options[name]);\n if (missingOptions.length > 0) {\n throw new Error(`Options ${requiredOptions.join(', ')} are required when using remote database. Missing: ${missingOptions.join(', ')}`);\n }\n }\n\n const binding = getD1BindingInfo({\n binding: options.binding,\n environment: options.environment,\n configPath: options.configPath,\n persistTo: options.persistTo,\n });\n\n const database = options.preview ? binding.previewDatabase : binding.database;\n\n if (!database) {\n throw new Error(`'${options.preview ? 'preview_database_id' : 'database_id'} is not set for D1 binding '${binding.binding}'`);\n }\n\n if (!options.remote && !database.exists) {\n if (binding.databaseName) {\n let bin: string | undefined;\n try {\n bin = createRequire(import.meta.url).resolve('wrangler/bin/wrangler');\n } catch (_) {}\n\n if (bin) {\n const args: string[] = ['d1', 'execute', binding.databaseName, \"--command='SELECT 1'\", '--local'];\n if (options.environment) {\n args.push(`--env=${options.environment}`);\n }\n if (options.configPath) {\n args.push(`--config=${options.configPath}`);\n }\n if (options.persistTo) {\n args.push(`--persist-to=${options.persistTo}`);\n }\n\n const command = ['wrangler', ...args].join(' ');\n console.log(`[!] SQLite file for D1 binding '${binding.binding}' does not exist.`);\n console.log('[!] The file can be created by executing the following command:');\n console.log(` ${command}`);\n\n const confirmed = confirmSync('[!] Run this command to create it?');\n if (!confirmed) {\n throw new Error('Aborted by user.');\n }\n\n console.log('[!] Command is being executed. Please wait...');\n\n try {\n execFileSync(bin, args, {\n stdio: 'ignore',\n });\n } catch (_) {}\n\n if (existsSync(database.filename)) {\n database.exists = true;\n\n console.log('[✓] Command success! SQLite file has been successfully created.');\n } else {\n console.log('[×] Command failed! Unable to create SQLite file.');\n process.exit(1);\n }\n }\n }\n if (!database.exists) {\n throw new Error(`Could not find SQLite file for D1 binding '${binding.binding}'`);\n }\n }\n\n console.log('----------------------------------------------------------');\n console.log(' Using following D1 Database:');\n console.log('----------------------------------------------------------');\n console.log(` Binding : ${binding.binding}`);\n console.log(` Database name : ${binding.databaseName ?? '(not set)'}`);\n console.log(` Database Id : ${database.id}`);\n if (options.remote) {\n console.log(' Mode : REMOTE');\n console.log(' (using remote Cloudflare D1 database)');\n } else {\n console.log(' Mode : LOCAL');\n console.log(' (using local SQLite database)');\n console.log(` SQLite file : ${database.filename}`);\n }\n console.log('----------------------------------------------------------');\n\n process.on('exit', () => {\n console.log('');\n });\n\n return {\n ...config,\n dialect: 'sqlite',\n ...(options.remote\n ? {\n driver: 'd1-http',\n dbCredentials: {\n databaseId: database.id,\n accountId: options.accountId,\n token: options.apiToken,\n },\n }\n : {\n dbCredentials: {\n url: `file:${database.filename}`,\n },\n }),\n };\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deox/drizzle-d1-utils",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Drizzle D1 utils",
|
|
6
6
|
"keywords": [
|
|
@@ -41,17 +41,24 @@
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
|
-
"devDependencies": {
|
|
45
|
-
"drizzle-kit": "^0.31.7",
|
|
46
|
-
"tsup": "^8.5.0",
|
|
47
|
-
"wrangler": "^4.39.0"
|
|
48
|
-
},
|
|
49
44
|
"peerDependencies": {
|
|
45
|
+
"drizzle-kit": ">=0.21.3",
|
|
50
46
|
"wrangler": "^4.0.0"
|
|
51
47
|
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"prompt-sync": "^4.2.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/prompt-sync": "^4.2.3",
|
|
53
|
+
"drizzle-kit": "^0.21.3",
|
|
54
|
+
"tsup": "^8.5.1",
|
|
55
|
+
"wrangler": "^4.76.0"
|
|
56
|
+
},
|
|
52
57
|
"scripts": {
|
|
58
|
+
"lint": "biome lint ./src",
|
|
59
|
+
"check": "biome check ./src",
|
|
53
60
|
"check:types": "tsc --noEmit",
|
|
54
|
-
"build": "tsup",
|
|
55
|
-
"
|
|
61
|
+
"build": "NODE_ENV=production tsup",
|
|
62
|
+
"dev": "NODE_ENV=development tsup --watch"
|
|
56
63
|
}
|
|
57
64
|
}
|