datasette-ts 0.0.5 → 0.0.7
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/cli.js +89 -8
- package/dist/cli.js.map +2 -2
- package/package.json +1 -1
- package/scripts/cloudflare-deploy-helpers.mjs +57 -5
package/dist/cli.js
CHANGED
|
@@ -23687,10 +23687,12 @@ async function dumpSqliteForD1(options) {
|
|
|
23687
23687
|
const baseName = options.outputName ?? path.basename(options.dbFile, path.extname(options.dbFile));
|
|
23688
23688
|
const outputPath = path.join(options.outputDir, `${baseName}.sql`);
|
|
23689
23689
|
const rawPath = path.join(options.outputDir, `${baseName}.raw.sql`);
|
|
23690
|
+
const log = typeof options.log === "function" ? options.log : null;
|
|
23691
|
+
const progressIntervalMs = typeof options.progressIntervalMs === "number" && Number.isFinite(options.progressIntervalMs) ? options.progressIntervalMs : 5e3;
|
|
23690
23692
|
await mkdir(options.outputDir, { recursive: true });
|
|
23691
|
-
await dumpSqliteToFile(options.dbFile, rawPath);
|
|
23693
|
+
await dumpSqliteToFile(options.dbFile, rawPath, { log, progressIntervalMs });
|
|
23692
23694
|
try {
|
|
23693
|
-
await normalizeDumpFile(rawPath, outputPath);
|
|
23695
|
+
await normalizeDumpFile(rawPath, outputPath, { log });
|
|
23694
23696
|
} finally {
|
|
23695
23697
|
await unlink(rawPath).catch(() => void 0);
|
|
23696
23698
|
}
|
|
@@ -23816,9 +23818,12 @@ function escapeIdentifier(name) {
|
|
|
23816
23818
|
const escaped = String(name).replace(/"/g, '""');
|
|
23817
23819
|
return `"${escaped}"`;
|
|
23818
23820
|
}
|
|
23819
|
-
async function normalizeDumpFile(inputPath, outputPath) {
|
|
23821
|
+
async function normalizeDumpFile(inputPath, outputPath, { log } = {}) {
|
|
23820
23822
|
const tablesInOrder = [];
|
|
23821
23823
|
const viewsInOrder = [];
|
|
23824
|
+
if (log) {
|
|
23825
|
+
log(`Normalizing D1 import SQL: ${outputPath}`);
|
|
23826
|
+
}
|
|
23822
23827
|
await forEachLine(inputPath, (line) => {
|
|
23823
23828
|
const tableMatch = line.match(/^CREATE TABLE\s+("?[^"]+"?)/i);
|
|
23824
23829
|
if (tableMatch) {
|
|
@@ -23848,8 +23853,15 @@ async function normalizeDumpFile(inputPath, outputPath) {
|
|
|
23848
23853
|
});
|
|
23849
23854
|
outputStream.end();
|
|
23850
23855
|
await once(outputStream, "finish");
|
|
23856
|
+
if (log) {
|
|
23857
|
+
const { size } = await stat(outputPath);
|
|
23858
|
+
log(`D1 import SQL ready (${formatBytes(size)})`);
|
|
23859
|
+
}
|
|
23851
23860
|
}
|
|
23852
|
-
async function dumpSqliteToFile(dbFile, outputPath) {
|
|
23861
|
+
async function dumpSqliteToFile(dbFile, outputPath, { log, progressIntervalMs } = {}) {
|
|
23862
|
+
if (log) {
|
|
23863
|
+
log(`Dumping SQLite database via sqlite3 .dump`);
|
|
23864
|
+
}
|
|
23853
23865
|
const child = spawn("sqlite3", [dbFile, ".dump"], {
|
|
23854
23866
|
stdio: ["ignore", "pipe", "pipe"]
|
|
23855
23867
|
});
|
|
@@ -23870,13 +23882,22 @@ async function dumpSqliteToFile(dbFile, outputPath) {
|
|
|
23870
23882
|
stdout.destroy(error);
|
|
23871
23883
|
outputStream.destroy(error);
|
|
23872
23884
|
});
|
|
23873
|
-
|
|
23885
|
+
const stopProgress = log ? startProgressLogger(outputPath, log, progressIntervalMs) : () => void 0;
|
|
23886
|
+
try {
|
|
23887
|
+
await pipeline(stdout, outputStream);
|
|
23888
|
+
} finally {
|
|
23889
|
+
stopProgress();
|
|
23890
|
+
}
|
|
23874
23891
|
const [code, signal] = await once(child, "close");
|
|
23875
23892
|
if (code !== 0) {
|
|
23876
23893
|
const suffix = signal ? ` (signal ${signal})` : "";
|
|
23877
23894
|
const message = stderr.trim() || `sqlite3 exited with code ${code ?? "unknown"}${suffix}`;
|
|
23878
23895
|
throw new Error(message);
|
|
23879
23896
|
}
|
|
23897
|
+
if (log) {
|
|
23898
|
+
const { size } = await stat(outputPath);
|
|
23899
|
+
log(`SQLite dump completed (${formatBytes(size)})`);
|
|
23900
|
+
}
|
|
23880
23901
|
}
|
|
23881
23902
|
async function forEachLine(filePath, handler) {
|
|
23882
23903
|
const stream = createReadStream(filePath, { encoding: "utf8" });
|
|
@@ -23896,6 +23917,28 @@ async function writeLine(stream, line) {
|
|
|
23896
23917
|
await once(stream, "drain");
|
|
23897
23918
|
}
|
|
23898
23919
|
}
|
|
23920
|
+
function startProgressLogger(filePath, log, intervalMs) {
|
|
23921
|
+
const interval = setInterval(() => {
|
|
23922
|
+
void stat(filePath).then((info) => {
|
|
23923
|
+
log(`Dump size: ${formatBytes(info.size)}`);
|
|
23924
|
+
}).catch(() => void 0);
|
|
23925
|
+
}, intervalMs);
|
|
23926
|
+
return () => clearInterval(interval);
|
|
23927
|
+
}
|
|
23928
|
+
function formatBytes(bytes) {
|
|
23929
|
+
if (!Number.isFinite(bytes) || bytes < 0) {
|
|
23930
|
+
return "0 B";
|
|
23931
|
+
}
|
|
23932
|
+
const units = ["B", "KB", "MB", "GB", "TB"];
|
|
23933
|
+
let value = bytes;
|
|
23934
|
+
let index = 0;
|
|
23935
|
+
while (value >= 1024 && index < units.length - 1) {
|
|
23936
|
+
value /= 1024;
|
|
23937
|
+
index += 1;
|
|
23938
|
+
}
|
|
23939
|
+
const rounded = index === 0 ? value.toFixed(0) : value.toFixed(1);
|
|
23940
|
+
return `${rounded} ${units[index]}`;
|
|
23941
|
+
}
|
|
23899
23942
|
async function hashFile(filePath) {
|
|
23900
23943
|
return new Promise((resolve2, reject) => {
|
|
23901
23944
|
const hash = createHash("sha256");
|
|
@@ -23975,20 +24018,32 @@ function normalizeLibsqlRows(result) {
|
|
|
23975
24018
|
// src/cli/deploy-cloudflare.ts
|
|
23976
24019
|
var DEFAULT_IMPORTS_DIR = ".datasette-ts/imports";
|
|
23977
24020
|
async function runCloudflareDeploy(args) {
|
|
24021
|
+
const startedAt = Date.now();
|
|
24022
|
+
logStep("Starting Cloudflare deploy");
|
|
23978
24023
|
const options = parseDeployArgs(args);
|
|
24024
|
+
logStep(`Database: ${options.dbFile}`);
|
|
24025
|
+
logStep(`Worker: ${options.workerName}`);
|
|
24026
|
+
logStep(`D1: ${options.d1Name}`);
|
|
23979
24027
|
await assertFileExists(options.dbFile, "SQLite database");
|
|
23980
24028
|
const packageRoot = await resolvePackageRoot();
|
|
24029
|
+
logStep(`Package root: ${packageRoot}`);
|
|
23981
24030
|
const workerEntrypoint = await resolveWorkerEntrypoint(packageRoot);
|
|
24031
|
+
logStep(`Worker entrypoint: ${workerEntrypoint}`);
|
|
23982
24032
|
const assetsPath = join(packageRoot, "public");
|
|
23983
24033
|
await assertFileExists(assetsPath, "assets directory");
|
|
24034
|
+
logStep("Initializing Alchemy app");
|
|
23984
24035
|
const app = await alchemy(options.workerName);
|
|
23985
24036
|
let importFile;
|
|
23986
24037
|
try {
|
|
24038
|
+
logStep("Exporting SQLite for D1 import");
|
|
23987
24039
|
importFile = await dumpSqliteForD1({
|
|
23988
24040
|
dbFile: options.dbFile,
|
|
23989
24041
|
outputDir: options.importsDir,
|
|
23990
|
-
outputName: options.d1Name
|
|
24042
|
+
outputName: options.d1Name,
|
|
24043
|
+
log: logStep,
|
|
24044
|
+
progressIntervalMs: 5e3
|
|
23991
24045
|
});
|
|
24046
|
+
logStep(`D1 import file: ${importFile}`);
|
|
23992
24047
|
} catch (error) {
|
|
23993
24048
|
if (isSqliteCliMissing(error)) {
|
|
23994
24049
|
throw new Error(
|
|
@@ -23997,14 +24052,21 @@ async function runCloudflareDeploy(args) {
|
|
|
23997
24052
|
}
|
|
23998
24053
|
throw error;
|
|
23999
24054
|
}
|
|
24055
|
+
logStep("Loading schema");
|
|
24000
24056
|
const schema = await loadSchemaFromFile(options.dbFile);
|
|
24001
|
-
|
|
24057
|
+
let inspectData = null;
|
|
24058
|
+
if (options.precomputeInspect) {
|
|
24059
|
+
logStep("Precomputing inspect data");
|
|
24060
|
+
inspectData = await loadInspectDataFromFile(options.dbFile, options.dbName);
|
|
24061
|
+
}
|
|
24062
|
+
logStep("Creating D1 database");
|
|
24002
24063
|
const db = await D1Database(`d1-${options.d1Name}`, {
|
|
24003
24064
|
name: options.d1Name,
|
|
24004
24065
|
importFiles: [importFile],
|
|
24005
24066
|
profile: options.profile,
|
|
24006
24067
|
adopt: true
|
|
24007
24068
|
});
|
|
24069
|
+
logStep("Configuring static assets");
|
|
24008
24070
|
const staticAssets = await Assets({
|
|
24009
24071
|
path: assetsPath
|
|
24010
24072
|
});
|
|
@@ -24017,6 +24079,7 @@ async function runCloudflareDeploy(args) {
|
|
|
24017
24079
|
if (inspectData) {
|
|
24018
24080
|
bindings.DATASETTE_INSPECT_DATA = JSON.stringify(inspectData);
|
|
24019
24081
|
}
|
|
24082
|
+
logStep("Deploying worker");
|
|
24020
24083
|
const worker = await Worker(`worker-${options.workerName}`, {
|
|
24021
24084
|
entrypoint: workerEntrypoint,
|
|
24022
24085
|
compatibilityFlags: ["nodejs_compat"],
|
|
@@ -24028,7 +24091,9 @@ async function runCloudflareDeploy(args) {
|
|
|
24028
24091
|
adopt: true
|
|
24029
24092
|
});
|
|
24030
24093
|
console.log(`Worker deployed at: ${worker.url}`);
|
|
24094
|
+
logStep("Finalizing Alchemy app");
|
|
24031
24095
|
await app.finalize();
|
|
24096
|
+
logStep(`Done in ${formatDuration(Date.now() - startedAt)}`);
|
|
24032
24097
|
}
|
|
24033
24098
|
function parseDeployArgs(args) {
|
|
24034
24099
|
const positional = [];
|
|
@@ -24206,6 +24271,16 @@ function isSqliteCliMissing(error) {
|
|
|
24206
24271
|
}
|
|
24207
24272
|
return "code" in error && error.code === "ENOENT";
|
|
24208
24273
|
}
|
|
24274
|
+
function logStep(message) {
|
|
24275
|
+
console.log(`[datasette-ts] ${message}`);
|
|
24276
|
+
}
|
|
24277
|
+
function formatDuration(ms) {
|
|
24278
|
+
if (ms < 1e3) {
|
|
24279
|
+
return `${ms}ms`;
|
|
24280
|
+
}
|
|
24281
|
+
const seconds = (ms / 1e3).toFixed(1);
|
|
24282
|
+
return `${seconds}s`;
|
|
24283
|
+
}
|
|
24209
24284
|
|
|
24210
24285
|
// src/cli/serve.ts
|
|
24211
24286
|
init_registry();
|
|
@@ -24507,10 +24582,16 @@ function parseNamedArg2(arg, nextValue) {
|
|
|
24507
24582
|
}
|
|
24508
24583
|
|
|
24509
24584
|
// src/cli.ts
|
|
24510
|
-
|
|
24585
|
+
var keepAlive = setInterval(() => {
|
|
24586
|
+
}, 1e3);
|
|
24587
|
+
var mainPromise = main();
|
|
24588
|
+
mainPromise.catch((error) => {
|
|
24511
24589
|
console.error(error);
|
|
24512
24590
|
process.exitCode = 1;
|
|
24513
24591
|
});
|
|
24592
|
+
mainPromise.finally(() => {
|
|
24593
|
+
clearInterval(keepAlive);
|
|
24594
|
+
});
|
|
24514
24595
|
async function main() {
|
|
24515
24596
|
const args = process.argv.slice(2);
|
|
24516
24597
|
const [command, subcommand] = args;
|