defang 0.5.21 → 0.5.26

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,9 +1,176 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || function (mod) {
20
+ if (mod && mod.__esModule) return mod;
21
+ var result = {};
22
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23
+ __setModuleDefault(result, mod);
24
+ return result;
25
+ };
26
+ var __importDefault = (this && this.__importDefault) || function (mod) {
27
+ return (mod && mod.__esModule) ? mod : { "default": mod };
28
+ };
3
29
  Object.defineProperty(exports, "__esModule", { value: true });
4
- const path = require("path");
5
- const child_process = require("child_process");
30
+ const adm_zip_1 = __importDefault(require("adm-zip"));
31
+ const axios_1 = __importDefault(require("axios"));
32
+ const child_process = __importStar(require("child_process"));
33
+ const fs_1 = require("fs");
34
+ const os = __importStar(require("os"));
35
+ const path = __importStar(require("path"));
36
+ const tar = __importStar(require("tar"));
37
+ const util_1 = require("util");
6
38
  const EXECUTABLE = "defang";
39
+ const URL_LATEST_RELEASE = "https://api.github.com/repos/DefangLabs/defang/releases/latest";
40
+ const HTTP_STATUS_OK = 200;
41
+ const exec = (0, util_1.promisify)(child_process.exec);
42
+ async function getLatestVersion() {
43
+ const response = await axios_1.default.get(URL_LATEST_RELEASE);
44
+ if (response.status !== HTTP_STATUS_OK) {
45
+ throw new Error(`Failed to get latest version from GitHub. Status code: ${response.status}`);
46
+ }
47
+ return response.data.tag_name.replace("v", "").trim();
48
+ }
49
+ async function downloadAppArchive(version, archiveFilename, outputPath) {
50
+ const repo = "DefangLabs/defang";
51
+ const downloadUrl = `https://github.com/${repo}/releases/download/v${version}/${archiveFilename}`;
52
+ const downloadTargetFile = path.join(outputPath, archiveFilename);
53
+ return await downloadFile(downloadUrl, downloadTargetFile);
54
+ }
55
+ async function downloadFile(downloadUrl, downloadTargetFile) {
56
+ try {
57
+ const response = await axios_1.default.get(downloadUrl, {
58
+ responseType: "arraybuffer",
59
+ headers: {
60
+ "Content-Type": "application/octet-stream",
61
+ },
62
+ });
63
+ if (response?.data === undefined) {
64
+ throw new Error(`Failed to download ${downloadUrl}. No data in response.`);
65
+ }
66
+ await fs_1.promises.writeFile(downloadTargetFile, response.data);
67
+ return downloadTargetFile;
68
+ }
69
+ catch (error) {
70
+ console.error(error);
71
+ await fs_1.promises.unlink(downloadTargetFile);
72
+ return null;
73
+ }
74
+ }
75
+ async function extractArchive(archiveFilePath, outputPath) {
76
+ let result = false;
77
+ const ext = path.extname(archiveFilePath).toLocaleLowerCase();
78
+ switch (ext) {
79
+ case ".zip":
80
+ result = await extractZip(archiveFilePath, outputPath);
81
+ break;
82
+ case ".gz":
83
+ result = extractTarGz(archiveFilePath, outputPath);
84
+ break;
85
+ default:
86
+ throw new Error(`Unsupported archive extension: ${ext}`);
87
+ }
88
+ return result;
89
+ }
90
+ async function extractZip(zipPath, outputPath) {
91
+ try {
92
+ const zip = new adm_zip_1.default(zipPath);
93
+ const result = zip.extractEntryTo(EXECUTABLE, outputPath, true, true);
94
+ await fs_1.promises.chmod(path.join(outputPath, EXECUTABLE), 755);
95
+ return result;
96
+ }
97
+ catch (error) {
98
+ console.error(`An error occurred during zip extraction: ${error}`);
99
+ return false;
100
+ }
101
+ }
102
+ function extractTarGz(tarGzFilePath, outputPath) {
103
+ try {
104
+ tar.extract({
105
+ cwd: outputPath,
106
+ file: tarGzFilePath,
107
+ sync: true,
108
+ strict: true,
109
+ }, [EXECUTABLE]);
110
+ return true;
111
+ }
112
+ catch (error) {
113
+ console.error(`An error occurred during tar.gz extraction: ${error}`);
114
+ return false;
115
+ }
116
+ }
117
+ async function deleteArchive(archiveFilePath) {
118
+ await fs_1.promises.unlink(archiveFilePath);
119
+ }
120
+ async function getVersion(filename) {
121
+ const data = await fs_1.promises.readFile(filename, "utf8");
122
+ const pkg = JSON.parse(data);
123
+ return pkg.version;
124
+ }
125
+ function getAppArchiveFilename(version, platform, arch) {
126
+ let compression = "zip";
127
+ switch (platform) {
128
+ case "windows":
129
+ platform = "windows";
130
+ break;
131
+ case "linux":
132
+ platform = "linux";
133
+ compression = "tar.gz";
134
+ break;
135
+ case "darwin":
136
+ platform = "macOS";
137
+ break;
138
+ default:
139
+ throw new Error(`Unsupported operating system: ${platform}`);
140
+ }
141
+ switch (arch) {
142
+ case "x64":
143
+ arch = "amd64";
144
+ break;
145
+ case "arm64":
146
+ arch = "arm64";
147
+ break;
148
+ default:
149
+ throw new Error(`Unsupported architecture: ${arch}`);
150
+ }
151
+ if (platform === "macOS") {
152
+ return `defang_${version}_${platform}.${compression}`;
153
+ }
154
+ return `defang_${version}_${platform}_${arch}.${compression}`;
155
+ }
156
+ async function install(version, saveDirectory) {
157
+ try {
158
+ console.log(`Getting latest defang cli`);
159
+ const filename = getAppArchiveFilename(version, os.platform(), os.arch());
160
+ const archiveFile = await downloadAppArchive(version, filename, saveDirectory);
161
+ if (archiveFile == null || archiveFile.length === 0) {
162
+ throw new Error(`Failed to download ${filename}`);
163
+ }
164
+ const result = await extractArchive(archiveFile, saveDirectory);
165
+ if (result === false) {
166
+ throw new Error(`Failed to install binaries!`);
167
+ }
168
+ await deleteArchive(archiveFile);
169
+ }
170
+ catch (error) {
171
+ console.error(error);
172
+ }
173
+ }
7
174
  function getPathToExecutable() {
8
175
  let extension = "";
9
176
  if (["win32", "cygwin"].includes(process.platform)) {
@@ -14,13 +181,75 @@ function getPathToExecutable() {
14
181
  return require.resolve(executablePath);
15
182
  }
16
183
  catch (e) {
17
- throw new Error(`Could not find application binary at ${executablePath}.`);
184
+ return null;
185
+ }
186
+ }
187
+ function extractCLIVersions(versionInfo) {
188
+ const versionRegex = /\d+\.\d+\.\d+/g;
189
+ const matches = versionInfo.match(versionRegex);
190
+ if (matches != null && matches.length >= 2) {
191
+ return {
192
+ defangCLI: matches[0],
193
+ latestCLI: matches[1],
194
+ };
195
+ }
196
+ else {
197
+ throw new Error("Could not extract CLI versions from the output.");
198
+ }
199
+ }
200
+ async function getVersionInfo() {
201
+ let result = { current: null, latest: null };
202
+ try {
203
+ const execPath = getPathToExecutable();
204
+ if (!execPath) {
205
+ const latestVersion = await getLatestVersion();
206
+ return { current: null, latest: latestVersion };
207
+ }
208
+ const versionInfo = await exec(execPath + " version");
209
+ const verInfo = extractCLIVersions(versionInfo.stdout);
210
+ result.current = verInfo.defangCLI;
211
+ result.latest = verInfo.latestCLI;
212
+ }
213
+ catch (error) {
214
+ console.error(error);
215
+ }
216
+ return result;
217
+ }
218
+ function extractCLIWrapperArgs(args) {
219
+ const cliParams = {
220
+ uselatest: true,
221
+ };
222
+ const outArgs = [];
223
+ for (const arg of args) {
224
+ const argLower = arg.toLowerCase().replaceAll(" ", "");
225
+ if (argLower.startsWith("--use-latest")) {
226
+ const startOfValue = argLower.indexOf("=");
227
+ if (startOfValue >= 0) {
228
+ if (argLower.slice(startOfValue + 1) == "false") {
229
+ cliParams.uselatest = false;
230
+ }
231
+ }
232
+ }
233
+ else {
234
+ outArgs.push(arg);
235
+ }
18
236
  }
237
+ return { cliParams, outArgs };
19
238
  }
20
- function run() {
239
+ async function run() {
21
240
  try {
22
- const args = process.argv.slice(2);
23
- const processResult = child_process.spawnSync(getPathToExecutable(), args, {
241
+ const { cliParams, outArgs: args } = extractCLIWrapperArgs(process.argv.slice(2));
242
+ if (cliParams.uselatest) {
243
+ const { current, latest } = await getVersionInfo();
244
+ if (latest != null && (current == null || current != latest)) {
245
+ await install(latest, __dirname);
246
+ }
247
+ }
248
+ const pathToExec = getPathToExecutable();
249
+ if (!pathToExec) {
250
+ throw new Error("Could not find the defang executable.");
251
+ }
252
+ const processResult = child_process.spawnSync(pathToExec, args, {
24
253
  stdio: "inherit",
25
254
  });
26
255
  processResult.error && console.error(processResult.error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "defang",
3
- "version": "0.5.21",
3
+ "version": "0.5.26",
4
4
  "author": "Defang Software Labs Inc.",
5
5
  "description": "CLI for the Defang Opinionated Platform",
6
6
  "license": "MIT",
@@ -17,11 +17,10 @@
17
17
  "url": "https://github.com/DefangLabs/defang/issues"
18
18
  },
19
19
  "scripts": {
20
- "build": "tsc",
21
- "postinstall": "node ./bin/installer.js"
20
+ "build": "tsc"
22
21
  },
23
22
  "dependencies": {
24
- "adm-zip": "^0.5.12",
23
+ "adm-zip": "^0.5.14",
25
24
  "axios": "^1.6.8",
26
25
  "https": "^1.0.0",
27
26
  "os": "^0.1.2",
package/bin/installer.js DELETED
@@ -1,137 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const os = require("os");
4
- const path = require("path");
5
- const tar = require("tar");
6
- const AdmZip = require("adm-zip");
7
- const axios_1 = require("axios");
8
- const fs_1 = require("fs");
9
- async function downloadAppArchive(version, archiveFilename, outputPath) {
10
- const repo = "DefangLabs/defang";
11
- const downloadUrl = `https://github.com/${repo}/releases/download/v${version}/${archiveFilename}`;
12
- const downloadTargetFile = path.join(outputPath, archiveFilename);
13
- return downloadFile(downloadUrl, downloadTargetFile);
14
- }
15
- async function downloadFile(downloadUrl, downloadTargetFile) {
16
- try {
17
- console.log(`Downloading ${downloadUrl}`);
18
- const response = await axios_1.default.get(downloadUrl, {
19
- responseType: "arraybuffer",
20
- headers: {
21
- "Content-Type": "application/octet-stream",
22
- },
23
- });
24
- if (response?.data === undefined) {
25
- throw new Error(`Failed to download ${downloadUrl}. No data in response.`);
26
- }
27
- await fs_1.promises.writeFile(downloadTargetFile, response.data);
28
- return downloadTargetFile;
29
- }
30
- catch (error) {
31
- console.error(error);
32
- await fs_1.promises.unlink(downloadTargetFile);
33
- return "";
34
- }
35
- }
36
- function extractArchive(archiveFilePath, outputPath) {
37
- let result = false;
38
- console.log(`Extracting ${archiveFilePath}`);
39
- const ext = path.extname(archiveFilePath).toLocaleLowerCase();
40
- switch (ext) {
41
- case ".zip":
42
- result = extractZip(archiveFilePath, outputPath);
43
- break;
44
- case ".gz":
45
- result = extractTarGz(archiveFilePath, outputPath);
46
- break;
47
- default:
48
- throw new Error(`Unsupported archive extension: ${ext}`);
49
- }
50
- return result;
51
- }
52
- function extractZip(zipPath, outputPath) {
53
- try {
54
- const zip = new AdmZip(zipPath);
55
- zip.extractAllTo(outputPath, true, true);
56
- return true;
57
- }
58
- catch (error) {
59
- console.error(`An error occurred during zip extraction: ${error}`);
60
- return false;
61
- }
62
- }
63
- function extractTarGz(tarGzFilePath, outputPath) {
64
- try {
65
- tar.extract({
66
- cwd: outputPath,
67
- file: tarGzFilePath,
68
- sync: true,
69
- strict: true,
70
- });
71
- return true;
72
- }
73
- catch (error) {
74
- console.error(`An error occurred during tar.gz extraction: ${error}`);
75
- return false;
76
- }
77
- }
78
- async function deleteArchive(archiveFilePath) {
79
- await fs_1.promises.unlink(archiveFilePath);
80
- }
81
- async function getVersion(filename) {
82
- const data = await fs_1.promises.readFile(filename, "utf8");
83
- const pkg = JSON.parse(data);
84
- return pkg.version;
85
- }
86
- function getAppArchiveFilename(version, platform, arch) {
87
- let compression = "zip";
88
- switch (platform) {
89
- case "windows":
90
- platform = "windows";
91
- break;
92
- case "linux":
93
- platform = "linux";
94
- compression = "tar.gz";
95
- break;
96
- case "darwin":
97
- platform = "macOS";
98
- break;
99
- default:
100
- throw new Error(`Unsupported operating system: ${platform}`);
101
- }
102
- switch (arch) {
103
- case "x64":
104
- arch = "amd64";
105
- break;
106
- case "arm64":
107
- arch = "arm64";
108
- break;
109
- default:
110
- throw new Error(`Unsupported architecture: ${arch}`);
111
- }
112
- if (platform === "macOS") {
113
- return `defang_${version}_${platform}.${compression}`;
114
- }
115
- return `defang_${version}_${platform}_${arch}.${compression}`;
116
- }
117
- async function install() {
118
- try {
119
- console.log(`Starting install of defang cli`);
120
- const version = await getVersion("package.json");
121
- const filename = getAppArchiveFilename(version, os.platform(), os.arch());
122
- const archiveFile = await downloadAppArchive(version, filename, __dirname);
123
- if (archiveFile.length === 0) {
124
- throw new Error(`Failed to download ${filename}`);
125
- }
126
- const result = extractArchive(archiveFile, "./bin");
127
- if (result === false) {
128
- throw new Error(`Failed to install binaries!`);
129
- }
130
- console.log(`Successfully installed defang cli!`);
131
- await deleteArchive(archiveFile);
132
- }
133
- catch (error) {
134
- console.error(error);
135
- }
136
- }
137
- install();