@knocklabs/cli 0.1.22 → 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/README.md +191 -106
- package/bin/dev.js +4 -4
- package/dist/commands/commit/list.js +21 -1
- package/dist/commands/guide/activate.js +121 -0
- package/dist/commands/guide/generate-types.js +148 -0
- package/dist/commands/guide/get.js +139 -0
- package/dist/commands/guide/list.js +112 -0
- package/dist/commands/guide/pull.js +209 -0
- package/dist/commands/guide/push.js +171 -0
- package/dist/commands/guide/validate.js +148 -0
- package/dist/commands/knock.js +3 -0
- package/dist/commands/login.js +50 -0
- package/dist/commands/logout.js +48 -0
- package/dist/commands/whoami.js +6 -2
- package/dist/commands/workflow/generate-types.js +6 -5
- package/dist/lib/api-v1.js +74 -4
- package/dist/lib/auth.js +256 -0
- package/dist/lib/base-command.js +85 -12
- package/dist/lib/helpers/browser.js +25 -0
- package/dist/lib/helpers/const.js +4 -4
- package/dist/lib/helpers/date.js +3 -3
- package/dist/lib/helpers/error.js +8 -8
- package/dist/lib/helpers/flag.js +7 -7
- package/dist/lib/helpers/json.js +5 -5
- package/dist/lib/helpers/object.isomorphic.js +8 -8
- package/dist/lib/helpers/page.js +9 -9
- package/dist/lib/helpers/request.js +4 -4
- package/dist/lib/helpers/string.js +3 -3
- package/dist/lib/helpers/typegen.js +59 -0
- package/dist/lib/helpers/ux.js +3 -3
- package/dist/lib/marshal/email-layout/helpers.js +5 -5
- package/dist/lib/marshal/email-layout/processor.isomorphic.js +3 -3
- package/dist/lib/marshal/email-layout/reader.js +5 -5
- package/dist/lib/marshal/email-layout/writer.js +4 -4
- package/dist/lib/marshal/guide/helpers.js +283 -0
- package/dist/lib/marshal/guide/index.js +3 -0
- package/dist/lib/marshal/guide/processor.isomorphic.js +3 -3
- package/dist/lib/marshal/guide/reader.js +193 -0
- package/dist/lib/marshal/guide/writer.js +175 -0
- package/dist/lib/marshal/index.isomorphic.js +7 -7
- package/dist/lib/marshal/message-type/helpers.js +5 -5
- package/dist/lib/marshal/message-type/processor.isomorphic.js +3 -3
- package/dist/lib/marshal/message-type/reader.js +5 -5
- package/dist/lib/marshal/message-type/writer.js +4 -4
- package/dist/lib/marshal/partial/helpers.js +5 -5
- package/dist/lib/marshal/partial/processor.isomorphic.js +3 -3
- package/dist/lib/marshal/partial/reader.js +5 -5
- package/dist/lib/marshal/partial/writer.js +4 -4
- package/dist/lib/marshal/shared/const.isomorphic.js +3 -3
- package/dist/lib/marshal/shared/helpers.isomorphic.js +9 -2
- package/dist/lib/marshal/shared/helpers.js +4 -4
- package/dist/lib/marshal/translation/helpers.js +10 -10
- package/dist/lib/marshal/translation/processor.isomorphic.js +6 -6
- package/dist/lib/marshal/translation/writer.js +3 -3
- package/dist/lib/marshal/workflow/generator.js +4 -4
- package/dist/lib/marshal/workflow/helpers.js +53 -10
- package/dist/lib/marshal/workflow/processor.isomorphic.js +5 -5
- package/dist/lib/marshal/workflow/reader.js +5 -5
- package/dist/lib/marshal/workflow/writer.js +5 -5
- package/dist/lib/resources.js +3 -3
- package/dist/lib/types.js +4 -0
- package/dist/lib/urls.js +32 -0
- package/dist/lib/user-config.js +69 -31
- package/oclif.manifest.json +749 -114
- package/package.json +12 -11
- package/dist/lib/type-generator.js +0 -100
|
@@ -17,8 +17,9 @@ const _flag = /*#__PURE__*/ _interop_require_wildcard(require("../../lib/helpers
|
|
|
17
17
|
const _objectisomorphic = require("../../lib/helpers/object.isomorphic");
|
|
18
18
|
const _page = require("../../lib/helpers/page");
|
|
19
19
|
const _request = require("../../lib/helpers/request");
|
|
20
|
+
const _typegen = require("../../lib/helpers/typegen");
|
|
20
21
|
const _ux = require("../../lib/helpers/ux");
|
|
21
|
-
const
|
|
22
|
+
const _workflow = /*#__PURE__*/ _interop_require_wildcard(require("../../lib/marshal/workflow"));
|
|
22
23
|
function _define_property(obj, key, value) {
|
|
23
24
|
if (key in obj) {
|
|
24
25
|
Object.defineProperty(obj, key, {
|
|
@@ -82,17 +83,17 @@ class WorkflowGenerateTypes extends _basecommand.default {
|
|
|
82
83
|
async run() {
|
|
83
84
|
const { flags } = this.props;
|
|
84
85
|
const fileExtension = flags["output-file"].abspath.split(".").pop();
|
|
85
|
-
const targetLanguage = (0,
|
|
86
|
+
const targetLanguage = (0, _typegen.getLanguageFromExtension)(fileExtension);
|
|
86
87
|
if (!targetLanguage) {
|
|
87
88
|
this.error(new _error.ApiError(`Unsupported file extension: ${fileExtension}. We currently support .ts, .rb, .go, .py files only.`));
|
|
88
89
|
}
|
|
89
90
|
_ux.spinner.start(`‣ Loading workflows`);
|
|
90
|
-
// 1. List all workflows in the
|
|
91
|
+
// 1. List all workflows in the target environment.
|
|
91
92
|
const workflows = await this.listAllWorkflows();
|
|
92
93
|
_ux.spinner.stop();
|
|
93
94
|
// 2. Generate types for all workflows.
|
|
94
95
|
_ux.spinner.start(`‣ Generating types`);
|
|
95
|
-
const { result, workflows: workflowsWithValidTypes } = await
|
|
96
|
+
const { result, workflows: workflowsWithValidTypes } = await _workflow.generateWorkflowTypes(workflows, targetLanguage);
|
|
96
97
|
_ux.spinner.stop();
|
|
97
98
|
if (!result) {
|
|
98
99
|
this.log(`‣ No workflows with valid trigger data JSON schema found, skipping type generation`);
|
|
@@ -125,7 +126,7 @@ class WorkflowGenerateTypes extends _basecommand.default {
|
|
|
125
126
|
}, workflows) : workflows;
|
|
126
127
|
}
|
|
127
128
|
}
|
|
128
|
-
_define_property(WorkflowGenerateTypes, "description", "Generate types for all workflows in
|
|
129
|
+
_define_property(WorkflowGenerateTypes, "description", "Generate types for all workflows in an environment and write them to a file.");
|
|
129
130
|
_define_property(WorkflowGenerateTypes, "flags", {
|
|
130
131
|
environment: _core.Flags.string({
|
|
131
132
|
summary: "Select the environment to generate types for.",
|
package/dist/lib/api-v1.js
CHANGED
|
@@ -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
|
}
|
|
@@ -113,6 +115,8 @@ class ApiV1 {
|
|
|
113
115
|
const params = (0, _objectisomorphic.prune)({
|
|
114
116
|
environment: flags.environment,
|
|
115
117
|
promoted: flags.promoted,
|
|
118
|
+
resource_type: flags["resource-type"],
|
|
119
|
+
resource_id: flags["resource-id"],
|
|
116
120
|
...(0, _page.toPageParams)(flags)
|
|
117
121
|
});
|
|
118
122
|
return this.get("/commits", {
|
|
@@ -333,6 +337,65 @@ class ApiV1 {
|
|
|
333
337
|
params
|
|
334
338
|
});
|
|
335
339
|
}
|
|
340
|
+
// By resources: Guides
|
|
341
|
+
async listGuides({ flags }) {
|
|
342
|
+
const params = (0, _objectisomorphic.prune)({
|
|
343
|
+
environment: flags.environment,
|
|
344
|
+
annotate: flags.annotate,
|
|
345
|
+
hide_uncommitted_changes: flags["hide-uncommitted-changes"],
|
|
346
|
+
include_json_schema: flags["include-json-schema"],
|
|
347
|
+
...(0, _page.toPageParams)(flags)
|
|
348
|
+
});
|
|
349
|
+
return this.get("/guides", {
|
|
350
|
+
params
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
async getGuide({ args, flags }) {
|
|
354
|
+
const params = (0, _objectisomorphic.prune)({
|
|
355
|
+
environment: flags.environment,
|
|
356
|
+
annotate: flags.annotate,
|
|
357
|
+
hide_uncommitted_changes: flags["hide-uncommitted-changes"]
|
|
358
|
+
});
|
|
359
|
+
return this.get(`/guides/${args.guideKey}`, {
|
|
360
|
+
params
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
async validateGuide({ flags }, guide) {
|
|
364
|
+
const params = (0, _objectisomorphic.prune)({
|
|
365
|
+
environment: flags.environment
|
|
366
|
+
});
|
|
367
|
+
const data = {
|
|
368
|
+
guide
|
|
369
|
+
};
|
|
370
|
+
return this.put(`/guides/${guide.key}/validate`, data, {
|
|
371
|
+
params
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
async upsertGuide({ flags }, guide) {
|
|
375
|
+
const params = (0, _objectisomorphic.prune)({
|
|
376
|
+
environment: flags.environment,
|
|
377
|
+
annotate: flags.annotate,
|
|
378
|
+
commit: flags.commit,
|
|
379
|
+
commit_message: flags["commit-message"]
|
|
380
|
+
});
|
|
381
|
+
const data = {
|
|
382
|
+
guide
|
|
383
|
+
};
|
|
384
|
+
return this.put(`/guides/${guide.key}`, data, {
|
|
385
|
+
params
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
async activateGuide({ args, flags }) {
|
|
389
|
+
const params = (0, _objectisomorphic.prune)({
|
|
390
|
+
environment: flags.environment,
|
|
391
|
+
status: flags.status,
|
|
392
|
+
from: flags.from,
|
|
393
|
+
until: flags.until
|
|
394
|
+
});
|
|
395
|
+
return this.put(`/guides/${args.guideKey}/activate`, {}, {
|
|
396
|
+
params
|
|
397
|
+
});
|
|
398
|
+
}
|
|
336
399
|
// By methods:
|
|
337
400
|
async get(subpath, config) {
|
|
338
401
|
return this.client.get(`/${API_VERSION}` + subpath, config);
|
|
@@ -340,13 +403,20 @@ class ApiV1 {
|
|
|
340
403
|
async put(subpath, data, config) {
|
|
341
404
|
return this.client.put(`/${API_VERSION}` + subpath, data, config);
|
|
342
405
|
}
|
|
343
|
-
constructor(
|
|
406
|
+
constructor(sessionContext, config){
|
|
407
|
+
var _sessionContext_session;
|
|
344
408
|
_define_property(this, "client", void 0);
|
|
345
|
-
const baseURL =
|
|
409
|
+
const baseURL = sessionContext.apiOrigin;
|
|
410
|
+
const token = this.getToken(sessionContext);
|
|
411
|
+
var _sessionContext_session_clientId;
|
|
346
412
|
this.client = _axios.default.create({
|
|
347
413
|
baseURL,
|
|
348
414
|
headers: {
|
|
349
|
-
|
|
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,
|
|
350
420
|
"User-Agent": `${config.userAgent}`
|
|
351
421
|
},
|
|
352
422
|
// Don't reject the promise based on a response status code.
|
package/dist/lib/auth.js
ADDED
|
@@ -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
|
+
};
|
package/dist/lib/base-command.js
CHANGED
|
@@ -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
|
|
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
|
|
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.
|
|
86
|
-
this.
|
|
87
|
-
// 4.
|
|
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:
|
|
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
|
|
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
|
+
};
|
|
@@ -5,17 +5,17 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
function _export(target, all) {
|
|
6
6
|
for(var name in all)Object.defineProperty(target, name, {
|
|
7
7
|
enumerable: true,
|
|
8
|
-
get: all
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
_export(exports, {
|
|
12
|
-
KnockEnv
|
|
12
|
+
get KnockEnv () {
|
|
13
13
|
return KnockEnv;
|
|
14
14
|
},
|
|
15
|
-
isTestEnv
|
|
15
|
+
get isTestEnv () {
|
|
16
16
|
return isTestEnv;
|
|
17
17
|
},
|
|
18
|
-
sandboxDir
|
|
18
|
+
get sandboxDir () {
|
|
19
19
|
return sandboxDir;
|
|
20
20
|
}
|
|
21
21
|
});
|
package/dist/lib/helpers/date.js
CHANGED
|
@@ -5,14 +5,14 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
function _export(target, all) {
|
|
6
6
|
for(var name in all)Object.defineProperty(target, name, {
|
|
7
7
|
enumerable: true,
|
|
8
|
-
get: all
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
_export(exports, {
|
|
12
|
-
formatDate
|
|
12
|
+
get formatDate () {
|
|
13
13
|
return formatDate;
|
|
14
14
|
},
|
|
15
|
-
formatDateTime
|
|
15
|
+
get formatDateTime () {
|
|
16
16
|
return formatDateTime;
|
|
17
17
|
}
|
|
18
18
|
});
|
|
@@ -5,29 +5,29 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
function _export(target, all) {
|
|
6
6
|
for(var name in all)Object.defineProperty(target, name, {
|
|
7
7
|
enumerable: true,
|
|
8
|
-
get: all
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
_export(exports, {
|
|
12
|
-
ApiError
|
|
12
|
+
get ApiError () {
|
|
13
13
|
return ApiError;
|
|
14
14
|
},
|
|
15
|
-
JsonDataError
|
|
15
|
+
get JsonDataError () {
|
|
16
16
|
return JsonDataError;
|
|
17
17
|
},
|
|
18
|
-
JsonSyntaxError
|
|
18
|
+
get JsonSyntaxError () {
|
|
19
19
|
return JsonSyntaxError;
|
|
20
20
|
},
|
|
21
|
-
LiquidParseError
|
|
21
|
+
get LiquidParseError () {
|
|
22
22
|
return LiquidParseError;
|
|
23
23
|
},
|
|
24
|
-
SourceError
|
|
24
|
+
get SourceError () {
|
|
25
25
|
return SourceError;
|
|
26
26
|
},
|
|
27
|
-
formatError
|
|
27
|
+
get formatError () {
|
|
28
28
|
return formatError;
|
|
29
29
|
},
|
|
30
|
-
formatErrors
|
|
30
|
+
get formatErrors () {
|
|
31
31
|
return formatErrors;
|
|
32
32
|
}
|
|
33
33
|
});
|