@knocklabs/cli 0.1.23 → 0.2.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/bin/dev.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node_modules/.bin/ts-node
2
2
  // eslint-disable-next-line node/shebang, unicorn/prefer-top-level-await
3
- ;(async () => {
4
- const oclif = await import('@oclif/core')
5
- await oclif.execute({development: true, dir: __dirname})
6
- })()
3
+ (async () => {
4
+ const oclif = await import("@oclif/core");
5
+ await oclif.execute({ development: true, dir: __dirname });
6
+ })();
@@ -112,6 +112,9 @@ class Knock extends _basecommand.default {
112
112
  this.log("");
113
113
  this.log("Thank you for using Knock, and have a nice day! 🙂");
114
114
  }
115
+ constructor(...args){
116
+ super(...args), _define_property(this, "requiresAuth", false);
117
+ }
115
118
  }
116
119
  // Because, it's a secret :)
117
120
  _define_property(Knock, "hidden", true);
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return Login;
9
+ }
10
+ });
11
+ const _auth = /*#__PURE__*/ _interop_require_default(require("../lib/auth"));
12
+ const _basecommand = /*#__PURE__*/ _interop_require_default(require("../lib/base-command"));
13
+ const _ux = require("../lib/helpers/ux");
14
+ function _define_property(obj, key, value) {
15
+ if (key in obj) {
16
+ Object.defineProperty(obj, key, {
17
+ value: value,
18
+ enumerable: true,
19
+ configurable: true,
20
+ writable: true
21
+ });
22
+ } else {
23
+ obj[key] = value;
24
+ }
25
+ return obj;
26
+ }
27
+ function _interop_require_default(obj) {
28
+ return obj && obj.__esModule ? obj : {
29
+ default: obj
30
+ };
31
+ }
32
+ class Login extends _basecommand.default {
33
+ async run() {
34
+ const { flags } = this.props;
35
+ if (flags["service-token"]) {
36
+ this.log("Service token provided, skipping login.");
37
+ return;
38
+ }
39
+ _ux.spinner.start("‣ Authenticating with Knock...");
40
+ const resp = await _auth.default.waitForAccessToken(this.sessionContext.dashboardOrigin, this.sessionContext.authOrigin);
41
+ _ux.spinner.stop();
42
+ await this.configStore.set({
43
+ userSession: resp
44
+ });
45
+ this.log("‣ Successfully authenticated with Knock.");
46
+ }
47
+ constructor(...args){
48
+ super(...args), _define_property(this, "requiresAuth", false);
49
+ }
50
+ }
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return Logout;
9
+ }
10
+ });
11
+ const _basecommand = /*#__PURE__*/ _interop_require_default(require("../lib/base-command"));
12
+ const _ux = require("../lib/helpers/ux");
13
+ function _define_property(obj, key, value) {
14
+ if (key in obj) {
15
+ Object.defineProperty(obj, key, {
16
+ value: value,
17
+ enumerable: true,
18
+ configurable: true,
19
+ writable: true
20
+ });
21
+ } else {
22
+ obj[key] = value;
23
+ }
24
+ return obj;
25
+ }
26
+ function _interop_require_default(obj) {
27
+ return obj && obj.__esModule ? obj : {
28
+ default: obj
29
+ };
30
+ }
31
+ class Logout extends _basecommand.default {
32
+ async run() {
33
+ const { flags } = this.props;
34
+ if (flags["service-token"]) {
35
+ this.log("Service token provided, skipping logout.");
36
+ return;
37
+ }
38
+ _ux.spinner.start("‣ Logging out of Knock...");
39
+ await this.configStore.set({
40
+ userSession: undefined
41
+ });
42
+ _ux.spinner.stop();
43
+ this.log("‣ Successfully logged out of Knock. See you around.");
44
+ }
45
+ constructor(...args){
46
+ super(...args), _define_property(this, "requiresAuth", false);
47
+ }
48
+ }
@@ -34,10 +34,14 @@ class Whoami extends _basecommand.default {
34
34
  const resp = await (0, _request.withSpinner)(()=>this.apiV1.whoami());
35
35
  const { flags } = this.props;
36
36
  if (flags.json) return resp.data;
37
- this.log(`‣ Successfully verified the provided service token:`);
38
- const info = [
37
+ this.log(`‣ Successfully authenticated:`);
38
+ let info = [];
39
+ info = resp.data.service_token_name ? [
39
40
  `Account name: ${resp.data.account_name}`,
40
41
  `Service token name: ${resp.data.service_token_name}`
42
+ ] : [
43
+ `Account name: ${resp.data.account_name}`,
44
+ `User ID: ${resp.data.user_id}`
41
45
  ];
42
46
  this.log((0, _string.indentString)(info.join("\n"), 4));
43
47
  }
@@ -29,9 +29,11 @@ function _interop_require_default(obj) {
29
29
  default: obj
30
30
  };
31
31
  }
