defang 1.1.16 → 1.1.18

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/bin/cli.js CHANGED
@@ -1,5 +1,3 @@
1
1
  #!/usr/bin/env node
2
- "use strict";
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- var clilib_1 = require("./clilib");
5
- (0, clilib_1.run)();
2
+ import { run } from "./clilib.js";
3
+ run();
package/bin/clilib.js CHANGED
@@ -1,215 +1,82 @@
1
- "use strict";
2
- var __assign = (this && this.__assign) || function () {
3
- __assign = Object.assign || function(t) {
4
- for (var s, i = 1, n = arguments.length; i < n; i++) {
5
- s = arguments[i];
6
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
- t[p] = s[p];
8
- }
9
- return t;
10
- };
11
- return __assign.apply(this, arguments);
12
- };
13
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
- if (k2 === undefined) k2 = k;
15
- var desc = Object.getOwnPropertyDescriptor(m, k);
16
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
- desc = { enumerable: true, get: function() { return m[k]; } };
18
- }
19
- Object.defineProperty(o, k2, desc);
20
- }) : (function(o, m, k, k2) {
21
- if (k2 === undefined) k2 = k;
22
- o[k2] = m[k];
23
- }));
24
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
- Object.defineProperty(o, "default", { enumerable: true, value: v });
26
- }) : function(o, v) {
27
- o["default"] = v;
28
- });
29
- var __importStar = (this && this.__importStar) || (function () {
30
- var ownKeys = function(o) {
31
- ownKeys = Object.getOwnPropertyNames || function (o) {
32
- var ar = [];
33
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
- return ar;
35
- };
36
- return ownKeys(o);
37
- };
38
- return function (mod) {
39
- if (mod && mod.__esModule) return mod;
40
- var result = {};
41
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
- __setModuleDefault(result, mod);
43
- return result;
44
- };
45
- })();
46
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
47
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
48
- return new (P || (P = Promise))(function (resolve, reject) {
49
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
50
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
51
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
52
- step((generator = generator.apply(thisArg, _arguments || [])).next());
53
- });
54
- };
55
- var __generator = (this && this.__generator) || function (thisArg, body) {
56
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
57
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
58
- function verb(n) { return function (v) { return step([n, v]); }; }
59
- function step(op) {
60
- if (f) throw new TypeError("Generator is already executing.");
61
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
62
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
63
- if (y = 0, t) op = [op[0] & 2, t.value];
64
- switch (op[0]) {
65
- case 0: case 1: t = op; break;
66
- case 4: _.label++; return { value: op[1], done: false };
67
- case 5: _.label++; y = op[1]; op = [0]; continue;
68
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
69
- default:
70
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
71
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
72
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
73
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
74
- if (t[2]) _.ops.pop();
75
- _.trys.pop(); continue;
76
- }
77
- op = body.call(thisArg, _);
78
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
79
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
1
+ import AdmZip from "adm-zip";
2
+ import axios from "axios";
3
+ import * as child_process from "child_process";
4
+ import * as fs from "fs";
5
+ import * as path from "path";
6
+ import * as tar from "tar";
7
+ import { promisify } from "util";
8
+ import { dirname } from 'path';
9
+ import { fileURLToPath } from 'url';
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = dirname(__filename);
12
+ const SEMVER_REGEX = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
13
+ const EXECUTABLE = "defang";
14
+ const URL_LATEST_RELEASE = "https://api.github.com/repos/DefangLabs/defang/releases/latest";
15
+ const HTTP_STATUS_OK = 200;
16
+ const exec = promisify(child_process.exec);
17
+ async function getLatestVersion() {
18
+ const response = await axios.get(URL_LATEST_RELEASE);
19
+ if (response.status !== HTTP_STATUS_OK) {
20
+ throw new Error(`Failed to get latest version from GitHub. Status code: ${response.status}`);
80
21
  }
81
- };
82
- var __importDefault = (this && this.__importDefault) || function (mod) {
83
- return (mod && mod.__esModule) ? mod : { "default": mod };
84
- };
85
- Object.defineProperty(exports, "__esModule", { value: true });
86
- exports.install = install;
87
- exports.run = run;
88
- var adm_zip_1 = __importDefault(require("adm-zip"));
89
- var axios_1 = __importDefault(require("axios"));
90
- var child_process = __importStar(require("child_process"));
91
- var fs = __importStar(require("fs"));
92
- var path = __importStar(require("path"));
93
- var tar = __importStar(require("tar"));
94
- var util_1 = require("util");
95
- var SEMVER_REGEX = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
96
- var EXECUTABLE = "defang";
97
- var URL_LATEST_RELEASE = "https://api.github.com/repos/DefangLabs/defang/releases/latest";
98
- var HTTP_STATUS_OK = 200;
99
- var exec = (0, util_1.promisify)(child_process.exec);
100
- function getLatestVersion() {
101
- return __awaiter(this, void 0, void 0, function () {
102
- var response;
103
- var _a, _b;
104
- return __generator(this, function (_c) {
105
- switch (_c.label) {
106
- case 0: return [4, axios_1.default.get(URL_LATEST_RELEASE)];
107
- case 1:
108
- response = _c.sent();
109
- if (response.status !== HTTP_STATUS_OK) {
110
- throw new Error("Failed to get latest version from GitHub. Status code: ".concat(response.status));
111
- }
112
- return [2, (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.tag_name) === null || _b === void 0 ? void 0 : _b.replace("v", "").trim()];
113
- }
114
- });
115
- });
22
+ return response.data?.tag_name?.replace("v", "").trim();
116
23
  }
117
- function downloadAppArchive(archiveFilename, outputPath) {
118
- return __awaiter(this, void 0, void 0, function () {
119
- var downloadUrl, downloadTargetFile;
120
- return __generator(this, function (_a) {
121
- switch (_a.label) {
122
- case 0:
123
- downloadUrl = "https://s.defang.io/".concat(archiveFilename, "?x-defang-source=npm");
124
- downloadTargetFile = path.join(outputPath, archiveFilename);
125
- return [4, downloadFile(downloadUrl, downloadTargetFile)];
126
- case 1: return [2, _a.sent()];
127
- }
128
- });
129
- });
24
+ async function downloadAppArchive(archiveFilename, outputPath) {
25
+ const downloadUrl = `https://s.defang.io/${archiveFilename}?x-defang-source=npm`;
26
+ const downloadTargetFile = path.join(outputPath, archiveFilename);
27
+ return await downloadFile(downloadUrl, downloadTargetFile);
130
28
  }
131
- function downloadFile(downloadUrl, downloadTargetFile) {
132
- return __awaiter(this, void 0, void 0, function () {
133
- var response, error_1;
134
- return __generator(this, function (_a) {
135
- switch (_a.label) {
136
- case 0:
137
- _a.trys.push([0, 3, , 5]);
138
- return [4, axios_1.default.get(downloadUrl, {
139
- responseType: "arraybuffer",
140
- headers: {
141
- "Content-Type": "application/octet-stream",
142
- },
143
- })];
144
- case 1:
145
- response = _a.sent();
146
- if (response.data == null) {
147
- throw new Error("Failed to download ".concat(downloadUrl, ". No data in response."));
148
- }
149
- return [4, fs.promises.writeFile(downloadTargetFile, response.data)];
150
- case 2:
151
- _a.sent();
152
- return [2, downloadTargetFile];
153
- case 3:
154
- error_1 = _a.sent();
155
- console.error(error_1);
156
- return [4, fs.promises.unlink(downloadTargetFile)];
157
- case 4:
158
- _a.sent();
159
- return [2, null];
160
- case 5: return [2];
161
- }
29
+ async function downloadFile(downloadUrl, downloadTargetFile) {
30
+ try {
31
+ const response = await axios.get(downloadUrl, {
32
+ responseType: "arraybuffer",
33
+ headers: {
34
+ "Content-Type": "application/octet-stream",
35
+ },
162
36
  });
163
- });
37
+ if (response.data == null) {
38
+ throw new Error(`Failed to download ${downloadUrl}. No data in response.`);
39
+ }
40
+ await fs.promises.writeFile(downloadTargetFile, response.data);
41
+ return downloadTargetFile;
42
+ }
43
+ catch (error) {
44
+ console.error(error);
45
+ await fs.promises.unlink(downloadTargetFile);
46
+ return null;
47
+ }
164
48
  }
165
- function extractArchive(archiveFilePath, outputPath) {
166
- return __awaiter(this, void 0, void 0, function () {
167
- var result, ext, _a;
168
- return __generator(this, function (_b) {
169
- switch (_b.label) {
170
- case 0:
171
- result = false;
172
- ext = path.extname(archiveFilePath).toLocaleLowerCase();
173
- _a = ext;
174
- switch (_a) {
175
- case ".zip": return [3, 1];
176
- case ".gz": return [3, 3];
177
- }
178
- return [3, 4];
179
- case 1: return [4, extractZip(archiveFilePath, outputPath)];
180
- case 2:
181
- result = _b.sent();
182
- return [3, 5];
183
- case 3:
184
- result = extractTarGz(archiveFilePath, outputPath);
185
- return [3, 5];
186
- case 4: return [2, false];
187
- case 5: return [2, result];
188
- }
189
- });
190
- });
49
+ async function extractArchive(archiveFilePath, outputPath) {
50
+ let result = false;
51
+ const ext = path.extname(archiveFilePath).toLocaleLowerCase();
52
+ switch (ext) {
53
+ case ".zip":
54
+ result = await extractZip(archiveFilePath, outputPath);
55
+ break;
56
+ case ".gz":
57
+ result = extractTarGz(archiveFilePath, outputPath);
58
+ break;
59
+ default:
60
+ return false;
61
+ }
62
+ return result;
191
63
  }
192
- function extractZip(zipPath, outputPath) {
193
- return __awaiter(this, void 0, void 0, function () {
194
- var zip, result, error_2;
195
- return __generator(this, function (_a) {
196
- switch (_a.label) {
197
- case 0:
198
- _a.trys.push([0, 2, , 3]);
199
- zip = new adm_zip_1.default(zipPath);
200
- result = zip.extractEntryTo(EXECUTABLE, outputPath, true, true);
201
- return [4, fs.promises.chmod(path.join(outputPath, EXECUTABLE), 755)];
202
- case 1:
203
- _a.sent();
204
- return [2, result];
205
- case 2:
206
- error_2 = _a.sent();
207
- console.error("An error occurred during zip extraction: ".concat(error_2));
208
- return [2, false];
209
- case 3: return [2];
210
- }
211
- });
212
- });
64
+ async function extractZip(zipPath, outputPath) {
65
+ try {
66
+ const zip = new AdmZip(zipPath);
67
+ let extension = "";
68
+ if (["win32", "cygwin"].includes(process.platform)) {
69
+ extension = ".exe";
70
+ }
71
+ const executableFullName = EXECUTABLE + extension;
72
+ const result = zip.extractEntryTo(executableFullName, outputPath, true, true);
73
+ await fs.promises.chmod(path.join(outputPath, executableFullName), 755);
74
+ return result;
75
+ }
76
+ catch (error) {
77
+ console.error(`An error occurred during zip extraction: ${error}`);
78
+ return false;
79
+ }
213
80
  }
214
81
  function extractTarGz(tarGzFilePath, outputPath) {
215
82
  try {
@@ -222,26 +89,17 @@ function extractTarGz(tarGzFilePath, outputPath) {
222
89
  return true;
223
90
  }
224
91
  catch (error) {
225
- console.error("An error occurred during tar.gz extraction: ".concat(error));
92
+ console.error(`An error occurred during tar.gz extraction: ${error}`);
226
93
  return false;
227
94
  }
228
95
  }
229
- function deleteArchive(archiveFilePath) {
230
- return __awaiter(this, void 0, void 0, function () {
231
- return __generator(this, function (_a) {
232
- switch (_a.label) {
233
- case 0: return [4, fs.promises.unlink(archiveFilePath)];
234
- case 1:
235
- _a.sent();
236
- return [2];
237
- }
238
- });
239
- });
96
+ async function deleteArchive(archiveFilePath) {
97
+ await fs.promises.unlink(archiveFilePath);
240
98
  }
241
99
  function getAppArchiveFilename(version, platform, arch) {
242
- var compression = "zip";
100
+ let compression = "zip";
243
101
  if (!SEMVER_REGEX.test(version)) {
244
- throw new Error("Unsupported version: ".concat(version));
102
+ throw new Error(`Unsupported version: ${version}`);
245
103
  }
246
104
  switch (platform) {
247
105
  case "win32":
@@ -256,7 +114,7 @@ function getAppArchiveFilename(version, platform, arch) {
256
114
  platform = "macOS";
257
115
  break;
258
116
  default:
259
- throw new Error("Unsupported operating system: ".concat(platform));
117
+ throw new Error(`Unsupported operating system: ${platform}`);
260
118
  }
261
119
  switch (arch) {
262
120
  case "x64":
@@ -266,81 +124,70 @@ function getAppArchiveFilename(version, platform, arch) {
266
124
  arch = "arm64";
267
125
  break;
268
126
  default:
269
- throw new Error("Unsupported architecture: ".concat(arch));
127
+ throw new Error(`Unsupported architecture: ${arch}`);
270
128
  }
271
129
  if (platform === "macOS") {
272
- return "defang_".concat(version, "_").concat(platform, ".").concat(compression);
130
+ return `defang_${version}_${platform}.${compression}`;
273
131
  }
274
- return "defang_".concat(version, "_").concat(platform, "_").concat(arch, ".").concat(compression);
132
+ return `defang_${version}_${platform}_${arch}.${compression}`;
275
133
  }
276
134
  function getPathToExecutable() {
277
- var extension = "";
135
+ let extension = "";
278
136
  if (["win32", "cygwin"].includes(process.platform)) {
279
137
  extension = ".exe";
280
138
  }
281
- var executablePath = path.join(__dirname, "".concat(EXECUTABLE).concat(extension));
139
+ const executablePath = path.join(__dirname, `${EXECUTABLE}${extension}`);
282
140
  try {
283
- return require.resolve(executablePath);
141
+ return fs.existsSync(executablePath) ? executablePath : null;
284
142
  }
285
143
  catch (e) {
286
144
  return null;
287
145
  }
288
146
  }
289
147
  function extractCLIVersions(versionInfo) {
290
- var versionRegex = /\d+\.\d+\.\d+/g;
291
- var matches = versionInfo.match(versionRegex);
292
- if (matches != null && matches.length >= 2) {
293
- return {
294
- defangCLI: matches[0],
295
- latestCLI: matches[1],
296
- };
297
- }
298
- else {
299
- throw new Error("Could not extract CLI versions from the output.");
148
+ const regex = /^([A-Za-z ]+):\s*v?(\d+\.\d+\.\d+(?:-[\w.-]+)?)$/gm;
149
+ const versions = {
150
+ defangCLI: null,
151
+ latestCLI: null,
152
+ };
153
+ for (const [, label, version] of versionInfo.matchAll(regex)) {
154
+ const key = label.trim().toLowerCase();
155
+ if (key === "defang cli")
156
+ versions.defangCLI = version;
157
+ else if (key === "latest cli")
158
+ versions.latestCLI = version;
300
159
  }
160
+ return versions;
301
161
  }
302
- function getVersionInfo() {
303
- return __awaiter(this, void 0, void 0, function () {
304
- var result, execPath, latestVersion, versionInfo, verInfo, error_3;
305
- return __generator(this, function (_a) {
306
- switch (_a.label) {
307
- case 0:
308
- result = { current: null, latest: null };
309
- _a.label = 1;
310
- case 1:
311
- _a.trys.push([1, 5, , 6]);
312
- execPath = getPathToExecutable();
313
- if (!!execPath) return [3, 3];
314
- return [4, getLatestVersion()];
315
- case 2:
316
- latestVersion = _a.sent();
317
- return [2, { current: null, latest: latestVersion }];
318
- case 3: return [4, exec(execPath + " version")];
319
- case 4:
320
- versionInfo = _a.sent();
321
- verInfo = extractCLIVersions(versionInfo.stdout);
322
- result.current = verInfo.defangCLI;
323
- result.latest = verInfo.latestCLI;
324
- return [3, 6];
325
- case 5:
326
- error_3 = _a.sent();
327
- console.error(error_3);
328
- return [3, 6];
329
- case 6: return [2, result];
330
- }
331
- });
332
- });
162
+ async function getVersionInfo() {
163
+ let result = { current: null, latest: null };
164
+ try {
165
+ const execPath = getPathToExecutable();
166
+ if (!execPath) {
167
+ const latestVersion = await getLatestVersion();
168
+ return { current: null, latest: latestVersion };
169
+ }
170
+ const versionInfo = await exec(quoteIfNeeded(execPath) + " version");
171
+ const verInfo = extractCLIVersions(versionInfo.stdout);
172
+ result.current = verInfo.defangCLI;
173
+ result.latest = verInfo.latestCLI;
174
+ verInfo.defangCLI ?? console.warn("Defang CLI version not found");
175
+ verInfo.latestCLI ?? console.warn("Latest CLI version not found");
176
+ }
177
+ catch (error) {
178
+ console.error(error);
179
+ }
180
+ return result;
333
181
  }
334
182
  function extractCLIWrapperArgs(args) {
335
- var cliParams = {
183
+ const cliParams = {
336
184
  uselatest: true,
337
185
  };
338
- var outArgs = [];
339
- for (var _i = 0, args_1 = args; _i < args_1.length; _i++) {
340
- var arg = args_1[_i];
341
- var argLower = arg.toLowerCase().replaceAll(" ", "");
186
+ const outArgs = [];
187
+ for (const arg of args) {
188
+ const argLower = arg.toLowerCase().replaceAll(" ", "");
342
189
  if (argLower.startsWith("--use-latest")) {
343
- var startOfValue = argLower.indexOf("=");
190
+ const startOfValue = argLower.indexOf("=");
344
191
  if (startOfValue >= 0) {
345
192
  if (argLower.slice(startOfValue + 1) == "false") {
346
193
  cliParams.uselatest = false;
@@ -351,103 +198,76 @@ function extractCLIWrapperArgs(args) {
351
198
  outArgs.push(arg);
352
199
  }
353
200
  }
354
- return { cliParams: cliParams, outArgs: outArgs };
201
+ return { cliParams, outArgs };
355
202
  }
356
203
  function getEndNameFromPath(pathLine) {
357
- var executableName = path.basename(pathLine);
204
+ const executableName = path.basename(pathLine);
358
205
  return executableName.split(".")[0];
359
206
  }
360
- function install(version, saveDirectory, os) {
361
- return __awaiter(this, void 0, void 0, function () {
362
- var filename, archiveFile, result, error_4;
363
- return __generator(this, function (_a) {
364
- switch (_a.label) {
365
- case 0:
366
- _a.trys.push([0, 4, , 5]);
367
- console.log("Getting latest defang cli");
368
- filename = getAppArchiveFilename(version, os.platform, os.arch);
369
- return [4, downloadAppArchive(filename, saveDirectory)];
370
- case 1:
371
- archiveFile = _a.sent();
372
- if (archiveFile == null || archiveFile.length === 0) {
373
- throw new Error("Failed to download ".concat(filename));
374
- }
375
- return [4, extractArchive(archiveFile, saveDirectory)];
376
- case 2:
377
- result = _a.sent();
378
- if (result === false) {
379
- throw new Error("Failed to install binaries!");
380
- }
381
- return [4, deleteArchive(archiveFile)];
382
- case 3:
383
- _a.sent();
384
- return [3, 5];
385
- case 4:
386
- error_4 = _a.sent();
387
- console.error(error_4);
388
- throw error_4;
389
- case 5: return [2];
390
- }
391
- });
392
- });
207
+ export async function install(version, saveDirectory, os) {
208
+ try {
209
+ console.log(`Getting latest defang cli`);
210
+ const filename = getAppArchiveFilename(version, os.platform, os.arch);
211
+ const archiveFile = await downloadAppArchive(filename, saveDirectory);
212
+ if (archiveFile == null || archiveFile.length === 0) {
213
+ throw new Error(`Failed to download ${filename}`);
214
+ }
215
+ const result = await extractArchive(archiveFile, saveDirectory);
216
+ if (result === false) {
217
+ throw new Error(`Failed to install binaries!`);
218
+ }
219
+ await deleteArchive(archiveFile);
220
+ }
221
+ catch (error) {
222
+ console.error(error);
223
+ throw error;
224
+ }
393
225
  }
394
- function run() {
395
- return __awaiter(this, void 0, void 0, function () {
396
- var _a, cliParams, args, _b, current, latest, pathToExec, commandline, processResult, error_5;
397
- var _c;
398
- return __generator(this, function (_d) {
399
- switch (_d.label) {
400
- case 0:
401
- _d.trys.push([0, 4, , 5]);
402
- _a = extractCLIWrapperArgs(process.argv.slice(2)), cliParams = _a.cliParams, args = _a.outArgs;
403
- if (!cliParams.uselatest) return [3, 3];
404
- return [4, getVersionInfo()];
405
- case 1:
406
- _b = _d.sent(), current = _b.current, latest = _b.latest;
407
- if (!(latest != null && (current == null || current != latest))) return [3, 3];
408
- return [4, install(latest, __dirname, {
409
- platform: process.platform,
410
- arch: process.arch,
411
- })];
412
- case 2:
413
- _d.sent();
414
- _d.label = 3;
415
- case 3:
416
- pathToExec = getPathToExecutable();
417
- if (!pathToExec) {
418
- throw new Error("Could not find the defang executable.");
419
- }
420
- commandline = ["npx", getEndNameFromPath(pathToExec)]
421
- .join(" ")
422
- .trim();
423
- processResult = child_process.spawnSync(pathToExec, args, {
424
- stdio: "inherit",
425
- env: __assign(__assign({}, process.env), { DEFANG_COMMAND_EXECUTOR: commandline }),
426
- });
427
- processResult.error && console.error(processResult.error);
428
- process.exitCode = (_c = processResult.status) !== null && _c !== void 0 ? _c : 1;
429
- return [3, 5];
430
- case 4:
431
- error_5 = _d.sent();
432
- console.error(error_5);
433
- process.exitCode = 2;
434
- return [3, 5];
435
- case 5: return [2];
226
+ function quoteIfNeeded(p) {
227
+ return /\s/.test(p) ? `"${p}"` : p;
228
+ }
229
+ export async function run() {
230
+ try {
231
+ const { cliParams, outArgs: args } = extractCLIWrapperArgs(process.argv.slice(2));
232
+ if (cliParams.uselatest) {
233
+ const { current, latest } = await getVersionInfo();
234
+ if (latest != null && (current == null || current != latest)) {
235
+ await install(latest, __dirname, {
236
+ platform: process.platform,
237
+ arch: process.arch,
238
+ });
436
239
  }
240
+ }
241
+ const pathToExec = getPathToExecutable();
242
+ if (!pathToExec) {
243
+ throw new Error("Could not find the defang executable.");
244
+ }
245
+ const commandline = ["npx", quoteIfNeeded(getEndNameFromPath(pathToExec))]
246
+ .join(" ")
247
+ .trim();
248
+ const processResult = child_process.spawnSync(pathToExec, args, {
249
+ stdio: "inherit",
250
+ env: { ...process.env, DEFANG_COMMAND_EXECUTOR: commandline },
437
251
  });
438
- });
252
+ processResult.error && console.error(processResult.error);
253
+ process.exitCode = processResult.status ?? 1;
254
+ }
255
+ catch (error) {
256
+ console.error(error);
257
+ process.exitCode = 2;
258
+ }
439
259
  }
440
- var clilib = {
441
- deleteArchive: deleteArchive,
442
- downloadAppArchive: downloadAppArchive,
443
- downloadFile: downloadFile,
444
- extractArchive: extractArchive,
445
- extractCLIVersions: extractCLIVersions,
446
- extractCLIWrapperArgs: extractCLIWrapperArgs,
447
- getAppArchiveFilename: getAppArchiveFilename,
448
- getEndNameFromPath: getEndNameFromPath,
449
- getLatestVersion: getLatestVersion,
450
- getVersionInfo: getVersionInfo,
451
- getPathToExecutable: getPathToExecutable,
260
+ const clilib = {
261
+ deleteArchive,
262
+ downloadAppArchive,
263
+ downloadFile,
264
+ extractArchive,
265
+ extractCLIVersions,
266
+ extractCLIWrapperArgs,
267
+ getAppArchiveFilename,
268
+ getEndNameFromPath,
269
+ getLatestVersion,
270
+ getVersionInfo,
271
+ getPathToExecutable,
452
272
  };
453
- exports.default = clilib;
273
+ export default clilib;
package/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "defang",
3
- "version": "1.1.16",
3
+ "version": "1.1.18",
4
4
  "author": "Defang Software Labs Inc.",
5
5
  "description": "CLI to take your app from Docker Compose to a secure and scalable deployment on your favorite cloud in minutes",
6
6
  "license": "MIT",
7
+ "type": "module",
8
+ "ts-node": {
9
+ "esm": true
10
+ },
7
11
  "bin": {
8
12
  "defang": "bin/cli.js"
9
13
  },
@@ -30,9 +34,9 @@
30
34
  "recursive": true
31
35
  },
32
36
  "scripts": {
33
- "build": "tsc",
37
+ "build": "tsc -p tsconfig.json",
34
38
  "postbuild": "chmod +x bin/cli.js",
35
- "test": "mocha -r ts-node/register -trace-warnings 'test/**/*.spec.ts'"
39
+ "test": "tsx --tsconfig tsconfig.test.json mocha.ts"
36
40
  },
37
41
  "dependencies": {
38
42
  "adm-zip": "^0.5.14",
@@ -43,19 +47,17 @@
43
47
  "@types/adm-zip": "^0.5.5",
44
48
  "@types/chai": "^5.1.1",
45
49
  "@types/chai-as-promised": "^8.0.0",
46
- "@types/mocha": "^10.0.7",
50
+ "@types/mocha": "^10.0.10",
47
51
  "@types/node": "^20.12.7",
48
52
  "@types/sinon": "^17.0.3",
49
- "@types/source-map-support": "^0.5.10",
50
53
  "@types/tar": "^6.1.13",
51
54
  "chai": "^5.1.1",
52
55
  "chai-as-promised": "^8.0.0",
53
- "cross-env": "^7.0.3",
54
- "mocha": "^10.6.0",
56
+ "mocha": "^10.8.2",
55
57
  "sinon": "^18.0.0",
56
- "source-map-support": "^0.5.21",
57
58
  "ts-node": "^10.9.2",
58
- "typescript": "^5.5.3"
59
+ "tsx": "^4.19.3",
60
+ "typescript": "^5.8.3"
59
61
  },
60
62
  "main": "./bin/cli.js"
61
63
  }
@@ -1,208 +0,0 @@
1
- import axios, { AxiosResponse } from "axios";
2
- import * as chai from "chai";
3
- import chaiAsPromised from "chai-as-promised";
4
- import fs from "fs";
5
- import "mocha";
6
- import * as sinon from "sinon";
7
- import clilib from "../src/clilib";
8
-
9
- chai.use(chaiAsPromised);
10
- const { assert, expect } = chai;
11
-
12
- var sandbox: sinon.SinonSandbox;
13
-
14
- describe("Testing getLatestVersion()", () => {
15
- beforeEach(() => {
16
- sandbox = sinon.createSandbox();
17
- });
18
-
19
- afterEach(() => {
20
- sandbox.restore();
21
- });
22
-
23
- it("sanity", async () => {
24
- const mockResponse: AxiosResponse = {
25
- status: 200,
26
- data: {
27
- tag_name: "v0.5.32",
28
- },
29
- } as AxiosResponse;
30
- sandbox.stub(axios, "get").returns(Promise.resolve(mockResponse));
31
-
32
- await expect(clilib.getLatestVersion()).to.eventually.equal("0.5.32");
33
- });
34
-
35
- it("bad HTTP Status", async () => {
36
- const mockResponse: AxiosResponse = {
37
- status: 500,
38
- } as AxiosResponse;
39
- sandbox.stub(axios, "get").returns(Promise.reject(mockResponse));
40
-
41
- await expect(clilib.getLatestVersion()).to.be.rejected;
42
- });
43
-
44
- it("empty tag_name", async () => {
45
- const mockResponse: AxiosResponse = {
46
- status: 200,
47
- data: {
48
- tag_name: "",
49
- },
50
- } as AxiosResponse;
51
- sandbox.stub(axios, "get").returns(Promise.resolve(mockResponse));
52
-
53
- await expect(clilib.getLatestVersion()).to.eventually.equal("");
54
- });
55
-
56
- it("ill-formed tag_name", async () => {
57
- const mockResponse: AxiosResponse = {
58
- status: 200,
59
- data: {},
60
- } as AxiosResponse;
61
- sandbox.stub(axios, "get").returns(Promise.resolve(mockResponse));
62
-
63
- await expect(clilib.getLatestVersion()).to.eventually.be.undefined;
64
- });
65
- });
66
-
67
- describe("Testing downloadFile()", () => {
68
- let axiosGetStub: sinon.SinonStub;
69
- let writeStub: sinon.SinonStub;
70
- let unlinkStub: sinon.SinonStub;
71
-
72
- let downloadFileName = "target";
73
- const url = "url";
74
- const header = {
75
- responseType: "arraybuffer",
76
- headers: {
77
- "Content-Type": "application/octet-stream",
78
- },
79
- };
80
- let mockResponse: AxiosResponse;
81
-
82
- beforeEach(() => {
83
- sandbox = sinon.createSandbox();
84
-
85
- downloadFileName = "target";
86
- mockResponse = {
87
- status: 200,
88
- data: {},
89
- } as AxiosResponse;
90
-
91
- axiosGetStub = sandbox
92
- .stub(axios, "get")
93
- .returns(Promise.resolve(mockResponse));
94
- writeStub = sandbox
95
- .stub(fs.promises, "writeFile")
96
- .callsFake(() => Promise.resolve());
97
- unlinkStub = sandbox
98
- .stub(fs.promises, "unlink")
99
- .callsFake(() => Promise.resolve());
100
- });
101
-
102
- afterEach(() => {
103
- sandbox.restore();
104
- });
105
-
106
- it("sanity", async () => {
107
- await expect(
108
- clilib.downloadFile(url, downloadFileName)
109
- ).to.eventually.equal(downloadFileName);
110
-
111
- sinon.assert.calledWith(axiosGetStub, url, header);
112
- sinon.assert.calledWith(writeStub, downloadFileName, mockResponse.data);
113
- sinon.assert.notCalled(unlinkStub);
114
- });
115
-
116
- it("download fails path", async () => {
117
- axiosGetStub.returns(Promise.reject("failed"));
118
- const targetFile = await clilib.downloadFile(url, downloadFileName);
119
- await expect(
120
- clilib.downloadFile(url, downloadFileName)
121
- ).to.eventually.equal(targetFile);
122
-
123
- sinon.assert.calledWith(axiosGetStub, url, header);
124
- sinon.assert.notCalled(writeStub);
125
- sinon.assert.calledWith(unlinkStub, downloadFileName);
126
- });
127
-
128
- it("write failed", async () => {
129
- writeStub.returns(Promise.reject("failed"));
130
- await expect(clilib.downloadFile(url, downloadFileName)).to.eventually.null;
131
- sinon.assert.calledWith(axiosGetStub, url, header);
132
- sinon.assert.calledWith(unlinkStub, downloadFileName);
133
- });
134
- });
135
-
136
- describe("Testing getAppArchiveFilename()", () => {
137
- it("returns expected filename", () => {
138
- const iterationData = [
139
- ["0.0.0", "win32", "x64", "defang_0.0.0_windows_amd64.zip"],
140
- ["0.1.0", "windows", "x64", "defang_0.1.0_windows_amd64.zip"],
141
- ["0.2.9", "windows", "arm64", "defang_0.2.9_windows_arm64.zip"],
142
- ["0.3.10", "linux", "x64", "defang_0.3.10_linux_amd64.tar.gz"],
143
- ["0.4.21", "linux", "arm64", "defang_0.4.21_linux_arm64.tar.gz"],
144
- ["0.5.45", "darwin", "arm64", "defang_0.5.45_macOS.zip"],
145
- ["0.5.45", "darwin", "x64", "defang_0.5.45_macOS.zip"],
146
- ] as const;
147
- const testFunc = (
148
- version: string,
149
- platform: string,
150
- arch: string,
151
- expected: string
152
- ) =>
153
- expect(clilib.getAppArchiveFilename(version, platform, arch)).to.be.equal(
154
- expected
155
- );
156
- iterationData.forEach((testData) => testFunc.call(null, ...testData));
157
- });
158
-
159
- it("check error cases", () => {
160
- const iterationData = [
161
- ["", "windows", "x64"],
162
- ["0.2.9", "windows", "risc64"],
163
- ["0.5.45", "darwin", "powerpc"],
164
- ] as const;
165
- const testFunc = (version: string, platform: string, arch: string) =>
166
- expect(() =>
167
- clilib.getAppArchiveFilename(version, platform, arch)
168
- ).to.throw();
169
- iterationData.forEach((testData) => testFunc.call(null, ...testData));
170
- });
171
- });
172
-
173
- describe("Testing extractCLIVersions()", () => {
174
- it("sanity", async () => {
175
- const versionInfo =
176
- "Defang CLI: v0.5.24\nLatest CLI: v0.5.32\nDefang Fabric: v0.5.0-643";
177
- const expected = { defangCLI: "0.5.24", latestCLI: "0.5.32" };
178
-
179
- expect(clilib.extractCLIVersions(versionInfo)).to.be.deep.equal(expected);
180
- });
181
-
182
- it("missing v in version text", async () => {
183
- const versionInfo =
184
- "Defang CLI: 0.5.24\nLatest CLI: 0.5.32\nDefang Fabric: v0.5.0-643";
185
- const expected = { defangCLI: "0.5.24", latestCLI: "0.5.32" };
186
-
187
- expect(clilib.extractCLIVersions(versionInfo)).to.be.deep.equal(expected);
188
- });
189
-
190
- it("missing Defang CLI", () => {
191
- const versionInfo =
192
- "Defang CLI: \nLatest CLI: v0.5.32\nDefang Fabric: v0.5.0-643";
193
- assert.doesNotThrow(() => clilib.extractCLIVersions(versionInfo));
194
- });
195
-
196
- it("missing Latest CLI", () => {
197
- const versionInfo =
198
- "Defang CLI: v0.5.24\nLatest CLI: \nDefang Fabric: v0.5.0-643";
199
- assert.doesNotThrow(() => clilib.extractCLIVersions(versionInfo));
200
- });
201
-
202
- it("no fabric version in input", async () => {
203
- const versionInfo = "Defang CLI: v0.5.24\nLatest CLI: v0.5.32\n";
204
- const expected = { defangCLI: "0.5.24", latestCLI: "0.5.32" };
205
-
206
- expect(clilib.extractCLIVersions(versionInfo)).to.be.deep.equal(expected);
207
- });
208
- });