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 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
- await pipeline(stdout, outputStream);
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
- const inspectData = options.precomputeInspect ? await loadInspectDataFromFile(options.dbFile, options.dbName) : null;
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
- void main().catch((error) => {
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;