magicbell-cli 0.3.0 → 1.1.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # magicbell-cli
2
2
 
3
+ ## 1.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#7393](https://github.com/magicbell/magicbell/pull/7393) [`00f79d4`](https://github.com/magicbell/magicbell/commit/00f79d46951300e9d603f5667243b9dee5cae8dd) Thanks [@smeijer](https://github.com/smeijer)! - The CLI can now be called using `npx`, like `npx magicbell-cli --version`
8
+
9
+ ## 1.0.0
10
+
11
+ ### Major Changes
12
+
13
+ - [#7371](https://github.com/magicbell/magicbell/pull/7371) [`8199f7d`](https://github.com/magicbell/magicbell/commit/8199f7dd852e1eb77822aa3f7e5605d51f1e9f1b) Thanks [@smeijer](https://github.com/smeijer)! - release magicbell-cli v1.0.0
14
+
3
15
  ## 0.3.0
4
16
 
5
17
  ### Minor Changes
package/package.json CHANGED
@@ -1,13 +1,18 @@
1
1
  {
2
2
  "name": "magicbell-cli",
3
- "version": "0.3.0",
3
+ "version": "1.1.0",
4
4
  "description": "MagicBell CLI",
5
+ "type": "module",
5
6
  "dependencies": {
6
- "golang-npm": "^0.0.6"
7
+ "node-fetch": "^3.3.2",
8
+ "tar": "^7.5.2"
9
+ },
10
+ "bin": {
11
+ "magicbell": "bin/magicbell"
7
12
  },
8
13
  "scripts": {
9
- "postinstall": "golang-npm install",
10
- "preuninstall": "golang-npm uninstall",
14
+ "postinstall": "node src/install.js install",
15
+ "preuninstall": "node src/install.js uninstall",
11
16
  "prepack": "npx -y pinst --enable",
12
17
  "postpack": "npx -y pinst --disable",
13
18
  "test": "echo \"Error: no test specified\" && exit 1"
package/src/install.js ADDED
@@ -0,0 +1,226 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /* eslint-disable no-console */
5
+
6
+ // copy from https://github.com/Nelwhix/go-npm/blob/main/src/index.js
7
+ // adjustments made so bin is installed to ./bin instead of node global .bin folder
8
+
9
+ import { exec } from 'child_process';
10
+ import fs from 'fs';
11
+ import fetch from 'node-fetch';
12
+ import path from 'path';
13
+ import * as tar from 'tar';
14
+ import zlib from 'zlib';
15
+
16
+ // Mapping from Node's `process.arch` to Golang's `$GOARCH`
17
+ const ARCH_MAPPING = {
18
+ ia32: '386',
19
+ x64: 'amd64',
20
+ arm: 'arm',
21
+ arm64: 'arm64',
22
+ };
23
+
24
+ // Mapping between Node's `process.platform` to Golang's
25
+ const PLATFORM_MAPPING = {
26
+ darwin: 'darwin',
27
+ linux: 'linux',
28
+ win32: 'windows',
29
+ freebsd: 'freebsd',
30
+ };
31
+
32
+ // to get the path where npm binaries are stored
33
+ function getInstallationPath(callback) {
34
+ exec('npm --v', (err, stdout, _stderr) => {
35
+ const npmVersion = parseFloat(stdout.trim());
36
+
37
+ // npm bin was deprecated after v9 https://github.blog/changelog/2022-10-24-npm-v9-0-0-released/
38
+ if (npmVersion < 9) {
39
+ exec('npm bin -g', (err, stdout, stderr) => {
40
+ let dir = null;
41
+
42
+ if (err || stderr || !stdout || stdout.length === 0) {
43
+ throw new Error('Could not get installation path');
44
+ } else {
45
+ dir = stdout.trim();
46
+ }
47
+
48
+ fs.mkdirSync(dir, { recursive: true });
49
+ callback(null, dir);
50
+ });
51
+ } else {
52
+ exec('npm prefix -g', (err, stdout, stderr) => {
53
+ let dir = null;
54
+
55
+ if (err || stderr || !stdout || stdout.length === 0) {
56
+ throw new Error('Could not get installation path');
57
+ } else {
58
+ dir = stdout.trim() + '/bin';
59
+ }
60
+
61
+ fs.mkdirSync(dir, { recursive: true });
62
+ callback(null, dir);
63
+ });
64
+ }
65
+ });
66
+ }
67
+
68
+ function verifyAndPlaceBinary(binName, binPath, callback) {
69
+ const targetPath = path.join(binPath, binName);
70
+
71
+ if (!fs.existsSync(targetPath)) {
72
+ throw new Error(`Downloaded binary does not contain the binary specified in configuration - ${binName}`);
73
+ }
74
+
75
+ try {
76
+ fs.chmodSync(targetPath, 0o755);
77
+ } catch (err) {
78
+ // ignore on Windows
79
+ }
80
+
81
+ callback();
82
+ }
83
+
84
+ function validateConfiguration(packageJson) {
85
+ if (!packageJson.version) {
86
+ return "'version' property is required";
87
+ }
88
+
89
+ if (!packageJson.goBinary || typeof packageJson.goBinary !== 'object') {
90
+ return "'goBinary' property must be defined and be an object";
91
+ }
92
+
93
+ if (!packageJson.goBinary.name) {
94
+ return "'name' property is required";
95
+ }
96
+
97
+ if (!packageJson.goBinary.path) {
98
+ return "'path' property is required";
99
+ }
100
+
101
+ if (!packageJson.goBinary.url) {
102
+ return "'url' property is required";
103
+ }
104
+ }
105
+
106
+ function parsePackageJson() {
107
+ if (!(process.arch in ARCH_MAPPING)) {
108
+ console.error('Installation is not supported for this architecture: ' + process.arch);
109
+ return;
110
+ }
111
+
112
+ if (!(process.platform in PLATFORM_MAPPING)) {
113
+ console.error('Installation is not supported for this platform: ' + process.platform);
114
+ return;
115
+ }
116
+
117
+ const packageJsonPath = path.join('.', 'package.json');
118
+ if (!fs.existsSync(packageJsonPath)) {
119
+ console.error(
120
+ 'Unable to find package.json. ' + 'Please run this script at root of the package you want to be installed',
121
+ );
122
+ return;
123
+ }
124
+
125
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath));
126
+ const error = validateConfiguration(packageJson);
127
+ if (error && error.length > 0) {
128
+ console.error('Invalid package.json: ' + error);
129
+ return;
130
+ }
131
+
132
+ let binName = packageJson.goBinary.name;
133
+ const binPath = packageJson.goBinary.path;
134
+ let url = packageJson.goBinary.url;
135
+ let version = packageJson.goBinary.binaryVersion || packageJson.version;
136
+ if (version[0] === 'v') version = version.substr(1);
137
+
138
+ if (process.platform === 'win32') {
139
+ binName += '.exe';
140
+ }
141
+
142
+ // Interpolate variables in URL, if necessary
143
+ url = url.replace(/{{arch}}/g, ARCH_MAPPING[process.arch]);
144
+ url = url.replace(/{{platform}}/g, PLATFORM_MAPPING[process.platform]);
145
+ url = url.replace(/{{version}}/g, version);
146
+ url = url.replace(/{{bin_name}}/g, binName);
147
+
148
+ return {
149
+ binName: binName,
150
+ binPath: binPath,
151
+ url: url,
152
+ version: version,
153
+ };
154
+ }
155
+
156
+ /**
157
+ * Reads the configuration from application's package.json,
158
+ * validates properties, downloads the binary, untars, and stores at
159
+ * ./bin in the package's root. NPM already has support to install binary files
160
+ * specific locations when invoked with "npm install -g"
161
+ *
162
+ * See: https://docs.npmjs.com/files/package.json#bin
163
+ */
164
+ const INVALID_INPUT = 'Invalid inputs';
165
+ function install(callback) {
166
+ const options = parsePackageJson();
167
+ if (!options) {
168
+ throw new Error(INVALID_INPUT);
169
+ }
170
+
171
+ fs.mkdirSync(options.binPath, { recursive: true });
172
+ const ungz = zlib.createGunzip();
173
+ const untar = tar.x({ cwd: options.binPath });
174
+
175
+ // First we will Un-GZip, then we will untar. So once untar is completed,
176
+ // binary is downloaded into `binPath`. Verify the binary and call it good
177
+ untar.on('end', () => {
178
+ verifyAndPlaceBinary(options.binName, options.binPath, callback);
179
+ });
180
+
181
+ console.log('Downloading from URL: ' + options.url);
182
+
183
+ fetch(options.url).then((res) => {
184
+ if (!res.ok) {
185
+ throw new Error('Error downloading binary. HTTP Status Code: ' + res.status);
186
+ }
187
+
188
+ res.body.pipe(ungz).pipe(untar);
189
+ });
190
+ }
191
+
192
+ function uninstall(callback) {
193
+ const options = parsePackageJson();
194
+
195
+ getInstallationPath(function (err, installationPath) {
196
+ if (err) {
197
+ throw new Error('Error finding binary installation directory');
198
+ }
199
+
200
+ fs.unlinkSync(path.join(installationPath, options.binName));
201
+ callback();
202
+ });
203
+ }
204
+
205
+ const actions = {
206
+ install: install,
207
+ uninstall: uninstall,
208
+ };
209
+
210
+ const argv = process.argv;
211
+ if (argv && argv.length > 2) {
212
+ const cmd = process.argv[2];
213
+ if (!actions[cmd]) {
214
+ console.log('Invalid command to go-npm. `install` and `uninstall` are the only supported commands');
215
+ process.exit(1);
216
+ }
217
+
218
+ try {
219
+ actions[cmd](() => {
220
+ process.exit(0);
221
+ });
222
+ } catch (err) {
223
+ console.error(err);
224
+ process.exit(1);
225
+ }
226
+ }