@knocklabs/cli 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +416 -9
- package/dist/commands/layout/get.js +98 -0
- package/dist/commands/layout/list.js +86 -0
- package/dist/commands/layout/pull.js +199 -0
- package/dist/commands/layout/push.js +159 -0
- package/dist/commands/layout/validate.js +134 -0
- package/dist/commands/workflow/get.js +39 -7
- package/dist/commands/workflow/list.js +4 -1
- package/dist/commands/workflow/run.js +6 -8
- package/dist/lib/api-v1.js +51 -2
- package/dist/lib/helpers/flag.js +19 -1
- package/dist/lib/helpers/json.js +9 -0
- package/dist/lib/marshal/email-layout/helpers.js +124 -0
- package/dist/lib/marshal/email-layout/index.js +19 -0
- package/dist/lib/marshal/email-layout/reader.js +193 -0
- package/dist/lib/marshal/email-layout/types.js +4 -0
- package/dist/lib/marshal/email-layout/writer.js +240 -0
- package/dist/lib/marshal/shared/helpers.js +135 -0
- package/dist/lib/marshal/workflow/generator.js +4 -2
- package/dist/lib/marshal/workflow/helpers.js +41 -6
- package/dist/lib/marshal/workflow/reader.js +8 -106
- package/dist/lib/marshal/workflow/types.js +2 -0
- package/dist/lib/marshal/workflow/writer.js +76 -40
- package/dist/lib/run-context/loader.js +11 -0
- package/oclif.manifest.json +338 -7
- package/package.json +13 -10
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "default", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: ()=>EmailLayoutList
|
|
8
|
+
});
|
|
9
|
+
const _core = require("@oclif/core");
|
|
10
|
+
const _baseCommand = /*#__PURE__*/ _interopRequireDefault(require("../../lib/base-command"));
|
|
11
|
+
const _date = require("../../lib/helpers/date");
|
|
12
|
+
const _object = require("../../lib/helpers/object");
|
|
13
|
+
const _page = require("../../lib/helpers/page");
|
|
14
|
+
const _request = require("../../lib/helpers/request");
|
|
15
|
+
function _interopRequireDefault(obj) {
|
|
16
|
+
return obj && obj.__esModule ? obj : {
|
|
17
|
+
default: obj
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
class EmailLayoutList extends _baseCommand.default {
|
|
21
|
+
async run() {
|
|
22
|
+
const resp = await this.request();
|
|
23
|
+
const { flags } = this.props;
|
|
24
|
+
if (flags.json) return resp.data;
|
|
25
|
+
this.render(resp.data);
|
|
26
|
+
}
|
|
27
|
+
async request(pageParams = {}) {
|
|
28
|
+
const props = (0, _object.merge)(this.props, {
|
|
29
|
+
flags: {
|
|
30
|
+
...pageParams
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
return (0, _request.withSpinner)(()=>this.apiV1.listEmailLayouts(props));
|
|
34
|
+
}
|
|
35
|
+
async render(data) {
|
|
36
|
+
const { entries } = data;
|
|
37
|
+
const { environment: env , "hide-uncommitted-changes": commitedOnly } = this.props.flags;
|
|
38
|
+
const qualifier = env === "development" && !commitedOnly ? "(including uncommitted)" : "";
|
|
39
|
+
this.log(`‣ Showing ${entries.length} email layouts in \`${env}\` environment ${qualifier}\n`);
|
|
40
|
+
/*
|
|
41
|
+
* Email layouts table
|
|
42
|
+
*/ _core.ux.table(entries, {
|
|
43
|
+
key: {
|
|
44
|
+
header: "Key"
|
|
45
|
+
},
|
|
46
|
+
name: {
|
|
47
|
+
header: "Name"
|
|
48
|
+
},
|
|
49
|
+
updated_at: {
|
|
50
|
+
header: "Updated at",
|
|
51
|
+
get: (entry)=>(0, _date.formatDate)(entry.updated_at)
|
|
52
|
+
},
|
|
53
|
+
created_at: {
|
|
54
|
+
header: "Created at",
|
|
55
|
+
get: (entry)=>(0, _date.formatDate)(entry.created_at)
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
return this.prompt(data);
|
|
59
|
+
}
|
|
60
|
+
async prompt(data) {
|
|
61
|
+
const { page_info } = data;
|
|
62
|
+
const pageAction = await (0, _page.maybePromptPageAction)(page_info);
|
|
63
|
+
const pageParams = pageAction && (0, _page.paramsForPageAction)(pageAction, page_info);
|
|
64
|
+
if (pageParams) {
|
|
65
|
+
this.log("\n");
|
|
66
|
+
const resp = await this.request(pageParams);
|
|
67
|
+
return this.render(resp.data);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
EmailLayoutList.aliases = [
|
|
72
|
+
"email-layout:list",
|
|
73
|
+
"email_layout:list"
|
|
74
|
+
];
|
|
75
|
+
EmailLayoutList.summary = "Display all email layouts for an environment.";
|
|
76
|
+
EmailLayoutList.flags = {
|
|
77
|
+
environment: _core.Flags.string({
|
|
78
|
+
default: "development",
|
|
79
|
+
summary: "The environment to use."
|
|
80
|
+
}),
|
|
81
|
+
"hide-uncommitted-changes": _core.Flags.boolean({
|
|
82
|
+
summary: "Hide any uncommitted changes."
|
|
83
|
+
}),
|
|
84
|
+
..._page.pageFlags
|
|
85
|
+
};
|
|
86
|
+
EmailLayoutList.enableJsonFlag = true;
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "default", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: ()=>EmailLayoutPull
|
|
8
|
+
});
|
|
9
|
+
const _nodePath = /*#__PURE__*/ _interopRequireWildcard(require("node:path"));
|
|
10
|
+
const _core = require("@oclif/core");
|
|
11
|
+
const _baseCommand = /*#__PURE__*/ _interopRequireDefault(require("../../lib/base-command"));
|
|
12
|
+
const _error = require("../../lib/helpers/error");
|
|
13
|
+
const _flag = /*#__PURE__*/ _interopRequireWildcard(require("../../lib/helpers/flag"));
|
|
14
|
+
const _object = require("../../lib/helpers/object");
|
|
15
|
+
const _page = require("../../lib/helpers/page");
|
|
16
|
+
const _request = require("../../lib/helpers/request");
|
|
17
|
+
const _ux = require("../../lib/helpers/ux");
|
|
18
|
+
const _emailLayout = /*#__PURE__*/ _interopRequireWildcard(require("../../lib/marshal/email-layout"));
|
|
19
|
+
const _runContext = require("../../lib/run-context");
|
|
20
|
+
function _interopRequireDefault(obj) {
|
|
21
|
+
return obj && obj.__esModule ? obj : {
|
|
22
|
+
default: obj
|
|
23
|
+
};
|
|
24
|
+
}
|
|
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 _interopRequireWildcard(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
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
48
|
+
for(var key in obj){
|
|
49
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
50
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
51
|
+
if (desc && (desc.get || desc.set)) {
|
|
52
|
+
Object.defineProperty(newObj, key, desc);
|
|
53
|
+
} else {
|
|
54
|
+
newObj[key] = obj[key];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
newObj.default = obj;
|
|
59
|
+
if (cache) {
|
|
60
|
+
cache.set(obj, newObj);
|
|
61
|
+
}
|
|
62
|
+
return newObj;
|
|
63
|
+
}
|
|
64
|
+
class EmailLayoutPull extends _baseCommand.default {
|
|
65
|
+
async run() {
|
|
66
|
+
const { args , flags } = this.props;
|
|
67
|
+
if (flags.all && args.emailLayoutKey) {
|
|
68
|
+
return this.error(`emailLayoutKey arg \`${args.emailLayoutKey}\` cannot also be provided when using --all`);
|
|
69
|
+
}
|
|
70
|
+
return flags.all ? this.pullAllEmailLayouts() : this.pullOneEmailLayout();
|
|
71
|
+
}
|
|
72
|
+
// Pull one email layout
|
|
73
|
+
async pullOneEmailLayout() {
|
|
74
|
+
const { flags } = this.props;
|
|
75
|
+
const dirContext = await this.getEmailLayoutDirContext();
|
|
76
|
+
if (dirContext.exists) {
|
|
77
|
+
this.log(`‣ Found \`${dirContext.key}\` at ${dirContext.abspath}`);
|
|
78
|
+
} else {
|
|
79
|
+
const prompt = `Create a new email layout directory \`${dirContext.key}\` at ${dirContext.abspath}?`;
|
|
80
|
+
const input = flags.force || await (0, _ux.promptToConfirm)(prompt);
|
|
81
|
+
if (!input) return;
|
|
82
|
+
}
|
|
83
|
+
const resp = await (0, _request.withSpinner)(()=>{
|
|
84
|
+
const props = (0, _object.merge)(this.props, {
|
|
85
|
+
args: {
|
|
86
|
+
emailLayoutKey: dirContext.key
|
|
87
|
+
},
|
|
88
|
+
flags: {
|
|
89
|
+
annotate: true
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
return this.apiV1.getEmailLayout(props);
|
|
93
|
+
});
|
|
94
|
+
await _emailLayout.writeEmailLayoutDirFromData(dirContext, resp.data);
|
|
95
|
+
const action = dirContext.exists ? "updated" : "created";
|
|
96
|
+
this.log(`‣ Successfully ${action} \`${dirContext.key}\` at ${dirContext.abspath}`);
|
|
97
|
+
}
|
|
98
|
+
// Pull all email layouts
|
|
99
|
+
async pullAllEmailLayouts() {
|
|
100
|
+
const { flags } = this.props;
|
|
101
|
+
const defaultToCwd = {
|
|
102
|
+
abspath: this.runContext.cwd,
|
|
103
|
+
exists: true
|
|
104
|
+
};
|
|
105
|
+
const targetDirCtx = flags["layouts-dir"] || defaultToCwd;
|
|
106
|
+
const prompt = targetDirCtx.exists ? `Pull latest layouts into ${targetDirCtx.abspath}?\n This will overwrite the contents of this directory.` : `Create a new layouts directory at ${targetDirCtx.abspath}?`;
|
|
107
|
+
const input = flags.force || await (0, _ux.promptToConfirm)(prompt);
|
|
108
|
+
if (!input) return;
|
|
109
|
+
_ux.spinner.start(`‣ Loading`);
|
|
110
|
+
const emailLayouts = await this.listAllEmailLayouts();
|
|
111
|
+
await _emailLayout.writeEmailLayoutIndexDir(targetDirCtx, emailLayouts);
|
|
112
|
+
_ux.spinner.stop();
|
|
113
|
+
const action = targetDirCtx.exists ? "updated" : "created";
|
|
114
|
+
this.log(`‣ Successfully ${action} the layouts directory at ${targetDirCtx.abspath}`);
|
|
115
|
+
}
|
|
116
|
+
async listAllEmailLayouts(pageParams = {}, emailLayoutsFetchedSoFar = []) {
|
|
117
|
+
const props = (0, _object.merge)(this.props, {
|
|
118
|
+
flags: {
|
|
119
|
+
...pageParams,
|
|
120
|
+
annotate: true,
|
|
121
|
+
limit: _page.MAX_PAGINATION_LIMIT
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
const resp = await this.apiV1.listEmailLayouts(props);
|
|
125
|
+
if (!(0, _request.isSuccessResp)(resp)) {
|
|
126
|
+
const message = (0, _request.formatErrorRespMessage)(resp);
|
|
127
|
+
this.error(new _error.ApiError(message));
|
|
128
|
+
}
|
|
129
|
+
const { entries , page_info: pageInfo } = resp.data;
|
|
130
|
+
const emailLayouts = [
|
|
131
|
+
...emailLayoutsFetchedSoFar,
|
|
132
|
+
...entries
|
|
133
|
+
];
|
|
134
|
+
return pageInfo.after ? this.listAllEmailLayouts({
|
|
135
|
+
after: pageInfo.after
|
|
136
|
+
}, emailLayouts) : emailLayouts;
|
|
137
|
+
}
|
|
138
|
+
async getEmailLayoutDirContext() {
|
|
139
|
+
const { emailLayoutKey } = this.props.args;
|
|
140
|
+
const { resourceDir , cwd: runCwd } = this.runContext;
|
|
141
|
+
// Inside an existing resource dir, use it if valid for the target email layout.
|
|
142
|
+
if (resourceDir) {
|
|
143
|
+
const target = {
|
|
144
|
+
commandId: _baseCommand.default.id,
|
|
145
|
+
type: "email_layout",
|
|
146
|
+
key: emailLayoutKey
|
|
147
|
+
};
|
|
148
|
+
return (0, _runContext.ensureResourceDirForTarget)(resourceDir, target);
|
|
149
|
+
}
|
|
150
|
+
// Not inside any existing email layout directory, which means either create a
|
|
151
|
+
// new email layout directory in the cwd, or update it if there is one already.
|
|
152
|
+
if (emailLayoutKey) {
|
|
153
|
+
const dirPath = _nodePath.resolve(runCwd, emailLayoutKey);
|
|
154
|
+
const exists = await _emailLayout.isEmailLayoutDir(dirPath);
|
|
155
|
+
return {
|
|
156
|
+
type: "email_layout",
|
|
157
|
+
key: emailLayoutKey,
|
|
158
|
+
abspath: dirPath,
|
|
159
|
+
exists
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
// Not in any email layout directory, nor a email layout key arg was given so error.
|
|
163
|
+
return this.error("Missing 1 required arg:\nemailLayoutKey");
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
EmailLayoutPull.aliases = [
|
|
167
|
+
"email-layout:pull",
|
|
168
|
+
"email_layout:pull"
|
|
169
|
+
];
|
|
170
|
+
EmailLayoutPull.summary = "Pull one or more email layouts from an environment into a local file system.";
|
|
171
|
+
EmailLayoutPull.flags = {
|
|
172
|
+
environment: _core.Flags.string({
|
|
173
|
+
default: "development",
|
|
174
|
+
summary: "The environment to use."
|
|
175
|
+
}),
|
|
176
|
+
all: _core.Flags.boolean({
|
|
177
|
+
summary: "Whether to pull all email layouts from the specified environment."
|
|
178
|
+
}),
|
|
179
|
+
"layouts-dir": _flag.dirPath({
|
|
180
|
+
summary: "The target directory path to pull all email layouts into.",
|
|
181
|
+
dependsOn: [
|
|
182
|
+
"all"
|
|
183
|
+
],
|
|
184
|
+
aliases: [
|
|
185
|
+
"email-layouts-dir"
|
|
186
|
+
]
|
|
187
|
+
}),
|
|
188
|
+
"hide-uncommitted-changes": _core.Flags.boolean({
|
|
189
|
+
summary: "Hide any uncommitted changes."
|
|
190
|
+
}),
|
|
191
|
+
force: _core.Flags.boolean({
|
|
192
|
+
summary: "Remove the confirmation prompt."
|
|
193
|
+
})
|
|
194
|
+
};
|
|
195
|
+
EmailLayoutPull.args = {
|
|
196
|
+
emailLayoutKey: _core.Args.string({
|
|
197
|
+
required: false
|
|
198
|
+
})
|
|
199
|
+
};
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "default", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: ()=>EmailLayoutPush
|
|
8
|
+
});
|
|
9
|
+
const _core = require("@oclif/core");
|
|
10
|
+
const _baseCommand = /*#__PURE__*/ _interopRequireDefault(require("../../lib/base-command"));
|
|
11
|
+
const _const = require("../../lib/helpers/const");
|
|
12
|
+
const _error = require("../../lib/helpers/error");
|
|
13
|
+
const _flag = /*#__PURE__*/ _interopRequireWildcard(require("../../lib/helpers/flag"));
|
|
14
|
+
const _object = require("../../lib/helpers/object");
|
|
15
|
+
const _request = require("../../lib/helpers/request");
|
|
16
|
+
const _string = require("../../lib/helpers/string");
|
|
17
|
+
const _ux = require("../../lib/helpers/ux");
|
|
18
|
+
const _emailLayout = /*#__PURE__*/ _interopRequireWildcard(require("../../lib/marshal/email-layout"));
|
|
19
|
+
const _validate = /*#__PURE__*/ _interopRequireDefault(require("./validate"));
|
|
20
|
+
function _interopRequireDefault(obj) {
|
|
21
|
+
return obj && obj.__esModule ? obj : {
|
|
22
|
+
default: obj
|
|
23
|
+
};
|
|
24
|
+
}
|
|
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 _interopRequireWildcard(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
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
48
|
+
for(var key in obj){
|
|
49
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
50
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
51
|
+
if (desc && (desc.get || desc.set)) {
|
|
52
|
+
Object.defineProperty(newObj, key, desc);
|
|
53
|
+
} else {
|
|
54
|
+
newObj[key] = obj[key];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
newObj.default = obj;
|
|
59
|
+
if (cache) {
|
|
60
|
+
cache.set(obj, newObj);
|
|
61
|
+
}
|
|
62
|
+
return newObj;
|
|
63
|
+
}
|
|
64
|
+
class EmailLayoutPush extends _baseCommand.default {
|
|
65
|
+
async run() {
|
|
66
|
+
const { flags } = this.props;
|
|
67
|
+
// 1. First read all layout directories found for the given command.
|
|
68
|
+
const target = await _emailLayout.ensureValidCommandTarget(this.props, this.runContext);
|
|
69
|
+
const [layouts, readErrors] = await _emailLayout.readAllForCommandTarget(target, {
|
|
70
|
+
withExtractedFiles: true
|
|
71
|
+
});
|
|
72
|
+
if (readErrors.length > 0) {
|
|
73
|
+
this.error((0, _error.formatErrors)(readErrors, {
|
|
74
|
+
prependBy: "\n\n"
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
if (layouts.length === 0) {
|
|
78
|
+
this.error(`No layout directories found in ${target.context.abspath}`);
|
|
79
|
+
}
|
|
80
|
+
// 2. Then validate them all ahead of pushing them.
|
|
81
|
+
_ux.spinner.start(`‣ Validating`);
|
|
82
|
+
const apiErrors = await _validate.default.validateAll(this.apiV1, this.props, layouts);
|
|
83
|
+
if (apiErrors.length > 0) {
|
|
84
|
+
this.error((0, _error.formatErrors)(apiErrors, {
|
|
85
|
+
prependBy: "\n\n"
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
_ux.spinner.stop();
|
|
89
|
+
// 3. Finally push up each layout, abort on the first error.
|
|
90
|
+
_ux.spinner.start(`‣ Pushing`);
|
|
91
|
+
for (const layout of layouts){
|
|
92
|
+
const props = (0, _object.merge)(this.props, {
|
|
93
|
+
flags: {
|
|
94
|
+
annotate: true
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
// eslint-disable-next-line no-await-in-loop
|
|
98
|
+
const resp = await this.apiV1.upsertEmailLayout(props, {
|
|
99
|
+
...layout.content,
|
|
100
|
+
key: layout.key
|
|
101
|
+
});
|
|
102
|
+
if ((0, _request.isSuccessResp)(resp)) {
|
|
103
|
+
// Update the layout directory with the successfully pushed layout
|
|
104
|
+
// payload from the server.
|
|
105
|
+
// eslint-disable-next-line no-await-in-loop
|
|
106
|
+
await _emailLayout.writeEmailLayoutDirFromData(layout, resp.data.email_layout);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const error = new _error.SourceError((0, _request.formatErrorRespMessage)(resp), _emailLayout.emailLayoutJsonPath(layout), "ApiError");
|
|
110
|
+
this.error((0, _error.formatError)(error));
|
|
111
|
+
}
|
|
112
|
+
_ux.spinner.stop();
|
|
113
|
+
// 4. Display a success message.
|
|
114
|
+
const layoutKeys = layouts.map((l)=>l.key);
|
|
115
|
+
const actioned = flags.commit ? "pushed and committed" : "pushed";
|
|
116
|
+
this.log(`‣ Successfully ${actioned} ${layouts.length} layout(s):\n` + (0, _string.indentString)(layoutKeys.join("\n"), 4));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
EmailLayoutPush.aliases = [
|
|
120
|
+
"email-layout:push",
|
|
121
|
+
"email_layout:push"
|
|
122
|
+
];
|
|
123
|
+
EmailLayoutPush.summary = "Push one or more email layouts from a local file system to Knock.";
|
|
124
|
+
EmailLayoutPush.flags = {
|
|
125
|
+
environment: _core.Flags.string({
|
|
126
|
+
summary: "Pushing an email layout is only allowed in the development environment",
|
|
127
|
+
default: _const.KnockEnv.Development,
|
|
128
|
+
options: [
|
|
129
|
+
_const.KnockEnv.Development
|
|
130
|
+
]
|
|
131
|
+
}),
|
|
132
|
+
all: _core.Flags.boolean({
|
|
133
|
+
summary: "Whether to push all layouts from the target directory."
|
|
134
|
+
}),
|
|
135
|
+
"layouts-dir": _flag.dirPath({
|
|
136
|
+
summary: "The target directory path to find all layouts to push.",
|
|
137
|
+
dependsOn: [
|
|
138
|
+
"all"
|
|
139
|
+
],
|
|
140
|
+
aliases: [
|
|
141
|
+
"email-layouts-dir"
|
|
142
|
+
]
|
|
143
|
+
}),
|
|
144
|
+
commit: _core.Flags.boolean({
|
|
145
|
+
summary: "Push and commit the layout(s) at the same time"
|
|
146
|
+
}),
|
|
147
|
+
"commit-message": _core.Flags.string({
|
|
148
|
+
summary: "Use the given value as the commit message",
|
|
149
|
+
char: "m",
|
|
150
|
+
dependsOn: [
|
|
151
|
+
"commit"
|
|
152
|
+
]
|
|
153
|
+
})
|
|
154
|
+
};
|
|
155
|
+
EmailLayoutPush.args = {
|
|
156
|
+
emailLayoutKey: _core.Args.string({
|
|
157
|
+
required: false
|
|
158
|
+
})
|
|
159
|
+
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "default", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: ()=>EmailLayoutValidate
|
|
8
|
+
});
|
|
9
|
+
const _core = require("@oclif/core");
|
|
10
|
+
const _baseCommand = /*#__PURE__*/ _interopRequireDefault(require("../../lib/base-command"));
|
|
11
|
+
const _const = require("../../lib/helpers/const");
|
|
12
|
+
const _error = require("../../lib/helpers/error");
|
|
13
|
+
const _flag = /*#__PURE__*/ _interopRequireWildcard(require("../../lib/helpers/flag"));
|
|
14
|
+
const _request = require("../../lib/helpers/request");
|
|
15
|
+
const _string = require("../../lib/helpers/string");
|
|
16
|
+
const _ux = require("../../lib/helpers/ux");
|
|
17
|
+
const _emailLayout = /*#__PURE__*/ _interopRequireWildcard(require("../../lib/marshal/email-layout"));
|
|
18
|
+
function _interopRequireDefault(obj) {
|
|
19
|
+
return obj && obj.__esModule ? obj : {
|
|
20
|
+
default: obj
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
24
|
+
if (typeof WeakMap !== "function") return null;
|
|
25
|
+
var cacheBabelInterop = new WeakMap();
|
|
26
|
+
var cacheNodeInterop = new WeakMap();
|
|
27
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
28
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
29
|
+
})(nodeInterop);
|
|
30
|
+
}
|
|
31
|
+
function _interopRequireWildcard(obj, nodeInterop) {
|
|
32
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
33
|
+
return obj;
|
|
34
|
+
}
|
|
35
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
36
|
+
return {
|
|
37
|
+
default: obj
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
41
|
+
if (cache && cache.has(obj)) {
|
|
42
|
+
return cache.get(obj);
|
|
43
|
+
}
|
|
44
|
+
var newObj = {};
|
|
45
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
46
|
+
for(var key in obj){
|
|
47
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
48
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
49
|
+
if (desc && (desc.get || desc.set)) {
|
|
50
|
+
Object.defineProperty(newObj, key, desc);
|
|
51
|
+
} else {
|
|
52
|
+
newObj[key] = obj[key];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
newObj.default = obj;
|
|
57
|
+
if (cache) {
|
|
58
|
+
cache.set(obj, newObj);
|
|
59
|
+
}
|
|
60
|
+
return newObj;
|
|
61
|
+
}
|
|
62
|
+
class EmailLayoutValidate extends _baseCommand.default {
|
|
63
|
+
async run() {
|
|
64
|
+
// 1. Read all layout directories found for the given command.
|
|
65
|
+
const target = await _emailLayout.ensureValidCommandTarget(this.props, this.runContext);
|
|
66
|
+
const [layouts, readErrors] = await _emailLayout.readAllForCommandTarget(target, {
|
|
67
|
+
withExtractedFiles: true
|
|
68
|
+
});
|
|
69
|
+
if (readErrors.length > 0) {
|
|
70
|
+
this.error((0, _error.formatErrors)(readErrors, {
|
|
71
|
+
prependBy: "\n\n"
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
if (layouts.length === 0) {
|
|
75
|
+
this.error(`No layout directories found in ${target.context.abspath}`);
|
|
76
|
+
}
|
|
77
|
+
// 2. Validate each layout data
|
|
78
|
+
_ux.spinner.start(`‣ Validating`);
|
|
79
|
+
const apiErrors = await EmailLayoutValidate.validateAll(this.apiV1, this.props, layouts);
|
|
80
|
+
if (apiErrors.length > 0) {
|
|
81
|
+
this.error((0, _error.formatErrors)(apiErrors, {
|
|
82
|
+
prependBy: "\n\n"
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
_ux.spinner.stop();
|
|
86
|
+
// 3. Display a success message.
|
|
87
|
+
const layoutsKey = layouts.map((l)=>l.key);
|
|
88
|
+
this.log(`‣ Successfully validated ${layouts.length} layout(s):\n` + (0, _string.indentString)(layoutsKey.join("\n"), 4));
|
|
89
|
+
}
|
|
90
|
+
static async validateAll(api, props, layouts) {
|
|
91
|
+
const errorPromises = layouts.map(async (layout)=>{
|
|
92
|
+
const resp = await api.validateEmailLayout(props, {
|
|
93
|
+
...layout.content,
|
|
94
|
+
key: layout.key
|
|
95
|
+
});
|
|
96
|
+
if ((0, _request.isSuccessResp)(resp)) return;
|
|
97
|
+
const error = new _error.SourceError((0, _request.formatErrorRespMessage)(resp), _emailLayout.emailLayoutJsonPath(layout), "ApiError");
|
|
98
|
+
return error;
|
|
99
|
+
});
|
|
100
|
+
const errors = (await Promise.all(errorPromises)).filter((e)=>Boolean(e));
|
|
101
|
+
return errors;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
EmailLayoutValidate.aliases = [
|
|
105
|
+
"email-layout:validate",
|
|
106
|
+
"email_layout:validate"
|
|
107
|
+
];
|
|
108
|
+
EmailLayoutValidate.summary = "Validate one or more layouts from a local file system.";
|
|
109
|
+
EmailLayoutValidate.flags = {
|
|
110
|
+
environment: _core.Flags.string({
|
|
111
|
+
summary: "Validating a layout is only done in the development environment",
|
|
112
|
+
default: _const.KnockEnv.Development,
|
|
113
|
+
options: [
|
|
114
|
+
_const.KnockEnv.Development
|
|
115
|
+
]
|
|
116
|
+
}),
|
|
117
|
+
all: _core.Flags.boolean({
|
|
118
|
+
summary: "Whether to validate all layouts from the target directory."
|
|
119
|
+
}),
|
|
120
|
+
"layouts-dir": _flag.dirPath({
|
|
121
|
+
summary: "The target directory path to find all layouts to validate.",
|
|
122
|
+
dependsOn: [
|
|
123
|
+
"all"
|
|
124
|
+
],
|
|
125
|
+
aliases: [
|
|
126
|
+
"email-layouts-dir"
|
|
127
|
+
]
|
|
128
|
+
})
|
|
129
|
+
};
|
|
130
|
+
EmailLayoutValidate.args = {
|
|
131
|
+
emailLayoutKey: _core.Args.string({
|
|
132
|
+
required: false
|
|
133
|
+
})
|
|
134
|
+
};
|
|
@@ -9,7 +9,10 @@ Object.defineProperty(exports, "default", {
|
|
|
9
9
|
const _core = require("@oclif/core");
|
|
10
10
|
const _baseCommand = /*#__PURE__*/ _interopRequireDefault(require("../../lib/base-command"));
|
|
11
11
|
const _date = require("../../lib/helpers/date");
|
|
12
|
+
const _error = require("../../lib/helpers/error");
|
|
12
13
|
const _request = require("../../lib/helpers/request");
|
|
14
|
+
const _string = require("../../lib/helpers/string");
|
|
15
|
+
const _ux = require("../../lib/helpers/ux");
|
|
13
16
|
const _conditions = /*#__PURE__*/ _interopRequireWildcard(require("../../lib/marshal/conditions"));
|
|
14
17
|
const _workflow = /*#__PURE__*/ _interopRequireWildcard(require("../../lib/marshal/workflow"));
|
|
15
18
|
function _interopRequireDefault(obj) {
|
|
@@ -58,12 +61,30 @@ function _interopRequireWildcard(obj, nodeInterop) {
|
|
|
58
61
|
}
|
|
59
62
|
class WorkflowGet extends _baseCommand.default {
|
|
60
63
|
async run() {
|
|
61
|
-
|
|
64
|
+
_ux.spinner.start("‣ Loading");
|
|
65
|
+
const { workflow , whoami } = await this.loadWorkflow();
|
|
66
|
+
_ux.spinner.stop();
|
|
62
67
|
const { flags } = this.props;
|
|
63
|
-
if (flags.json) return
|
|
64
|
-
this.render(
|
|
68
|
+
if (flags.json) return workflow;
|
|
69
|
+
this.render(workflow, whoami);
|
|
65
70
|
}
|
|
66
|
-
|
|
71
|
+
async loadWorkflow() {
|
|
72
|
+
const workflowResp = await this.apiV1.getWorkflow(this.props);
|
|
73
|
+
if (!(0, _request.isSuccessResp)(workflowResp)) {
|
|
74
|
+
const message = (0, _request.formatErrorRespMessage)(workflowResp);
|
|
75
|
+
_core.ux.error(new _error.ApiError(message));
|
|
76
|
+
}
|
|
77
|
+
const whoamiResp = await this.apiV1.whoami();
|
|
78
|
+
if (!(0, _request.isSuccessResp)(whoamiResp)) {
|
|
79
|
+
const message = (0, _request.formatErrorRespMessage)(whoamiResp);
|
|
80
|
+
_core.ux.error(new _error.ApiError(message));
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
workflow: workflowResp.data,
|
|
84
|
+
whoami: whoamiResp.data
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
render(workflow, whoami) {
|
|
67
88
|
const { workflowKey } = this.props.args;
|
|
68
89
|
const { environment: env , "hide-uncommitted-changes": commitedOnly } = this.props.flags;
|
|
69
90
|
const qualifier = env === "development" && !commitedOnly ? "(including uncommitted)" : "";
|
|
@@ -130,11 +151,13 @@ class WorkflowGet extends _baseCommand.default {
|
|
|
130
151
|
},
|
|
131
152
|
ref: {
|
|
132
153
|
header: "Ref",
|
|
133
|
-
minWidth: 18
|
|
154
|
+
minWidth: 18,
|
|
155
|
+
get: (step)=>step.ref
|
|
134
156
|
},
|
|
135
157
|
type: {
|
|
136
158
|
header: "Type",
|
|
137
|
-
minWidth: 12
|
|
159
|
+
minWidth: 12,
|
|
160
|
+
get: (step)=>step.type
|
|
138
161
|
},
|
|
139
162
|
summary: {
|
|
140
163
|
header: "Summary",
|
|
@@ -142,9 +165,18 @@ class WorkflowGet extends _baseCommand.default {
|
|
|
142
165
|
},
|
|
143
166
|
conditions: {
|
|
144
167
|
header: "Conditions",
|
|
145
|
-
get: (step)=>
|
|
168
|
+
get: (step)=>{
|
|
169
|
+
if (step.type === _workflow.StepType.Branch) return "-";
|
|
170
|
+
if (!step.conditions) return "-";
|
|
171
|
+
return _conditions.formatConditions(step.conditions);
|
|
172
|
+
}
|
|
146
173
|
}
|
|
147
174
|
});
|
|
175
|
+
const hasTopLevelBranchStep = workflow.steps.some((step)=>step.type === _workflow.StepType.Branch);
|
|
176
|
+
const dashboardLinkMessage = hasTopLevelBranchStep ? `\n‣ This workflow has branches with nested steps, view the full workflow tree in the Knock Dashboard:` : `\n‣ View the full workflow in the Knock Dashboard:`;
|
|
177
|
+
const viewWorkflowUrl = `https://dashboard.knock.app/${whoami.account_slug}/${env.toLowerCase()}/workflows/${workflow.key}`;
|
|
178
|
+
this.log(dashboardLinkMessage);
|
|
179
|
+
this.log((0, _string.indentString)(viewWorkflowUrl, 2));
|
|
148
180
|
}
|
|
149
181
|
}
|
|
150
182
|
WorkflowGet.summary = "Display a single workflow from an environment.";
|
|
@@ -98,7 +98,10 @@ class WorkflowList extends _baseCommand.default {
|
|
|
98
98
|
},
|
|
99
99
|
steps: {
|
|
100
100
|
header: "Steps",
|
|
101
|
-
get: (entry)=>
|
|
101
|
+
get: (entry)=>{
|
|
102
|
+
const result = _workflow.countSteps(entry);
|
|
103
|
+
return result > 0 ? result : "-";
|
|
104
|
+
}
|
|
102
105
|
},
|
|
103
106
|
updated_at: {
|
|
104
107
|
header: "Updated at",
|