opal-security 2.3.4 → 3.0.1-beta.4262451

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 (69) hide show
  1. package/README.md +67 -38
  2. package/lib/commands/aws/identity.d.ts +1 -1
  3. package/lib/commands/aws/identity.js +2 -2
  4. package/lib/commands/{migrate-creds.d.ts → clear-auth-provider.d.ts} +3 -2
  5. package/lib/commands/clear-auth-provider.js +28 -0
  6. package/lib/commands/curl-example.d.ts +1 -1
  7. package/lib/commands/curl-example.js +10 -3
  8. package/lib/commands/iam-roles/start.d.ts +1 -1
  9. package/lib/commands/iam-roles/start.js +14 -14
  10. package/lib/commands/kube-roles/start.d.ts +1 -1
  11. package/lib/commands/kube-roles/start.js +10 -10
  12. package/lib/commands/login.d.ts +2 -1
  13. package/lib/commands/login.js +134 -74
  14. package/lib/commands/logout.d.ts +1 -1
  15. package/lib/commands/logout.js +3 -3
  16. package/lib/commands/postgres-instances/start.d.ts +1 -1
  17. package/lib/commands/postgres-instances/start.js +35 -34
  18. package/lib/commands/resources/get.d.ts +1 -1
  19. package/lib/commands/resources/get.js +6 -4
  20. package/lib/commands/set-auth-provider.d.ts +11 -0
  21. package/lib/commands/set-auth-provider.js +44 -0
  22. package/lib/commands/set-custom-header.d.ts +1 -1
  23. package/lib/commands/set-custom-header.js +5 -3
  24. package/lib/commands/set-token.d.ts +1 -1
  25. package/lib/commands/set-token.js +26 -19
  26. package/lib/commands/set-url.d.ts +1 -1
  27. package/lib/commands/set-url.js +13 -12
  28. package/lib/commands/ssh/copyFrom.d.ts +1 -1
  29. package/lib/commands/ssh/copyFrom.js +13 -13
  30. package/lib/commands/ssh/copyTo.d.ts +1 -1
  31. package/lib/commands/ssh/copyTo.js +13 -13
  32. package/lib/commands/ssh/start.d.ts +1 -1
  33. package/lib/commands/ssh/start.js +14 -15
  34. package/lib/graphql/fragment-masking.d.ts +19 -0
  35. package/lib/graphql/fragment-masking.js +21 -0
  36. package/lib/graphql/gql.d.ts +36 -0
  37. package/lib/graphql/gql.js +12 -0
  38. package/lib/graphql/graphql.d.ts +11413 -0
  39. package/lib/graphql/graphql.js +1491 -0
  40. package/lib/graphql/index.d.ts +2 -0
  41. package/lib/graphql/index.js +5 -0
  42. package/lib/handler.d.ts +5 -5
  43. package/lib/handler.js +7 -7
  44. package/lib/index.d.ts +1 -1
  45. package/lib/lib/apollo.d.ts +4 -2
  46. package/lib/lib/apollo.js +107 -55
  47. package/lib/lib/aws.js +15 -12
  48. package/lib/lib/cmd.d.ts +4 -6
  49. package/lib/lib/cmd.js +11 -11
  50. package/lib/lib/config.js +14 -15
  51. package/lib/lib/credentials/index.d.ts +9 -4
  52. package/lib/lib/credentials/index.js +26 -15
  53. package/lib/lib/credentials/keychain.d.ts +3 -3
  54. package/lib/lib/credentials/keychain.js +12 -12
  55. package/lib/lib/credentials/localEncryption.d.ts +3 -3
  56. package/lib/lib/credentials/localEncryption.js +40 -31
  57. package/lib/lib/flags.js +9 -9
  58. package/lib/lib/resources.d.ts +2 -2
  59. package/lib/lib/resources.js +29 -23
  60. package/lib/lib/sessions.d.ts +2 -2
  61. package/lib/lib/sessions.js +18 -17
  62. package/lib/lib/ssh.d.ts +1 -1
  63. package/lib/lib/ssh.js +8 -8
  64. package/lib/lib/util.d.ts +0 -1
  65. package/lib/lib/util.js +13 -13
  66. package/lib/types.d.ts +1787 -1787
  67. package/oclif.manifest.json +56 -7
  68. package/package.json +23 -29
  69. package/lib/commands/migrate-creds.js +0 -48
@@ -0,0 +1,2 @@
1
+ export * from "./fragment-masking";
2
+ export * from "./gql";
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./fragment-masking"), exports);
5
+ tslib_1.__exportStar(require("./gql"), exports);
package/lib/handler.d.ts CHANGED
@@ -1,16 +1,16 @@
1
- import { Command } from '@oclif/core';
2
- import { OperationVariables, ApolloError } from '@apollo/client/core';
1
+ import type { ApolloError, OperationVariables } from "@apollo/client/core";
2
+ import type { Command } from "@oclif/core";
3
3
  interface QueryHandlerProps<TVar = Record<string, any>> {
4
4
  command: Command;
5
5
  query: string;
6
6
  variables?: TVar;
7
7
  }
