@dbcube/core 4.1.4 → 4.1.6

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 CHANGED
@@ -104,9 +104,11 @@ interface BinaryType {
104
104
  declare class Binary {
105
105
  private static isDownloading;
106
106
  private static downloadPromise;
107
+ private static cachedBinaries;
107
108
  static ensureBinariesExist(): Promise<void>;
108
109
  private static downloadBinaries;
109
110
  private static getBinDir;
111
+ private static findVersionedBinary;
110
112
  static get(): Promise<BinaryType>;
111
113
  }
112
114
 
package/dist/index.d.ts CHANGED
@@ -104,9 +104,11 @@ interface BinaryType {
104
104
  declare class Binary {
105
105
  private static isDownloading;
106
106
  private static downloadPromise;
107
+ private static cachedBinaries;
107
108
  static ensureBinariesExist(): Promise<void>;
108
109
  private static downloadBinaries;
109
110
  private static getBinDir;
111
+ private static findVersionedBinary;
110
112
  static get(): Promise<BinaryType>;
111
113
  }
112
114
 
package/dist/index.js CHANGED
@@ -137,6 +137,97 @@ var { https } = followRedirects;
137
137
  var Downloader = class {
138
138
  static mainSpinner = null;
139
139
  static currentSpinner = null;
140
+ static VERSION_URLS = {
141
+ query: "https://raw.githubusercontent.com/Dbcube/binaries/main/query-engines.json",
142
+ schema: "https://raw.githubusercontent.com/Dbcube/binaries/main/schema-engines.json",
143
+ sqlite: "https://raw.githubusercontent.com/Dbcube/binaries/main/sqlite-engines.json"
144
+ };
145
+ /**
146
+ * Fetch latest version from GitHub
147
+ */
148
+ static async fetchLatestVersion(prefix) {
149
+ const url = this.VERSION_URLS[prefix];
150
+ return new Promise((resolve5, reject) => {
151
+ https.get(url, (response) => {
152
+ let data = "";
153
+ response.on("data", (chunk) => {
154
+ data += chunk;
155
+ });
156
+ response.on("end", () => {
157
+ try {
158
+ const versions = JSON.parse(data);
159
+ if (versions && versions.length > 0) {
160
+ resolve5(versions[0].version);
161
+ } else {
162
+ reject(new Error("No versions found"));
163
+ }
164
+ } catch (error) {
165
+ reject(error);
166
+ }
167
+ });
168
+ response.on("error", reject);
169
+ }).on("error", reject);
170
+ });
171
+ }
172
+ /**
173
+ * Extract version from binary filename
174
+ * Example: schema-engine-v1.0.0-windows-x64.exe -> v1.0.0
175
+ */
176
+ static extractVersionFromFilename(filename) {
177
+ const match = filename.match(/-(v\d+\.\d+\.\d+)-/);
178
+ return match ? match[1] : null;
179
+ }
180
+ /**
181
+ * Get local version of installed binary
182
+ */
183
+ static getLocalVersion(binDir, prefix) {
184
+ try {
185
+ const files = fs.readdirSync(binDir);
186
+ const binaryPattern = new RegExp(`^${prefix}-engine-v`);
187
+ const binaryFile = files.find((f) => binaryPattern.test(f));
188
+ if (binaryFile) {
189
+ return this.extractVersionFromFilename(binaryFile);
190
+ }
191
+ } catch (error) {
192
+ }
193
+ return null;
194
+ }
195
+ /**
196
+ * Compare versions (returns true if remote is newer)
197
+ */
198
+ static isNewerVersion(localVersion, remoteVersion) {
199
+ if (!localVersion) return true;
200
+ const cleanLocal = localVersion.replace(/^v/, "");
201
+ const cleanRemote = remoteVersion.replace(/^v/, "");
202
+ const localParts = cleanLocal.split(".").map(Number);
203
+ const remoteParts = cleanRemote.split(".").map(Number);
204
+ for (let i = 0; i < 3; i++) {
205
+ if (remoteParts[i] > localParts[i]) return true;
206
+ if (remoteParts[i] < localParts[i]) return false;
207
+ }
208
+ return false;
209
+ }
210
+ /**
211
+ * Delete old binary files
212
+ */
213
+ static deleteOldBinary(binDir, prefix) {
214
+ try {
215
+ const files = fs.readdirSync(binDir);
216
+ const binaryPattern = new RegExp(`^${prefix}-engine-`);
217
+ files.forEach((file) => {
218
+ if (binaryPattern.test(file)) {
219
+ const filePath = path.join(binDir, file);
220
+ try {
221
+ fs.unlinkSync(filePath);
222
+ console.log(`\u{1F5D1}\uFE0F Deleted old binary: ${file}`);
223
+ } catch (err) {
224
+ console.warn(`\u26A0\uFE0F Could not delete: ${file}`);
225
+ }
226
+ }
227
+ });
228
+ } catch (error) {
229
+ }
230
+ }
140
231
  static get(prefix) {
141
232
  const arch2 = new Arquitecture();
142
233
  const platform2 = arch2.getPlatform();
@@ -159,6 +250,7 @@ var Downloader = class {
159
250
  return {
160
251
  name: binaryName,
161
252
  url,
253
+ version: "latest",
162
254
  query_engine: binaryName,
163
255
  schema_engine: `${prefix}-engine-${plat}-${archSuffix}${platform2 === "windows" ? ".exe" : ""}`
164
256
  };
@@ -166,69 +258,125 @@ var Downloader = class {
166
258
  return {
167
259
  name: "",
168
260
  url: "",
261
+ version: "",
262
+ query_engine: "",
263
+ schema_engine: ""
264
+ };
265
+ }
266
+ /**
267
+ * Get binary info with actual version from GitHub
268
+ */
269
+ static async getWithVersion(prefix) {
270
+ const arch2 = new Arquitecture();
271
+ const platform2 = arch2.getPlatform();
272
+ const architecture = arch2.getArchitecture();
273
+ const platformMap = {
274
+ windows: "windows",
275
+ linux: "linux",
276
+ darwin: "macos"
277
+ };
278
+ const archMap = {
279
+ x86_64: "x64",
280
+ aarch64: "arm64"
281
+ };
282
+ const plat = platformMap[platform2];
283
+ const archSuffix = archMap[architecture];
284
+ if (plat && archSuffix) {
285
+ const version = await this.fetchLatestVersion(prefix);
286
+ const baseName = `${prefix}-engine-${version}-${plat}-${archSuffix}`;
287
+ const binaryName = platform2 === "windows" ? `${baseName}.exe` : baseName;
288
+ const url = `https://github.com/Dbcube/binaries/releases/download/${prefix}-engine/${prefix}-engine-${version}-${plat}-${archSuffix}.zip`;
289
+ return {
290
+ name: binaryName,
291
+ url,
292
+ version,
293
+ query_engine: binaryName,
294
+ schema_engine: binaryName
295
+ };
296
+ }
297
+ return {
298
+ name: "",
299
+ url: "",
300
+ version: "",
169
301
  query_engine: "",
170
302
  schema_engine: ""
171
303
  };
172
304
  }
173
305
  static async download(targetDir) {
174
- const binaries = ["schema", "query", "sqlite"];
175
306
  const binDir = targetDir || this.getDefaultBinDir();
176
307
  fs.mkdirSync(binDir, { recursive: true });
177
308
  this.mainSpinner = ora({
178
- text: chalk.blue("Descargando binarios necesarios..."),
309
+ text: chalk.blue("Verificando versiones de binarios..."),
179
310
  spinner: "dots12"
180
311
  }).start();
181
- const binariesToDownload = [];
182
- let existingCount = 0;
183
- for (const prefix of binaries) {
184
- const binaryInfo = this.get(prefix);
185
- if (!binaryInfo.name || !binaryInfo.url) {
186
- throw new Error(`Plataforma o arquitectura no soportada para ${prefix}`);
187
- }
188
- const finalBinaryPath = path.join(binDir, binaryInfo.name);
189
- if (fs.existsSync(finalBinaryPath)) {
190
- existingCount++;
191
- continue;
312
+ const binariesToProcess = [];
313
+ for (const prefix of ["query", "schema", "sqlite"]) {
314
+ try {
315
+ const localVersion = this.getLocalVersion(binDir, prefix);
316
+ const remoteVersion = await this.fetchLatestVersion(prefix);
317
+ const needsUpdate = this.isNewerVersion(localVersion, remoteVersion);
318
+ binariesToProcess.push({
319
+ prefix,
320
+ needsUpdate,
321
+ localVersion,
322
+ remoteVersion
323
+ });
324
+ if (needsUpdate) {
325
+ console.log(`
326
+ \u{1F4E6} ${prefix}-engine: ${localVersion || "not installed"} \u2192 ${remoteVersion}`);
327
+ } else if (localVersion) {
328
+ console.log(`
329
+ \u2705 ${prefix}-engine: ${localVersion} (up to date)`);
330
+ }
331
+ } catch (error) {
332
+ console.warn(`\u26A0\uFE0F Could not check version for ${prefix}-engine, will attempt download`);
333
+ binariesToProcess.push({
334
+ prefix,
335
+ needsUpdate: true,
336
+ localVersion: null,
337
+ remoteVersion: "latest"
338
+ });
192
339
  }
193
- binariesToDownload.push({
194
- prefix,
195
- binaryInfo,
196
- tempZipPath: path.join(os2.tmpdir(), `dbcube-${prefix}-${Date.now()}.zip`),
197
- finalBinaryPath
198
- });
199
340
  }
341
+ const binariesToDownload = binariesToProcess.filter((b) => b.needsUpdate);
200
342
  if (binariesToDownload.length === 0) {
201
- this.mainSpinner.succeed(chalk.green("Todos los binarios ya est\xE1n descargados"));
343
+ this.mainSpinner.succeed(chalk.green("All binaries are up to date"));
202
344
  return;
203
345
  }
204
- this.updateMainProgress("paralelo", existingCount, binaries.length, "downloading");
346
+ this.mainSpinner.text = chalk.blue(`Updating ${binariesToDownload.length} binary(ies)...`);
205
347
  try {
206
- await Promise.all(binariesToDownload.map(async (binary, index) => {
348
+ await Promise.all(binariesToDownload.map(async (binary) => {
207
349
  const maxRetries = 3;
208
350
  let attempt = 0;
209
351
  while (attempt <= maxRetries) {
210
352
  try {
211
- await this.downloadFileWithProgress(binary.binaryInfo.url, binary.tempZipPath, binary.prefix);
212
- await this.extractBinary(binary.tempZipPath, binary.finalBinaryPath, binary.prefix);
213
- const completed = existingCount + index + 1;
214
- this.updateMainProgress(binary.prefix, completed, binaries.length, "completed");
353
+ const binaryInfo = await this.getWithVersion(binary.prefix);
354
+ if (!binaryInfo.name || !binaryInfo.url) {
355
+ throw new Error(`Platform or architecture not supported for ${binary.prefix}`);
356
+ }
357
+ const tempZipPath = path.join(os2.tmpdir(), `dbcube-${binary.prefix}-${Date.now()}.zip`);
358
+ const finalBinaryPath = path.join(binDir, binaryInfo.name);
359
+ this.deleteOldBinary(binDir, binary.prefix);
360
+ await this.downloadFileWithProgress(binaryInfo.url, tempZipPath, binary.prefix);
361
+ await this.extractBinary(tempZipPath, finalBinaryPath, binary.prefix);
362
+ console.log(`\u2705 ${binary.prefix}-engine updated to ${binary.remoteVersion}`);
215
363
  break;
216
364
  } catch (error) {
217
- const errorMessage = error instanceof Error ? error.message : "Error desconocido";
365
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
218
366
  if (attempt < maxRetries && (errorMessage.includes("ECONNRESET") || errorMessage.includes("timeout") || errorMessage.includes("ETIMEDOUT") || errorMessage.includes("ENOTFOUND"))) {
219
367
  attempt++;
220
- this.updateMainProgress(binary.prefix, existingCount, binaries.length, "retrying", attempt);
368
+ console.log(`\u{1F504} Retrying ${binary.prefix}-engine (${attempt}/${maxRetries})...`);
221
369
  await new Promise((resolve5) => setTimeout(resolve5, 1e3 + Math.random() * 1e3));
222
370
  } else {
223
- throw new Error(`Error descargando ${binary.prefix}: ${errorMessage}`);
371
+ throw new Error(`Error downloading ${binary.prefix}: ${errorMessage}`);
224
372
  }
225
373
  }
226
374
  }
227
375
  }));
228
- this.mainSpinner.succeed(chalk.green("Binarios descargados correctamente"));
376
+ this.mainSpinner.succeed(chalk.green("Binaries updated successfully"));
229
377
  } catch (error) {
230
- const errorMessage = error instanceof Error ? error.message : "Error desconocido";
231
- this.mainSpinner.fail(chalk.red(`Error en descarga paralela: ${errorMessage}`));
378
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
379
+ this.mainSpinner.fail(chalk.red(`Error updating binaries: ${errorMessage}`));
232
380
  throw error;
233
381
  }
234
382
  }
@@ -398,22 +546,13 @@ import { dirname as dirname2 } from "path";
398
546
  var Binary = class {
399
547
  static isDownloading = false;
400
548
  static downloadPromise = null;
549
+ static cachedBinaries = {};
401
550
  static async ensureBinariesExist() {
402
551
  if (this.isDownloading && this.downloadPromise) {
403
552
  await this.downloadPromise;
404
553
  return;
405
554
  }
406
555
  const binDir = this.getBinDir();
407
- const binaries = ["schema", "query", "sqlite"];
408
- const allExist = binaries.every((prefix) => {
409
- const binaryInfo = Downloader.get(prefix);
410
- if (!binaryInfo.name) return false;
411
- const binaryPath = path2.join(binDir, binaryInfo.name);
412
- return fs2.existsSync(binaryPath);
413
- });
414
- if (allExist) {
415
- return;
416
- }
417
556
  if (!this.isDownloading) {
418
557
  this.isDownloading = true;
419
558
  this.downloadPromise = this.downloadBinaries();
@@ -456,58 +595,50 @@ var Binary = class {
456
595
  fs2.mkdirSync(tempDir, { recursive: true });
457
596
  return tempDir;
458
597
  }
598
+ static findVersionedBinary(binDir, prefix, platform2, arch2) {
599
+ const cacheKey = `${prefix}-${platform2}-${arch2}`;
600
+ if (this.cachedBinaries[cacheKey]) {
601
+ const cachedPath = path2.join(binDir, this.cachedBinaries[cacheKey]);
602
+ if (fs2.existsSync(cachedPath)) {
603
+ return cachedPath;
604
+ }
605
+ }
606
+ try {
607
+ const files = fs2.readdirSync(binDir);
608
+ const extension = platform2 === "windows" ? ".exe" : "";
609
+ const pattern = new RegExp(`^${prefix}-engine-v\\d+\\.\\d+\\.\\d+-${platform2}-${arch2}${extension.replace(".", "\\.")}$`);
610
+ const matchingFile = files.find((f) => pattern.test(f));
611
+ if (matchingFile) {
612
+ this.cachedBinaries[cacheKey] = matchingFile;
613
+ return path2.join(binDir, matchingFile);
614
+ }
615
+ } catch (error) {
616
+ }
617
+ const fallbackName = `${prefix}-engine-${platform2}-${arch2}${platform2 === "windows" ? ".exe" : ""}`;
618
+ return path2.join(binDir, fallbackName);
619
+ }
459
620
  static async get() {
460
621
  await this.ensureBinariesExist();
461
622
  const arch2 = new Arquitecture();
462
623
  const platform2 = arch2.getPlatform();
463
624
  const architecture = arch2.getArchitecture();
464
625
  const binDir = this.getBinDir();
465
- const getFullPath = (binaryName) => {
466
- return path2.join(binDir, binaryName);
626
+ const platformMap = {
627
+ windows: "windows",
628
+ linux: "linux",
629
+ darwin: "macos"
467
630
  };
468
- switch (platform2) {
469
- case "windows":
470
- if (architecture == "x86_64") {
471
- return {
472
- query_engine: getFullPath("query-engine-windows-x64.exe"),
473
- schema_engine: getFullPath("schema-engine-windows-x64.exe")
474
- };
475
- }
476
- if (architecture == "aarch64") {
477
- return {
478
- query_engine: getFullPath("query-engine-windows-arm64.exe"),
479
- schema_engine: getFullPath("schema-engine-windows-arm64.exe")
480
- };
481
- }
482
- break;
483
- case "linux":
484
- if (architecture == "x86_64") {
485
- return {
486
- query_engine: getFullPath("query-engine-linux-x64"),
487
- schema_engine: getFullPath("schema-engine-linux-x64")
488
- };
489
- }
490
- if (architecture == "aarch64") {
491
- return {
492
- query_engine: getFullPath("query-engine-linux-arm64"),
493
- schema_engine: getFullPath("schema-engine-linux-arm64")
494
- };
495
- }
496
- break;
497
- case "macos":
498
- if (architecture == "x86_64") {
499
- return {
500
- query_engine: getFullPath("query-engine-macos-x64"),
501
- schema_engine: getFullPath("schema-engine-macos-x64")
502
- };
503
- }
504
- if (architecture == "aarch64") {
505
- return {
506
- query_engine: getFullPath("query-engine-macos-arm64"),
507
- schema_engine: getFullPath("schema-engine-macos-arm64")
508
- };
509
- }
510
- break;
631
+ const archMap = {
632
+ x86_64: "x64",
633
+ aarch64: "arm64"
634
+ };
635
+ const plat = platformMap[platform2];
636
+ const archSuffix = archMap[architecture];
637
+ if (plat && archSuffix) {
638
+ return {
639
+ query_engine: this.findVersionedBinary(binDir, "query", plat, archSuffix),
640
+ schema_engine: this.findVersionedBinary(binDir, "schema", plat, archSuffix)
641
+ };
511
642
  }
512
643
  return {
513
644
  query_engine: "",