@knocklabs/cli 0.2.0 → 0.2.2

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 (64) hide show
  1. package/README.md +258 -36
  2. package/dist/commands/branch/create.js +56 -0
  3. package/dist/commands/branch/delete.js +60 -0
  4. package/dist/commands/branch/list.js +89 -0
  5. package/dist/commands/commit/get.js +4 -4
  6. package/dist/commands/commit/index.js +47 -2
  7. package/dist/commands/commit/list.js +61 -13
  8. package/dist/commands/guide/activate.js +48 -4
  9. package/dist/commands/guide/generate-types.js +4 -1
  10. package/dist/commands/guide/get.js +46 -3
  11. package/dist/commands/guide/list.js +46 -3
  12. package/dist/commands/guide/pull.js +6 -4
  13. package/dist/commands/guide/push.js +4 -3
  14. package/dist/commands/guide/validate.js +4 -3
  15. package/dist/commands/layout/get.js +46 -1
  16. package/dist/commands/layout/list.js +46 -1
  17. package/dist/commands/layout/pull.js +6 -2
  18. package/dist/commands/layout/push.js +4 -1
  19. package/dist/commands/layout/validate.js +4 -1
  20. package/dist/commands/login.js +1 -0
  21. package/dist/commands/logout.js +1 -0
  22. package/dist/commands/message-type/get.js +46 -3
  23. package/dist/commands/message-type/list.js +46 -3
  24. package/dist/commands/message-type/pull.js +6 -4
  25. package/dist/commands/message-type/push.js +4 -3
  26. package/dist/commands/message-type/validate.js +4 -3
  27. package/dist/commands/partial/get.js +46 -1
  28. package/dist/commands/partial/list.js +46 -1
  29. package/dist/commands/partial/pull.js +6 -2
  30. package/dist/commands/partial/push.js +4 -1
  31. package/dist/commands/partial/validate.js +6 -1
  32. package/dist/commands/pull.js +28 -8
  33. package/dist/commands/push.js +27 -8
  34. package/dist/commands/translation/get.js +5 -1
  35. package/dist/commands/translation/list.js +5 -1
  36. package/dist/commands/translation/pull.js +8 -3
  37. package/dist/commands/translation/push.js +4 -1
  38. package/dist/commands/translation/validate.js +4 -1
  39. package/dist/commands/whoami.js +7 -8
  40. package/dist/commands/workflow/activate.js +47 -3
  41. package/dist/commands/workflow/generate-types.js +4 -1
  42. package/dist/commands/workflow/get.js +9 -4
  43. package/dist/commands/workflow/list.js +5 -1
  44. package/dist/commands/workflow/pull.js +6 -2
  45. package/dist/commands/workflow/push.js +4 -1
  46. package/dist/commands/workflow/run.js +46 -2
  47. package/dist/commands/workflow/validate.js +4 -1
  48. package/dist/lib/api-v1.js +57 -20
  49. package/dist/lib/helpers/arg.js +24 -0
  50. package/dist/lib/helpers/command.js +14 -0
  51. package/dist/lib/helpers/flag.js +18 -0
  52. package/dist/lib/helpers/request.js +48 -2
  53. package/dist/lib/helpers/string.js +4 -0
  54. package/dist/lib/marshal/commit/index.js +0 -1
  55. package/dist/lib/marshal/index.isomorphic.js +8 -4
  56. package/dist/lib/marshal/reusable-step/helpers.js +72 -0
  57. package/dist/lib/marshal/reusable-step/index.js +19 -0
  58. package/dist/lib/marshal/reusable-step/processor.isomorphic.js +86 -0
  59. package/dist/lib/marshal/{commit → reusable-step}/types.js +0 -1
  60. package/dist/lib/resources.js +6 -1
  61. package/dist/lib/urls.js +4 -0
  62. package/oclif.manifest.json +489 -50
  63. package/package.json +16 -5
  64. package/dist/commands/ping.js +0 -37
