@airmoney-degn/airmoney-cli 0.24.1 → 0.25.1

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/build.js CHANGED
@@ -41,12 +41,13 @@ const child_process_1 = require("child_process");
41
41
  const metadata_1 = require("../util/metadata");
42
42
  const tarball_1 = require("../util/tarball");
43
43
  const LogService_1 = require("../service/log/LogService");
44
- async function buildCommand({ locationFolder }) {
44
+ async function buildCommand({ locationFolder, publicDir }) {
45
45
  const projectPath = locationFolder ? path.resolve(process.cwd(), locationFolder) : process.cwd();
46
46
  const meta = await (0, metadata_1.loadMetadata)(projectPath);
47
47
  if (!meta) {
48
48
  throw new Error('No metadata.json found.');
49
49
  }
50
+ (0, metadata_1.applyVersionFromCargoToml)(meta, projectPath);
50
51
  // Populate build metadata before building
51
52
  (0, LogService_1.log)('Populating build metadata...').white();
52
53
  (0, metadata_1.populateBuildMetadata)(meta, projectPath);
@@ -71,12 +72,10 @@ async function buildCommand({ locationFolder }) {
71
72
  cwd: projectPath,
72
73
  stdio: 'inherit',
73
74
  });
74
- // 2. Find the binary
75
- // Using standardized binary name "user_app" to match degn-launcher expectations
76
- const binName = "user_app";
75
+ // 2. Find the binary (name from Cargo.toml [package] name)
76
+ const binName = (0, metadata_1.readPackageNameFromCargoToml)(projectPath) ?? 'user_app';
77
77
  const binPath = path.join(projectPath, 'target', 'aarch64-unknown-linux-gnu', 'release', binName);
78
78
  if (!fs.existsSync(binPath)) {
79
- // Fallback: try to find any executable in the release folder if the name doesn't match exactly
80
79
  (0, LogService_1.log)(`Binary not found at expected path: ${binPath}`).white();
81
80
  throw new Error(`Could not find native binary for app: ${binName}`);
82
81
  }
@@ -91,8 +90,11 @@ async function buildCommand({ locationFolder }) {
91
90
  if (fs.existsSync(logoPath)) {
92
91
  fs.copyFileSync(logoPath, path.join(tempDir, 'dapp-logo.png'));
93
92
  }
94
- // Copy the binary as "user_app" for degn-launcher compatibility
95
- fs.copyFileSync(binPath, path.join(tempDir, "user_app"));
93
+ fs.copyFileSync(binPath, path.join(tempDir, binName));
94
+ if (publicDir) {
95
+ const publicPath = path.join(projectPath, publicDir);
96
+ (0, tarball_1.copyDirContents)(publicPath, tempDir);
97
+ }
96
98
  // 4. Pack the project
97
99
  await (0, tarball_1.packProject)(meta, tempDir);
98
100
  (0, LogService_1.log)('Build and packaging complete!').green();
@@ -60,12 +60,20 @@ function getProjectPath(locationFolder) {
60
60
  return path_1.default.join(process.cwd(), locationFolder);
61
61
  }
62
62
  /**
63
- * Prompts user for confirmation when uploading from current directory
63
+ * Prompts user for confirmation when uploading from current directory.
64
+ * Web: warns that all files from the directory will be packed/uploaded.
65
+ * Native: only mentions building and uploading the package (binary + metadata + logo).
64
66
  */
65
- async function confirmUploadFromCurrentDirectory(projectPath) {
66
- (0, LogService_1.log)('⚠️ WARNING: You are about to upload all files from the current directory!').red();
67
- (0, LogService_1.log)(`Upload folder: ${path_1.default.resolve(projectPath)}`).white();
68
- (0, LogService_1.log)('To upload a specific folder, use: airmoney-cli upload -f <folder-path>').white();
67
+ async function confirmUploadFromCurrentDirectory(projectPath, appType) {
68
+ if (appType === 'Native') {
69
+ (0, LogService_1.log)(`Upload folder: ${path_1.default.resolve(projectPath)}`).white();
70
+ (0, LogService_1.log)('A package (binary + metadata + logo) will be built and uploaded.').white();
71
+ }
72
+ else {
73
+ (0, LogService_1.log)('⚠️ WARNING: You are about to upload all files from the current directory!').red();
74
+ (0, LogService_1.log)(`Upload folder: ${path_1.default.resolve(projectPath)}`).white();
75
+ (0, LogService_1.log)('To upload a specific folder, use: airmoney-cli upload -f <folder-path>').white();
76
+ }
69
77
  const answer = await inquirer_1.default.prompt([
70
78
  {
71
79
  type: 'confirm',
@@ -119,30 +127,44 @@ async function calculateFileHash(filePath) {
119
127
  /**
120
128
  * Prepares the package by packing and reading it
121
129
  */
122
- async function preparePackage(meta, projectPath) {
130
+ async function preparePackage(meta, projectPath, publicDir) {
123
131
  const pkgName = (0, metadata_1.getPackageName)(meta);
124
132
  if (meta.type === 'Native') {
125
133
  (0, LogService_1.log)(`Preparing Native package for ${meta.displayName}...`).white();
126
- // 1. Find the binary
127
- const binName = "user_app";
128
- const binPath = path_1.default.join(projectPath, 'target', 'aarch64-unknown-linux-gnu', 'release', binName);
129
- if (!fs.existsSync(binPath)) {
130
- throw new Error('Native binary not found. Please run "airmoney-cli build" first to compile your application.');
134
+ const binName = (0, metadata_1.readPackageNameFromCargoToml)(projectPath) ?? 'user_app';
135
+ const binInTarget = path_1.default.join(projectPath, 'target', 'aarch64-unknown-linux-gnu', 'release', binName);
136
+ const binAtRoot = path_1.default.join(projectPath, binName);
137
+ const metadataAtRoot = path_1.default.join(projectPath, 'metadata.json');
138
+ const logoAtRoot = path_1.default.join(projectPath, 'dapp-logo.png');
139
+ // If folder already has binary + metadata + dapp-logo at root (e.g. dist/ or production/), zip the whole folder (includes all *.png and other assets)
140
+ if (fs.existsSync(binAtRoot) && fs.existsSync(metadataAtRoot) && fs.existsSync(logoAtRoot)) {
141
+ (0, LogService_1.log)(`Uploading folder as-is (binary and metadata at root; all files will be included).`).white();
142
+ (0, LogService_1.log)(`Packing ${pkgName}...`).white();
143
+ await (0, tarball_1.packProject)(meta, projectPath);
131
144
  }
132
- // 2. Prepare packaging in a temp directory to avoid including target/ and other junk
133
- const tempDir = fs.mkdtempSync(path_1.default.join(os.tmpdir(), 'airmoney-upload-'));
134
- try {
135
- fs.copyFileSync(path_1.default.join(projectPath, 'metadata.json'), path_1.default.join(tempDir, 'metadata.json'));
136
- const logoPath = path_1.default.join(projectPath, 'dapp-logo.png');
137
- if (fs.existsSync(logoPath)) {
138
- fs.copyFileSync(logoPath, path_1.default.join(tempDir, 'dapp-logo.png'));
145
+ else if (fs.existsSync(binInTarget)) {
146
+ // Build layout: binary in target/; copy only metadata, logo, binary to avoid target/ and other junk
147
+ const tempDir = fs.mkdtempSync(path_1.default.join(os.tmpdir(), 'airmoney-upload-'));
148
+ try {
149
+ fs.copyFileSync(path_1.default.join(projectPath, 'metadata.json'), path_1.default.join(tempDir, 'metadata.json'));
150
+ const logoPath = path_1.default.join(projectPath, 'dapp-logo.png');
151
+ if (fs.existsSync(logoPath)) {
152
+ fs.copyFileSync(logoPath, path_1.default.join(tempDir, 'dapp-logo.png'));
153
+ }
154
+ fs.copyFileSync(binInTarget, path_1.default.join(tempDir, binName));
155
+ if (publicDir) {
156
+ const publicPath = path_1.default.join(projectPath, publicDir);
157
+ (0, tarball_1.copyDirContents)(publicPath, tempDir);
158
+ }
159
+ (0, LogService_1.log)(`Packing ${pkgName}...`).white();
160
+ await (0, tarball_1.packProject)(meta, tempDir);
161
+ }
162
+ finally {
163
+ fs.rmSync(tempDir, { recursive: true, force: true });
139
164
  }
140
- fs.copyFileSync(binPath, path_1.default.join(tempDir, "user_app"));
141
- (0, LogService_1.log)(`Packing ${pkgName}...`).white();
142
- await (0, tarball_1.packProject)(meta, tempDir);
143
165
  }
144
- finally {
145
- fs.rmSync(tempDir, { recursive: true, force: true });
166
+ else {
167
+ throw new Error(`Native binary not found. Either run "airmoney-cli build" first, or point -f to a folder that already contains ${binName}, metadata.json, and dapp-logo.png at root (e.g. dist/).`);
146
168
  }
147
169
  }
148
170
  else {
@@ -212,16 +234,55 @@ function cleanupPackageFile(pkgPath) {
212
234
  /**
213
235
  * Main upload command
214
236
  */
215
- async function uploadCommand({ network, locationFolder, }) {
237
+ async function uploadCommand({ network, locationFolder, publicDir, packagePath: packagePathOpt, }) {
216
238
  let packageData = null;
239
+ let createdPackageByUs = false;
217
240
  try {
218
241
  const credentials = (0, env_1.validateCredential)();
219
242
  const { userId, apiKey, network } = credentials;
220
243
  (0, format_1.logUserAndNetwork)(userId, network);
244
+ if (packagePathOpt) {
245
+ // Upload an existing zip (e.g. output of airmoney-cli build)
246
+ const zipPath = path_1.default.isAbsolute(packagePathOpt)
247
+ ? packagePathOpt
248
+ : path_1.default.join(process.cwd(), packagePathOpt);
249
+ if (!fs.existsSync(zipPath) || !fs.statSync(zipPath).isFile()) {
250
+ throw new Error(`Package file not found: ${zipPath}`);
251
+ }
252
+ const projectPath = path_1.default.dirname(zipPath);
253
+ const meta = await (0, metadata_1.loadMetadata)(projectPath);
254
+ if (!meta) {
255
+ throw new Error(`No metadata.json found next to the package. Put metadata.json in the same directory as ${path_1.default.basename(zipPath)}.`);
256
+ }
257
+ (0, LogService_1.log)('Verifying zip package...').white();
258
+ const verifyOptions = meta.type === 'Native'
259
+ ? { binaryName: (0, metadata_1.readPackageNameFromCargoToml)(projectPath) ?? 'user_app' }
260
+ : undefined;
261
+ await (0, tarball_1.verifyZipPackage)(zipPath, meta.type, verifyOptions);
262
+ (0, LogService_1.log)('Zip package verified.').green();
263
+ const dappService = new DappService_1.DappService(userId, apiKey, network);
264
+ (0, LogService_1.log)(`Checking for existing versions of ${meta.name}...`).white();
265
+ const existingBuilds = await dappService.fetchDappVersions(meta.name);
266
+ const conflict = existingBuilds.find(b => b.version === meta.version);
267
+ if (conflict) {
268
+ (0, LogService_1.log)(`\nERROR: Version ${meta.version} already exists on the server.`).red();
269
+ (0, LogService_1.log)(`Status: ${conflict.status || 'Unknown'}`).red();
270
+ (0, LogService_1.log)(`Please bump your version and rebuild before uploading.`).yellow();
271
+ throw new Error(`Version conflict: ${meta.version} already exists.`);
272
+ }
273
+ const fileSize = fs.statSync(zipPath).size;
274
+ const fileHash = await calculateFileHash(zipPath);
275
+ (0, LogService_1.log)(`Package Hash: ${fileHash}`).white();
276
+ (0, LogService_1.log)(`Package Size: ${formatFileSize(fileSize)}`).white();
277
+ (0, LogService_1.log)('Publishing package to DEGN Dapp Store...').white();
278
+ await uploadPackageToServer(network || 'devnet', userId, apiKey, meta, zipPath, fileSize);
279
+ return;
280
+ }
221
281
  const projectPath = getProjectPath(locationFolder);
222
282
  // Prompt for confirmation if uploading from current directory
223
283
  if (!locationFolder) {
224
- const confirmed = await confirmUploadFromCurrentDirectory(projectPath);
284
+ const metaForConfirm = await (0, metadata_1.loadMetadata)(projectPath);
285
+ const confirmed = await confirmUploadFromCurrentDirectory(projectPath, metaForConfirm?.type);
225
286
  if (!confirmed) {
226
287
  (0, LogService_1.log)('Upload cancelled by user').yellow();
227
288
  return;
@@ -231,6 +292,7 @@ async function uploadCommand({ network, locationFolder, }) {
231
292
  (0, LogService_1.log)(`Upload folder: ${path_1.default.resolve(projectPath)}`).white();
232
293
  }
233
294
  const meta = await loadAndValidateMetadata(locationFolder);
295
+ (0, metadata_1.applyVersionFromCargoToml)(meta, projectPath);
234
296
  // Version Conflict Check
235
297
  const dappService = new DappService_1.DappService(userId, apiKey, network);
236
298
  (0, LogService_1.log)(`Checking for existing versions of ${meta.name}...`).white();
@@ -246,7 +308,8 @@ async function uploadCommand({ network, locationFolder, }) {
246
308
  (0, LogService_1.log)('Populating build metadata...').white();
247
309
  (0, metadata_1.populateBuildMetadata)(meta, projectPath);
248
310
  (0, metadata_1.saveMetadata)(meta, projectPath);
249
- packageData = await preparePackage(meta, projectPath);
311
+ packageData = await preparePackage(meta, projectPath, publicDir);
312
+ createdPackageByUs = true;
250
313
  (0, LogService_1.log)('Publishing package to DEGN Dapp Store...').white();
251
314
  await uploadPackageToServer(network || "devnet", userId, apiKey, meta, packageData.pkgPath, packageData.fileSize);
252
315
  }
@@ -256,8 +319,7 @@ async function uploadCommand({ network, locationFolder, }) {
256
319
  throw err;
257
320
  }
258
321
  finally {
259
- // Clean up package file if it was created
260
- if (packageData) {
322
+ if (createdPackageByUs && packageData) {
261
323
  cleanupPackageFile(packageData.pkgPath);
262
324
  }
263
325
  }
package/dist/config.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "0.24.1"
2
+ "version": "0.25.1"
3
3
  }
package/dist/index.js CHANGED
@@ -54,10 +54,11 @@ program
54
54
  .command('build')
55
55
  .description('Build and package the project')
56
56
  .option('-f, --app-path <string>', 'path to the project')
57
+ .option('--public-dir <string>', 'folder whose contents are bundled as static assets (default: public)', 'public')
57
58
  .action(async (opts) => {
58
59
  try {
59
- const { appPath } = opts;
60
- await (0, build_1.buildCommand)({ locationFolder: appPath });
60
+ const { appPath, publicDir } = opts;
61
+ await (0, build_1.buildCommand)({ locationFolder: appPath, publicDir });
61
62
  }
62
63
  catch (err) {
63
64
  process.exit(1);
@@ -134,8 +135,10 @@ program
134
135
  .description('Publish the app to the DEGN Dapp Store')
135
136
  .option('-n, --network <string>', 'network devnet|mainnet')
136
137
  .option('-f, --index-app-path <string>', 'path for the index.html', './')
138
+ .option('-p, --package <path>', 'path to existing zip (e.g. output of build); upload this file and skip re-packing')
139
+ .option('--public-dir <string>', 'folder whose contents are bundled as static assets (default: public)', 'public')
137
140
  .action(async (opts) => {
138
- let { network, indexAppPath } = opts;
141
+ let { network, indexAppPath, package: packagePath, publicDir } = opts;
139
142
  if (indexAppPath == './') {
140
143
  indexAppPath = undefined;
141
144
  }
@@ -143,6 +146,8 @@ program
143
146
  await (0, upload_1.uploadCommand)({
144
147
  network,
145
148
  locationFolder: indexAppPath,
149
+ publicDir,
150
+ packagePath,
146
151
  });
147
152
  }
148
153
  catch (err) {
@@ -32,13 +32,20 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
35
38
  Object.defineProperty(exports, "__esModule", { value: true });
36
39
  exports.loadMetadata = loadMetadata;
37
40
  exports.saveMetadata = saveMetadata;
38
41
  exports.getPackageName = getPackageName;
42
+ exports.readPackageNameFromCargoToml = readPackageNameFromCargoToml;
43
+ exports.readVersionFromCargoToml = readVersionFromCargoToml;
44
+ exports.applyVersionFromCargoToml = applyVersionFromCargoToml;
39
45
  exports.populateBuildMetadata = populateBuildMetadata;
40
46
  const fs = __importStar(require("fs"));
41
47
  const path = __importStar(require("path"));
48
+ const toml_1 = __importDefault(require("toml"));
42
49
  const LogService_1 = require("../service/log/LogService");
43
50
  const child_process_1 = require("child_process");
44
51
  const remote_1 = require("./remote");
@@ -87,14 +94,75 @@ function getPackageName(pkg) {
87
94
  // e.g. myApp-0.1.0.zip
88
95
  return `${pkg.name}-${pkg.version}.zip`;
89
96
  }
97
+ function parseCargoToml(projectPath) {
98
+ const cargoPath = path.join(projectPath, 'Cargo.toml');
99
+ if (!fs.existsSync(cargoPath)) {
100
+ return null;
101
+ }
102
+ try {
103
+ const content = fs.readFileSync(cargoPath, 'utf8');
104
+ return toml_1.default.parse(content);
105
+ }
106
+ catch {
107
+ return null;
108
+ }
109
+ }
110
+ /**
111
+ * Reads the package name from Cargo.toml [package] section (used as binary name).
112
+ * Returns null if file is missing or name is not found.
113
+ */
114
+ function readPackageNameFromCargoToml(projectPath) {
115
+ const parsed = parseCargoToml(projectPath);
116
+ const name = parsed?.package?.name;
117
+ return typeof name === 'string' ? name : null;
118
+ }
119
+ /**
120
+ * Reads the package version from Cargo.toml [package] section.
121
+ * Returns null if file is missing or version is not found.
122
+ */
123
+ function readVersionFromCargoToml(projectPath) {
124
+ const parsed = parseCargoToml(projectPath);
125
+ const version = parsed?.package?.version;
126
+ return typeof version === 'string' ? version : null;
127
+ }
128
+ /**
129
+ * For Native projects, reads version from Cargo.toml, sets meta.version, and saves metadata.json.
130
+ * No-op for Web or when Cargo.toml is missing / has no version.
131
+ */
132
+ function applyVersionFromCargoToml(meta, projectPath) {
133
+ if (meta.type !== 'Native') {
134
+ return;
135
+ }
136
+ const versionFromCargo = readVersionFromCargoToml(projectPath);
137
+ if (versionFromCargo) {
138
+ meta.version = versionFromCargo;
139
+ saveMetadata(meta, projectPath);
140
+ }
141
+ }
90
142
  function populateBuildMetadata(pkg, projectPath) {
91
- // 1. Build Number: Increment if numeric, or use timestamp
92
- const currentBuild = parseInt(pkg.buildNumber || '0', 10);
93
- if (!isNaN(currentBuild)) {
94
- pkg.buildNumber = (currentBuild + 1).toString();
143
+ // 1. Build Number: use git rev-list --count HEAD; on failure fall back to increment or timestamp
144
+ try {
145
+ const count = (0, child_process_1.execSync)('git rev-list --count HEAD', {
146
+ cwd: projectPath,
147
+ stdio: ['ignore', 'pipe', 'ignore'],
148
+ encoding: 'utf8',
149
+ })
150
+ .trim();
151
+ if (count !== '') {
152
+ pkg.buildNumber = count;
153
+ }
154
+ else {
155
+ throw new Error('empty');
156
+ }
95
157
  }
96
- else {
97
- pkg.buildNumber = Math.floor(Date.now() / 1000).toString();
158
+ catch {
159
+ const currentBuild = parseInt(pkg.buildNumber || '0', 10);
160
+ if (!isNaN(currentBuild)) {
161
+ pkg.buildNumber = (currentBuild + 1).toString();
162
+ }
163
+ else {
164
+ pkg.buildNumber = Math.floor(Date.now() / 1000).toString();
165
+ }
98
166
  }
99
167
  // 2. Commit Hash
100
168
  try {
@@ -36,15 +36,93 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.verifyZipPackage = verifyZipPackage;
40
+ exports.copyDirContents = copyDirContents;
39
41
  exports.packProject = packProject;
40
42
  const fs = __importStar(require("fs"));
41
43
  const path = __importStar(require("path"));
42
44
  const crypto = __importStar(require("crypto"));
43
45
  const archiver_1 = __importDefault(require("archiver"));
46
+ const yauzl_1 = __importDefault(require("yauzl"));
44
47
  const metadata_1 = require("./metadata");
45
48
  const LogService_1 = require("../service/log/LogService");
46
49
  const REQUIRED_FILES_WEB = ['metadata.json', 'dapp-logo.png', 'index.html'];
47
50
  const REQUIRED_FILES_NATIVE = ['metadata.json', 'dapp-logo.png'];
51
+ /**
52
+ * Returns entry file names in the zip (directories excluded; names may include path).
53
+ */
54
+ function getZipEntryNames(zipPath) {
55
+ return new Promise((resolve, reject) => {
56
+ yauzl_1.default.open(zipPath, { lazyEntries: true }, (err, zipfile) => {
57
+ if (err) {
58
+ reject(err);
59
+ return;
60
+ }
61
+ const names = [];
62
+ zipfile.on('entry', (entry) => {
63
+ if (!/\/$/.test(entry.fileName)) {
64
+ names.push(entry.fileName);
65
+ }
66
+ zipfile.readEntry();
67
+ });
68
+ zipfile.on('end', () => {
69
+ zipfile.close();
70
+ resolve(names);
71
+ });
72
+ zipfile.readEntry();
73
+ });
74
+ });
75
+ }
76
+ /**
77
+ * Verifies the zip is valid and contains required files for the given package type.
78
+ * For Native, also verifies the binary file is present when binaryName is provided.
79
+ * @throws Error if the zip is invalid or missing required files
80
+ */
81
+ async function verifyZipPackage(zipPath, type, options) {
82
+ const required = type === 'Native' ? REQUIRED_FILES_NATIVE : REQUIRED_FILES_WEB;
83
+ let names;
84
+ try {
85
+ names = await getZipEntryNames(zipPath);
86
+ }
87
+ catch (err) {
88
+ const msg = err instanceof Error ? err.message : String(err);
89
+ throw new Error(`Invalid or corrupt zip file: ${msg}`);
90
+ }
91
+ const hasFile = (name) => names.some(n => n === name || n.endsWith('/' + name));
92
+ const missing = required.filter(r => !hasFile(r));
93
+ if (missing.length > 0) {
94
+ throw new Error(`Zip is missing required files: ${missing.join(', ')}. Required for ${type}: ${required.join(', ')}.`);
95
+ }
96
+ if (type === 'Native' && options?.binaryName) {
97
+ if (!hasFile(options.binaryName)) {
98
+ throw new Error(`Zip is missing Native binary: ${options.binaryName}. Required for Native packages.`);
99
+ }
100
+ }
101
+ }
102
+ /**
103
+ * Copies the contents of srcDir into destDir (merge; destDir gets srcDir's files/subdirs at root).
104
+ */
105
+ function copyDirContents(srcDir, destDir) {
106
+ if (!fs.existsSync(srcDir)) {
107
+ return;
108
+ }
109
+ const stat = fs.statSync(srcDir);
110
+ if (!stat.isDirectory()) {
111
+ return;
112
+ }
113
+ const entries = fs.readdirSync(srcDir, { withFileTypes: true });
114
+ for (const e of entries) {
115
+ const src = path.join(srcDir, e.name);
116
+ const dest = path.join(destDir, e.name);
117
+ if (e.isDirectory()) {
118
+ fs.mkdirSync(dest, { recursive: true });
119
+ copyDirContents(src, dest);
120
+ }
121
+ else {
122
+ fs.copyFileSync(src, dest);
123
+ }
124
+ }
125
+ }
48
126
  /**
49
127
  * Validates that the project path exists
50
128
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@airmoney-degn/airmoney-cli",
3
- "version": "0.24.1",
3
+ "version": "0.25.1",
4
4
  "description": "airmoney-cli is a command-line interface tool designed to facilitate the development and management of decentralized applications (DApps) for Airmoney.",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -50,8 +50,10 @@
50
50
  "node-fetch": "^2.6.7",
51
51
  "open": "^8.4.0",
52
52
  "tar": "^6.1.13",
53
+ "toml": "^3.0.0",
53
54
  "websocket": "^1.0.35",
54
- "ws": "^8.18.1"
55
+ "ws": "^8.18.1",
56
+ "yauzl": "^3.2.0"
55
57
  },
56
58
  "devDependencies": {
57
59
  "@airmoney-degn/controller-sdk": "^5.4.1",
@@ -67,6 +69,7 @@
67
69
  "@types/node-fetch": "^2.6.12",
68
70
  "@types/tar": "^6.1.13",
69
71
  "@types/websocket": "^1.0.10",
72
+ "@types/yauzl": "^2.10.3",
70
73
  "prettier": "^3.6.1",
71
74
  "typescript": "^5.0.4"
72
75
  },