@apollo/rover 0.36.2 → 0.38.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 (3) hide show
  1. package/README.md +17 -8
  2. package/binary.js +107 -38
  3. package/package.json +12 -17
package/README.md CHANGED
@@ -47,10 +47,14 @@ Commands:
47
47
  Cloud configuration commands
48
48
  connector
49
49
  Work with Apollo Connectors
50
+ completion
51
+ Generate shell completion scripts
50
52
  config
51
53
  Configuration profile commands
52
54
  contract
53
55
  Contract configuration commands
56
+ schema
57
+ Schema inspection commands
54
58
  dev
55
59
  Run a supergraph locally to develop and test subgraph changes
56
60
  supergraph
@@ -69,6 +73,8 @@ Commands:
69
73
  Commands related to updating rover
70
74
  persisted-queries
71
75
  Commands for persisted queries [aliases: pq]
76
+ install
77
+ Installs Rover
72
78
  explain
73
79
  Explain error codes
74
80
  license
@@ -82,7 +88,7 @@ Options:
82
88
 
83
89
  --format <FORMAT_KIND>
84
90
  Specify Rover's format type
85
-
91
+
86
92
  [default: plain]
87
93
  [possible values: plain, json]
88
94
 
@@ -91,21 +97,21 @@ Options:
91
97
 
92
98
  --insecure-accept-invalid-certs
93
99
  Accept invalid certificates when performing HTTPS requests.
94
-
100
+
95
101
  You should think very carefully before using this flag.
96
-
102
+
97
103
  If invalid certificates are trusted, any certificate for any site will be trusted for use. This includes expired certificates. This introduces significant vulnerabilities, and should only be used as a last resort.
98
104
 
99
105
  --insecure-accept-invalid-hostnames
100
106
  Accept invalid hostnames when performing HTTPS requests.
101
-
107
+
102
108
  You should think very carefully before using this flag.
103
-
109
+
104
110
  If hostname verification is not used, any valid certificate for any site will be trusted for use from any other. This introduces a significant vulnerability to man-in-the-middle attacks.
105
111
 
106
112
  --client-timeout <CLIENT_TIMEOUT>
107
113
  Configure the timeout length (in seconds) when performing HTTP(S) requests
108
-
114
+
109
115
  [default: 30]
110
116
 
111
117
  --skip-update-check
@@ -120,7 +126,7 @@ Options:
120
126
 
121
127
 
122
128
  ** Getting Started with Rover **
123
-
129
+
124
130
  Run the following command to authenticate with GraphOS:
125
131
 
126
132
  $ rover config auth
@@ -209,7 +215,10 @@ If you'd like to call `rover` from any directory on your machine, you can run `n
209
215
 
210
216
  Note: Unfortunately if you've installed `npm` without a version manager such as `nvm`, you may have trouble with global installs. If you encounter an `EACCES` permission-related error while trying to install globally, DO NOT run the install command with `sudo`. [This support page](https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally) has information that should help to resolve this issue.
211
217
 