8
8
  export declare const runMutation: ({ command, query, variables, }: QueryHandlerProps) => Promise<{
9
- resp: import("@apollo/client/core").FetchResult<any> | null;
9
+ resp: import("@apollo/client/core").FetchResult<any> | null | undefined;
10
10
  error: unknown;
11
11
  }>;
12
- export declare const runQuery: <TResponse = any, TVar extends OperationVariables = Record<string, any>>({ command, query, variables, }: QueryHandlerProps<TVar>) => Promise<{
13
- resp: import("@apollo/client/core").ApolloQueryResult<TResponse> | null;
12
+ export declare const runQueryDeprecated: <TResponse = any, TVar extends OperationVariables = Record<string, any>>({ command, query, variables, }: QueryHandlerProps<TVar>) => Promise<{
13
+ resp: import("@apollo/client/core").ApolloQueryResult<TResponse> | null | undefined;
14
14
  error: ApolloError;
15
15
  }>;
16
16
  export {};
package/lib/handler.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.runQuery = exports.runMutation = void 0;
3
+ exports.runQueryDeprecated = exports.runMutation = void 0;
4
4
  const graphql_tag_1 = require("graphql-tag");
5
5
  const apollo_1 = require("./lib/apollo");
6
6
  const runMutation = async ({ command, query, variables, }) => {
@@ -8,12 +8,12 @@ const runMutation = async ({ command, query, variables, }) => {
8
8
  let mutationResp = null;
9
9
  let mutationError = null;
10
10
  try {
11
- mutationResp = await apollo_1.client.mutate({
11
+ mutationResp = await (apollo_1.client === null || apollo_1.client === void 0 ? void 0 : apollo_1.client.mutate({
12
12
  mutation: (0, graphql_tag_1.default) `
13
13
  ${query}
14
14
  `,
15
15
  variables: variables,
16
- });
16
+ }));
17
17
  }
18
18
  catch (error) {
19
19
  mutationError = error;
@@ -21,21 +21,21 @@ const runMutation = async ({ command, query, variables, }) => {
21
21
  return { resp: mutationResp, error: mutationError };
22
22
  };
23
23
  exports.runMutation = runMutation;
24
- const runQuery = async ({ command, query, variables, }) => {
24
+ const runQueryDeprecated = async ({ command, query, variables, }) => {
25
25
  await (0, apollo_1.initClient)(command);
26
26
  let queryResp = null;
27
27
  let queryError = null;
28
28
  try {
29
- queryResp = await apollo_1.client.query({
29
+ queryResp = await (apollo_1.client === null || apollo_1.client === void 0 ? void 0 : apollo_1.client.query({
30
30
  query: (0, graphql_tag_1.default) `
31
31
  ${query}
32
32
  `,
33
33
  variables: variables,
34
- });
34
+ }));
35
35
  }
36
36
  catch (error) {
37
37
  queryError = error;
38
38
  }
39
39
  return { resp: queryResp, error: queryError };
40
40
  };
41
- exports.runQuery = runQuery;
41
+ exports.runQueryDeprecated = runQueryDeprecated;
package/lib/index.d.ts CHANGED
@@ -1 +1 @@
1
- export { run } from '@oclif/core';
1
+ export { run } from "@oclif/core";
@@ -1,6 +1,8 @@
1
- import { ApolloClient, NormalizedCacheObject } from '@apollo/client/core';
2
- import { Command } from '@oclif/core';
1
+ import { ApolloClient, type NormalizedCacheObject } from "@apollo/client/core";
2
+ import type { Command } from "@oclif/core";
3
3
  export declare let client: ApolloClient<NormalizedCacheObject> | null;
4
+ export declare let cookieStr: string;
4
5
  export declare const printResponse: (command: Command, resp: any) => void;
5
6
  export declare const handleError: (command: Command, err: any, resp?: any) => void;
6
7
  export declare const initClient: (command: Command, fetchAccessToken?: boolean) => Promise<void>;
8
+ export declare function getClient(command: Command, fetchAccessToken?: boolean): Promise<ApolloClient<NormalizedCacheObject>>;
package/lib/lib/apollo.js CHANGED
@@ -1,25 +1,32 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.initClient = exports.handleError = exports.printResponse = exports.client = void 0;
3
+ exports.initClient = exports.handleError = exports.printResponse = exports.cookieStr = exports.client = void 0;
4
+ exports.getClient = getClient;
4
5
  const core_1 = require("@apollo/client/core");
5
6
  const context_1 = require("@apollo/client/link/context");
6
7
  const error_1 = require("@apollo/client/link/error");
7
- const prettyjson_1 = require("prettyjson");
8
- const semver_1 = require("semver");
9
8
  const chalk_1 = require("chalk");
10
9
  const moment = require("moment");
11
- const config_1 = require("../lib/config");
12
- const credentials_1 = require("../lib/credentials");
10
+ const prettyjson_1 = require("prettyjson");
11
+ const semver_1 = require("semver");
12
+ const globals_1 = require("@apollo/client/utilities/globals");
13
13
  const login_1 = require("../commands/login");
14
14
  const cmd_1 = require("../lib/cmd");
15
- const fetch = require('node-fetch');
16
- const https = require('https');
17
- const http = require('http');
15
+ const config_1 = require("../lib/config");
16
+ const credentials_1 = require("../lib/credentials");
17
+ const fetch = require("node-fetch");
18
+ const https = require("node:https");
19
+ const http = require("node:http");
20
+ // DO NOT USE DIRECTLY, use getClient instead
18
21
  exports.client = null;
19
- let alreadyNotifiedRecommendedVersion = false;
22
+ // This is used to keep track of the auth-session cookie during login, before we can persist it into the credential store
23
+ exports.cookieStr = "";
24
+ let alreadyWarnedAboutVersion = false;
20
25
  const printResponse = (command, resp) => {
21
26
  const filteredJson = JSON.parse(JSON.stringify(resp.data, (k, v) => {
22
- if (k === '__typename' || v === null || (Array.isArray(v) && v.length === 0)) {
27
+ if (k === "__typename" ||
28
+ v === null ||
29
+ (Array.isArray(v) && v.length === 0)) {
23
30
  return undefined;
24
31
  }
25
32
  return v;
@@ -28,27 +35,32 @@ const printResponse = (command, resp) => {
28
35
  };
29
36
  exports.printResponse = printResponse;
30
37
  const handleError = (command, err, resp) => {
31
- if (err && typeof err === 'object' && ('networkError' in err && 'statusCode' in err.networkError)) {
38
+ if (err &&
39
+ typeof err === "object" &&
40
+ "networkError" in err &&
41
+ "statusCode" in err.networkError) {
32
42
  // Status code errors are already handled in the global Apollo handler, so we can just return here.
33
43
  return;
34
44
  }
35
45
  let errorMsg;
36
46
  if (!err) {
37
- errorMsg = 'Unexpected response from server (see below). Please contact Opal support if this issue persists.';
47
+ errorMsg =
48
+ "Unexpected response from server (see below). Please contact Opal support if this issue persists.";
38
49
  }
39
- else if (typeof err === 'object' && err.toString().includes('self signed certificate')) {
40
- errorMsg = 'Request failed due to a self-signed certificate appearing in the certificate chain. Try setting your CLI to allow self-signed certs by running: "opal set-url --custom INSERT_URL_HERE --allowSelfSignedCerts"';
50
+ else if (typeof err === "object" &&
51
+ err.toString().includes("self signed certificate")) {
52
+ errorMsg =
53
+ 'Request failed due to a self-signed certificate appearing in the certificate chain. Try setting your CLI to allow self-signed certs by running: "opal set-url --custom INSERT_URL_HERE --allowSelfSignedCerts"';
41
54
  }
42
55
  else {
43
56
  errorMsg = `Error: ${err}`;
44
57
  }
45
- errorMsg = '❗ ' + errorMsg;
58
+ errorMsg = `❗ ${errorMsg}`;
46
59
  command.log(errorMsg);
47
60
  if (resp) {
48
61
  (0, exports.printResponse)(command, resp);
49
62
  }
50
63
  // OPAL-6579: Use process.exit to avoid UnhandledPromiseRejectionWarning
51
- // eslint-disable-next-line no-process-exit,unicorn/no-process-exit
52
64
  process.exit(1);
53
65
  };
54
66
  exports.handleError = handleError;
@@ -57,7 +69,6 @@ const initClient = async (command, fetchAccessToken = true) => {
57
69
  const currentCLIVersion = command.config.version;
58
70
  const configData = (0, config_1.getOrCreateConfigData)(configDir);
59
71
  const opalCreds = await (0, credentials_1.getOpalCredentials)(command, fetchAccessToken);
60
- const accessToken = opalCreds === null || opalCreds === void 0 ? void 0 : opalCreds.accessToken;
61
72
  const organizationID = opalCreds === null || opalCreds === void 0 ? void 0 : opalCreds.organizationID;
62
73
  const httpsAgent = new https.Agent({
63
74
  rejectUnauthorized: !configData[config_1.allowSelfSignedCertsKey],
@@ -65,22 +76,26 @@ const initClient = async (command, fetchAccessToken = true) => {
65
76
  const httpAgent = new http.Agent({});
66
77
  const specifiedUrl = configData[config_1.urlKey];
67
78
  const customHeader = configData[config_1.customHttpHeaderKey];
68
- const customHeaderKey = customHeader === undefined ?
69
- '' :
70
- customHeader.split(':')[0];
71
- const customHeaderValue = customHeader === undefined ?
72
- '' :
73
- customHeader.split(':')[1];
74
- const agent = specifiedUrl.includes('https') ? httpsAgent : httpAgent;
79
+ const customHeaderKey = customHeader === undefined ? "" : customHeader.split(":")[0];
80
+ const customHeaderValue = customHeader === undefined ? "" : customHeader.split(":")[1];
81
+ const agent = specifiedUrl.includes("https") ? httpsAgent : httpAgent;
75
82
  const httpLink = (0, core_1.createHttpLink)({
76
83
  uri: `${specifiedUrl}/query`,
84
+ credentials: "include",
77
85
  fetch,
78
86
  fetchOptions: {
79
87
  agent: agent,
88
+ credentials: "include",
80
89
  },
81
90
  });
82
91
  const authLink = (0, context_1.setContext)((_, { headers }) => {
83
- const baseHeaders = Object.assign(Object.assign({}, headers), { authorization: `Bearer ${accessToken}`, 'X-Opal-Organization-ID': organizationID, 'X-Opal-Cli-Version': currentCLIVersion });
92
+ const baseHeaders = Object.assign(Object.assign({}, headers), { "User-Agent": `Opal CLI v${currentCLIVersion}`, "X-Opal-Organization-ID": organizationID, "X-Opal-Cli-Version": currentCLIVersion });
93
+ if (opalCreds.secretType === credentials_1.SecretType.ApiToken) {
94
+ baseHeaders.authorization = `Bearer ${opalCreds.secret}`;
95
+ }
96
+ else if (!!opalCreds.secret || !!exports.cookieStr) {
97
+ baseHeaders.cookie = opalCreds.secret || exports.cookieStr;
98
+ }
84
99
  if (customHeaderKey) {
85
100
  return {
86
101
  headers: Object.assign(Object.assign({}, baseHeaders), { [customHeaderKey]: customHeaderValue }),
@@ -90,58 +105,75 @@ const initClient = async (command, fetchAccessToken = true) => {
90
105
  headers: Object.assign({}, baseHeaders),
91
106
  };
92
107
  });
108
+ /**
109
+ * How this check actually works:
110
+ * - no hard fails throughout, just warns
111
+ * - Looks for an 'expected CLI major version' header from the backend, and:
112
+ * - if CLI version is < that, warns you need to upgrade CLI
113
+ * - if CLI version is > that, warns you need to upgrade Opal
114
+ * - also, if there's a 'recommended version' header and CLI version is less, just suggests that you upgrade your CLI
115
+ * - note the backend does not currently send this header)
116
+ */
93
117
  const checkCLIVersion = (operation) => {
94
118
  var _a;
95
119
  const headers = (_a = operation.getContext().response) === null || _a === void 0 ? void 0 : _a.headers;
96
- if (headers) {
97
- const expectedCLIMajorVersion = headers.get('Opal-CLI-Expected-Major-Version');
98
- if (expectedCLIMajorVersion) {
120
+ if (!alreadyWarnedAboutVersion && headers) {
121
+ // we expect these versions to be a single number - a major version
122
+ const expectedCLIMajorVersion = headers.get("Opal-CLI-Expected-Major-Version");
123
+ if (expectedCLIMajorVersion === null || expectedCLIMajorVersion === void 0 ? void 0 : expectedCLIMajorVersion.match(/^\d+$/)) {
99
124
  const semverExpectedMinCLIVersion = `${expectedCLIMajorVersion}.0.0`;
100
125
  if ((0, semver_1.major)(currentCLIVersion) < (0, semver_1.major)(semverExpectedMinCLIVersion)) {
101
- command.warn(chalk_1.default.yellow(`
102
- ❗️ Your CLI is outdated and is incompatible with your Opal server.
126
+ command.log(chalk_1.default.yellow(`
127
+ Your CLI is outdated and is incompatible with your Opal server.
103
128
  Expected major version ${chalk_1.default.blueBright(semverExpectedMinCLIVersion)}, but version ${chalk_1.default.blueBright(currentCLIVersion)} is installed.
104
- Upgrade using the following command: ${chalk_1.default.blueBright('brew upgrade opalsecurity/brew/opal-security')}\n`));
129
+ Upgrade using the following command: ${chalk_1.default.blueBright("brew upgrade opalsecurity/brew/opal-security")}\n`));
130
+ alreadyWarnedAboutVersion = true;
105
131
  }
106
132
  else if ((0, semver_1.major)(currentCLIVersion) > (0, semver_1.major)(semverExpectedMinCLIVersion)) {
107
- command.warn(chalk_1.default.yellow(`
108
- ❗️ Uh oh! The currently installed Opal server is outdated. Please contact your Opal admins to let them know they need to upgrade their deployment.\n`));
133
+ command.log(chalk_1.default.yellow(`
134
+ Uh oh! The currently installed Opal server is outdated. Please contact your Opal admins to let them know they need to upgrade their deployment.\n`));
135
+ alreadyWarnedAboutVersion = true;
109
136
  }
110
137
  }
111
- if (!alreadyNotifiedRecommendedVersion) {
112
- const recommendedCLIMinorVersion = headers.get('Opal-CLI-Recommended-Version');
113
- if (recommendedCLIMinorVersion && (0, semver_1.compare)(currentCLIVersion, recommendedCLIMinorVersion) < 0) {
138
+ const recommendedCLIMajorVersion = headers.get("Opal-CLI-Recommended-Version");
139
+ if (recommendedCLIMajorVersion === null || recommendedCLIMajorVersion === void 0 ? void 0 : recommendedCLIMajorVersion.match(/^\d+$/)) {
140
+ const recommendedSemverString = `${recommendedCLIMajorVersion}.0.0`;
141
+ if (recommendedSemverString &&
142
+ (0, semver_1.major)(currentCLIVersion) < (0, semver_1.major)(recommendedSemverString)) {
114
143
  command.log(chalk_1.default.yellow(`
115
- ❗️ Opal recommends that you upgrade your CLI.
116
- Recommended version >=${chalk_1.default.blueBright(recommendedCLIMinorVersion)}, but version ${chalk_1.default.blueBright(currentCLIVersion)} is installed.
117
- Upgrade using the following command: ${chalk_1.default.blueBright('brew upgrade opalsecurity/brew/opal-security')}\n`));
144
+ Opal recommends that you upgrade your CLI.
145
+ Recommended version >=${chalk_1.default.blueBright(recommendedSemverString)}, but version ${chalk_1.default.blueBright(currentCLIVersion)} is installed.
146
+ Upgrade using the following command: ${chalk_1.default.blueBright("brew upgrade opalsecurity/brew/opal-security")}\n`));
118
147
  }
119
- alreadyNotifiedRecommendedVersion = true;
148
+ alreadyWarnedAboutVersion = true;
120
149
  }
121
150
  }
122
151
  };
123
152
  const checkCLIVersionLink = new core_1.ApolloLink((operation, forward) => {
124
- return forward(operation).map(response => {
153
+ return forward(operation).map((response) => {
125
154
  checkCLIVersion(operation);
126
155
  return response;
127
156
  });
128
157
  });
129
158
  const errorLink = (0, error_1.onError)(({ networkError, operation }) => {
130
159
  var _a;
131
- if (operation.operationName === login_1.CLIAuthSessionCheckName) {
132
- // These operations are triggered after the user just called `opal login` or `opal set-token`,
133
- // so we have special handling if they fail and we don't want to trigger an automatic redirect
134
- // to the login screen again.
135
- return;
136
- }
137
- if (operation.operationName === login_1.CLISignInMethodName) {
138
- // We have special handling for this operation due to the fact that the backend version
160
+ // There's a few GQL operations where we don't want to use this error handler:
161
+ const customErrorOperations = [
162
+ // This is triggered just after the user called `opal login` or `opal set-token`, and has
163
+ // special handling if they fail, so we don't trigger an automatic re-login
164
+ login_1.CLIAuthSessionCheckName,
165
+ // This has special error handling to fall back to an older auth method that uses the OAuth access token
166
+ login_1.CLITokenExchangeName,
167
+ // This has special error handling due to the fact that the backend version
139
168
  // can be out of date and not include the new cliClientId field.
169
+ login_1.CLISignInMethodName,
170
+ ];
171
+ if (customErrorOperations.includes(operation.operationName)) {
140
172
  return;
141
173
  }
142
- if (networkError && 'statusCode' in networkError) {
174
+ if (networkError && "statusCode" in networkError) {
143
175
  let errorMessage = null;
144
- if ('result' in networkError) {
176
+ if ("result" in networkError) {
145
177
  const result = networkError.result;
146
178
  // result is now of type string | Record<string, any>
147
179
  if (typeof result === "string")
@@ -152,12 +184,13 @@ const initClient = async (command, fetchAccessToken = true) => {
152
184
  }
153
185
  switch (networkError.statusCode) {
154
186
  case 401: {
155
- command.log('Your session is invalid or expired. Authenticating now...\n');
187
+ command.log("Your session is invalid or expired. Authenticating now...\n");
156
188
  const loginCommand = new login_1.default([], command.config);
157
189
  loginCommand.run().then(() => {
158
190
  if (cmd_1.mostRecentCommandTime && cmd_1.mostRecentCommand) {
159
- const lastCommandReexecutionDuration = moment.duration(2, 'minutes');
160
- const lastCommandReexecutionDurationHasElapsed = cmd_1.mostRecentCommandTime.add(lastCommandReexecutionDuration) > moment(new Date());
191
+ const lastCommandReexecutionDuration = moment.duration(2, "minutes");
192
+ const lastCommandReexecutionDurationHasElapsed = cmd_1.mostRecentCommandTime.add(lastCommandReexecutionDuration) >
193
+ moment(new Date());
161
194
  if (lastCommandReexecutionDurationHasElapsed) {
162
195
  cmd_1.mostRecentCommand.run();
163
196
  }
@@ -166,16 +199,35 @@ const initClient = async (command, fetchAccessToken = true) => {
166
199
  break;
167
200
  }
168
201
  default:
169
- return (0, exports.handleError)(command, `Received status code ${networkError.statusCode} from server${errorMessage ? ` with message "${errorMessage}"` : ''}`);
202
+ return (0, exports.handleError)(command, `Received status code ${networkError.statusCode} from server${errorMessage ? ` with message "${errorMessage}"` : ""}`);
170
203
  }
171
204
  }
172
205
  });
206
+ // Parses our auth-session cookie out of the Set-Cookie response header, saving it locally so we can use it for future requests
207
+ const preserveCookiesLink = new core_1.ApolloLink((operation, forward) => {
208
+ return forward(operation).map((response) => {
209
+ var _a, _b, _c, _d;
210
+ const cookieHeaderStr = (_c = (_b = (_a = operation.getContext().response) === null || _a === void 0 ? void 0 : _a.headers) === null || _b === void 0 ? void 0 : _b.get("Set-Cookie")) !== null && _c !== void 0 ? _c : "";
211
+ const authSessionCookie = (_d = cookieHeaderStr.match(/auth-session=[^;]+;/)) === null || _d === void 0 ? void 0 : _d[0];
212
+ if (authSessionCookie) {
213
+ exports.cookieStr = authSessionCookie;
214
+ }
215
+ return response;
216
+ });
217
+ });
173
218
  let link = authLink.concat(httpLink);
174
219
  link = checkCLIVersionLink.concat(link);
220
+ link = preserveCookiesLink.concat(link);
175
221
  link = errorLink.concat(link);
176
222
  exports.client = new core_1.ApolloClient({
177
223
  link: link,
224
+ credentials: "include",
178
225
  cache: new core_1.InMemoryCache(),
179
226
  });
180
227
  };
181
228
  exports.initClient = initClient;
229
+ async function getClient(command, fetchAccessToken = true) {
230
+ await (0, exports.initClient)(command, fetchAccessToken);
231
+ (0, globals_1.invariant)(exports.client, "Failed to initialize Opal Client");
232
+ return exports.client;
233
+ }
package/lib/lib/aws.js CHANGED
@@ -1,20 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getAwsEnvVarMessage = exports.getAwsConfigUpdateCmd = void 0;
4
- const opalProfileKey = 'opal';
4
+ const opalProfileKey = "opal";
5
5
  const sanitize = (str) => {
6
6
  // Remove non standard characters.
7
7
  // Note: AWS supports profile names containing alphanumeric characters, symbols, and white spaces
8
8
  // from the ASCII character set.
9
- let sanitizedStr = str.replace(/[^A-Za-z0-9-_ ]/g, '');
9
+ let sanitizedStr = str.replace(/[^A-Za-z0-9-_ ]/g, "");
10
10
  // De-dupe spaces
11
- sanitizedStr = sanitizedStr.replace(/\s+/g, ' ');
11
+ sanitizedStr = sanitizedStr.replace(/\s+/g, " ");
12
12
  // Map remaining spaces to '-'
13
- sanitizedStr = sanitizedStr.replace(/ /g, '-');
13
+ sanitizedStr = sanitizedStr.replace(/ /g, "-");
14
14
  return sanitizedStr;
15
15
  };
16
16
  const getAwsConfigUpdateCmd = (itemName, awsAccessKeyId, awsSecretAccessKey, awsSessionToken) => {
17
- let updateProfilesCmd = '';
17
+ let updateProfilesCmd = "";
18
18
  const sanitizedProfileName = sanitize(itemName);
19
19
  const profileNames = [opalProfileKey, sanitizedProfileName];
20
20
  profileNames.forEach((profileName, i) => {
@@ -25,25 +25,28 @@ const getAwsConfigUpdateCmd = (itemName, awsAccessKeyId, awsSecretAccessKey, aws
25
25
  const cmd = `${updateAccessKeyCmd} && ${updateAccessSecretCmd} && ${updateSessionTokenCmd}`;
26
26
  updateProfilesCmd += cmd;
27
27
  if (i !== profileNames.length - 1) {
28
- updateProfilesCmd += '&& ';
28
+ updateProfilesCmd += "&& ";
29
29
  }
30
30
  });
31
31
  return updateProfilesCmd;
32
32
  };
33
33
  exports.getAwsConfigUpdateCmd = getAwsConfigUpdateCmd;
34
34
  const getAwsEnvVarMessage = () => {
35
- if (!process.env.AWS_DEFAULT_PROFILE || process.env.AWS_DEFAULT_PROFILE !== opalProfileKey) {
36
- let envVarPhrase = '';
35
+ if (!process.env.AWS_DEFAULT_PROFILE ||
36
+ process.env.AWS_DEFAULT_PROFILE !== opalProfileKey) {
37
+ let envVarPhrase = "";
37
38
  if (!process.env.AWS_DEFAULT_PROFILE) {
38
- envVarPhrase = 'unset';
39
+ envVarPhrase = "unset";
39
40
  }
40
41
  else if (process.env.AWS_DEFAULT_PROFILE !== opalProfileKey) {
41
42
  envVarPhrase = `set to "${process.env.AWS_DEFAULT_PROFILE}"`;
42
43
  }
43
- return '\n\n💡 Did you know you can set your AWS_DEFAULT_PROFILE environment ' +
44
+ return (
45
+ // biome-ignore lint/style/useTemplate: it's more readable if split across lines
46
+ "\n\n💡 Did you know you can set your AWS_DEFAULT_PROFILE environment " +
44
47
  `variable to "${opalProfileKey}" to avoid explicitly specifying profile in each command? ` +
45
- `Currently, this variable is ${envVarPhrase}.`;
48
+ `Currently, this variable is ${envVarPhrase}.`);
46
49
  }
47
- return '';
50
+ return "";
48
51
  };
49
52
  exports.getAwsEnvVarMessage = getAwsEnvVarMessage;
package/lib/lib/cmd.d.ts CHANGED
@@ -1,12 +1,10 @@
1
- /// <reference types="node" />
2
- /// <reference types="node" />
3
- import { ExecException } from 'child_process';
4
- import { Command } from '@oclif/core';
5
- import * as moment from 'moment';
1
+ import type { ExecException } from "node:child_process";
2
+ import type { Command } from "@oclif/core";
3
+ import * as moment from "moment";
6
4
  export declare let mostRecentCommand: Command | null;
7
5
  export declare let mostRecentCommandTime: moment.Moment | null;
8
6
  export declare const setMostRecentCommand: (cmd: Command) => void;
9
7
  export declare const startInteractiveShell: (runCmd: string, shellName?: string) => void;
10
8
  export declare const runCommandExec: (runCmd: string, successMessage: string, errorMessage: string, envVars?: Record<string, any>) => void;
11
- export declare const runCommandExecWithCallback: (cmd: string, callback?: ((error: ExecException | null, stdout: Buffer, stderr: Buffer) => void) | undefined) => Promise<unknown>;
9
+ export declare const runCommandExecWithCallback: (cmd: string, callback?: (error: ExecException | null, stdout: Buffer, stderr: Buffer) => void) => Promise<unknown>;
12
10
  export declare const runCommandSpawn: (runCmd: string, successMessage: string, errorMessage: string, envVars?: Record<string, any>) => void;
package/lib/lib/cmd.js CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.runCommandSpawn = exports.runCommandExecWithCallback = exports.runCommandExec = exports.startInteractiveShell = exports.setMostRecentCommand = exports.mostRecentCommandTime = exports.mostRecentCommand = void 0;
4
4
  const _ = require("lodash");
5
5
  const moment = require("moment");
6
- const { exec, spawn } = require('child_process');
6
+ const { exec, spawn } = require("node:child_process");
7
7
  exports.mostRecentCommand = null;
8
8
  exports.mostRecentCommandTime = null;
9
9
  const setMostRecentCommand = (cmd) => {
@@ -14,10 +14,10 @@ exports.setMostRecentCommand = setMostRecentCommand;
14
14
  const startInteractiveShell = (runCmd, shellName) => {
15
15
  const shell = spawn(`${runCmd}`, [], {
16
16
  env: Object.assign(Object.assign({}, process.env), { SCRIPT_PATH: __dirname }),
17
- stdio: 'inherit',
17
+ stdio: "inherit",
18
18
  shell: true,
19
19
  });
20
- shell.on('close', (code) => {
20
+ shell.on("close", (code) => {
21
21
  if (shellName) {
22
22
  if (code === 0) {
23
23
  console.log(`The previously launched ${shellName} has successfully terminated.`);
@@ -30,10 +30,10 @@ const startInteractiveShell = (runCmd, shellName) => {
30
30
  console.log(`❗ Error: shell terminated with code ${code}.`);
31
31
  }
32
32
  });
33
- process.on('SIGINT', () => {
33
+ process.on("SIGINT", () => {
34
34
  // intercepting SIGINT
35
35
  });
36
- process.on('SIGTSTP', () => {
36
+ process.on("SIGTSTP", () => {
37
37
  // intercepting SIGTSTP
38
38
  });
39
39
  };
@@ -42,7 +42,7 @@ const runCommandExec = (runCmd, successMessage, errorMessage, envVars) => {
42
42
  const envVarsToUse = envVars || {};
43
43
  exec(`${runCmd}`, {
44
44
  env: Object.assign(Object.assign(Object.assign({}, process.env), { SCRIPT_PATH: __dirname }), envVarsToUse),
45
- }, function (error, stdOut, stdErr) {
45
+ }, (error, stdOut, stdErr) => {
46
46
  if (error) {
47
47
  console.log(`\n❗ Error: ${_.upperFirst(errorMessage)}`);
48
48
  }
@@ -59,9 +59,9 @@ const runCommandExec = (runCmd, successMessage, errorMessage, envVars) => {
59
59
  };
60
60
  exports.runCommandExec = runCommandExec;
61
61
  const runCommandExecWithCallback = (cmd, callback) => {
62
- return new Promise(resolve => {
63
- exec(cmd, function (error, stdOut, stdErr) {
64
- callback && callback(error, stdOut, stdErr);
62
+ return new Promise((resolve) => {
63
+ exec(cmd, (error, stdOut, stdErr) => {
64
+ callback === null || callback === void 0 ? void 0 : callback(error, stdOut, stdErr);
65
65
  resolve(stdOut);
66
66
  });
67
67
  });
@@ -71,10 +71,10 @@ const runCommandSpawn = (runCmd, successMessage, errorMessage, envVars) => {
71
71
  const envVarsToUse = envVars || {};
72
72
  const shell = spawn(`${runCmd}`, [], {
73
73
  env: Object.assign(Object.assign(Object.assign({}, process.env), { SCRIPT_PATH: __dirname }), envVarsToUse),
74
- stdio: 'inherit',
74
+ stdio: "inherit",
75
75
  shell: true,
76
76
  });
77
- shell.on('close', (code) => {
77
+ shell.on("close", (code) => {
78
78
  if (code === 0) {
79
79
  console.log(`🎉 Success! ${_.upperFirst(successMessage)}`);
80
80
  }
package/lib/lib/config.js CHANGED
@@ -1,18 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isProduction = exports.writeConfigData = exports.getOrCreateConfigData = exports.customHttpHeaderKey = exports.defaultAllowSelfSignedCerts = exports.allowSelfSignedCertsKey = exports.defaultUrl = exports.urlKey = void 0;
4
- const fs = require("fs");
5
- const path = require("path");
6
- exports.urlKey = 'url';
7
- exports.defaultUrl = 'https://app.opal.dev';
8
- exports.allowSelfSignedCertsKey = 'allowSelfSignedCerts';
4
+ const fs = require("node:fs");
5
+ const path = require("node:path");
6
+ exports.urlKey = "url";
7
+ exports.defaultUrl = "https://app.opal.dev";
8
+ exports.allowSelfSignedCertsKey = "allowSelfSignedCerts";
9
9
  exports.defaultAllowSelfSignedCerts = false;
10
- exports.customHttpHeaderKey = 'customHttpHeader';
10
+ exports.customHttpHeaderKey = "customHttpHeader";
11
11
  const getOrCreateConfigData = (configDir) => {
12
12
  if (!fs.existsSync(configDir)) {
13
13
  fs.mkdirSync(configDir, { recursive: true });
14
14
  }
15
- const configFilePath = path.join(configDir, 'config.json');
15
+ const configFilePath = path.join(configDir, "config.json");
16
16
  if (!fs.existsSync(configFilePath)) {
17
17
  fs.writeFileSync(configFilePath, JSON.stringify({
18
18
  [exports.urlKey]: exports.defaultUrl,
@@ -22,10 +22,10 @@ const getOrCreateConfigData = (configDir) => {
22
22
  let configData = {};
23
23
  try {
24
24
  const configDataRaw = fs.readFileSync(configFilePath);
25
- configData = JSON.parse(configDataRaw.toString());
25
+ configData = JSON.parse(configDataRaw === null || configDataRaw === void 0 ? void 0 : configDataRaw.toString());
26
26
  }
27
27
  catch (error) {
28
- if (error.code !== 'ENOENT') {
28
+ if (error.code !== "ENOENT") {
29
29
  throw error;
30
30
  }
31
31
  }
@@ -37,7 +37,7 @@ const writeConfigData = (configDir, newConfigData) => {
37
37
  for (const [key, value] of Object.entries(newConfigData)) {
38
38
  existingData[key] = value;
39
39
  }
40
- const configFilePath = path.join(configDir, 'config.json');
40
+ const configFilePath = path.join(configDir, "config.json");
41
41
  fs.writeFileSync(configFilePath, JSON.stringify(existingData), {
42
42
  mode: 0o0600,
43
43
  });
@@ -46,10 +46,9 @@ exports.writeConfigData = writeConfigData;
46
46
  const isProduction = (configDir) => {
47
47
  const configData = (0, exports.getOrCreateConfigData)(configDir);
48
48
  // Custom URLs are considered production since it includes on-prem
49
- return configData[exports.urlKey] !== 'https://dev.opal.dev' &&
50
- configData[exports.urlKey] !== 'http://localhost:3000' &&
51
- configData[exports.urlKey] !== 'http://localhost:4000' &&
52
- configData[exports.urlKey] !== 'https://demo.opal.dev' &&
53
- configData[exports.urlKey] !== 'https://staging.opal.dev';
49
+ return (configData[exports.urlKey] !== "https://dev.opal.dev" &&
50
+ configData[exports.urlKey] !== "https://demo.opal.dev" &&
51
+ configData[exports.urlKey] !== "https://staging.opal.dev" &&
52
+ !configData[exports.urlKey].match(/https?:\/\/localhost/));
54
53
  };
55
54
  exports.isProduction = isProduction;
@@ -1,11 +1,16 @@
1
- import { Command } from '@oclif/core';
1
+ import type { Command } from "@oclif/core";
2
2
  interface OpalCredentials {
3
3
  email?: string;
4
4
  organizationID?: string;
5
5
  clientIDCandidate?: string;
6
- accessToken?: string;
6
+ secret?: string;
7
+ secretType?: SecretType;
7
8
  }
8
- export declare const setOpalCredentials: (command: Command, email: string | undefined, organizationID: string, clientIDCandidate: string | undefined | null, accessToken: string) => Promise<void>;
9
- export declare const getOpalCredentials: (command: Command, includeAccessToken?: boolean) => Promise<OpalCredentials>;
9
+ export declare enum SecretType {
10
+ Cookie = "COOKIE",
11
+ ApiToken = "API_TOKEN"
12
+ }
13
+ export declare const setOpalCredentials: (command: Command, email: string | undefined, organizationID: string, clientIDCandidate: string | undefined | null, secret: string, secretType: SecretType) => Promise<void>;
14
+ export declare const getOpalCredentials: (command: Command, includeAuthSecret?: boolean) => Promise<OpalCredentials>;
10
15
  export declare const removeOpalCredentials: (command: Command) => Promise<void>;
11
16
  export {};