32
- const DEFAULT_ORIGIN = "https://control.knock.app";
33
32
  const API_VERSION = "v1";
34
33
  class ApiV1 {
34
+ getToken(sessionContext) {
35
+ return sessionContext.session ? sessionContext.session.accessToken : sessionContext.token;
36
+ }
35
37
  async ping() {
36
38
  return this.get("/ping");
37
39
  }
@@ -401,13 +403,20 @@ class ApiV1 {
401
403
  async put(subpath, data, config) {
402
404
  return this.client.put(`/${API_VERSION}` + subpath, data, config);
403
405
  }
404
- constructor(flags, config){
406
+ constructor(sessionContext, config){
407
+ var _sessionContext_session;
405
408
  _define_property(this, "client", void 0);
406
- const baseURL = flags["api-origin"] || DEFAULT_ORIGIN;
409
+ const baseURL = sessionContext.apiOrigin;
410
+ const token = this.getToken(sessionContext);
411
+ var _sessionContext_session_clientId;
407
412
  this.client = _axios.default.create({
408
413
  baseURL,
409
414
  headers: {
410
- Authorization: `Bearer ${flags["service-token"]}`,
415
+ // Used to authenticate the request to the API.
416
+ Authorization: `Bearer ${token}`,
417
+ // Used in conjunction with the JWT access token, to allow the OAuth server to
418
+ // verify the client ID of the OAuth client that issued the access token.
419
+ "x-knock-client-id": (_sessionContext_session_clientId = (_sessionContext_session = sessionContext.session) === null || _sessionContext_session === void 0 ? void 0 : _sessionContext_session.clientId) !== null && _sessionContext_session_clientId !== void 0 ? _sessionContext_session_clientId : undefined,
411
420
  "User-Agent": `${config.userAgent}`
412
421
  },
413
422
  // Don't reject the promise based on a response status code.
@@ -0,0 +1,256 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get default () {
13
+ return _default;
14
+ },
15
+ get exchangeCodeForToken () {
16
+ return exchangeCodeForToken;
17
+ },
18
+ get getOAuthServerUrls () {
19
+ return getOAuthServerUrls;
20
+ },
21
+ get refreshAccessToken () {
22
+ return refreshAccessToken;
23
+ },
24
+ get registerClient () {
25
+ return registerClient;
26
+ },
27
+ get waitForAccessToken () {
28
+ return waitForAccessToken;
29
+ }
30
+ });
31
+ const _nodecrypto = /*#__PURE__*/ _interop_require_default(require("node:crypto"));
32
+ const _nodehttp = /*#__PURE__*/ _interop_require_default(require("node:http"));
33
+ const _browser = require("./helpers/browser");
34
+ const _urls = require("./urls");
35
+ function _interop_require_default(obj) {
36
+ return obj && obj.__esModule ? obj : {
37
+ default: obj
38
+ };
39
+ }
40
+ const DEFAULT_TIMEOUT = 5000;
41
+ function createChallenge() {
42
+ // PKCE code verifier and challenge
43
+ const codeVerifier = _nodecrypto.default.randomBytes(32).toString("base64url");
44
+ const codeChallenge = _nodecrypto.default.createHash("sha256").update(codeVerifier).digest("base64").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
45
+ const state = _nodecrypto.default.randomUUID();
46
+ return {
47
+ codeVerifier,
48
+ codeChallenge,
49
+ state
50
+ };
51
+ }
52
+ async function getOAuthServerUrls(apiUrl) {
53
+ const { protocol, host } = new URL(apiUrl);
54
+ const wellKnownUrl = `${protocol}//${host}/.well-known/oauth-authorization-server`;
55
+ const response = await fetch(wellKnownUrl, {
56
+ signal: AbortSignal.timeout(DEFAULT_TIMEOUT)
57
+ });
58
+ if (response.ok) {
59
+ const data = await response.json();
60
+ return {
61
+ registrationEndpoint: data.registration_endpoint,
62
+ authorizationEndpoint: data.authorization_endpoint,
63
+ tokenEndpoint: data.token_endpoint,
64
+ issuer: data.issuer
65
+ };
66
+ }
67
+ throw new Error("Failed to fetch OAuth server metadata");
68
+ }
69
+ async function registerClient(registrationEndpoint, redirectUri) {
70
+ const registrationResponse = await fetch(registrationEndpoint, {
71
+ method: "POST",
72
+ headers: {
73
+ "Content-Type": "application/json"
74
+ },
75
+ body: JSON.stringify({
76
+ client_name: "Knock CLI",
77
+ token_endpoint_auth_method: "none",
78
+ grant_types: [
79
+ "authorization_code"
80
+ ],
81
+ response_types: [
82
+ "code"
83
+ ],
84
+ redirect_uris: [
85
+ redirectUri
86
+ ]
87
+ }),
88
+ signal: AbortSignal.timeout(DEFAULT_TIMEOUT)
89
+ });
90
+ if (!registrationResponse.ok) {
91
+ console.log(await registrationResponse.json());
92
+ throw new Error(`Could not register client with OAuth server`);
93
+ }
94
+ const registrationData = await registrationResponse.json();
95
+ return registrationData.client_id;
96
+ }
97
+ async function parseTokenResponse(response) {
98
+ const data = await response.json();
99
+ return {
100
+ accessToken: data.access_token,
101
+ refreshToken: data.refresh_token,
102
+ idToken: data.id_token,
103
+ expiresAt: new Date(Date.now() + data.expires_in * 1000)
104
+ };
105
+ }
106
+ async function exchangeCodeForToken(params) {
107
+ const response = await fetch(params.tokenEndpoint, {
108
+ method: "POST",
109
+ headers: {
110
+ "Content-Type": "application/x-www-form-urlencoded"
111
+ },
112
+ body: new URLSearchParams({
113
+ grant_type: "authorization_code",
114
+ client_id: params.clientId,
115
+ code: params.code,
116
+ code_verifier: params.codeVerifier,
117
+ redirect_uri: params.redirectUri
118
+ }),
119
+ signal: AbortSignal.timeout(5000)
120
+ });
121
+ if (!response.ok) {
122
+ let errorDescription;
123
+ try {
124
+ const errorResponse = await response.json();
125
+ errorDescription = errorResponse.error_description || errorResponse.error;
126
+ } catch {
127
+ // ignore
128
+ }
129
+ return {
130
+ error: errorDescription !== null && errorDescription !== void 0 ? errorDescription : "unknown error"
131
+ };
132
+ }
133
+ return {
134
+ ...await parseTokenResponse(response),
135
+ clientId: params.clientId
136
+ };
137
+ }
138
+ async function refreshAccessToken(params) {
139
+ const { tokenEndpoint } = await getOAuthServerUrls(params.authUrl);
140
+ const response = await fetch(tokenEndpoint, {
141
+ method: "POST",
142
+ headers: {
143
+ "Content-Type": "application/x-www-form-urlencoded"
144
+ },
145
+ body: new URLSearchParams({
146
+ grant_type: "refresh_token",
147
+ client_id: params.clientId,
148
+ refresh_token: params.refreshToken
149
+ }),
150
+ signal: AbortSignal.timeout(5000)
151
+ });
152
+ if (!response.ok) {
153
+ throw new Error("Failed to refresh access token");
154
+ }
155
+ return {
156
+ ...await parseTokenResponse(response),
157
+ clientId: params.clientId
158
+ };
159
+ }
160
+ async function waitForAccessToken(dashboardUrl, authUrl) {
161
+ const { authorizationEndpoint, tokenEndpoint, registrationEndpoint } = await getOAuthServerUrls(authUrl);
162
+ let resolve;
163
+ let reject;
164
+ const promise = new Promise((res, rej)=>{
165
+ resolve = res;
166
+ reject = rej;
167
+ });
168
+ const { codeVerifier, codeChallenge, state } = createChallenge();
169
+ const timeout = setTimeout(()=>{
170
+ cleanupAndReject(`authentication timed out after ${DEFAULT_TIMEOUT / 1000} seconds`);
171
+ }, 60000);
172
+ function cleanupAndReject(message) {
173
+ cleanup();
174
+ reject(new Error(`Could not authenticate: ${message}`));
175
+ }
176
+ function cleanup() {
177
+ clearTimeout(timeout);
178
+ server.close();
179
+ server.closeAllConnections();
180
+ }
181
+ const server = _nodehttp.default.createServer();
182
+ server.listen();
183
+ const address = server.address();
184
+ if (address === null || typeof address !== "object") {
185
+ throw new Error("Could not start server");
186
+ }
187
+ const callbackPath = "/oauth_callback";
188
+ const redirectUri = `http://localhost:${address.port}${callbackPath}`;
189
+ const clientId = await registerClient(registrationEndpoint, redirectUri);
190
+ const params = {
191
+ response_type: "code",
192
+ client_id: clientId,
193
+ redirect_uri: redirectUri,
194
+ state,
195
+ code_challenge: codeChallenge,
196
+ code_challenge_method: "S256",
197
+ scope: "openid email offline_access"
198
+ };
199
+ const browserUrl = `${authorizationEndpoint}?${new URLSearchParams(params).toString()}`;
200
+ server.on("request", async (req, res)=>{
201
+ if (!clientId || !redirectUri) {
202
+ res.writeHead(500).end("Something went wrong");
203
+ cleanupAndReject("something went wrong");
204
+ return;
205
+ }
206
+ var _req_url;
207
+ const url = new URL((_req_url = req.url) !== null && _req_url !== void 0 ? _req_url : "/", "http://127.0.0.1");
208
+ if (url.pathname !== callbackPath) {
209
+ res.writeHead(404).end("Invalid path");
210
+ cleanupAndReject("invalid path");
211
+ return;
212
+ }
213
+ const error = url.searchParams.get("error");
214
+ if (error) {
215
+ res.writeHead(400).end("Could not authenticate");
216
+ const errorDescription = url.searchParams.get("error_description");
217
+ cleanupAndReject(`${errorDescription || error} `);
218
+ return;
219
+ }
220
+ const code = url.searchParams.get("code");
221
+ if (!code) {
222
+ res.writeHead(400).end("Could not authenticate");
223
+ cleanupAndReject("no code provided");
224
+ return;
225
+ }
226
+ const response = await exchangeCodeForToken({
227
+ tokenEndpoint,
228
+ clientId,
229
+ code,
230
+ codeVerifier,
231
+ redirectUri
232
+ });
233
+ if ("error" in response) {
234
+ res.writeHead(302, {
235
+ location: (0, _urls.authErrorUrl)(dashboardUrl, "Could not authenticate: unable to fetch access token")
236
+ }).end("Could not authenticate");
237
+ cleanupAndReject(JSON.stringify(response.error));
238
+ return;
239
+ }
240
+ res.writeHead(302, {
241
+ location: (0, _urls.authSuccessUrl)(dashboardUrl)
242
+ }).end("Authentication successful");
243
+ cleanup();
244
+ resolve({
245
+ ...response,
246
+ clientId
247
+ });
248
+ });
249
+ console.log(`Opened web browser to facilitate auth: ${browserUrl}`);
250
+ _browser.browser.openUrl(browserUrl);
251
+ return promise;
252
+ }
253
+ const _default = {
254
+ waitForAccessToken,
255
+ refreshAccessToken
256
+ };
@@ -10,8 +10,10 @@ Object.defineProperty(exports, "default", {
10
10
  });
11
11
  const _core = require("@oclif/core");
12
12
  const _apiv1 = /*#__PURE__*/ _interop_require_default(require("./api-v1"));
13
+ const _auth = /*#__PURE__*/ _interop_require_default(require("./auth"));
13
14
  const _runcontext = /*#__PURE__*/ _interop_require_wildcard(require("./run-context"));
14
- const _userconfig = /*#__PURE__*/ _interop_require_default(require("./user-config"));
15
+ const _urls = require("./urls");
16
+ const _userconfig = require("./user-config");
15
17
  function _define_property(obj, key, value) {
16
18
  if (key in obj) {
17
19
  Object.defineProperty(obj, key, {
@@ -71,24 +73,97 @@ function _interop_require_wildcard(obj, nodeInterop) {
71
73
  }
72
74
  return newObj;
73
75
  }
76
+ function sessionWithDefaultOrigins(sessionContext) {
77
+ var _sessionContext_apiOrigin, _sessionContext_dashboardOrigin, _sessionContext_authOrigin;
78
+ return {
79
+ ...sessionContext,
80
+ apiOrigin: (_sessionContext_apiOrigin = sessionContext.apiOrigin) !== null && _sessionContext_apiOrigin !== void 0 ? _sessionContext_apiOrigin : _urls.DEFAULT_API_URL,
81
+ dashboardOrigin: (_sessionContext_dashboardOrigin = sessionContext.dashboardOrigin) !== null && _sessionContext_dashboardOrigin !== void 0 ? _sessionContext_dashboardOrigin : _urls.DEFAULT_DASHBOARD_URL,
82
+ authOrigin: (_sessionContext_authOrigin = sessionContext.authOrigin) !== null && _sessionContext_authOrigin !== void 0 ? _sessionContext_authOrigin : _urls.DEFAULT_AUTH_URL
83
+ };
84
+ }
74
85
  class BaseCommand extends _core.Command {
75
86
  async init() {
76
87
  await super.init();
88
+ this.configStore = new _userconfig.UserConfigStore(this.config.configDir);
77
89
  // 1. Load user's config from the config dir, as available.
78
- await _userconfig.default.load(this.config.configDir);
90
+ await this.configStore.load();
79
91
  // 2. Parse flags and args, must come after the user config load.
80
92
  const { args, flags } = await this.parse(this.ctor);
81
93
  this.props = {
82
94
  args: args,
83
95
  flags: flags
84
96
  };
85
- // 3. Instantiate a knock api client.
86
- this.apiV1 = new _apiv1.default(this.props.flags, this.config);
87
- // 4. Load the run context of the invoked command.
97
+ // 3. Build the initial session context.
98
+ this.sessionContext = this.buildSessionContext();
99
+ // 4. If the command requires authentication, ensure the session is authenticated.
100
+ if (this.requiresAuth) {
101
+ this.ensureAuthenticated();
102
+ }
103
+ // 5. If the session context is an OAuth session, refresh the access token.
104
+ if (this.sessionContext.type === "oauth") {
105
+ await this.refreshAccessTokenForSession();
106
+ }
107
+ // 6. Instantiate a knock api client.
108
+ this.apiV1 = new _apiv1.default(this.sessionContext, this.config);
109
+ // 7. Load the run context of the invoked command.
88
110
  this.runContext = await _runcontext.load(this.id);
89
111
  }
112
+ buildSessionContext() {
113
+ const userConfig = this.configStore.get();
114
+ const session = userConfig.userSession;
115
+ // If the user has a session and a service token is not provided, use the session.
116
+ if (session && !this.props.flags["service-token"]) {
117
+ var _this_props_flags_apiorigin;
118
+ return sessionWithDefaultOrigins({
119
+ type: "oauth",
120
+ session,
121
+ apiOrigin: (_this_props_flags_apiorigin = this.props.flags["api-origin"]) !== null && _this_props_flags_apiorigin !== void 0 ? _this_props_flags_apiorigin : userConfig.apiOrigin,
122
+ dashboardOrigin: userConfig.dashboardOrigin,
123
+ authOrigin: userConfig.authOrigin
124
+ });
125
+ }
126
+ var _this_props_flags_servicetoken, _this_props_flags_apiorigin1;
127
+ // Otherwise, default to this being a service token session.
128
+ return sessionWithDefaultOrigins({
129
+ type: "service",
130
+ token: (_this_props_flags_servicetoken = this.props.flags["service-token"]) !== null && _this_props_flags_servicetoken !== void 0 ? _this_props_flags_servicetoken : userConfig.serviceToken,
131
+ apiOrigin: (_this_props_flags_apiorigin1 = this.props.flags["api-origin"]) !== null && _this_props_flags_apiorigin1 !== void 0 ? _this_props_flags_apiorigin1 : userConfig.apiOrigin,
132
+ dashboardOrigin: userConfig.dashboardOrigin,
133
+ authOrigin: userConfig.authOrigin
134
+ });
135
+ }
136
+ ensureAuthenticated() {
137
+ if (this.sessionContext.type === "service" && !this.sessionContext.token || this.sessionContext.type === "oauth" && !this.sessionContext.session) {
138
+ this.error("No token found. Refusing to run command.");
139
+ }
140
+ }
141
+ async refreshAccessTokenForSession() {
142
+ // Maybe refresh the access token?
143
+ try {
144
+ var _this_sessionContext_session, _this_sessionContext_session1;
145
+ var _this_sessionContext_session_clientId, _this_sessionContext_session_refreshToken;
146
+ const refreshedSession = await _auth.default.refreshAccessToken({
147
+ authUrl: this.sessionContext.authOrigin,
148
+ clientId: (_this_sessionContext_session_clientId = (_this_sessionContext_session = this.sessionContext.session) === null || _this_sessionContext_session === void 0 ? void 0 : _this_sessionContext_session.clientId) !== null && _this_sessionContext_session_clientId !== void 0 ? _this_sessionContext_session_clientId : "",
149
+ refreshToken: (_this_sessionContext_session_refreshToken = (_this_sessionContext_session1 = this.sessionContext.session) === null || _this_sessionContext_session1 === void 0 ? void 0 : _this_sessionContext_session1.refreshToken) !== null && _this_sessionContext_session_refreshToken !== void 0 ? _this_sessionContext_session_refreshToken : ""
150
+ });
151
+ this.debug("Successfully refreshed access token.");
152
+ // Update the user config to use the new session.
153
+ await this.configStore.set({
154
+ userSession: refreshedSession
155
+ });
156
+ // Update the session context to use the new session.
157
+ this.sessionContext = this.buildSessionContext();
158
+ } catch {
159
+ this.debug("Failed to refresh access token, clearing session.");
160
+ await this.configStore.set({
161
+ userSession: undefined
162
+ });
163
+ }
164
+ }
90
165
  constructor(...args){
91
- super(...args), _define_property(this, "props", void 0), _define_property(this, "apiV1", void 0), _define_property(this, "runContext", void 0);
166
+ super(...args), _define_property(this, "props", void 0), _define_property(this, "apiV1", void 0), _define_property(this, "runContext", void 0), _define_property(this, "sessionContext", void 0), _define_property(this, "configStore", void 0), _define_property(this, "requiresAuth", true);
92
167
  }
93
168
  }
94
169
  // Base flags are inherited by any command that extends BaseCommand.
@@ -99,17 +174,15 @@ _define_property(BaseCommand, "baseFlags", {
99
174
  // - if not available, fall back to user config
100
175
  "service-token": _core.Flags.string({
101
176
  summary: "The service token to authenticate with.",
102
- required: true,
177
+ required: false,
103
178
  multiple: false,
104
- env: "KNOCK_SERVICE_TOKEN",
105
- default: async ()=>_userconfig.default.get().serviceToken
179
+ env: "KNOCK_SERVICE_TOKEN"
106
180
  }),
107
- // Hidden flag to use a different api base url for development purposes.
181
+ // Hidden flags to use a different api url for development purposes.
108
182
  "api-origin": _core.Flags.string({
109
183
  hidden: true,
110
184
  required: false,
111
- multiple: false,
112
- default: async ()=>_userconfig.default.get().apiOrigin
185
+ multiple: false
113
186
  })
114
187
  });
115
188
  const _default = BaseCommand;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "browser", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return browser;
9
+ }
10
+ });
11
+ const _open = /*#__PURE__*/ _interop_require_default(require("open"));
12
+ function _interop_require_default(obj) {
13
+ return obj && obj.__esModule ? obj : {
14
+ default: obj
15
+ };
16
+ }
17
+ const browser = {
18
+ /**
19
+ * Opens a URL in the default browser
20
+ * @param url The URL to open
21
+ * @returns A promise that resolves when the URL is opened
22
+ */ async openUrl (url) {
23
+ await (0, _open.default)(url);
24
+ }
25
+ };
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get DEFAULT_API_URL () {
13
+ return DEFAULT_API_URL;
14
+ },
15
+ get DEFAULT_AUTH_URL () {
16
+ return DEFAULT_AUTH_URL;
17
+ },
18
+ get DEFAULT_DASHBOARD_URL () {
19
+ return DEFAULT_DASHBOARD_URL;
20
+ },
21
+ get authErrorUrl () {
22
+ return authErrorUrl;
23
+ },
24
+ get authSuccessUrl () {
25
+ return authSuccessUrl;
26
+ }
27
+ });
28
+ const DEFAULT_DASHBOARD_URL = "https://dashboard.knock.app";
29
+ const DEFAULT_AUTH_URL = "https://signin.knock.app";
30
+ const DEFAULT_API_URL = "https://control.knock.app";
31
+ const authSuccessUrl = (dashboardUrl)=>`${dashboardUrl}/auth/oauth/cli`;
32
+ const authErrorUrl = (dashboardUrl, error)=>`${dashboardUrl}/auth/oauth/cli?error=${error}`;