datasette-ts 0.0.16 → 0.0.18
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/README.md +8 -17
- package/dist/cli.js +63 -141
- package/dist/cli.js.map +3 -3
- package/package.json +1 -1
- package/scripts/cloudflare-deploy-helpers.mjs +7 -1
package/README.md
CHANGED
|
@@ -24,31 +24,22 @@ Open `http://127.0.0.1:8001`.
|
|
|
24
24
|
datasette-ts inspect ./my.db --inspect-file inspect-data.json
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
## Deploy to Cloudflare
|
|
27
|
+
## Deploy to Cloudflare
|
|
28
28
|
|
|
29
|
-
Prereqs:
|
|
30
|
-
- `sqlite3` available on your PATH
|
|
31
|
-
- Alchemy configured and logged in (`alchemy configure`, `alchemy login`)
|
|
32
|
-
|
|
33
|
-
Basic deploy (worker/D1 names default to the SQLite basename):
|
|
29
|
+
Prereqs: Alchemy configured (`npx alchemy login`)
|
|
34
30
|
|
|
35
31
|
```bash
|
|
32
|
+
# Deploy with name derived from filename
|
|
36
33
|
datasette-ts deploy cloudflare ./my.db
|
|
37
|
-
```
|
|
38
34
|
|
|
39
|
-
|
|
35
|
+
# Deploy with explicit name
|
|
36
|
+
datasette-ts deploy cloudflare ./my.db --name my-app
|
|
40
37
|
|
|
41
|
-
|
|
42
|
-
datasette-ts deploy cloudflare ./my.db
|
|
43
|
-
--worker my-datasette \
|
|
44
|
-
--d1 my-datasette-db \
|
|
45
|
-
--db-name mydb \
|
|
46
|
-
--profile prod
|
|
38
|
+
# Deploy with specific Cloudflare profile
|
|
39
|
+
datasette-ts deploy cloudflare ./my.db --name my-app --profile prod
|
|
47
40
|
```
|
|
48
41
|
|
|
49
|
-
|
|
50
|
-
- The CLI generates a D1 import SQL file at `.datasette-ts/imports/<db-name>.sql`.
|
|
51
|
-
- Use `--no-precompute-inspect` if you want to skip inspect metadata generation.
|
|
42
|
+
This creates a Cloudflare Worker and D1 database with your data.
|
|
52
43
|
|
|
53
44
|
## CLI help
|
|
54
45
|
|
package/dist/cli.js
CHANGED
|
@@ -23686,12 +23686,13 @@ var init_node4 = __esm({
|
|
|
23686
23686
|
});
|
|
23687
23687
|
|
|
23688
23688
|
// src/cli.ts
|
|
23689
|
-
import { parseArgs as
|
|
23689
|
+
import { parseArgs as parseArgs3 } from "node:util";
|
|
23690
23690
|
|
|
23691
23691
|
// src/cli/deploy-cloudflare.ts
|
|
23692
23692
|
import { mkdir as mkdir2, stat as stat2, writeFile as writeFile2 } from "node:fs/promises";
|
|
23693
23693
|
import { dirname, extname, join, relative, resolve } from "node:path";
|
|
23694
23694
|
import { fileURLToPath } from "node:url";
|
|
23695
|
+
import { parseArgs } from "node:util";
|
|
23695
23696
|
import alchemy from "alchemy";
|
|
23696
23697
|
import { Assets, D1Database, Worker } from "alchemy/cloudflare";
|
|
23697
23698
|
|
|
@@ -23783,6 +23784,9 @@ function escapeSqlValue(value) {
|
|
|
23783
23784
|
if (value === null || value === void 0) {
|
|
23784
23785
|
return "NULL";
|
|
23785
23786
|
}
|
|
23787
|
+
if (typeof value === "bigint") {
|
|
23788
|
+
return String(value);
|
|
23789
|
+
}
|
|
23786
23790
|
if (typeof value === "number") {
|
|
23787
23791
|
return Number.isFinite(value) ? String(value) : "NULL";
|
|
23788
23792
|
}
|
|
@@ -23927,7 +23931,11 @@ async function countTables(dbFile) {
|
|
|
23927
23931
|
}
|
|
23928
23932
|
}
|
|
23929
23933
|
function createReadonlyClient(dbFile) {
|
|
23930
|
-
return createClient({
|
|
23934
|
+
return createClient({
|
|
23935
|
+
url: pathToFileURL(dbFile).toString(),
|
|
23936
|
+
intMode: "bigint"
|
|
23937
|
+
// Handle integers > MAX_SAFE_INTEGER
|
|
23938
|
+
});
|
|
23931
23939
|
}
|
|
23932
23940
|
async function executeRows(db, sql2, args = []) {
|
|
23933
23941
|
const result = await db.execute({ sql: sql2, args });
|
|
@@ -24058,138 +24066,48 @@ async function runCloudflareDeploy(args) {
|
|
|
24058
24066
|
logStep(`Done in ${formatDuration(Date.now() - startedAt)}`);
|
|
24059
24067
|
}
|
|
24060
24068
|
function parseDeployArgs(args) {
|
|
24061
|
-
const
|
|
24062
|
-
|
|
24063
|
-
|
|
24064
|
-
|
|
24065
|
-
|
|
24066
|
-
|
|
24067
|
-
|
|
24068
|
-
|
|
24069
|
-
|
|
24070
|
-
|
|
24071
|
-
|
|
24072
|
-
|
|
24073
|
-
|
|
24074
|
-
if (arg === "--precompute-inspect") {
|
|
24075
|
-
precomputeInspect = true;
|
|
24076
|
-
continue;
|
|
24077
|
-
}
|
|
24078
|
-
if (arg === "--no-precompute-inspect") {
|
|
24079
|
-
precomputeInspect = false;
|
|
24080
|
-
continue;
|
|
24081
|
-
}
|
|
24082
|
-
const parsedArg = parseNamedArg(arg, args[index + 1]);
|
|
24083
|
-
if (!parsedArg) {
|
|
24084
|
-
positional.push(arg);
|
|
24085
|
-
continue;
|
|
24086
|
-
}
|
|
24087
|
-
const { key, value } = parsedArg;
|
|
24088
|
-
switch (key) {
|
|
24089
|
-
case "db":
|
|
24090
|
-
case "db-file":
|
|
24091
|
-
dbFile = value ?? dbFile;
|
|
24092
|
-
if (!arg.includes("=")) {
|
|
24093
|
-
index += 1;
|
|
24094
|
-
}
|
|
24095
|
-
break;
|
|
24096
|
-
case "db-name":
|
|
24097
|
-
dbName = value ?? dbName;
|
|
24098
|
-
if (!arg.includes("=")) {
|
|
24099
|
-
index += 1;
|
|
24100
|
-
}
|
|
24101
|
-
break;
|
|
24102
|
-
case "worker":
|
|
24103
|
-
workerName = value ?? workerName;
|
|
24104
|
-
if (!arg.includes("=")) {
|
|
24105
|
-
index += 1;
|
|
24106
|
-
}
|
|
24107
|
-
break;
|
|
24108
|
-
case "d1":
|
|
24109
|
-
d1Name = value ?? d1Name;
|
|
24110
|
-
if (!arg.includes("=")) {
|
|
24111
|
-
index += 1;
|
|
24112
|
-
}
|
|
24113
|
-
break;
|
|
24114
|
-
case "profile":
|
|
24115
|
-
profile = value ?? profile;
|
|
24116
|
-
if (!arg.includes("=")) {
|
|
24117
|
-
index += 1;
|
|
24118
|
-
}
|
|
24119
|
-
break;
|
|
24120
|
-
case "imports-dir":
|
|
24121
|
-
importsDir = value ?? importsDir;
|
|
24122
|
-
if (!arg.includes("=")) {
|
|
24123
|
-
index += 1;
|
|
24124
|
-
}
|
|
24125
|
-
break;
|
|
24126
|
-
case "precompute-inspect":
|
|
24127
|
-
precomputeInspect = parseBooleanFlag(value, true);
|
|
24128
|
-
if (!arg.includes("=")) {
|
|
24129
|
-
index += 1;
|
|
24130
|
-
}
|
|
24131
|
-
break;
|
|
24132
|
-
default:
|
|
24133
|
-
break;
|
|
24069
|
+
const { values, positionals } = parseArgs({
|
|
24070
|
+
args,
|
|
24071
|
+
allowPositionals: true,
|
|
24072
|
+
strict: false,
|
|
24073
|
+
options: {
|
|
24074
|
+
name: { type: "string", short: "n" },
|
|
24075
|
+
worker: { type: "string" },
|
|
24076
|
+
d1: { type: "string" },
|
|
24077
|
+
"db-name": { type: "string" },
|
|
24078
|
+
profile: { type: "string", short: "p" },
|
|
24079
|
+
"imports-dir": { type: "string" },
|
|
24080
|
+
"precompute-inspect": { type: "boolean", default: true },
|
|
24081
|
+
"no-precompute-inspect": { type: "boolean" }
|
|
24134
24082
|
}
|
|
24135
|
-
}
|
|
24136
|
-
|
|
24137
|
-
dbFile = positional[0];
|
|
24138
|
-
}
|
|
24083
|
+
});
|
|
24084
|
+
const dbFile = positionals[0];
|
|
24139
24085
|
if (!dbFile) {
|
|
24140
|
-
throw new Error("Missing SQLite database path
|
|
24086
|
+
throw new Error("Missing SQLite database path.\n\nUsage: datasette-ts deploy cloudflare <db-file> [--name <name>]");
|
|
24141
24087
|
}
|
|
24142
24088
|
const resolvedDbFile = resolve(dbFile);
|
|
24143
|
-
const
|
|
24144
|
-
const
|
|
24145
|
-
const
|
|
24089
|
+
const derivedName = deriveNameFromPath(resolvedDbFile);
|
|
24090
|
+
const normalizedName = normalizeResourceName(values.name ?? derivedName);
|
|
24091
|
+
const precomputeInspect = values["no-precompute-inspect"] ? false : values["precompute-inspect"] !== false;
|
|
24146
24092
|
return {
|
|
24147
24093
|
dbFile: resolvedDbFile,
|
|
24148
|
-
dbName:
|
|
24149
|
-
workerName:
|
|
24150
|
-
d1Name:
|
|
24151
|
-
profile,
|
|
24094
|
+
dbName: values["db-name"] ?? values.name ?? derivedName,
|
|
24095
|
+
workerName: values.worker ?? normalizedName,
|
|
24096
|
+
d1Name: values.d1 ?? normalizedName,
|
|
24097
|
+
profile: values.profile,
|
|
24152
24098
|
precomputeInspect,
|
|
24153
|
-
importsDir:
|
|
24099
|
+
importsDir: resolve(values["imports-dir"] ?? DEFAULT_IMPORTS_DIR)
|
|
24154
24100
|
};
|
|
24155
24101
|
}
|
|
24156
|
-
function
|
|
24157
|
-
const base =
|
|
24158
|
-
const
|
|
24159
|
-
|
|
24102
|
+
function deriveNameFromPath(filePath) {
|
|
24103
|
+
const base = filePath.split(/[\\/]/).pop() ?? filePath;
|
|
24104
|
+
const ext = extname(base);
|
|
24105
|
+
const name = ext ? base.slice(0, -ext.length) : base;
|
|
24106
|
+
return name || "db";
|
|
24160
24107
|
}
|
|
24161
24108
|
function normalizeResourceName(name) {
|
|
24162
24109
|
const normalized = name.trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
24163
|
-
return normalized
|
|
24164
|
-
}
|
|
24165
|
-
function escapeRegex(value) {
|
|
24166
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
24167
|
-
}
|
|
24168
|
-
function parseNamedArg(arg, nextValue) {
|
|
24169
|
-
if (!arg.startsWith("--")) {
|
|
24170
|
-
return null;
|
|
24171
|
-
}
|
|
24172
|
-
const [key, value] = arg.slice(2).split("=");
|
|
24173
|
-
if (!key) {
|
|
24174
|
-
return null;
|
|
24175
|
-
}
|
|
24176
|
-
if (value !== void 0) {
|
|
24177
|
-
return { key, value };
|
|
24178
|
-
}
|
|
24179
|
-
return { key, value: nextValue };
|
|
24180
|
-
}
|
|
24181
|
-
function parseBooleanFlag(value, defaultValue) {
|
|
24182
|
-
if (value == null) {
|
|
24183
|
-
return defaultValue;
|
|
24184
|
-
}
|
|
24185
|
-
const normalized = value.trim().toLowerCase();
|
|
24186
|
-
if (["0", "false", "no", "off"].includes(normalized)) {
|
|
24187
|
-
return false;
|
|
24188
|
-
}
|
|
24189
|
-
if (["1", "true", "yes", "on"].includes(normalized)) {
|
|
24190
|
-
return true;
|
|
24191
|
-
}
|
|
24192
|
-
return defaultValue;
|
|
24110
|
+
return normalized || "db";
|
|
24193
24111
|
}
|
|
24194
24112
|
async function resolvePackageRoot() {
|
|
24195
24113
|
let current = dirname(fileURLToPath(import.meta.url));
|
|
@@ -24314,7 +24232,7 @@ async function loadInspectData(inspectFile) {
|
|
|
24314
24232
|
async function inspectDatabases(databasePaths) {
|
|
24315
24233
|
const results = {};
|
|
24316
24234
|
for (const filename of databasePaths) {
|
|
24317
|
-
const name =
|
|
24235
|
+
const name = deriveName(filename);
|
|
24318
24236
|
results[name] = await inspectDatabase(filename);
|
|
24319
24237
|
}
|
|
24320
24238
|
return results;
|
|
@@ -24370,7 +24288,7 @@ function escapeIdentifier3(name) {
|
|
|
24370
24288
|
const escaped = name.replace(/"/g, '""');
|
|
24371
24289
|
return `"${escaped}"`;
|
|
24372
24290
|
}
|
|
24373
|
-
function
|
|
24291
|
+
function deriveName(path7) {
|
|
24374
24292
|
const parts = path7.split(/[\\/]/);
|
|
24375
24293
|
const last = parts[parts.length - 1] ?? path7;
|
|
24376
24294
|
const name = last.replace(/\.[^/.]+$/, "");
|
|
@@ -24413,7 +24331,7 @@ async function startServer(options) {
|
|
|
24413
24331
|
// src/cli/serve.ts
|
|
24414
24332
|
var DEFAULT_DB = "data.db";
|
|
24415
24333
|
async function runServeCommand(args) {
|
|
24416
|
-
const options = await
|
|
24334
|
+
const options = await parseArgs2(args);
|
|
24417
24335
|
const registry = new DatabaseRegistry(
|
|
24418
24336
|
options.databases,
|
|
24419
24337
|
options.metadata ?? null,
|
|
@@ -24450,7 +24368,7 @@ async function runInspectCommand(args) {
|
|
|
24450
24368
|
if (!arg) {
|
|
24451
24369
|
continue;
|
|
24452
24370
|
}
|
|
24453
|
-
const parsedArg =
|
|
24371
|
+
const parsedArg = parseNamedArg(arg, args[index + 1]);
|
|
24454
24372
|
if (parsedArg?.key === "inspect-file") {
|
|
24455
24373
|
if (parsedArg.value) {
|
|
24456
24374
|
inspectFile = parsedArg.value;
|
|
@@ -24474,7 +24392,7 @@ async function runInspectCommand(args) {
|
|
|
24474
24392
|
process.stdout.write(`${json}
|
|
24475
24393
|
`);
|
|
24476
24394
|
}
|
|
24477
|
-
async function
|
|
24395
|
+
async function parseArgs2(args) {
|
|
24478
24396
|
const databasePaths = [];
|
|
24479
24397
|
let port;
|
|
24480
24398
|
let hostname;
|
|
@@ -24487,7 +24405,7 @@ async function parseArgs(args) {
|
|
|
24487
24405
|
if (!arg) {
|
|
24488
24406
|
continue;
|
|
24489
24407
|
}
|
|
24490
|
-
const parsedArg =
|
|
24408
|
+
const parsedArg = parseNamedArg(arg, args[index + 1]);
|
|
24491
24409
|
if (parsedArg?.key === "port") {
|
|
24492
24410
|
if (parsedArg.value) {
|
|
24493
24411
|
port = Number(parsedArg.value);
|
|
@@ -24542,7 +24460,7 @@ async function parseArgs(args) {
|
|
|
24542
24460
|
databasePaths.push(DEFAULT_DB);
|
|
24543
24461
|
}
|
|
24544
24462
|
const databases = databasePaths.map((filename) => ({
|
|
24545
|
-
name:
|
|
24463
|
+
name: deriveName2(filename),
|
|
24546
24464
|
filename,
|
|
24547
24465
|
mutable
|
|
24548
24466
|
}));
|
|
@@ -24572,13 +24490,13 @@ async function parseArgs(args) {
|
|
|
24572
24490
|
}
|
|
24573
24491
|
return result;
|
|
24574
24492
|
}
|
|
24575
|
-
function
|
|
24493
|
+
function deriveName2(path7) {
|
|
24576
24494
|
const parts = path7.split(/[\\/]/);
|
|
24577
24495
|
const last = parts[parts.length - 1] ?? path7;
|
|
24578
24496
|
const name = last.replace(/\.[^/.]+$/, "");
|
|
24579
24497
|
return name === "" ? "db" : name;
|
|
24580
24498
|
}
|
|
24581
|
-
function
|
|
24499
|
+
function parseNamedArg(arg, nextValue) {
|
|
24582
24500
|
if (!arg.startsWith("--")) {
|
|
24583
24501
|
return null;
|
|
24584
24502
|
}
|
|
@@ -24600,7 +24518,7 @@ mainPromise.catch((error) => {
|
|
|
24600
24518
|
});
|
|
24601
24519
|
async function main() {
|
|
24602
24520
|
const args = process.argv.slice(2);
|
|
24603
|
-
const parsed =
|
|
24521
|
+
const parsed = parseArgs3({
|
|
24604
24522
|
args,
|
|
24605
24523
|
allowPositionals: true,
|
|
24606
24524
|
strict: false,
|
|
@@ -24674,7 +24592,7 @@ function dropPositionals(args, positionalIndices, count) {
|
|
|
24674
24592
|
return args.filter((_, index) => !remove.has(index));
|
|
24675
24593
|
}
|
|
24676
24594
|
function hasHelpFlag(args) {
|
|
24677
|
-
const parsed =
|
|
24595
|
+
const parsed = parseArgs3({
|
|
24678
24596
|
args,
|
|
24679
24597
|
allowPositionals: true,
|
|
24680
24598
|
strict: false,
|
|
@@ -24715,14 +24633,18 @@ Options:
|
|
|
24715
24633
|
function printDeployHelp() {
|
|
24716
24634
|
console.log(`datasette-ts deploy cloudflare <db-file> [options]
|
|
24717
24635
|
|
|
24636
|
+
Examples:
|
|
24637
|
+
datasette-ts deploy cloudflare ./data.db
|
|
24638
|
+
datasette-ts deploy cloudflare ./data.db --name my-app
|
|
24639
|
+
|
|
24718
24640
|
Options:
|
|
24719
|
-
|
|
24720
|
-
|
|
24721
|
-
|
|
24722
|
-
|
|
24723
|
-
--
|
|
24724
|
-
--
|
|
24725
|
-
--
|
|
24726
|
-
--no-precompute-inspect
|
|
24641
|
+
-n, --name <name> Name for worker and D1 database (default: db filename)
|
|
24642
|
+
-p, --profile <name> Cloudflare profile to use
|
|
24643
|
+
|
|
24644
|
+
Advanced:
|
|
24645
|
+
--worker <name> Override worker name
|
|
24646
|
+
--d1 <name> Override D1 database name
|
|
24647
|
+
--db-name <name> Override Datasette display name
|
|
24648
|
+
--no-precompute-inspect Skip precomputing inspect data`);
|
|
24727
24649
|
}
|
|
24728
24650
|
//# sourceMappingURL=cli.js.map
|