@@ -12,16 +12,28 @@ _export(exports, {
12
12
  get formatErrorRespMessage () {
13
13
  return formatErrorRespMessage;
14
14
  },
15
+ get formatMgmtError () {
16
+ return formatMgmtError;
17
+ },
15
18
  get isSuccessResp () {
16
19
  return isSuccessResp;
17
20
  },
18
21
  get withSpinner () {
19
22
  return withSpinner;
23
+ },
24
+ get withSpinnerV2 () {
25
+ return withSpinnerV2;
20
26
  }
21
27
  });
28
+ const _mgmt = /*#__PURE__*/ _interop_require_default(require("@knocklabs/mgmt"));
22
29
  const _core = require("@oclif/core");
23
30
  const _error = require("./error");
24
31
  const _ux = require("./ux");
32
+ function _interop_require_default(obj) {
33
+ return obj && obj.__esModule ? obj : {
34
+ default: obj
35
+ };
36
+ }
25
37
  const isSuccessResp = (resp)=>resp.status >= 200 && resp.status < 300;
26
38
  const formatErrorRespMessage = ({ status, data })=>{
27
39
  if (status === 500) {
@@ -36,16 +48,50 @@ const formatErrorRespMessage = ({ status, data })=>{
36
48
  }
37
49
  return message;
38
50
  };
51
+ const formatMgmtError = (apiError)=>{
52
+ if (apiError.status === 500) {
53
+ return "An internal server error occurred";
54
+ }
55
+ var _apiError_error_message;
56
+ // Prefer the error message from the error object over
57
+ // the error message formatted by the Stainless SDK
58
+ const description = `${(_apiError_error_message = apiError.error.message) !== null && _apiError_error_message !== void 0 ? _apiError_error_message : apiError.message} (status: ${apiError.status})`;
59
+ var _apiError_error_errors;
60
+ const inputErrors = (_apiError_error_errors = apiError.error.errors) !== null && _apiError_error_errors !== void 0 ? _apiError_error_errors : [];
61
+ if (Array.isArray(inputErrors) && inputErrors.length > 0) {
62
+ const errs = inputErrors.map((e)=>new _error.JsonDataError(e.message, e.field));
63
+ return errs.length === 0 ? description : description + "\n\n" + (0, _error.formatErrors)(errs, {
64
+ indentBy: 2
65
+ });
66
+ }
67
+ return description;
68
+ };
39
69
  const withSpinner = async (requestFn, opts = {})=>{
40
- const { action = "‣ Loading", ensureSuccess = true } = opts;
70
+ const { action = "‣ Loading" } = opts;
41
71
  // Suppress printing the spinner in tests, oclif doesn't for some reasons.
42
72
  _ux.spinner.start(action);
43
73
  const resp = await requestFn();
44
74
  // Error out before the action stop so the spinner can update accordingly.
45
- if (ensureSuccess && !isSuccessResp(resp)) {
75
+ if (!isSuccessResp(resp)) {
46
76
  const message = formatErrorRespMessage(resp);
47
77
  _core.ux.error(new _error.ApiError(message));
48
78
  }
49
79
  _ux.spinner.stop();
50
80
  return resp;
51
81
  };
82
+ const withSpinnerV2 = async (requestFn, opts = {})=>{
83
+ const { action = "‣ Loading" } = opts;
84
+ // Suppress printing the spinner in tests, oclif doesn't for some reasons.
85
+ _ux.spinner.start(action);
86
+ try {
87
+ const resp = await requestFn();
88
+ _ux.spinner.stop();
89
+ return resp;
90
+ } catch (error) {
91
+ if (error instanceof _mgmt.default.APIError) {
92
+ const message = formatMgmtError(error);
93
+ return _core.ux.error(new _error.ApiError(message));
94
+ }
95
+ throw error;
96
+ }
97
+ };
@@ -16,6 +16,9 @@ _export(exports, {
16
16
  },
17
17
  get indentString () {
18
18
  return indentString;
19
+ },
20
+ get slugify () {
21
+ return slugify;
19
22
  }
20
23
  });
21
24
  const SLUG_FORMAT_RE = /^[\w-]+$/;
@@ -44,3 +47,4 @@ const indentString = (string, count = 0, options = {})=>{
44
47
  const regex = includeEmptyLines ? /^/gm : /^(?!\s*$)/gm;
45
48
  return string.replace(regex, indent.repeat(count));
46
49
  };
50
+ const slugify = (input)=>input.toLowerCase().trim().replace(/\s+/g, "-");
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
5
  _export_star(require("./helpers"), exports);
6
- _export_star(require("./types"), exports);
7
6
  function _export_star(from, to) {
8
7
  Object.keys(from).forEach(function(k) {
9
8
  if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
@@ -23,16 +23,20 @@ _export(exports, {
23
23
  get buildPartialDirBundle () {
24
24
  return _processorisomorphic3.buildPartialDirBundle;
25
25
  },
26
+ get buildReusableStepDirBundle () {
27
+ return _processorisomorphic4.buildReusableStepDirBundle;
28
+ },
26
29
  get buildTranslationDirBundle () {
27
- return _processorisomorphic4.buildTranslationDirBundle;
30
+ return _processorisomorphic5.buildTranslationDirBundle;
28
31
  },
29
32
  get buildWorkflowDirBundle () {
30
- return _processorisomorphic5.buildWorkflowDirBundle;
33
+ return _processorisomorphic6.buildWorkflowDirBundle;
31
34
  }
32
35
  });
33
36
  const _processorisomorphic = require("./email-layout/processor.isomorphic");
34
37
  const _processorisomorphic1 = require("./guide/processor.isomorphic");
35
38
  const _processorisomorphic2 = require("./message-type/processor.isomorphic");
36
39
  const _processorisomorphic3 = require("./partial/processor.isomorphic");
37
- const _processorisomorphic4 = require("./translation/processor.isomorphic");
38
- const _processorisomorphic5 = require("./workflow/processor.isomorphic");
40
+ const _processorisomorphic4 = require("./reusable-step/processor.isomorphic");
41
+ const _processorisomorphic5 = require("./translation/processor.isomorphic");
42
+ const _processorisomorphic6 = require("./workflow/processor.isomorphic");
@@ -0,0 +1,72 @@
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 isReusableStepDir () {
13
+ return isReusableStepDir;
14
+ },
15
+ get lsReusableStepJson () {
16
+ return lsReusableStepJson;
17
+ },
18
+ get reusableStepJsonPath () {
19
+ return reusableStepJsonPath;
20
+ }
21
+ });
22
+ const _nodepath = /*#__PURE__*/ _interop_require_wildcard(require("node:path"));
23
+ const _fsextra = /*#__PURE__*/ _interop_require_wildcard(require("fs-extra"));
24
+ const _processorisomorphic = require("./processor.isomorphic");
25
+ function _getRequireWildcardCache(nodeInterop) {
26
+ if (typeof WeakMap !== "function") return null;
27
+ var cacheBabelInterop = new WeakMap();
28
+ var cacheNodeInterop = new WeakMap();
29
+ return (_getRequireWildcardCache = function(nodeInterop) {
30
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
31
+ })(nodeInterop);
32
+ }
33
+ function _interop_require_wildcard(obj, nodeInterop) {
34
+ if (!nodeInterop && obj && obj.__esModule) {
35
+ return obj;
36
+ }
37
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
38
+ return {
39
+ default: obj
40
+ };
41
+ }
42
+ var cache = _getRequireWildcardCache(nodeInterop);
43
+ if (cache && cache.has(obj)) {
44
+ return cache.get(obj);
45
+ }
46
+ var newObj = {
47
+ __proto__: null
48
+ };
49
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
50
+ for(var key in obj){
51
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
52
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
53
+ if (desc && (desc.get || desc.set)) {
54
+ Object.defineProperty(newObj, key, desc);
55
+ } else {
56
+ newObj[key] = obj[key];
57
+ }
58
+ }
59
+ }
60
+ newObj.default = obj;
61
+ if (cache) {
62
+ cache.set(obj, newObj);
63
+ }
64
+ return newObj;
65
+ }
66
+ const reusableStepJsonPath = (reusableStepDirCtx)=>_nodepath.resolve(reusableStepDirCtx.abspath, _processorisomorphic.REUSABLE_STEP_JSON);
67
+ const isReusableStepDir = async (dirPath)=>Boolean(await lsReusableStepJson(dirPath));
68
+ const lsReusableStepJson = async (dirPath)=>{
69
+ const reusableStepJsonPath = _nodepath.resolve(dirPath, _processorisomorphic.REUSABLE_STEP_JSON);
70
+ const exists = await _fsextra.pathExists(reusableStepJsonPath);
71
+ return exists ? reusableStepJsonPath : undefined;
72
+ };
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ _export_star(require("./processor.isomorphic"), exports);
6
+ _export_star(require("./types"), exports);
7
+ function _export_star(from, to) {
8
+ Object.keys(from).forEach(function(k) {
9
+ if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
10
+ Object.defineProperty(to, k, {
11
+ enumerable: true,
12
+ get: function() {
13
+ return from[k];
14
+ }
15
+ });
16
+ }
17
+ });
18
+ return from;
19
+ }
@@ -0,0 +1,86 @@
1
+ /*
2
+ * IMPORTANT:
3
+ *
4
+ * This file is suffixed with `.isomorphic` because the code in this file is
5
+ * meant to run not just in a nodejs environment but also in a browser. For this
6
+ * reason there are some restrictions for which nodejs imports are allowed in
7
+ * this module. See `.eslintrc.json` for more details.
8
+ */ "use strict";
9
+ Object.defineProperty(exports, "__esModule", {
10
+ value: true
11
+ });
12
+ function _export(target, all) {
13
+ for(var name in all)Object.defineProperty(target, name, {
14
+ enumerable: true,
15
+ get: Object.getOwnPropertyDescriptor(all, name).get
16
+ });
17
+ }
18
+ _export(exports, {
19
+ get REUSABLE_STEP_JSON () {
20
+ return REUSABLE_STEP_JSON;
21
+ },
22
+ get buildReusableStepDirBundle () {
23
+ return buildReusableStepDirBundle;
24
+ }
25
+ });
26
+ const _lodash = require("lodash");
27
+ const _objectisomorphic = require("../../helpers/object.isomorphic");
28
+ const _constisomorphic = require("../shared/const.isomorphic");
29
+ const _helpersisomorphic = require("../shared/helpers.isomorphic");
30
+ const REUSABLE_STEP_JSON = "reusable_step.json";
31
+ const compileExtractionSettings = (reusableStep)=>{
32
+ const extractableFields = (0, _lodash.get)(reusableStep, [
33
+ "__annotation",
34
+ "extractable_fields"
35
+ ], {});
36
+ const map = new Map();
37
+ for (const key of Object.keys(reusableStep)){
38
+ // If the field we are on is extractable, then add its extraction
39
+ // settings to the map with the current object path.
40
+ if (key in extractableFields) {
41
+ map.set([
42
+ key
43
+ ], extractableFields[key]);
44
+ }
45
+ }
46
+ return map;
47
+ };
48
+ const buildReusableStepDirBundle = (remoteReusableStep, localReusableStep = {})=>{
49
+ const bundle = {};
50
+ const mutRemoteReusableStep = (0, _lodash.cloneDeep)(remoteReusableStep);
51
+ // A map of extraction settings of every field in the reusable step
52
+ const compiledExtractionSettings = compileExtractionSettings(mutRemoteReusableStep);
53
+ // Iterate through each extractable field, determine whether we need to
54
+ // extract the field content, and if so, perform the extraction.
55
+ for (const [objPathParts, extractionSettings] of compiledExtractionSettings){
56
+ // If this reusable step doesn't have this field path, then we don't extract.
57
+ if (!(0, _lodash.has)(mutRemoteReusableStep, objPathParts)) continue;
58
+ // If the field at this path is extracted in the local reusable step, then
59
+ // always extract; otherwise extract based on the field settings default.
60
+ const objPathStr = _objectisomorphic.ObjPath.stringify(objPathParts);
61
+ const extractedFilePath = (0, _lodash.get)(localReusableStep, `${objPathStr}${_constisomorphic.FILEPATH_MARKER}`);
62
+ const { default: extractByDefault, file_ext: fileExt } = extractionSettings;
63
+ if (!extractedFilePath && !extractByDefault) continue;
64
+ // By this point, we have a field where we need to extract its content.
65
+ const data = (0, _lodash.get)(mutRemoteReusableStep, objPathParts);
66
+ const fileName = objPathParts.pop();
67
+ // If we have an extracted file path from the local reusable step, we use that.
68
+ // In the other case we use the default path.
69
+ const relpath = typeof extractedFilePath === "string" ? extractedFilePath : `${fileName}.${fileExt}`;
70
+ // Perform the extraction by adding the content and its file path to the
71
+ // bundle for writing to the file system later. Then replace the field
72
+ // content with the extracted file path and mark the field as extracted
73
+ // with @ suffix.
74
+ const content = typeof data === "string" ? data : JSON.stringify(data, null, 2);
75
+ (0, _lodash.set)(bundle, [
76
+ relpath
77
+ ], content);
78
+ (0, _lodash.set)(mutRemoteReusableStep, `${objPathStr}${_constisomorphic.FILEPATH_MARKER}`, relpath);
79
+ (0, _lodash.unset)(mutRemoteReusableStep, objPathStr);
80
+ }
81
+ // At this point the bundle contains all extractable files, so we finally add
82
+ // the reusable step JSON relative path + the file content.
83
+ return (0, _lodash.set)(bundle, [
84
+ REUSABLE_STEP_JSON
85
+ ], (0, _helpersisomorphic.prepareResourceJson)(mutRemoteReusableStep));
86
+ };
@@ -1,4 +1,3 @@
1
- // Commit payload data from the API.
2
1
  "use strict";
