@vm0/cli 1.15.0 → 2.0.0

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.
Files changed (2) hide show
  1. package/index.js +195 -136
  2. package/package.json +2 -2
package/index.js CHANGED
@@ -13446,15 +13446,96 @@ var initCommand = new Command3().name("init").description("Initialize a volume i
13446
13446
  // src/commands/volume/push.ts
13447
13447
  import { Command as Command4 } from "commander";
13448
13448
  import chalk6 from "chalk";
13449
- import path3 from "path";
13449
+ import path4 from "path";
13450
+ import * as fs2 from "fs";
13451
+ import * as os from "os";
13452
+ import * as tar2 from "tar";
13453
+
13454
+ // src/lib/file-utils.ts
13450
13455
  import * as fs from "fs";
13451
- import AdmZip from "adm-zip";
13456
+ import * as path3 from "path";
13457
+ import * as tar from "tar";
13458
+ function excludeVm0Filter(filePath) {
13459
+ const shouldExclude = filePath === ".vm0" || filePath.startsWith(".vm0/") || filePath.startsWith("./.vm0");
13460
+ return !shouldExclude;
13461
+ }
13462
+ function listTarFiles(tarPath) {
13463
+ return new Promise((resolve, reject) => {
13464
+ const files = [];
13465
+ tar.list({
13466
+ file: tarPath,
13467
+ onReadEntry: (entry) => {
13468
+ if (entry.type === "File") {
13469
+ files.push(entry.path);
13470
+ }
13471
+ }
13472
+ }).then(() => resolve(files)).catch(reject);
13473
+ });
13474
+ }
13475
+ async function listLocalFiles(dir, excludeDirs = [".vm0"]) {
13476
+ const files = [];
13477
+ async function walkDir(currentDir, relativePath = "") {
13478
+ const entries = await fs.promises.readdir(currentDir, {
13479
+ withFileTypes: true
13480
+ });
13481
+ for (const entry of entries) {
13482
+ const entryRelativePath = relativePath ? path3.join(relativePath, entry.name) : entry.name;
13483
+ if (entry.isDirectory()) {
13484
+ if (!excludeDirs.includes(entry.name)) {
13485
+ await walkDir(path3.join(currentDir, entry.name), entryRelativePath);
13486
+ }
13487
+ } else {
13488
+ files.push(entryRelativePath);
13489
+ }
13490
+ }
13491
+ }
13492
+ await walkDir(dir);
13493
+ return files;
13494
+ }
13495
+ async function removeExtraFiles(dir, remoteFiles, excludeDirs = [".vm0"]) {
13496
+ const localFiles = await listLocalFiles(dir, excludeDirs);
13497
+ let removedCount = 0;
13498
+ for (const localFile of localFiles) {
13499
+ const normalizedPath = localFile.replace(/\\/g, "/");
13500
+ if (!remoteFiles.has(normalizedPath)) {
13501
+ const fullPath = path3.join(dir, localFile);
13502
+ await fs.promises.unlink(fullPath);
13503
+ removedCount++;
13504
+ }
13505
+ }
13506
+ await removeEmptyDirs(dir, excludeDirs);
13507
+ return removedCount;
13508
+ }
13509
+ async function removeEmptyDirs(dir, excludeDirs = [".vm0"]) {
13510
+ const entries = await fs.promises.readdir(dir, { withFileTypes: true });
13511
+ let isEmpty = true;
13512
+ for (const entry of entries) {
13513
+ const fullPath = path3.join(dir, entry.name);
13514
+ if (entry.isDirectory()) {
13515
+ if (excludeDirs.includes(entry.name)) {
13516
+ isEmpty = false;
13517
+ } else {
13518
+ const subDirEmpty = await removeEmptyDirs(fullPath, excludeDirs);
13519
+ if (subDirEmpty) {
13520
+ await fs.promises.rmdir(fullPath);
13521
+ } else {
13522
+ isEmpty = false;
13523
+ }
13524
+ }
13525
+ } else {
13526
+ isEmpty = false;
13527
+ }
13528
+ }
13529
+ return isEmpty;
13530
+ }
13531
+
13532
+ // src/commands/volume/push.ts
13452
13533
  async function getAllFiles(dirPath, baseDir = dirPath) {
13453
13534
  const files = [];
13454
- const entries = await fs.promises.readdir(dirPath, { withFileTypes: true });
13535
+ const entries = await fs2.promises.readdir(dirPath, { withFileTypes: true });
13455
13536
  for (const entry of entries) {
13456
- const fullPath = path3.join(dirPath, entry.name);
13457
- const relativePath = path3.relative(baseDir, fullPath);
13537
+ const fullPath = path4.join(dirPath, entry.name);
13538
+ const relativePath = path4.relative(baseDir, fullPath);
13458
13539
  if (relativePath.startsWith(".vm0")) {
13459
13540
  continue;
13460
13541
  }
@@ -13491,7 +13572,7 @@ var pushCommand = new Command4().name("push").description("Push local files to c
13491
13572
  const files = await getAllFiles(cwd);
13492
13573
  let totalSize = 0;
13493
13574
  for (const file2 of files) {
13494
- const stats = await fs.promises.stat(file2);
13575
+ const stats = await fs2.promises.stat(file2);
13495
13576
  totalSize += stats.size;
13496
13577
  }
13497
13578
  if (files.length === 0) {
@@ -13502,14 +13583,34 @@ var pushCommand = new Command4().name("push").description("Push local files to c
13502
13583
  );
13503
13584
  }
13504
13585
  console.log(chalk6.gray("Compressing files..."));
13505
- const zip = new AdmZip();
13506
- for (const file2 of files) {
13507
- const relativePath = path3.relative(cwd, file2);
13508
- zip.addLocalFile(file2, path3.dirname(relativePath));
13586
+ const tmpDir = fs2.mkdtempSync(path4.join(os.tmpdir(), "vm0-"));
13587
+ const tarPath = path4.join(tmpDir, "volume.tar.gz");
13588
+ const relativePaths = files.map((file2) => path4.relative(cwd, file2));
13589
+ if (relativePaths.length > 0) {
13590
+ await tar2.create(
13591
+ {
13592
+ gzip: true,
13593
+ file: tarPath,
13594
+ cwd
13595
+ },
13596
+ relativePaths
13597
+ );
13598
+ } else {
13599
+ await tar2.create(
13600
+ {
13601
+ gzip: true,
13602
+ file: tarPath,
13603
+ cwd,
13604
+ filter: excludeVm0Filter
13605
+ },
13606
+ ["."]
13607
+ );
13509
13608
  }
13510
- const zipBuffer = zip.toBuffer();
13609
+ const tarBuffer = await fs2.promises.readFile(tarPath);
13610
+ await fs2.promises.unlink(tarPath);
13611
+ await fs2.promises.rmdir(tmpDir);
13511
13612
  console.log(
13512
- chalk6.green(`\u2713 Compressed to ${formatBytes(zipBuffer.length)}`)
13613
+ chalk6.green(`\u2713 Compressed to ${formatBytes(tarBuffer.length)}`)
13513
13614
  );
13514
13615
  console.log(chalk6.gray("Uploading..."));
13515
13616
  const formData = new FormData();
@@ -13520,8 +13621,8 @@ var pushCommand = new Command4().name("push").description("Push local files to c
13520
13621
  }
13521
13622
  formData.append(
13522
13623
  "file",
13523
- new Blob([zipBuffer], { type: "application/zip" }),
13524
- "volume.zip"
13624
+ new Blob([tarBuffer], { type: "application/gzip" }),
13625
+ "volume.tar.gz"
13525
13626
  );
13526
13627
  const response = await apiClient.post("/api/storages", {
13527
13628
  body: formData
@@ -13555,78 +13656,8 @@ import { Command as Command5 } from "commander";
13555
13656
  import chalk7 from "chalk";
13556
13657
  import path5 from "path";
13557
13658
  import * as fs3 from "fs";
13558
- import AdmZip2 from "adm-zip";
13559
-
13560
- // src/lib/file-utils.ts
13561
- import * as fs2 from "fs";
13562
- import * as path4 from "path";
13563
- function getRemoteFilesFromZip(zipEntries) {
13564
- const remoteFiles = /* @__PURE__ */ new Set();
13565
- for (const entry of zipEntries) {
13566
- if (!entry.isDirectory) {
13567
- remoteFiles.add(entry.entryName.replace(/\\/g, "/"));
13568
- }
13569
- }
13570
- return remoteFiles;
13571
- }
13572
- async function listLocalFiles(dir, excludeDirs = [".vm0"]) {
13573
- const files = [];
13574
- async function walkDir(currentDir, relativePath = "") {
13575
- const entries = await fs2.promises.readdir(currentDir, {
13576
- withFileTypes: true
13577
- });
13578
- for (const entry of entries) {
13579
- const entryRelativePath = relativePath ? path4.join(relativePath, entry.name) : entry.name;
13580
- if (entry.isDirectory()) {
13581
- if (!excludeDirs.includes(entry.name)) {
13582
- await walkDir(path4.join(currentDir, entry.name), entryRelativePath);
13583
- }
13584
- } else {
13585
- files.push(entryRelativePath);
13586
- }
13587
- }
13588
- }
13589
- await walkDir(dir);
13590
- return files;
13591
- }
13592
- async function removeExtraFiles(dir, remoteFiles, excludeDirs = [".vm0"]) {
13593
- const localFiles = await listLocalFiles(dir, excludeDirs);
13594
- let removedCount = 0;
13595
- for (const localFile of localFiles) {
13596
- const normalizedPath = localFile.replace(/\\/g, "/");
13597
- if (!remoteFiles.has(normalizedPath)) {
13598
- const fullPath = path4.join(dir, localFile);
13599
- await fs2.promises.unlink(fullPath);
13600
- removedCount++;
13601
- }
13602
- }
13603
- await removeEmptyDirs(dir, excludeDirs);
13604
- return removedCount;
13605
- }
13606
- async function removeEmptyDirs(dir, excludeDirs = [".vm0"]) {
13607
- const entries = await fs2.promises.readdir(dir, { withFileTypes: true });
13608
- let isEmpty = true;
13609
- for (const entry of entries) {
13610
- const fullPath = path4.join(dir, entry.name);
13611
- if (entry.isDirectory()) {
13612
- if (excludeDirs.includes(entry.name)) {
13613
- isEmpty = false;
13614
- } else {
13615
- const subDirEmpty = await removeEmptyDirs(fullPath, excludeDirs);
13616
- if (subDirEmpty) {
13617
- await fs2.promises.rmdir(fullPath);
13618
- } else {
13619
- isEmpty = false;
13620
- }
13621
- }
13622
- } else {
13623
- isEmpty = false;
13624
- }
13625
- }
13626
- return isEmpty;
13627
- }
13628
-
13629
- // src/commands/volume/pull.ts
13659
+ import * as os2 from "os";
13660
+ import * as tar3 from "tar";
13630
13661
  function formatBytes2(bytes) {
13631
13662
  if (bytes === 0) return "0 B";
13632
13663
  const k = 1024;
@@ -13674,31 +13705,31 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
13674
13705
  process.exit(1);
13675
13706
  }
13676
13707
  const arrayBuffer = await response.arrayBuffer();
13677
- const zipBuffer = Buffer.from(arrayBuffer);
13678
- console.log(chalk7.green(`\u2713 Downloaded ${formatBytes2(zipBuffer.length)}`));
13679
- console.log(chalk7.gray("Extracting files..."));
13680
- const zip = new AdmZip2(zipBuffer);
13681
- const zipEntries = zip.getEntries();
13682
- const remoteFiles = getRemoteFilesFromZip(zipEntries);
13708
+ const tarBuffer = Buffer.from(arrayBuffer);
13709
+ console.log(chalk7.green(`\u2713 Downloaded ${formatBytes2(tarBuffer.length)}`));
13710
+ const tmpDir = fs3.mkdtempSync(path5.join(os2.tmpdir(), "vm0-"));
13711
+ const tarPath = path5.join(tmpDir, "volume.tar.gz");
13712
+ await fs3.promises.writeFile(tarPath, tarBuffer);
13683
13713
  console.log(chalk7.gray("Syncing local files..."));
13684
- const removedCount = await removeExtraFiles(cwd, remoteFiles);
13714
+ const remoteFiles = await listTarFiles(tarPath);
13715
+ const remoteFilesSet = new Set(
13716
+ remoteFiles.map((f) => f.replace(/\\/g, "/"))
13717
+ );
13718
+ const removedCount = await removeExtraFiles(cwd, remoteFilesSet);
13685
13719
  if (removedCount > 0) {
13686
13720
  console.log(
13687
13721
  chalk7.green(`\u2713 Removed ${removedCount} files not in remote`)
13688
13722
  );
13689
13723
  }
13690
- let extractedCount = 0;
13691
- for (const entry of zipEntries) {
13692
- if (!entry.isDirectory) {
13693
- const targetPath = path5.join(cwd, entry.entryName);
13694
- const dir = path5.dirname(targetPath);
13695
- await fs3.promises.mkdir(dir, { recursive: true });
13696
- const data = entry.getData();
13697
- await fs3.promises.writeFile(targetPath, data);
13698
- extractedCount++;
13699
- }
13700
- }
13701
- console.log(chalk7.green(`\u2713 Extracted ${extractedCount} files`));
13724
+ console.log(chalk7.gray("Extracting files..."));
13725
+ await tar3.extract({
13726
+ file: tarPath,
13727
+ cwd,
13728
+ gzip: true
13729
+ });
13730
+ await fs3.promises.unlink(tarPath);
13731
+ await fs3.promises.rmdir(tmpDir);
13732
+ console.log(chalk7.green(`\u2713 Extracted ${remoteFiles.length} files`));
13702
13733
  } catch (error43) {
13703
13734
  console.error(chalk7.red("\u2717 Pull failed"));
13704
13735
  if (error43 instanceof Error) {
@@ -13781,7 +13812,8 @@ import { Command as Command8 } from "commander";
13781
13812
  import chalk9 from "chalk";
13782
13813
  import path7 from "path";
13783
13814
  import * as fs4 from "fs";
13784
- import AdmZip3 from "adm-zip";
13815
+ import * as os3 from "os";
13816
+ import * as tar4 from "tar";
13785
13817
  async function getAllFiles2(dirPath, baseDir = dirPath) {
13786
13818
  const files = [];
13787
13819
  const entries = await fs4.promises.readdir(dirPath, { withFileTypes: true });
@@ -13807,7 +13839,10 @@ function formatBytes3(bytes) {
13807
13839
  const i = Math.floor(Math.log(bytes) / Math.log(k));
13808
13840
  return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
13809
13841
  }
13810
- var pushCommand2 = new Command8().name("push").description("Push local files to cloud artifact").action(async () => {
13842
+ var pushCommand2 = new Command8().name("push").description("Push local files to cloud artifact").option(
13843
+ "-f, --force",
13844
+ "Force upload even if content unchanged (recreate archive)"
13845
+ ).action(async (options) => {
13811
13846
  try {
13812
13847
  const cwd = process.cwd();
13813
13848
  const config2 = await readStorageConfig(cwd);
@@ -13841,23 +13876,46 @@ var pushCommand2 = new Command8().name("push").description("Push local files to
13841
13876
  );
13842
13877
  }
13843
13878
  console.log(chalk9.gray("Compressing files..."));
13844
- const zip = new AdmZip3();
13845
- for (const file2 of files) {
13846
- const relativePath = path7.relative(cwd, file2);
13847
- zip.addLocalFile(file2, path7.dirname(relativePath));
13879
+ const tmpDir = fs4.mkdtempSync(path7.join(os3.tmpdir(), "vm0-"));
13880
+ const tarPath = path7.join(tmpDir, "artifact.tar.gz");
13881
+ const relativePaths = files.map((file2) => path7.relative(cwd, file2));
13882
+ if (relativePaths.length > 0) {
13883
+ await tar4.create(
13884
+ {
13885
+ gzip: true,
13886
+ file: tarPath,
13887
+ cwd
13888
+ },
13889
+ relativePaths
13890
+ );
13891
+ } else {
13892
+ await tar4.create(
13893
+ {
13894
+ gzip: true,
13895
+ file: tarPath,
13896
+ cwd,
13897
+ filter: excludeVm0Filter
13898
+ },
13899
+ ["."]
13900
+ );
13848
13901
  }
13849
- const zipBuffer = zip.toBuffer();
13902
+ const tarBuffer = await fs4.promises.readFile(tarPath);
13903
+ await fs4.promises.unlink(tarPath);
13904
+ await fs4.promises.rmdir(tmpDir);
13850
13905
  console.log(
13851
- chalk9.green(`\u2713 Compressed to ${formatBytes3(zipBuffer.length)}`)
13906
+ chalk9.green(`\u2713 Compressed to ${formatBytes3(tarBuffer.length)}`)
13852
13907
  );
13853
13908
  console.log(chalk9.gray("Uploading..."));
13854
13909
  const formData = new FormData();
13855
13910
  formData.append("name", config2.name);
13856
13911
  formData.append("type", "artifact");
13912
+ if (options.force) {
13913
+ formData.append("force", "true");
13914
+ }
13857
13915
  formData.append(
13858
13916
  "file",
13859
- new Blob([zipBuffer], { type: "application/zip" }),
13860
- "artifact.zip"
13917
+ new Blob([tarBuffer], { type: "application/gzip" }),
13918
+ "artifact.tar.gz"
13861
13919
  );
13862
13920
  const response = await apiClient.post("/api/storages", {
13863
13921
  body: formData
@@ -13890,7 +13948,8 @@ import { Command as Command9 } from "commander";
13890
13948
  import chalk10 from "chalk";
13891
13949
  import path8 from "path";
13892
13950
  import * as fs5 from "fs";
13893
- import AdmZip4 from "adm-zip";
13951
+ import * as os4 from "os";
13952
+ import * as tar5 from "tar";
13894
13953
  function formatBytes4(bytes) {
13895
13954
  if (bytes === 0) return "0 B";
13896
13955
  const k = 1024;
@@ -13949,31 +14008,31 @@ var pullCommand2 = new Command9().name("pull").description("Pull cloud artifact
13949
14008
  process.exit(1);
13950
14009
  }
13951
14010
  const arrayBuffer = await response.arrayBuffer();
13952
- const zipBuffer = Buffer.from(arrayBuffer);
13953
- console.log(chalk10.green(`\u2713 Downloaded ${formatBytes4(zipBuffer.length)}`));
13954
- console.log(chalk10.gray("Extracting files..."));
13955
- const zip = new AdmZip4(zipBuffer);
13956
- const zipEntries = zip.getEntries();
13957
- const remoteFiles = getRemoteFilesFromZip(zipEntries);
14011
+ const tarBuffer = Buffer.from(arrayBuffer);
14012
+ console.log(chalk10.green(`\u2713 Downloaded ${formatBytes4(tarBuffer.length)}`));
14013
+ const tmpDir = fs5.mkdtempSync(path8.join(os4.tmpdir(), "vm0-"));
14014
+ const tarPath = path8.join(tmpDir, "artifact.tar.gz");
14015
+ await fs5.promises.writeFile(tarPath, tarBuffer);
13958
14016
  console.log(chalk10.gray("Syncing local files..."));
13959
- const removedCount = await removeExtraFiles(cwd, remoteFiles);
14017
+ const remoteFiles = await listTarFiles(tarPath);
14018
+ const remoteFilesSet = new Set(
14019
+ remoteFiles.map((f) => f.replace(/\\/g, "/"))
14020
+ );
14021
+ const removedCount = await removeExtraFiles(cwd, remoteFilesSet);
13960
14022
  if (removedCount > 0) {
13961
14023
  console.log(
13962
14024
  chalk10.green(`\u2713 Removed ${removedCount} files not in remote`)
13963
14025
  );
13964
14026
  }
13965
- let extractedCount = 0;
13966
- for (const entry of zipEntries) {
13967
- if (!entry.isDirectory) {
13968
- const targetPath = path8.join(cwd, entry.entryName);
13969
- const dir = path8.dirname(targetPath);
13970
- await fs5.promises.mkdir(dir, { recursive: true });
13971
- const data = entry.getData();
13972
- await fs5.promises.writeFile(targetPath, data);
13973
- extractedCount++;
13974
- }
13975
- }
13976
- console.log(chalk10.green(`\u2713 Extracted ${extractedCount} files`));
14027
+ console.log(chalk10.gray("Extracting files..."));
14028
+ await tar5.extract({
14029
+ file: tarPath,
14030
+ cwd,
14031
+ gzip: true
14032
+ });
14033
+ await fs5.promises.unlink(tarPath);
14034
+ await fs5.promises.rmdir(tmpDir);
14035
+ console.log(chalk10.green(`\u2713 Extracted ${remoteFiles.length} files`));
13977
14036
  } catch (error43) {
13978
14037
  console.error(chalk10.red("\u2717 Pull failed"));
13979
14038
  if (error43 instanceof Error) {
@@ -13988,7 +14047,7 @@ var artifactCommand = new Command10().name("artifact").description("Manage cloud
13988
14047
 
13989
14048
  // src/index.ts
13990
14049
  var program = new Command11();
13991
- program.name("vm0").description("VM0 CLI - A modern build tool").version("1.15.0");
14050
+ program.name("vm0").description("VM0 CLI - A modern build tool").version("2.0.0");
13992
14051
  program.command("hello").description("Say hello from the App").action(() => {
13993
14052
  console.log(chalk11.blue("Welcome to the VM0 CLI!"));
13994
14053
  console.log(chalk11.green(`Core says: ${FOO}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "1.15.0",
3
+ "version": "2.0.0",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",
@@ -15,9 +15,9 @@
15
15
  "."
16
16
  ],
17
17
  "dependencies": {
18
- "adm-zip": "^0.5.16",
19
18
  "chalk": "^5.6.0",
20
19
  "commander": "^14.0.0",
20
+ "tar": "^7.5.2",
21
21
  "yaml": "^2.3.4"
22
22
  }
23
23
  }