212
- #### Without curl
218
+ #### Homebrew
219
+ While we recommend using one of the other installation methods above, we do have a homebrew recipe `brew install rover`. The code for this recipe is in the [homebrew-core repo](https://github.com/Homebrew/homebrew-core/blob/master/Formula/r/rover.rb).
220
+
221
+ #### Manual binary download
213
222
 
214
223
  You can also [download the binary for your operating system](https://github.com/apollographql/rover/releases) and manually add its location to your `PATH`.
215
224
 
package/binary.js CHANGED
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
2
 
3
- const axios = require("axios");
4
- const cTable = require("console.table");
5
3
  const libc = require("detect-libc");
6
4
  const os = require("os");
7
5
  const tar = require("tar");
8
- const { configureProxy } = require("axios-proxy-builder");
6
+ const { Console } = require("node:console");
9
7
  const { existsSync, mkdirSync, rmSync } = require("fs");
10
8
  const { join } = require("path");
11
9
  const { spawnSync } = require("child_process");
10
+ const { Readable } = require("stream");
11
+ const { ProxyAgent, fetch } = require("undici");
12
12
 
13
13
  const error = (msg) => {
14
14
  console.error(msg);
@@ -25,35 +25,35 @@ const supportedPlatforms = [
25
25
  ARCHITECTURE: "x64",
26
26
  RUST_TARGET: "x86_64-pc-windows-msvc",
27
27
  BINARY_NAME: `${name}-${version}.exe`,
28
- RAW_NAME: `${name}.exe`
28
+ RAW_NAME: `${name}.exe`,
29
29
  },
30
30
  {
31
31
  TYPE: "Linux",
32
32
  ARCHITECTURE: "x64",
33
33
  RUST_TARGET: "x86_64-unknown-linux-gnu",
34
34
  BINARY_NAME: `${name}-${version}`,
35
- RAW_NAME: `${name}`
35
+ RAW_NAME: `${name}`,
36
36
  },
37
37
  {
38
38
  TYPE: "Linux",
39
39
  ARCHITECTURE: "arm64",
40
40
  RUST_TARGET: "aarch64-unknown-linux-gnu",
41
41
  BINARY_NAME: `${name}-${version}`,
42
- RAW_NAME: `${name}`
42
+ RAW_NAME: `${name}`,
43
43
  },
44
44
  {
45
45
  TYPE: "Darwin",
46
46
  ARCHITECTURE: "x64",
47
47
  RUST_TARGET: "x86_64-apple-darwin",
48
48
  BINARY_NAME: `${name}-${version}`,
49
- RAW_NAME: `${name}`
49
+ RAW_NAME: `${name}`,
50
50
  },
51
51
  {
52
52
  TYPE: "Darwin",
53
53
  ARCHITECTURE: "arm64",
54
54
  RUST_TARGET: "aarch64-apple-darwin",
55
55
  BINARY_NAME: `${name}-${version}`,
56
- RAW_NAME: `${name}`
56
+ RAW_NAME: `${name}`,
57
57
  },
58
58
  ];
59
59
 
@@ -68,7 +68,7 @@ const getPlatform = (type = os.type(), architecture = os.arch()) => {
68
68
  "Downloading musl binary that does not include `rover supergraph compose`.";
69
69
  if (libc.isNonGlibcLinuxSync()) {
70
70
  console.warn(
71
- "This operating system does not support dynamic linking to glibc."
71
+ "This operating system does not support dynamic linking to glibc.",
72
72
  );
73
73
  console.warn(musl_warning);
74
74
  supportedPlatform.RUST_TARGET = "x86_64-unknown-linux-musl";
@@ -84,7 +84,7 @@ const getPlatform = (type = os.type(), architecture = os.arch()) => {
84
84
  libc_minor_version < min_minor_version
85
85
  ) {
86
86
  console.warn(
87
- `This operating system needs glibc >= ${min_major_version}.${min_minor_version}, but only has ${libc_version} installed.`
87
+ `This operating system needs glibc >= ${min_major_version}.${min_minor_version}, but only has ${libc_version} installed.`,
88
88
  );
89
89
  console.warn(musl_warning);
90
90
  supportedPlatform.RUST_TARGET = "x86_64-unknown-linux-musl";
@@ -95,11 +95,61 @@ const getPlatform = (type = os.type(), architecture = os.arch()) => {
95
95
  }
96
96
  }
97
97
 
98
- error(
99
- `Platform with type "${type}" and architecture "${architecture}" is not supported by ${name}.\nYour system must be one of the following:\n\n${cTable.getTable(
100
- supportedPlatforms
101
- )}`
98
+ const stderr = new Console(process.stderr);
99
+ stderr.log(
100
+ `Platform with type "${type}" and architecture "${architecture}" is not supported by ${name}.`,
102
101
  );
102
+ stderr.table(supportedPlatforms);
103
+ process.exit(1);
104
+ };
105
+
106
+ /*! Copyright (c) 2022 Mitchell Alderson - MIT License */
107
+ const getProxyEnv = (requestURL) => {
108
+ const noProxy = process.env.NO_PROXY || process.env.no_proxy || "";
109
+
110
+ // if the noProxy is a wildcard then return null
111
+ if (noProxy === "*") {
112
+ return null;
113
+ }
114
+
115
+ // if the noProxy is not empty and the uri is found, return null
116
+ if (noProxy !== "" && urlInNoProxy(requestURL, noProxy)) {
117
+ return null;
118
+ }
119
+
120
+ // get proxy based on request url's protocol
121
+ if (requestURL.protocol == "http:") {
122
+ return process.env.HTTP_PROXY || process.env.http_proxy || null;
123
+ }
124
+
125
+ if (requestURL.protocol == "https:") {
126
+ return process.env.HTTPS_PROXY || process.env.https_proxy || null;
127
+ }
128
+
129
+ // not a supported protocol...
130
+ return null;
131
+ };
132
+
133
+ /*! Copyright (c) 2022 Mitchell Alderson - MIT License */
134
+ const urlInNoProxy = (requestURL, noProxy) => {
135
+ const port =
136
+ requestURL.port || (requestURL.protocol === "https:" ? "443" : "80");
137
+ const hostname = formatHostName(requestURL.hostname);
138
+ //testing: internal.example.com,internal2.example.com
139
+ const noProxyList = noProxy.split(",");
140
+
141
+ return noProxyList.map(parseNoProxyZone).some((noProxyZone) => {
142
+ const isMatchedAt = hostname.indexOf(noProxyZone.hostname);
143
+ const hostnameMatched =
144
+ isMatchedAt > -1 &&
145
+ isMatchedAt === hostname.length - noProxyZone.hostname.length;
146
+
147
+ if (noProxyZone.hasPort) {
148
+ return port === noProxyZone.port && hostnameMatched;
149
+ }
150
+
151
+ return hostnameMatched;
152
+ });
103
153
  };
104
154
 
105
155
  /*! Copyright (c) 2019 Avery Harnish - MIT License */
@@ -125,7 +175,7 @@ class Binary {
125
175
  if (errors.length > 0) {
126
176
  let errorMsg =
127
177
  "One or more of the parameters you passed to the Binary constructor are invalid:\n";
128
- errors.forEach(error => {
178
+ errors.forEach((error) => {
129
179
  errorMsg += error;
130
180
  });
131
181
  errorMsg +=
@@ -148,11 +198,11 @@ class Binary {
148
198
  return existsSync(this.binaryPath);
149
199
  }
150
200
 
151
- install(fetchOptions, suppressLogs = false) {
201
+ install(suppressLogs = false) {
152
202
  if (this.exists()) {
153
203
  if (!suppressLogs) {
154
204
  console.error(
155
- `${this.name} is already installed, skipping installation.`
205
+ `${this.name} is already installed, skipping installation.`,
156
206
  );
157
207
  }
158
208
  return Promise.resolve();
@@ -168,31 +218,43 @@ class Binary {
168
218
  console.error(`Downloading release from ${this.url}`);
169
219
  }
170
220
 
171
- return axios({ ...fetchOptions, url: this.url, responseType: "stream" })
172
- .then(res => {
221
+ const proxyUrl = getProxyEnv(this.url);
222
+
223
+ const agent = proxyUrl ? new ProxyAgent(proxyUrl) : null;
224
+ const fetchPromise = fetch(this.url, agent ? { dispatcher: agent } : {});
225
+
226
+ return fetchPromise
227
+ .then((res) => {
228
+ if (!res.ok) {
229
+ throw new Error(
230
+ `Failed to download binary: HTTP ${res.status} ${res.statusText}`,
231
+ );
232
+ }
173
233
  return new Promise((resolve, reject) => {
174
- const sink = res.data.pipe(
175
- tar.x({ strip: 1, C: this.installDirectory })
234
+ const sink = Readable.fromWeb(res.body).pipe(
235
+ tar.x({ strip: 1, C: this.installDirectory }),
176
236
  );
177
237
  sink.on("finish", () => resolve());
178
- sink.on("error", err => reject(err));
238
+ sink.on("error", (err) => reject(err));
179
239
  });
180
240
  })
181
241
  .then(() => {
182
- fs.renameSync(join(this.installDirectory, this.raw_name), this.binaryPath);
242
+ fs.renameSync(
243
+ join(this.installDirectory, this.raw_name),
244
+ this.binaryPath,
245
+ );
183
246
  if (!suppressLogs) {
184
247
  console.error(`${this.name} has been installed!`);
185
248
  }
186
249
  })
187
- .catch(e => {
250
+ .finally(() => agent && agent.close())
251
+ .catch((e) => {
188
252
  error(`Error fetching release: ${e.message}`);
189
253
  });
190
254
  }
191
255
 
192
- run(fetchOptions) {
193
- const promise = !this.exists()
194
- ? this.install(fetchOptions, true)
195
- : Promise.resolve();
256
+ run() {
257
+ const promise = !this.exists() ? this.install(true) : Promise.resolve();
196
258
 
197
259
  promise
198
260
  .then(() => {
@@ -208,7 +270,7 @@ class Binary {
208
270
 
209
271
  process.exit(result.status);
210
272
  })
211
- .catch(e => {
273
+ .catch((e) => {
212
274
  error(e.message);
213
275
  process.exit(1);
214
276
  });
@@ -216,17 +278,25 @@ class Binary {
216
278
  }
217
279
 
218
280
  const getBinary = (overrideInstallDirectory, platform = getPlatform()) => {
219
- const download_host = process.env.npm_config_apollo_rover_download_host || process.env.APOLLO_ROVER_DOWNLOAD_HOST || 'https://rover.apollo.dev'
281
+ const download_host =
282
+ process.env.npm_config_apollo_rover_download_host ||
283
+ process.env.APOLLO_ROVER_DOWNLOAD_HOST ||
284
+ "https://rover.apollo.dev";
220
285
  // the url for this binary is constructed from values in `package.json`
221
- // https://rover.apollo.dev/tar/rover/x86_64-unknown-linux-gnu/v0.4.8
286
+ // https://rover.apollo.dev/tar/rover/x86_64-unknown-linux-gnu/vx.x.x
222
287
  const url = `${download_host}/tar/${name}/${platform.RUST_TARGET}/v${version}`;
223
- const { dirname } = require('path');
288
+ const { dirname } = require("path");
224
289
  const appDir = dirname(require.main.filename);
225
290
  let installDirectory = join(appDir, "binary");
226
291
  if (overrideInstallDirectory != null && overrideInstallDirectory !== "") {
227
- installDirectory = overrideInstallDirectory
292
+ installDirectory = overrideInstallDirectory;
228
293
  }
229
- let binary = new Binary(platform.BINARY_NAME, platform.RAW_NAME, url, installDirectory);
294
+ let binary = new Binary(
295
+ platform.BINARY_NAME,
296
+ platform.RAW_NAME,
297
+ url,
298
+ installDirectory,
299
+ );
230
300
 
231
301
  // setting this allows us to extract supergraph plugins to the proper directory
232
302
  // the variable itself is read in Rust code
@@ -236,19 +306,18 @@ const getBinary = (overrideInstallDirectory, platform = getPlatform()) => {
236
306
 
237
307
  const install = (suppressLogs = false) => {
238
308
  const binary = getBinary();
239
- const proxy = configureProxy(binary.url);
240
309
  // these messages are duplicated in `src/command/install/mod.rs`
241
310
  // for the curl installer.
242
311
  if (!suppressLogs) {
243
312
  console.error(
244
- "If you would like to disable Rover's anonymized usage collection, you can set APOLLO_TELEMETRY_DISABLED=true"
313
+ "If you would like to disable Rover's anonymized usage collection, you can set APOLLO_TELEMETRY_DISABLED=true",
245
314
  );
246
315
  console.error(
247
- "You can check out our documentation at https://go.apollo.dev/r/docs."
316
+ "You can check out our documentation at https://go.apollo.dev/r/docs.",
248
317
  );
249
318
  }
250
319
 
251
- return binary.install(proxy, suppressLogs);
320
+ return binary.install(suppressLogs);
252
321
  };
253
322
 
254
323
  const run = () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apollo/rover",
3
- "version": "0.36.2",
3
+ "version": "0.38.0",
4
4
  "description": "The new Apollo CLI",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -13,7 +13,10 @@
13
13
  "fmt:check": "prettier --check **/*.js",
14
14
  "test": "jest"
15
15
  },
16
- "repository": "https://github.com/apollographql/rover",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/apollographql/rover.git"
19
+ },
17
20
  "keywords": [
18
21
  "rover",
19
22
  "graphql",
@@ -29,25 +32,17 @@
29
32
  "url": "https://github.com/apollographql/rover/issues"
30
33
  },
31
34
  "engines": {
32
- "node": ">=14",
33
- "npm": ">=6"
34
- },
35
- "volta": {
36
- "node": "20.19.5",
37
- "npm": "11.6.0"
35
+ "node": ">=22.14.0"
38
36
  },
39
37
  "homepage": "https://github.com/apollographql/rover#readme",
40
38
  "dependencies": {
41
- "axios": "^1.6.5",
42
- "axios-proxy-builder": "^0.1.1",
43
- "console.table": "^0.10.0",
44
- "detect-libc": "^2.0.0",
45
- "tar": "^7.0.0"
39
+ "detect-libc": "2.1.2",
40
+ "tar": "^7.0.0",
41
+ "undici": "^7.0.0"
46
42
  },
47
43
  "devDependencies": {
48
- "prettier": "3.6.2",
49
- "jest": "30.1.3",
50
- "axios-mock-adapter": "2.1.0",
51
- "jest-junit": "16.0.0"
44
+ "jest": "30.3.0",
45
+ "jest-junit": "16.0.0",
46
+ "prettier": "3.8.1"
52
47
  }
53
48
  }