3
2
  Object.defineProperty(exports, "__esModule", {
4
3
  value: true
@@ -22,11 +22,16 @@ const ALL_RESOURCE_TYPES = [
22
22
  // Email layouts next, as workflows with email channel steps may reference them
23
23
  "email_layout",
24
24
  "workflow",
25
+ // Message types then guides, as guides use message types.
26
+ "message_type",
27
+ "guide",
25
28
  "translation"
26
29
  ];
27
30
  const RESOURCE_SUBDIRS = {
28
31
  email_layout: "layouts",
29
32
  partial: "partials",
30
33
  translation: "translations",
31
- workflow: "workflows"
34
+ workflow: "workflows",
35
+ message_type: "message-types",
36
+ guide: "guides"
32
37
  };
package/dist/lib/urls.js CHANGED
@@ -23,6 +23,9 @@ _export(exports, {
23
23
  },
24
24
  get authSuccessUrl () {
25
25
  return authSuccessUrl;
26
+ },
27
+ get viewWorkflowUrl () {
28
+ return viewWorkflowUrl;
26
29
  }
27
30
  });
28
31
  const DEFAULT_DASHBOARD_URL = "https://dashboard.knock.app";
@@ -30,3 +33,4 @@ const DEFAULT_AUTH_URL = "https://signin.knock.app";
30
33
  const DEFAULT_API_URL = "https://control.knock.app";
31
34
  const authSuccessUrl = (dashboardUrl)=>`${dashboardUrl}/auth/oauth/cli`;
32
35
  const authErrorUrl = (dashboardUrl, error)=>`${dashboardUrl}/auth/oauth/cli?error=${error}`;
36
+ const viewWorkflowUrl = (dashboardUrl, accountSlug, envOrBranchSlug, workflowKey)=>`${dashboardUrl}/${accountSlug}/${envOrBranchSlug.toLowerCase()}/workflows/${workflowKey}`;