@knocklabs/cli 0.2.4 → 0.3.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 +80 -84
- package/dist/commands/commit/list.js +11 -5
- package/dist/commands/guide/pull.js +6 -2
- package/dist/commands/guide/push.js +5 -6
- package/dist/commands/guide/validate.js +2 -5
- package/dist/commands/layout/pull.js +6 -2
- package/dist/commands/layout/push.js +3 -1
- package/dist/commands/message-type/pull.js +6 -2
- package/dist/commands/message-type/push.js +3 -1
- package/dist/commands/partial/pull.js +6 -2
- package/dist/commands/partial/push.js +3 -1
- package/dist/commands/translation/get.js +1 -0
- package/dist/commands/translation/list.js +1 -0
- package/dist/commands/translation/pull.js +1 -0
- package/dist/commands/translation/push.js +1 -0
- package/dist/commands/translation/validate.js +1 -0
- package/dist/commands/workflow/new.js +8 -9
- package/dist/commands/workflow/pull.js +6 -2
- package/dist/commands/workflow/push.js +5 -6
- package/dist/commands/workflow/validate.js +2 -5
- package/dist/lib/base-command.js +17 -1
- package/dist/lib/helpers/account-features.js +53 -0
- package/dist/lib/marshal/email-layout/processor.isomorphic.js +3 -2
- package/dist/lib/marshal/email-layout/writer.js +6 -4
- package/dist/lib/marshal/guide/processor.isomorphic.js +3 -2
- package/dist/lib/marshal/guide/writer.js +6 -4
- package/dist/lib/marshal/message-type/processor.isomorphic.js +3 -2
- package/dist/lib/marshal/message-type/writer.js +6 -4
- package/dist/lib/marshal/partial/processor.isomorphic.js +3 -2
- package/dist/lib/marshal/partial/writer.js +6 -4
- package/dist/lib/marshal/shared/helpers.isomorphic.js +7 -1
- package/dist/lib/marshal/workflow/processor.isomorphic.js +3 -2
- package/dist/lib/marshal/workflow/writer.js +6 -4
- package/oclif.manifest.json +20 -19
- package/package.json +7 -4
|
@@ -109,7 +109,9 @@ class EmailLayoutPull extends _basecommand.default {
|
|
|
109
109
|
});
|
|
110
110
|
return this.apiV1.getEmailLayout(props);
|
|
111
111
|
});
|
|
112
|
-
await _emaillayout.writeEmailLayoutDirFromData(dirContext, resp.data
|
|
112
|
+
await _emaillayout.writeEmailLayoutDirFromData(dirContext, resp.data, {
|
|
113
|
+
withSchema: true
|
|
114
|
+
});
|
|
113
115
|
const action = dirContext.exists ? "updated" : "created";
|
|
114
116
|
const scope = (0, _command.formatCommandScope)(flags);
|
|
115
117
|
this.log(`‣ Successfully ${action} \`${dirContext.key}\` at ${dirContext.abspath} using ${scope}`);
|
|
@@ -127,7 +129,9 @@ class EmailLayoutPull extends _basecommand.default {
|
|
|
127
129
|
if (!input) return;
|
|
128
130
|
_ux.spinner.start(`‣ Loading`);
|
|
129
131
|
const emailLayouts = await this.listAllEmailLayouts();
|
|
130
|
-
await _emaillayout.writeEmailLayoutIndexDir(targetDirCtx, emailLayouts
|
|
132
|
+
await _emaillayout.writeEmailLayoutIndexDir(targetDirCtx, emailLayouts, {
|
|
133
|
+
withSchema: true
|
|
134
|
+
});
|
|
131
135
|
_ux.spinner.stop();
|
|
132
136
|
const action = targetDirCtx.exists ? "updated" : "created";
|
|
133
137
|
const scope = (0, _command.formatCommandScope)(flags);
|
|
@@ -121,7 +121,9 @@ class EmailLayoutPush extends _basecommand.default {
|
|
|
121
121
|
// Update the layout directory with the successfully pushed layout
|
|
122
122
|
// payload from the server.
|
|
123
123
|
// eslint-disable-next-line no-await-in-loop
|
|
124
|
-
await _emaillayout.writeEmailLayoutDirFromData(layout, resp.data.email_layout
|
|
124
|
+
await _emaillayout.writeEmailLayoutDirFromData(layout, resp.data.email_layout, {
|
|
125
|
+
withSchema: true
|
|
126
|
+
});
|
|
125
127
|
continue;
|
|
126
128
|
}
|
|
127
129
|
const error = new _error.SourceError((0, _request.formatErrorRespMessage)(resp), _emaillayout.emailLayoutJsonPath(layout), "ApiError");
|
|
@@ -112,7 +112,9 @@ class MessageTypePull extends _basecommand.default {
|
|
|
112
112
|
});
|
|
113
113
|
return this.apiV1.getMessageType(props);
|
|
114
114
|
});
|
|
115
|
-
await _messagetype.writeMessageTypeDirFromData(dirContext, resp.data
|
|
115
|
+
await _messagetype.writeMessageTypeDirFromData(dirContext, resp.data, {
|
|
116
|
+
withSchema: true
|
|
117
|
+
});
|
|
116
118
|
const action = dirContext.exists ? "updated" : "created";
|
|
117
119
|
const scope = (0, _command.formatCommandScope)(flags);
|
|
118
120
|
this.log(`‣ Successfully ${action} \`${dirContext.key}\` at ${dirContext.abspath} using ${scope}`);
|
|
@@ -161,7 +163,9 @@ class MessageTypePull extends _basecommand.default {
|
|
|
161
163
|
if (!input) return;
|
|
162
164
|
_ux.spinner.start(`‣ Loading`);
|
|
163
165
|
const messageTypes = await this.listAllMessageTypes();
|
|
164
|
-
await _messagetype.writeMessageTypesIndexDir(targetDirCtx, messageTypes
|
|
166
|
+
await _messagetype.writeMessageTypesIndexDir(targetDirCtx, messageTypes, {
|
|
167
|
+
withSchema: true
|
|
168
|
+
});
|
|
165
169
|
_ux.spinner.stop();
|
|
166
170
|
const action = targetDirCtx.exists ? "updated" : "created";
|
|
167
171
|
const scope = (0, _command.formatCommandScope)(flags);
|
|
@@ -121,7 +121,9 @@ class MessageTypePush extends _basecommand.default {
|
|
|
121
121
|
// Update the message type directory with the successfully pushed message
|
|
122
122
|
// type payload from the server.
|
|
123
123
|
// eslint-disable-next-line no-await-in-loop
|
|
124
|
-
await _messagetype.writeMessageTypeDirFromData(messageType, resp.data.message_type
|
|
124
|
+
await _messagetype.writeMessageTypeDirFromData(messageType, resp.data.message_type, {
|
|
125
|
+
withSchema: true
|
|
126
|
+
});
|
|
125
127
|
continue;
|
|
126
128
|
}
|
|
127
129
|
const error = new _error.SourceError((0, _request.formatErrorRespMessage)(resp), _messagetype.messageTypeJsonPath(messageType), "ApiError");
|
|
@@ -109,7 +109,9 @@ class PartialPull extends _basecommand.default {
|
|
|
109
109
|
});
|
|
110
110
|
return this.apiV1.getPartial(props);
|
|
111
111
|
});
|
|
112
|
-
await _partial.writePartialDirFromData(dirContext, resp.data
|
|
112
|
+
await _partial.writePartialDirFromData(dirContext, resp.data, {
|
|
113
|
+
withSchema: true
|
|
114
|
+
});
|
|
113
115
|
const action = dirContext.exists ? "updated" : "created";
|
|
114
116
|
const scope = (0, _command.formatCommandScope)(flags);
|
|
115
117
|
this.log(`‣ Successfully ${action} \`${dirContext.key}\` at ${dirContext.abspath} using ${scope}`);
|
|
@@ -127,7 +129,9 @@ class PartialPull extends _basecommand.default {
|
|
|
127
129
|
if (!input) return;
|
|
128
130
|
_ux.spinner.start(`‣ Loading`);
|
|
129
131
|
const partials = await this.listAllPartials();
|
|
130
|
-
await _partial.writePartialsIndexDir(targetDirCtx, partials
|
|
132
|
+
await _partial.writePartialsIndexDir(targetDirCtx, partials, {
|
|
133
|
+
withSchema: true
|
|
134
|
+
});
|
|
131
135
|
_ux.spinner.stop();
|
|
132
136
|
const action = targetDirCtx.exists ? "updated" : "created";
|
|
133
137
|
const scope = (0, _command.formatCommandScope)(flags);
|
|
@@ -121,7 +121,9 @@ class PartialPush extends _basecommand.default {
|
|
|
121
121
|
// Update the partial directory with the successfully pushed partial
|
|
122
122
|
// payload from the server.
|
|
123
123
|
// eslint-disable-next-line no-await-in-loop
|
|
124
|
-
await _partial.writePartialDirFromData(partial, resp.data.partial
|
|
124
|
+
await _partial.writePartialDirFromData(partial, resp.data.partial, {
|
|
125
|
+
withSchema: true
|
|
126
|
+
});
|
|
125
127
|
continue;
|
|
126
128
|
}
|
|
127
129
|
const error = new _error.SourceError((0, _request.formatErrorRespMessage)(resp), _partial.partialJsonPath(partial), "ApiError");
|
|
@@ -134,6 +134,7 @@ class TranslationGet extends _basecommand.default {
|
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
_define_property(TranslationGet, "summary", "Display a single translation from an environment.");
|
|
137
|
+
_define_property(TranslationGet, "verifyFeatureEnabled", "translations");
|
|
137
138
|
_define_property(TranslationGet, "flags", {
|
|
138
139
|
environment: _core.Flags.string({
|
|
139
140
|
default: "development",
|
|
@@ -137,6 +137,7 @@ class TranslationList extends _basecommand.default {
|
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
_define_property(TranslationList, "summary", "Display all translations for an environment.");
|
|
140
|
+
_define_property(TranslationList, "verifyFeatureEnabled", "translations");
|
|
140
141
|
_define_property(TranslationList, "flags", {
|
|
141
142
|
environment: _core.Flags.string({
|
|
142
143
|
default: "development",
|
|
@@ -173,6 +173,7 @@ class TranslationPull extends _basecommand.default {
|
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
_define_property(TranslationPull, "summary", "Pull one or more translations from an environment into a local file system.");
|
|
176
|
+
_define_property(TranslationPull, "verifyFeatureEnabled", "translations");
|
|
176
177
|
_define_property(TranslationPull, "flags", {
|
|
177
178
|
environment: _core.Flags.string({
|
|
178
179
|
default: "development",
|
|
@@ -125,6 +125,7 @@ class TranslationPush extends _basecommand.default {
|
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
_define_property(TranslationPush, "summary", "Push one or more translations from a local file system to Knock.");
|
|
128
|
+
_define_property(TranslationPush, "verifyFeatureEnabled", "translations");
|
|
128
129
|
_define_property(TranslationPush, "flags", {
|
|
129
130
|
environment: _core.Flags.string({
|
|
130
131
|
summary: "Pushing a translation is only allowed in the development environment",
|
|
@@ -120,6 +120,7 @@ class TranslationValidate extends _basecommand.default {
|
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
_define_property(TranslationValidate, "summary", "Validate one or more translations from a local file system.");
|
|
123
|
+
_define_property(TranslationValidate, "verifyFeatureEnabled", "translations");
|
|
123
124
|
_define_property(TranslationValidate, "flags", {
|
|
124
125
|
environment: _core.Flags.string({
|
|
125
126
|
summary: "Validating a translation is only done in the development environment",
|
|
@@ -12,7 +12,7 @@ const _nodepath = /*#__PURE__*/ _interop_require_wildcard(require("node:path"));
|
|
|
12
12
|
const _core = require("@oclif/core");
|
|
13
13
|
const _fsextra = /*#__PURE__*/ _interop_require_wildcard(require("fs-extra"));
|
|
14
14
|
const _basecommand = /*#__PURE__*/ _interop_require_default(require("../../lib/base-command"));
|
|
15
|
-
const
|
|
15
|
+
const _const = require("../../lib/helpers/const");
|
|
16
16
|
const _ux = require("../../lib/helpers/ux");
|
|
17
17
|
const _workflow = /*#__PURE__*/ _interop_require_wildcard(require("../../lib/marshal/workflow"));
|
|
18
18
|
function _define_property(obj, key, value) {
|
|
@@ -119,17 +119,12 @@ class WorkflowNew extends _basecommand.default {
|
|
|
119
119
|
const isExistingWorkflow = await this.checkExistingWorkflow();
|
|
120
120
|
if (isExistingWorkflow) {
|
|
121
121
|
this.log("");
|
|
122
|
-
this.warn(`Workflow \`${args.workflowKey}\` already exists in \`
|
|
122
|
+
this.warn(`Workflow \`${args.workflowKey}\` already exists in \`${flags.environment}\` environment`);
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
async checkExistingWorkflow() {
|
|
126
|
-
const props = (0, _objectisomorphic.merge)(this.props, {
|
|
127
|
-
flags: {
|
|
128
|
-
environment: "development"
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
126
|
try {
|
|
132
|
-
const resp = await this.apiV1.getWorkflow(props);
|
|
127
|
+
const resp = await this.apiV1.getWorkflow(this.props);
|
|
133
128
|
return resp.status === 200;
|
|
134
129
|
} catch {}
|
|
135
130
|
}
|
|
@@ -140,7 +135,11 @@ _define_property(WorkflowNew, "flags", {
|
|
|
140
135
|
"step"
|
|
141
136
|
]
|
|
142
137
|
}),
|
|
143
|
-
force: _core.Flags.boolean()
|
|
138
|
+
force: _core.Flags.boolean(),
|
|
139
|
+
environment: _core.Flags.string({
|
|
140
|
+
hidden: true,
|
|
141
|
+
default: _const.KnockEnv.Development
|
|
142
|
+
})
|
|
144
143
|
});
|
|
145
144
|
_define_property(WorkflowNew, "args", {
|
|
146
145
|
workflowKey: _core.Args.string({
|
|
@@ -113,7 +113,9 @@ class WorkflowPull extends _basecommand.default {
|
|
|
113
113
|
return this.apiV1.getWorkflow(props);
|
|
114
114
|
});
|
|
115
115
|
// 3. Write the fetched workflow to create or update the workflow directory.
|
|
116
|
-
await _workflow.writeWorkflowDirFromData(dirContext, resp.data
|
|
116
|
+
await _workflow.writeWorkflowDirFromData(dirContext, resp.data, {
|
|
117
|
+
withSchema: true
|
|
118
|
+
});
|
|
117
119
|
const action = dirContext.exists ? "updated" : "created";
|
|
118
120
|
const scope = (0, _command.formatCommandScope)(flags);
|
|
119
121
|
this.log(`‣ Successfully ${action} \`${dirContext.key}\` at ${dirContext.abspath} using ${scope}`);
|
|
@@ -162,7 +164,9 @@ class WorkflowPull extends _basecommand.default {
|
|
|
162
164
|
// Fetch all workflows then write them to the local file system.
|
|
163
165
|
_ux.spinner.start(`‣ Loading`);
|
|
164
166
|
const workflows = await this.listAllWorkflows();
|
|
165
|
-
await _workflow.writeWorkflowsIndexDir(targetDirCtx, workflows
|
|
167
|
+
await _workflow.writeWorkflowsIndexDir(targetDirCtx, workflows, {
|
|
168
|
+
withSchema: true
|
|
169
|
+
});
|
|
166
170
|
_ux.spinner.stop();
|
|
167
171
|
const action = targetDirCtx.exists ? "updated" : "created";
|
|
168
172
|
const scope = (0, _command.formatCommandScope)(flags);
|
|
@@ -121,7 +121,9 @@ class WorkflowPush extends _basecommand.default {
|
|
|
121
121
|
// Update the workflow directory with the successfully pushed workflow
|
|
122
122
|
// payload from the server.
|
|
123
123
|
// eslint-disable-next-line no-await-in-loop
|
|
124
|
-
await _workflow.writeWorkflowDirFromData(workflow, resp.data.workflow
|
|
124
|
+
await _workflow.writeWorkflowDirFromData(workflow, resp.data.workflow, {
|
|
125
|
+
withSchema: true
|
|
126
|
+
});
|
|
125
127
|
continue;
|
|
126
128
|
}
|
|
127
129
|
const error = new _error.SourceError((0, _request.formatErrorRespMessage)(resp), _workflow.workflowJsonPath(workflow), "ApiError");
|
|
@@ -138,11 +140,8 @@ class WorkflowPush extends _basecommand.default {
|
|
|
138
140
|
_define_property(WorkflowPush, "summary", "Push one or more workflows from a local file system to Knock.");
|
|
139
141
|
_define_property(WorkflowPush, "flags", {
|
|
140
142
|
environment: _core.Flags.string({
|
|
141
|
-
summary: "
|
|
142
|
-
default: _const.KnockEnv.Development
|
|
143
|
-
options: [
|
|
144
|
-
_const.KnockEnv.Development
|
|
145
|
-
]
|
|
143
|
+
summary: "The environment to push the workflow to. Defaults to development.",
|
|
144
|
+
default: _const.KnockEnv.Development
|
|
146
145
|
}),
|
|
147
146
|
branch: _flag.branch,
|
|
148
147
|
all: _core.Flags.boolean({
|
|
@@ -125,11 +125,8 @@ class WorkflowValidate extends _basecommand.default {
|
|
|
125
125
|
_define_property(WorkflowValidate, "summary", "Validate one or more workflows from a local file system.");
|
|
126
126
|
_define_property(WorkflowValidate, "flags", {
|
|
127
127
|
environment: _core.Flags.string({
|
|
128
|
-
summary: "
|
|
129
|
-
default: _const.KnockEnv.Development
|
|
130
|
-
options: [
|
|
131
|
-
_const.KnockEnv.Development
|
|
132
|
-
]
|
|
128
|
+
summary: "The environment to validate the workflow in. Defaults to development.",
|
|
129
|
+
default: _const.KnockEnv.Development
|
|
133
130
|
}),
|
|
134
131
|
branch: _flag.branch,
|
|
135
132
|
all: _core.Flags.boolean({
|
package/dist/lib/base-command.js
CHANGED
|
@@ -11,6 +11,7 @@ Object.defineProperty(exports, "default", {
|
|
|
11
11
|
const _core = require("@oclif/core");
|
|
12
12
|
const _apiv1 = /*#__PURE__*/ _interop_require_default(require("./api-v1"));
|
|
13
13
|
const _auth = /*#__PURE__*/ _interop_require_default(require("./auth"));
|
|
14
|
+
const _accountfeatures = require("./helpers/account-features");
|
|
14
15
|
const _runcontext = /*#__PURE__*/ _interop_require_wildcard(require("./run-context"));
|
|
15
16
|
const _urls = require("./urls");
|
|
16
17
|
const _userconfig = require("./user-config");
|
|
@@ -106,7 +107,12 @@ class BaseCommand extends _core.Command {
|
|
|
106
107
|
}
|
|
107
108
|
// 6. Instantiate a knock api client.
|
|
108
109
|
this.apiV1 = new _apiv1.default(this.sessionContext, this.config);
|
|
109
|
-
// 7.
|
|
110
|
+
// 7. Verify that required features are enabled for the account.
|
|
111
|
+
const ctor = this.ctor;
|
|
112
|
+
if (ctor.verifyFeatureEnabled) {
|
|
113
|
+
await this.verifyFeatureEnabled(ctor.verifyFeatureEnabled);
|
|
114
|
+
}
|
|
115
|
+
// 8. Load the run context of the invoked command.
|
|
110
116
|
this.runContext = await _runcontext.load(this.id);
|
|
111
117
|
}
|
|
112
118
|
buildSessionContext() {
|
|
@@ -138,6 +144,15 @@ class BaseCommand extends _core.Command {
|
|
|
138
144
|
this.error("No token found. Refusing to run command.");
|
|
139
145
|
}
|
|
140
146
|
}
|
|
147
|
+
async verifyFeatureEnabled(feature) {
|
|
148
|
+
if (feature === "translations") {
|
|
149
|
+
const featureCheck = await (0, _accountfeatures.checkTranslationsFeature)(this.apiV1);
|
|
150
|
+
if (!featureCheck.enabled) {
|
|
151
|
+
this.log(featureCheck.message);
|
|
152
|
+
this.exit(0);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
141
156
|
async refreshAccessTokenForSession() {
|
|
142
157
|
// Maybe refresh the access token?
|
|
143
158
|
try {
|
|
@@ -166,6 +181,7 @@ class BaseCommand extends _core.Command {
|
|
|
166
181
|
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);
|
|
167
182
|
}
|
|
168
183
|
}
|
|
184
|
+
_define_property(BaseCommand, "verifyFeatureEnabled", void 0);
|
|
169
185
|
// Base flags are inherited by any command that extends BaseCommand.
|
|
170
186
|
_define_property(BaseCommand, "baseFlags", {
|
|
171
187
|
// Evaluated in the following precedence:
|
|
@@ -0,0 +1,53 @@
|
|
|
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 checkAccountFeature () {
|
|
13
|
+
return checkAccountFeature;
|
|
14
|
+
},
|
|
15
|
+
get checkTranslationsFeature () {
|
|
16
|
+
return checkTranslationsFeature;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
const _request = require("./request");
|
|
20
|
+
async function checkAccountFeature(apiV1, featureName, options = {}) {
|
|
21
|
+
try {
|
|
22
|
+
const whoamiResp = await apiV1.whoami();
|
|
23
|
+
if (!(0, _request.isSuccessResp)(whoamiResp)) {
|
|
24
|
+
return {
|
|
25
|
+
enabled: false,
|
|
26
|
+
message: `Unable to retrieve account information: ${whoamiResp.status} ${whoamiResp.statusText}`
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const accountFeatures = whoamiResp.data.account_features;
|
|
30
|
+
const isFeatureEnabled = (accountFeatures === null || accountFeatures === void 0 ? void 0 : accountFeatures[featureName]) === true;
|
|
31
|
+
if (!isFeatureEnabled) {
|
|
32
|
+
const defaultMessage = `The ${featureName} feature is not enabled for your account. Please contact support to enable this feature.`;
|
|
33
|
+
return {
|
|
34
|
+
enabled: false,
|
|
35
|
+
message: options.errorMessage || defaultMessage
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
enabled: true
|
|
40
|
+
};
|
|
41
|
+
} catch (error) {
|
|
42
|
+
return {
|
|
43
|
+
enabled: false,
|
|
44
|
+
message: error instanceof Error ? error.message : "Unknown error occurred while checking translations feature"
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async function checkTranslationsFeature(apiV1, options = {}) {
|
|
49
|
+
return checkAccountFeature(apiV1, "translations_allowed", {
|
|
50
|
+
errorMessage: options.errorMessage || "Translations are not enabled for your account. Please contact support to enable the translations feature.",
|
|
51
|
+
...options
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -38,8 +38,9 @@ const compileExtractionSettings = (emailLayout)=>{
|
|
|
38
38
|
}
|
|
39
39
|
return map;
|
|
40
40
|
};
|
|
41
|
-
const buildEmailLayoutDirBundle = (remoteEmailLayout, localEmailLayout
|
|
41
|
+
const buildEmailLayoutDirBundle = (remoteEmailLayout, localEmailLayout, $schema)=>{
|
|
42
42
|
const bundle = {};
|
|
43
|
+
localEmailLayout = localEmailLayout || {};
|
|
43
44
|
const mutRemoteEmailLayout = (0, _lodash.cloneDeep)(remoteEmailLayout);
|
|
44
45
|
// A map of extraction settings of every field in the email layout
|
|
45
46
|
const compiledExtractionSettings = compileExtractionSettings(mutRemoteEmailLayout);
|
|
@@ -75,5 +76,5 @@ const buildEmailLayoutDirBundle = (remoteEmailLayout, localEmailLayout = {})=>{
|
|
|
75
76
|
// the layout JSON realtive path + the file content.
|
|
76
77
|
return (0, _lodash.set)(bundle, [
|
|
77
78
|
LAYOUT_JSON
|
|
78
|
-
], (0, _helpersisomorphic.prepareResourceJson)(mutRemoteEmailLayout));
|
|
79
|
+
], (0, _helpersisomorphic.prepareResourceJson)(mutRemoteEmailLayout, $schema));
|
|
79
80
|
};
|
|
@@ -73,13 +73,15 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
73
73
|
}
|
|
74
74
|
return newObj;
|
|
75
75
|
}
|
|
76
|
-
const
|
|
76
|
+
const EMAIL_LAYOUT_SCHEMA = "https://schemas.knock.app/cli/email-layout.json";
|
|
77
|
+
const writeEmailLayoutDirFromData = async (emailLayoutDirCtx, remoteEmailLayout, options)=>{
|
|
78
|
+
const { withSchema = false } = options || {};
|
|
77
79
|
// If the layout directory exists on the file system (i.e. previously
|
|
78
80
|
// pulled before), then read the layout file to use as a reference.
|
|
79
81
|
const [localEmailLayout] = emailLayoutDirCtx.exists ? await (0, _reader.readEmailLayoutDir)(emailLayoutDirCtx, {
|
|
80
82
|
withExtractedFiles: true
|
|
81
83
|
}) : [];
|
|
82
|
-
const bundle = (0, _processorisomorphic.buildEmailLayoutDirBundle)(remoteEmailLayout, localEmailLayout);
|
|
84
|
+
const bundle = (0, _processorisomorphic.buildEmailLayoutDirBundle)(remoteEmailLayout, localEmailLayout, withSchema ? EMAIL_LAYOUT_SCHEMA : undefined);
|
|
83
85
|
const backupDirPath = _nodepath.default.resolve(_const.sandboxDir, (0, _lodash.uniqueId)("backup"));
|
|
84
86
|
try {
|
|
85
87
|
// We store a backup in case there's an error.
|
|
@@ -109,7 +111,7 @@ const writeEmailLayoutDirFromData = async (emailLayoutDirCtx, remoteEmailLayout)
|
|
|
109
111
|
await _fsextra.remove(backupDirPath);
|
|
110
112
|
}
|
|
111
113
|
};
|
|
112
|
-
const writeEmailLayoutIndexDir = async (indexDirCtx, remoteEmailLayouts)=>{
|
|
114
|
+
const writeEmailLayoutIndexDir = async (indexDirCtx, remoteEmailLayouts, options)=>{
|
|
113
115
|
const backupDirPath = _nodepath.default.resolve(_const.sandboxDir, (0, _lodash.uniqueId)("backup"));
|
|
114
116
|
try {
|
|
115
117
|
if (indexDirCtx.exists) {
|
|
@@ -124,7 +126,7 @@ const writeEmailLayoutIndexDir = async (indexDirCtx, remoteEmailLayouts)=>{
|
|
|
124
126
|
abspath: emailLayoutDirPath,
|
|
125
127
|
exists: indexDirCtx.exists ? await (0, _helpers.isEmailLayoutDir)(emailLayoutDirPath) : false
|
|
126
128
|
};
|
|
127
|
-
return writeEmailLayoutDirFromData(emailLayoutDirCtx, remoteEmailLayout);
|
|
129
|
+
return writeEmailLayoutDirFromData(emailLayoutDirCtx, remoteEmailLayout, options);
|
|
128
130
|
});
|
|
129
131
|
await Promise.all(writeEmailLayoutDirPromises);
|
|
130
132
|
} catch (error) {
|
|
@@ -45,8 +45,9 @@ const compileExtractionSettings = (guide)=>{
|
|
|
45
45
|
}
|
|
46
46
|
return map;
|
|
47
47
|
};
|
|
48
|
-
const buildGuideDirBundle = (remoteGuide, localGuide
|
|
48
|
+
const buildGuideDirBundle = (remoteGuide, localGuide, $schema)=>{
|
|
49
49
|
const bundle = {};
|
|
50
|
+
localGuide = localGuide || {};
|
|
50
51
|
const mutRemoteGuide = (0, _lodash.cloneDeep)(remoteGuide);
|
|
51
52
|
// A map of extraction settings of every field in the guide.
|
|
52
53
|
const compiledExtractionSettings = compileExtractionSettings(mutRemoteGuide);
|
|
@@ -81,5 +82,5 @@ const buildGuideDirBundle = (remoteGuide, localGuide = {})=>{
|
|
|
81
82
|
// the guide JSON relative path + the file content.
|
|
82
83
|
return (0, _lodash.set)(bundle, [
|
|
83
84
|
GUIDE_JSON
|
|
84
|
-
], (0, _helpersisomorphic.prepareResourceJson)(mutRemoteGuide));
|
|
85
|
+
], (0, _helpersisomorphic.prepareResourceJson)(mutRemoteGuide, $schema));
|
|
85
86
|
};
|
|
@@ -68,13 +68,15 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
68
68
|
}
|
|
69
69
|
return newObj;
|
|
70
70
|
}
|
|
71
|
-
const
|
|
71
|
+
const GUIDE_SCHEMA = "https://schemas.knock.app/cli/guide.json";
|
|
72
|
+
const writeGuideDirFromData = async (guideDirCtx, remoteGuide, options)=>{
|
|
73
|
+
const { withSchema = false } = options || {};
|
|
72
74
|
// If the guide directory exists on the file system (i.e. previously
|
|
73
75
|
// pulled before), then read the guide file to use as a reference.
|
|
74
76
|
const [localGuide] = guideDirCtx.exists ? await (0, _reader.readGuideDir)(guideDirCtx, {
|
|
75
77
|
withExtractedFiles: true
|
|
76
78
|
}) : [];
|
|
77
|
-
const bundle = (0, _processorisomorphic.buildGuideDirBundle)(remoteGuide, localGuide);
|
|
79
|
+
const bundle = (0, _processorisomorphic.buildGuideDirBundle)(remoteGuide, localGuide, withSchema ? GUIDE_SCHEMA : undefined);
|
|
78
80
|
return writeGuideDirFromBundle(guideDirCtx, bundle);
|
|
79
81
|
};
|
|
80
82
|
/*
|
|
@@ -136,7 +138,7 @@ const writeGuideDirFromData = async (guideDirCtx, remoteGuide)=>{
|
|
|
136
138
|
});
|
|
137
139
|
await Promise.all(promises);
|
|
138
140
|
};
|
|
139
|
-
const writeGuidesIndexDir = async (indexDirCtx, remoteGuides)=>{
|
|
141
|
+
const writeGuidesIndexDir = async (indexDirCtx, remoteGuides, options)=>{
|
|
140
142
|
const backupDirPath = _nodepath.resolve(_const.sandboxDir, (0, _lodash.uniqueId)("backup"));
|
|
141
143
|
try {
|
|
142
144
|
// If the index directory already exists, back it up in the temp sandbox
|
|
@@ -154,7 +156,7 @@ const writeGuidesIndexDir = async (indexDirCtx, remoteGuides)=>{
|
|
|
154
156
|
abspath: guideDirPath,
|
|
155
157
|
exists: indexDirCtx.exists ? await (0, _helpers.isGuideDir)(guideDirPath) : false
|
|
156
158
|
};
|
|
157
|
-
return writeGuideDirFromData(guideDirCtx, guide);
|
|
159
|
+
return writeGuideDirFromData(guideDirCtx, guide, options);
|
|
158
160
|
});
|
|
159
161
|
await Promise.all(writeGuideDirPromises);
|
|
160
162
|
} catch (error) {
|
|
@@ -38,9 +38,10 @@ const compileExtractionSettings = (messageType)=>{
|
|
|
38
38
|
}
|
|
39
39
|
return map;
|
|
40
40
|
};
|
|
41
|
-
const buildMessageTypeDirBundle = (remoteMessageType, localMessageType
|
|
41
|
+
const buildMessageTypeDirBundle = (remoteMessageType, localMessageType, $schema)=>{
|
|
42
42
|
const bundle = {};
|
|
43
43
|
const mutRemoteMessageType = (0, _lodash.cloneDeep)(remoteMessageType);
|
|
44
|
+
localMessageType = localMessageType || {};
|
|
44
45
|
// A map of extraction settings of every field in the message type
|
|
45
46
|
const compiledExtractionSettings = compileExtractionSettings(mutRemoteMessageType);
|
|
46
47
|
// Iterate through each extractable field, determine whether we need to
|
|
@@ -74,5 +75,5 @@ const buildMessageTypeDirBundle = (remoteMessageType, localMessageType = {})=>{
|
|
|
74
75
|
// the message type JSON relative path + the file content.
|
|
75
76
|
return (0, _lodash.set)(bundle, [
|
|
76
77
|
MESSAGE_TYPE_JSON
|
|
77
|
-
], (0, _helpersisomorphic.prepareResourceJson)(mutRemoteMessageType));
|
|
78
|
+
], (0, _helpersisomorphic.prepareResourceJson)(mutRemoteMessageType, $schema));
|
|
78
79
|
};
|
|
@@ -68,13 +68,15 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
68
68
|
}
|
|
69
69
|
return newObj;
|
|
70
70
|
}
|
|
71
|
-
const
|
|
71
|
+
const MESSAGE_TYPE_SCHEMA = "https://schemas.knock.app/cli/message-type.json";
|
|
72
|
+
const writeMessageTypeDirFromData = async (messageTypeDirCtx, remoteMessageType, options)=>{
|
|
73
|
+
const { withSchema = false } = options || {};
|
|
72
74
|
// If the message type directory exists on the file system (i.e. previously
|
|
73
75
|
// pulled before), then read the message type file to use as a reference.
|
|
74
76
|
const [localMessageType] = messageTypeDirCtx.exists ? await (0, _reader.readMessageTypeDir)(messageTypeDirCtx, {
|
|
75
77
|
withExtractedFiles: true
|
|
76
78
|
}) : [];
|
|
77
|
-
const bundle = (0, _processorisomorphic.buildMessageTypeDirBundle)(remoteMessageType, localMessageType);
|
|
79
|
+
const bundle = (0, _processorisomorphic.buildMessageTypeDirBundle)(remoteMessageType, localMessageType, withSchema ? MESSAGE_TYPE_SCHEMA : undefined);
|
|
78
80
|
return writeMessageTypeDirFromBundle(messageTypeDirCtx, bundle);
|
|
79
81
|
};
|
|
80
82
|
/*
|
|
@@ -136,7 +138,7 @@ const writeMessageTypeDirFromData = async (messageTypeDirCtx, remoteMessageType)
|
|
|
136
138
|
});
|
|
137
139
|
await Promise.all(promises);
|
|
138
140
|
};
|
|
139
|
-
const writeMessageTypesIndexDir = async (indexDirCtx, remoteMessageTypes)=>{
|
|
141
|
+
const writeMessageTypesIndexDir = async (indexDirCtx, remoteMessageTypes, options)=>{
|
|
140
142
|
const backupDirPath = _nodepath.resolve(_const.sandboxDir, (0, _lodash.uniqueId)("backup"));
|
|
141
143
|
try {
|
|
142
144
|
// If the index directory already exists, back it up in the temp sandbox
|
|
@@ -154,7 +156,7 @@ const writeMessageTypesIndexDir = async (indexDirCtx, remoteMessageTypes)=>{
|
|
|
154
156
|
abspath: messageTypeDirPath,
|
|
155
157
|
exists: indexDirCtx.exists ? await (0, _helpers.isMessageTypeDir)(messageTypeDirPath) : false
|
|
156
158
|
};
|
|
157
|
-
return writeMessageTypeDirFromData(messageTypeDirCtx, messageType);
|
|
159
|
+
return writeMessageTypeDirFromData(messageTypeDirCtx, messageType, options);
|
|
158
160
|
});
|
|
159
161
|
await Promise.all(promises);
|
|
160
162
|
} catch (error) {
|
|
@@ -61,8 +61,9 @@ const compileExtractionSettings = (partial)=>{
|
|
|
61
61
|
}
|
|
62
62
|
return map;
|
|
63
63
|
};
|
|
64
|
-
const buildPartialDirBundle = (remotePartial, localPartial
|
|
64
|
+
const buildPartialDirBundle = (remotePartial, localPartial, $schema)=>{
|
|
65
65
|
const bundle = {};
|
|
66
|
+
localPartial = localPartial || {};
|
|
66
67
|
const mutRemotePartial = (0, _lodash.cloneDeep)(remotePartial);
|
|
67
68
|
// A map of extraction settings of every field in the partial
|
|
68
69
|
const compiledExtractionSettings = compileExtractionSettings(mutRemotePartial);
|
|
@@ -97,5 +98,5 @@ const buildPartialDirBundle = (remotePartial, localPartial = {})=>{
|
|
|
97
98
|
// the partial JSON relative path + the file content.
|
|
98
99
|
return (0, _lodash.set)(bundle, [
|
|
99
100
|
PARTIAL_JSON
|
|
100
|
-
], (0, _helpersisomorphic.prepareResourceJson)(mutRemotePartial));
|
|
101
|
+
], (0, _helpersisomorphic.prepareResourceJson)(mutRemotePartial, $schema));
|
|
101
102
|
};
|
|
@@ -68,13 +68,15 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
68
68
|
}
|
|
69
69
|
return newObj;
|
|
70
70
|
}
|
|
71
|
-
const
|
|
71
|
+
const PARTIAL_SCHEMA = "https://schemas.knock.app/cli/partial.json";
|
|
72
|
+
const writePartialDirFromData = async (partialDirCtx, remotePartial, options)=>{
|
|
73
|
+
const { withSchema = false } = options || {};
|
|
72
74
|
// If the partial directory exists on the file system (i.e. previously
|
|
73
75
|
// pulled before), then read the partial file to use as a reference.
|
|
74
76
|
const [localPartial] = partialDirCtx.exists ? await (0, _reader.readPartialDir)(partialDirCtx, {
|
|
75
77
|
withExtractedFiles: true
|
|
76
78
|
}) : [];
|
|
77
|
-
const bundle = (0, _processorisomorphic.buildPartialDirBundle)(remotePartial, localPartial);
|
|
79
|
+
const bundle = (0, _processorisomorphic.buildPartialDirBundle)(remotePartial, localPartial, withSchema ? PARTIAL_SCHEMA : undefined);
|
|
78
80
|
return writePartialDirFromBundle(partialDirCtx, bundle);
|
|
79
81
|
};
|
|
80
82
|
/*
|
|
@@ -136,7 +138,7 @@ const writePartialDirFromData = async (partialDirCtx, remotePartial)=>{
|
|
|
136
138
|
});
|
|
137
139
|
await Promise.all(promises);
|
|
138
140
|
};
|
|
139
|
-
const writePartialsIndexDir = async (indexDirCtx, remotePartials)=>{
|
|
141
|
+
const writePartialsIndexDir = async (indexDirCtx, remotePartials, options)=>{
|
|
140
142
|
const backupDirPath = _nodepath.resolve(_const.sandboxDir, (0, _lodash.uniqueId)("backup"));
|
|
141
143
|
try {
|
|
142
144
|
// If the index directory already exists, back it up in the temp sandbox
|
|
@@ -154,7 +156,7 @@ const writePartialsIndexDir = async (indexDirCtx, remotePartials)=>{
|
|
|
154
156
|
abspath: partialDirPath,
|
|
155
157
|
exists: indexDirCtx.exists ? await (0, _helpers.isPartialDir)(partialDirPath) : false
|
|
156
158
|
};
|
|
157
|
-
return writePartialDirFromData(partialDirCtx, partial);
|
|
159
|
+
return writePartialDirFromData(partialDirCtx, partial, options);
|
|
158
160
|
});
|
|
159
161
|
await Promise.all(writePartialDirPromises);
|
|
160
162
|
} catch (error) {
|
|
@@ -15,7 +15,7 @@ const REMOVED_READONLY_FIELDS = [
|
|
|
15
15
|
"sha",
|
|
16
16
|
"updated_at"
|
|
17
17
|
];
|
|
18
|
-
const prepareResourceJson = (resource)=>{
|
|
18
|
+
const prepareResourceJson = (resource, $schema)=>{
|
|
19
19
|
var _resource___annotation;
|
|
20
20
|
const readonlyFields = ((_resource___annotation = resource.__annotation) === null || _resource___annotation === void 0 ? void 0 : _resource___annotation.readonly_fields) || [];
|
|
21
21
|
const [readonly, remainder] = (0, _objectisomorphic.split)(resource, readonlyFields);
|
|
@@ -25,6 +25,12 @@ const prepareResourceJson = (resource)=>{
|
|
|
25
25
|
...remainder,
|
|
26
26
|
__readonly: filteredReadonlyFields
|
|
27
27
|
};
|
|
28
|
+
// Append the $schema property to the resource JSON if it is provided.
|
|
29
|
+
if ($schema) {
|
|
30
|
+
Object.assign(resourceJson, {
|
|
31
|
+
$schema
|
|
32
|
+
});
|
|
33
|
+
}
|
|
28
34
|
// Strip out all schema annotations, so not to expose them to end users.
|
|
29
35
|
return (0, _objectisomorphic.omitDeep)(resourceJson, [
|
|
30
36
|
"__annotation"
|
|
@@ -250,8 +250,9 @@ const recursivelyBuildWorkflowDirBundle = (bundle, steps, localWorkflowStepsByRe
|
|
|
250
250
|
}
|
|
251
251
|
}
|
|
252
252
|
};
|
|
253
|
-
const buildWorkflowDirBundle = (remoteWorkflow, localWorkflow
|
|
253
|
+
const buildWorkflowDirBundle = (remoteWorkflow, localWorkflow, $schema)=>{
|
|
254
254
|
const bundle = {};
|
|
255
|
+
localWorkflow = localWorkflow || {};
|
|
255
256
|
const mutWorkflow = (0, _lodash.cloneDeep)(remoteWorkflow);
|
|
256
257
|
const localWorkflowStepsByRef = keyLocalWorkflowStepsByRef(localWorkflow.steps);
|
|
257
258
|
// Recursively traverse the workflow step tree, mutating it and the bundle
|
|
@@ -260,5 +261,5 @@ const buildWorkflowDirBundle = (remoteWorkflow, localWorkflow = {})=>{
|
|
|
260
261
|
// Then, prepare the workflow data to be written into a workflow json file.
|
|
261
262
|
return (0, _lodash.set)(bundle, [
|
|
262
263
|
WORKFLOW_JSON
|
|
263
|
-
], (0, _helpersisomorphic.prepareResourceJson)(mutWorkflow));
|
|
264
|
+
], (0, _helpersisomorphic.prepareResourceJson)(mutWorkflow, $schema));
|
|
264
265
|
};
|