neonctl 1.29.4 → 1.29.5

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/auth.js CHANGED
@@ -5,6 +5,8 @@ import { join } from 'node:path';
5
5
  import open from 'open';
6
6
  import { log } from './log.js';
7
7
  import { fileURLToPath } from 'node:url';
8
+ import { sendError } from './analytics.js';
9
+ import { matchErrorCode } from './errors.js';
8
10
  // oauth server timeouts
9
11
  const SERVER_TIMEOUT = 10000;
10
12
  // where to wait for incoming redirect request from oauth server to arrive
@@ -18,6 +20,7 @@ const NEONCTL_SCOPES = [
18
20
  'urn:neoncloud:projects:update',
19
21
  'urn:neoncloud:projects:delete',
20
22
  ];
23
+ const AUTH_TIMEOUT_SECONDS = 60;
21
24
  export const defaultClientID = 'neonctl';
22
25
  custom.setHttpOptionsDefaults({
23
26
  timeout: SERVER_TIMEOUT,
@@ -38,6 +41,7 @@ export const auth = async ({ oauthHost, clientId }) => {
38
41
  //
39
42
  // Start HTTP server and wait till /callback is hit
40
43
  //
44
+ log.debug('Starting HTTP Server for callback');
41
45
  const server = createServer();
42
46
  server.listen(0, '127.0.0.1', function () {
43
47
  log.debug(`Listening on port ${this.address().port}`);
@@ -55,7 +59,10 @@ export const auth = async ({ oauthHost, clientId }) => {
55
59
  // we store the code_verifier in memory
56
60
  const codeVerifier = generators.codeVerifier();
57
61
  const codeChallenge = generators.codeChallenge(codeVerifier);
58
- return new Promise((resolve) => {
62
+ return new Promise((resolve, reject) => {
63
+ const timer = setTimeout(() => {
64
+ reject(new Error(`Authentication timed out after ${AUTH_TIMEOUT_SECONDS} seconds`));
65
+ }, AUTH_TIMEOUT_SECONDS * 1000);
59
66
  server.on('request', async (request, response) => {
60
67
  //
61
68
  // Wait for callback and follow oauth flow.
@@ -83,6 +90,7 @@ export const auth = async ({ oauthHost, clientId }) => {
83
90
  });
84
91
  response.writeHead(200, { 'Content-Type': 'text/html' });
85
92
  createReadStream(join(fileURLToPath(new URL('.', import.meta.url)), './callback.html')).pipe(response);
93
+ clearTimeout(timer);
86
94
  resolve(tokenSet);
87
95
  server.close();
88
96
  });
@@ -96,6 +104,12 @@ export const auth = async ({ oauthHost, clientId }) => {
96
104
  code_challenge: codeChallenge,
97
105
  code_challenge_method: 'S256',
98
106
  });
99
- open(authUrl);
107
+ log.info('Awaiting authentication in web browser.');
108
+ log.info(`Auth Url: ${authUrl}`);
109
+ open(authUrl).catch((err) => {
110
+ const msg = `Failed to open web browser. Please copy & paste auth url to authenticate in browser.`;
111
+ sendError(err || new Error(msg), matchErrorCode(msg || err?.message));
112
+ log.error(msg || err?.message);
113
+ });
100
114
  });
101
115
  };
@@ -6,7 +6,7 @@ import { runMockServer } from '../test_utils/mock_server';
6
6
  jest.unstable_mockModule('open', () => ({
7
7
  __esModule: true,
8
8
  default: jest.fn((url) => {
9
- axios.get(url);
9
+ return axios.get(url);
10
10
  }),
11
11
  }));
12
12
  // "open" module should be imported after mocking
package/errors.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const ERROR_MATCHERS = [
2
2
  [/^Unknown command: (.*)$/, 'UNKNOWN_COMMAND'],
3
3
  [/^Missing required argument: (.*)$/, 'MISSING_ARGUMENT'],
4
+ [/^Failed to open web browser. (.*)$/, 'AUTH_BROWSER_FAILED'],
4
5
  ];
5
6
  export const matchErrorCode = (message) => {
6
7
  if (!message) {
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "url": "git+ssh://git@github.com/neondatabase/neonctl.git"
6
6
  },
7
7
  "type": "module",
8
- "version": "1.29.4",
8
+ "version": "1.29.5",
9
9
  "description": "CLI tool for NeonDB Cloud management",
10
10
  "main": "index.js",
11
11
  "author": "NeonDB",
@@ -60,8 +60,8 @@
60
60
  "chalk": "^5.2.0",
61
61
  "cli-table": "^0.3.11",
62
62
  "inquirer": "^9.2.6",
63
- "open": "^8.4.0",
64
- "openid-client": "^5.1.9",
63
+ "open": "^10.1.0",
64
+ "openid-client": "^5.6.5",
65
65
  "which": "^3.0.1",
66
66
  "yaml": "^2.1.1",
67
67
  "yargs": "^17.7.2"