@knocklabs/cli 0.1.0-rc.3 → 0.1.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 +48 -30
- package/dist/commands/ping.js +2 -0
- package/dist/commands/translation/get.js +124 -0
- package/dist/commands/translation/list.js +50 -6
- package/dist/commands/translation/pull.js +59 -17
- package/dist/commands/translation/push.js +13 -6
- package/dist/commands/translation/validate.js +1 -1
- package/dist/commands/whoami.js +28 -0
- package/dist/commands/workflow/pull.js +2 -2
- package/dist/commands/workflow/push.js +52 -42
- package/dist/commands/workflow/validate.js +44 -43
- package/dist/lib/api-v1.js +20 -5
- package/dist/lib/marshal/translation/helpers.js +11 -3
- package/dist/lib/marshal/translation/reader.js +17 -14
- package/dist/lib/marshal/translation/types.js +1 -0
- package/dist/lib/marshal/translation/writer.js +27 -15
- package/dist/lib/marshal/workflow/helpers.js +64 -2
- package/dist/lib/marshal/workflow/reader.js +62 -0
- package/dist/lib/marshal/workflow/writer.js +44 -8
- package/oclif.manifest.json +114 -2
- package/package.json +7 -7
|
@@ -6,15 +6,17 @@ Object.defineProperty(exports, "default", {
|
|
|
6
6
|
enumerable: true,
|
|
7
7
|
get: ()=>WorkflowPush
|
|
8
8
|
});
|
|
9
|
-
const _nodePath = /*#__PURE__*/ _interopRequireWildcard(require("node:path"));
|
|
10
9
|
const _core = require("@oclif/core");
|
|
11
10
|
const _baseCommand = /*#__PURE__*/ _interopRequireDefault(require("../../lib/base-command"));
|
|
12
11
|
const _const = require("../../lib/helpers/const");
|
|
13
12
|
const _error = require("../../lib/helpers/error");
|
|
13
|
+
const _flag = /*#__PURE__*/ _interopRequireWildcard(require("../../lib/helpers/flag"));
|
|
14
14
|
const _object = require("../../lib/helpers/object");
|
|
15
15
|
const _request = require("../../lib/helpers/request");
|
|
16
|
+
const _string = require("../../lib/helpers/string");
|
|
17
|
+
const _ux = require("../../lib/helpers/ux");
|
|
16
18
|
const _workflow = /*#__PURE__*/ _interopRequireWildcard(require("../../lib/marshal/workflow"));
|
|
17
|
-
const
|
|
19
|
+
const _validate = /*#__PURE__*/ _interopRequireDefault(require("./validate"));
|
|
18
20
|
function _interopRequireDefault(obj) {
|
|
19
21
|
return obj && obj.__esModule ? obj : {
|
|
20
22
|
default: obj
|
|
@@ -61,55 +63,57 @@ function _interopRequireWildcard(obj, nodeInterop) {
|
|
|
61
63
|
}
|
|
62
64
|
class WorkflowPush extends _baseCommand.default {
|
|
63
65
|
async run() {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const [workflow, errors] = await _workflow.readWorkflowDir(dirContext, {
|
|
66
|
+
const { flags } = this.props;
|
|
67
|
+
// 1. First read all workflow directories found for the given command.
|
|
68
|
+
const target = await _workflow.ensureValidCommandTarget(this.props, this.runContext);
|
|
69
|
+
const [workflows, readErrors] = await _workflow.readAllForCommandTarget(target, {
|
|
69
70
|
withExtractedFiles: true
|
|
70
71
|
});
|
|
71
|
-
if (
|
|
72
|
-
this.error(
|
|
72
|
+
if (readErrors.length > 0) {
|
|
73
|
+
this.error((0, _error.formatErrors)(readErrors, {
|
|
74
|
+
prependBy: "\n\n"
|
|
75
|
+
}));
|
|
73
76
|
}
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
if (workflows.length === 0) {
|
|
78
|
+
this.error(`No workflow 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, workflows);
|
|
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 workflow, abort on the first error.
|
|
90
|
+
_ux.spinner.start(`‣ Pushing`);
|
|
91
|
+
for (const workflow of workflows){
|
|
76
92
|
const props = (0, _object.merge)(this.props, {
|
|
77
|
-
args: {
|
|
78
|
-
workflowKey: dirContext.key
|
|
79
|
-
},
|
|
80
93
|
flags: {
|
|
81
94
|
annotate: true
|
|
82
95
|
}
|
|
83
96
|
});
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
key: workflowKey
|
|
99
|
-
};
|
|
100
|
-
return (0, _runContext.ensureResourceDirForTarget)(resourceDir, target);
|
|
101
|
-
}
|
|
102
|
-
if (workflowKey) {
|
|
103
|
-
const dirPath = _nodePath.resolve(runCwd, workflowKey);
|
|
104
|
-
const exists = await _workflow.isWorkflowDir(dirPath);
|
|
105
|
-
return exists ? {
|
|
106
|
-
type: "workflow",
|
|
107
|
-
key: workflowKey,
|
|
108
|
-
abspath: dirPath,
|
|
109
|
-
exists
|
|
110
|
-
} : this.error(`Cannot locate a workflow directory for \`${workflowKey}\``);
|
|
97
|
+
// eslint-disable-next-line no-await-in-loop
|
|
98
|
+
const resp = await this.apiV1.upsertWorkflow(props, {
|
|
99
|
+
...workflow.content,
|
|
100
|
+
key: workflow.key
|
|
101
|
+
});
|
|
102
|
+
if ((0, _request.isSuccessResp)(resp)) {
|
|
103
|
+
// Update the workflow directory with the successfully pushed workflow
|
|
104
|
+
// payload from the server.
|
|
105
|
+
// eslint-disable-next-line no-await-in-loop
|
|
106
|
+
await _workflow.writeWorkflowDirFromData(workflow, resp.data.workflow);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const error = new _error.SourceError((0, _request.formatErrorRespMessage)(resp), _workflow.workflowJsonPath(workflow), "ApiError");
|
|
110
|
+
this.error((0, _error.formatError)(error));
|
|
111
111
|
}
|
|
112
|
-
|
|
112
|
+
_ux.spinner.stop();
|
|
113
|
+
// 4. Display a success message.
|
|
114
|
+
const workflowKeys = workflows.map((w)=>w.key);
|
|
115
|
+
const actioned = flags.commit ? "pushed and committed" : "pushed";
|
|
116
|
+
this.log(`‣ Successfully ${actioned} ${workflows.length} workflow(s):\n` + (0, _string.indentString)(workflowKeys.join("\n"), 4));
|
|
113
117
|
}
|
|
114
118
|
}
|
|
115
119
|
WorkflowPush.flags = {
|
|
@@ -120,6 +124,12 @@ WorkflowPush.flags = {
|
|
|
120
124
|
_const.KnockEnv.Development
|
|
121
125
|
]
|
|
122
126
|
}),
|
|
127
|
+
all: _core.Flags.boolean(),
|
|
128
|
+
"workflows-dir": _flag.dirPath({
|
|
129
|
+
dependsOn: [
|
|
130
|
+
"all"
|
|
131
|
+
]
|
|
132
|
+
}),
|
|
123
133
|
commit: _core.Flags.boolean({
|
|
124
134
|
summary: "Push and commit the workflow(s) at the same time"
|
|
125
135
|
}),
|
|
@@ -6,15 +6,15 @@ Object.defineProperty(exports, "default", {
|
|
|
6
6
|
enumerable: true,
|
|
7
7
|
get: ()=>WorkflowValidate
|
|
8
8
|
});
|
|
9
|
-
const _nodePath = /*#__PURE__*/ _interopRequireWildcard(require("node:path"));
|
|
10
9
|
const _core = require("@oclif/core");
|
|
11
10
|
const _baseCommand = /*#__PURE__*/ _interopRequireDefault(require("../../lib/base-command"));
|
|
12
11
|
const _const = require("../../lib/helpers/const");
|
|
13
12
|
const _error = require("../../lib/helpers/error");
|
|
14
|
-
const
|
|
13
|
+
const _flag = /*#__PURE__*/ _interopRequireWildcard(require("../../lib/helpers/flag"));
|
|
15
14
|
const _request = require("../../lib/helpers/request");
|
|
15
|
+
const _string = require("../../lib/helpers/string");
|
|
16
|
+
const _ux = require("../../lib/helpers/ux");
|
|
16
17
|
const _workflow = /*#__PURE__*/ _interopRequireWildcard(require("../../lib/marshal/workflow"));
|
|
17
|
-
const _runContext = require("../../lib/run-context");
|
|
18
18
|
function _interopRequireDefault(obj) {
|
|
19
19
|
return obj && obj.__esModule ? obj : {
|
|
20
20
|
default: obj
|
|
@@ -61,51 +61,46 @@ function _interopRequireWildcard(obj, nodeInterop) {
|
|
|
61
61
|
}
|
|
62
62
|
class WorkflowValidate extends _baseCommand.default {
|
|
63
63
|
async run() {
|
|
64
|
-
// 1.
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
// 2. Read the workflow.json with its template files.
|
|
68
|
-
const [workflow, errors] = await _workflow.readWorkflowDir(dirContext, {
|
|
64
|
+
// 1. Read all workflow directories found for the given command.
|
|
65
|
+
const target = await _workflow.ensureValidCommandTarget(this.props, this.runContext);
|
|
66
|
+
const [workflows, readErrors] = await _workflow.readAllForCommandTarget(target, {
|
|
69
67
|
withExtractedFiles: true
|
|
70
68
|
});
|
|
71
|
-
if (
|
|
72
|
-
this.error(
|
|
69
|
+
if (readErrors.length > 0) {
|
|
70
|
+
this.error((0, _error.formatErrors)(readErrors, {
|
|
71
|
+
prependBy: "\n\n"
|
|
72
|
+
}));
|
|
73
73
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const props = (0, _object.merge)(this.props, {
|
|
77
|
-
args: {
|
|
78
|
-
workflowKey: dirContext.key
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
return this.apiV1.validateWorkflow(props, workflow);
|
|
82
|
-
}, {
|
|
83
|
-
action: "‣ Validating"
|
|
84
|
-
});
|
|
85
|
-
this.log(`‣ Successfully validated \`${dirContext.key}\``);
|
|
86
|
-
}
|
|
87
|
-
async getWorkflowDirContext() {
|
|
88
|
-
const { workflowKey } = this.props.args;
|
|
89
|
-
const { resourceDir , cwd: runCwd } = this.runContext;
|
|
90
|
-
if (resourceDir) {
|
|
91
|
-
const target = {
|
|
92
|
-
commandId: _baseCommand.default.id,
|
|
93
|
-
type: "workflow",
|
|
94
|
-
key: workflowKey
|
|
95
|
-
};
|
|
96
|
-
return (0, _runContext.ensureResourceDirForTarget)(resourceDir, target);
|
|
74
|
+
if (workflows.length === 0) {
|
|
75
|
+
this.error(`No workflow directories found in ${target.context.abspath}`);
|
|
97
76
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
exists
|
|
106
|
-
} : this.error(`Cannot locate a workflow directory for \`${workflowKey}\``);
|
|
77
|
+
// 2. Validate each workflow data.
|
|
78
|
+
_ux.spinner.start(`‣ Validating`);
|
|
79
|
+
const apiErrors = await WorkflowValidate.validateAll(this.apiV1, this.props, workflows);
|
|
80
|
+
if (apiErrors.length > 0) {
|
|
81
|
+
this.error((0, _error.formatErrors)(apiErrors, {
|
|
82
|
+
prependBy: "\n\n"
|
|
83
|
+
}));
|
|
107
84
|
}
|
|
108
|
-
|
|
85
|
+
_ux.spinner.stop();
|
|
86
|
+
// 3. Display a success message.
|
|
87
|
+
const workflowKeys = workflows.map((w)=>w.key);
|
|
88
|
+
this.log(`‣ Successfully validated ${workflows.length} workflow(s):\n` + (0, _string.indentString)(workflowKeys.join("\n"), 4));
|
|
89
|
+
}
|
|
90
|
+
static async validateAll(api, props, workflows) {
|
|
91
|
+
// TODO: Throw an error if a non validation error (e.g. authentication error)
|
|
92
|
+
// instead of printing out same error messages repeatedly.
|
|
93
|
+
const errorPromises = workflows.map(async (workflow)=>{
|
|
94
|
+
const resp = await api.validateWorkflow(props, {
|
|
95
|
+
...workflow.content,
|
|
96
|
+
key: workflow.key
|
|
97
|
+
});
|
|
98
|
+
if ((0, _request.isSuccessResp)(resp)) return;
|
|
99
|
+
const error = new _error.SourceError((0, _request.formatErrorRespMessage)(resp), _workflow.workflowJsonPath(workflow), "ApiError");
|
|
100
|
+
return error;
|
|
101
|
+
});
|
|
102
|
+
const errors = (await Promise.all(errorPromises)).filter((e)=>Boolean(e));
|
|
103
|
+
return errors;
|
|
109
104
|
}
|
|
110
105
|
}
|
|
111
106
|
WorkflowValidate.flags = {
|
|
@@ -115,6 +110,12 @@ WorkflowValidate.flags = {
|
|
|
115
110
|
options: [
|
|
116
111
|
_const.KnockEnv.Development
|
|
117
112
|
]
|
|
113
|
+
}),
|
|
114
|
+
all: _core.Flags.boolean(),
|
|
115
|
+
"workflows-dir": _flag.dirPath({
|
|
116
|
+
dependsOn: [
|
|
117
|
+
"all"
|
|
118
|
+
]
|
|
118
119
|
})
|
|
119
120
|
};
|
|
120
121
|
WorkflowValidate.args = [
|
package/dist/lib/api-v1.js
CHANGED
|
@@ -20,6 +20,9 @@ class ApiV1 {
|
|
|
20
20
|
async ping() {
|
|
21
21
|
return this.get("/ping");
|
|
22
22
|
}
|
|
23
|
+
async whoami() {
|
|
24
|
+
return this.get("/whoami");
|
|
25
|
+
}
|
|
23
26
|
// By resources: Workflows
|
|
24
27
|
async listWorkflows({ flags }) {
|
|
25
28
|
const params = (0, _object.prune)({
|
|
@@ -42,7 +45,7 @@ class ApiV1 {
|
|
|
42
45
|
params
|
|
43
46
|
});
|
|
44
47
|
}
|
|
45
|
-
async upsertWorkflow({
|
|
48
|
+
async upsertWorkflow({ flags }, workflow) {
|
|
46
49
|
const params = (0, _object.prune)({
|
|
47
50
|
environment: flags.environment,
|
|
48
51
|
annotate: flags.annotate,
|
|
@@ -52,18 +55,18 @@ class ApiV1 {
|
|
|
52
55
|
const data = {
|
|
53
56
|
workflow
|
|
54
57
|
};
|
|
55
|
-
return this.put(`/workflows/${
|
|
58
|
+
return this.put(`/workflows/${workflow.key}`, data, {
|
|
56
59
|
params
|
|
57
60
|
});
|
|
58
61
|
}
|
|
59
|
-
async validateWorkflow({
|
|
62
|
+
async validateWorkflow({ flags }, workflow) {
|
|
60
63
|
const params = (0, _object.prune)({
|
|
61
64
|
environment: flags.environment
|
|
62
65
|
});
|
|
63
66
|
const data = {
|
|
64
67
|
workflow
|
|
65
68
|
};
|
|
66
|
-
return this.put(`/workflows/${
|
|
69
|
+
return this.put(`/workflows/${workflow.key}/validate`, data, {
|
|
67
70
|
params
|
|
68
71
|
});
|
|
69
72
|
}
|
|
@@ -95,16 +98,28 @@ class ApiV1 {
|
|
|
95
98
|
});
|
|
96
99
|
}
|
|
97
100
|
// By resources: Translations
|
|
98
|
-
async listTranslations({ flags }) {
|
|
101
|
+
async listTranslations({ flags }, filters = {}) {
|
|
99
102
|
const params = (0, _object.prune)({
|
|
100
103
|
environment: flags.environment,
|
|
101
104
|
hide_uncommitted_changes: flags["hide-uncommitted-changes"],
|
|
105
|
+
locale_code: filters.localeCode,
|
|
106
|
+
namespace: filters.namespace,
|
|
102
107
|
...(0, _page.toPageParams)(flags)
|
|
103
108
|
});
|
|
104
109
|
return this.get("/translations", {
|
|
105
110
|
params
|
|
106
111
|
});
|
|
107
112
|
}
|
|
113
|
+
async getTranslation({ flags }, translation) {
|
|
114
|
+
const params = (0, _object.prune)({
|
|
115
|
+
environment: flags.environment,
|
|
116
|
+
hide_uncommitted_changes: flags["hide-uncommitted-changes"],
|
|
117
|
+
namespace: translation.namespace
|
|
118
|
+
});
|
|
119
|
+
return this.get(`/translations/${translation.localeCode}`, {
|
|
120
|
+
params
|
|
121
|
+
});
|
|
122
|
+
}
|
|
108
123
|
async upsertTranslation({ flags }, translation) {
|
|
109
124
|
const params = (0, _object.prune)({
|
|
110
125
|
environment: flags.environment,
|
|
@@ -9,6 +9,8 @@ function _export(target, all) {
|
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
_export(exports, {
|
|
12
|
+
formatLanguage: ()=>formatLanguage,
|
|
13
|
+
formatRef: ()=>formatRef,
|
|
12
14
|
isValidLocale: ()=>isValidLocale,
|
|
13
15
|
isTranslationDir: ()=>isTranslationDir,
|
|
14
16
|
buildTranslationFileCtx: ()=>buildTranslationFileCtx,
|
|
@@ -65,6 +67,11 @@ function _interopRequireWildcard(obj, nodeInterop) {
|
|
|
65
67
|
}
|
|
66
68
|
return newObj;
|
|
67
69
|
}
|
|
70
|
+
const formatLanguage = (translation)=>{
|
|
71
|
+
const lang = _localeCodes.default.getByTag(translation.locale_code);
|
|
72
|
+
return lang.location ? `${lang.name}, ${lang.location}` : lang.name;
|
|
73
|
+
};
|
|
74
|
+
const formatRef = ({ locale_code , namespace })=>namespace ? `${namespace}.${locale_code}` : locale_code;
|
|
68
75
|
const isValidLocale = (localeCode)=>Boolean(_localeCodes.default.getByTag(localeCode));
|
|
69
76
|
const isTranslationDir = (dirPath)=>{
|
|
70
77
|
const locale = _nodePath.basename(dirPath);
|
|
@@ -87,7 +94,8 @@ const parseTranslationRef = (reference)=>{
|
|
|
87
94
|
// Locale code only (e.g. `en`)
|
|
88
95
|
if (strings.length === 1) {
|
|
89
96
|
return {
|
|
90
|
-
localeCode: strings[0]
|
|
97
|
+
localeCode: strings[0],
|
|
98
|
+
namespace: undefined
|
|
91
99
|
};
|
|
92
100
|
}
|
|
93
101
|
// Locale code prefixed with a namespace (e.g. `admin.en`)
|
|
@@ -114,7 +122,7 @@ const ensureValidCommandTarget = async (props, runContext)=>{
|
|
|
114
122
|
// No translationRef arg, which means --all flag is used.
|
|
115
123
|
if (!args.translationRef) {
|
|
116
124
|
// Targeting all translation files in the current locale directory.
|
|
117
|
-
if (resourceDirCtx) {
|
|
125
|
+
if (resourceDirCtx && !flags["translations-dir"]) {
|
|
118
126
|
return {
|
|
119
127
|
type: "translationDir",
|
|
120
128
|
context: resourceDirCtx
|
|
@@ -135,7 +143,7 @@ const ensureValidCommandTarget = async (props, runContext)=>{
|
|
|
135
143
|
// From this point on, we have translationRef so parse and validate the format.
|
|
136
144
|
const parsedRef = parseTranslationRef(args.translationRef);
|
|
137
145
|
if (!parsedRef) {
|
|
138
|
-
return _core.CliUx.ux.error(`Invalid
|
|
146
|
+
return _core.CliUx.ux.error(`Invalid translation ref \`${args.translationRef}\`, use valid <locale> or <namespace>.<locale> for namespaced translations`);
|
|
139
147
|
}
|
|
140
148
|
const { localeCode , namespace } = parsedRef;
|
|
141
149
|
// If we are in the translation dir, make sure the locale matches.
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
-
Object.defineProperty(exports, "
|
|
5
|
+
Object.defineProperty(exports, "readAllForCommandTarget", {
|
|
6
6
|
enumerable: true,
|
|
7
|
-
get: ()=>
|
|
7
|
+
get: ()=>readAllForCommandTarget
|
|
8
8
|
});
|
|
9
9
|
const _nodePath = /*#__PURE__*/ _interopRequireWildcard(require("node:path"));
|
|
10
10
|
const _core = require("@oclif/core");
|
|
@@ -56,6 +56,9 @@ function _interopRequireWildcard(obj, nodeInterop) {
|
|
|
56
56
|
* translation file data.
|
|
57
57
|
*
|
|
58
58
|
* Note, it assumes they are valid file paths to translation files.
|
|
59
|
+
*
|
|
60
|
+
* TODO: Refactor to take translation file contexts instead of raw file paths,
|
|
61
|
+
* to keep things consistent with the workflow reader module.
|
|
59
62
|
*/ const readTranslationFiles = async (filePaths)=>{
|
|
60
63
|
const translations = [];
|
|
61
64
|
const errors = [];
|
|
@@ -69,27 +72,27 @@ function _interopRequireWildcard(obj, nodeInterop) {
|
|
|
69
72
|
if (readJsonErrors.length > 0) {
|
|
70
73
|
const e = new _error.SourceError((0, _error.formatErrors)(readJsonErrors), abspath);
|
|
71
74
|
errors.push(e);
|
|
75
|
+
continue;
|
|
72
76
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
});
|
|
82
|
-
}
|
|
77
|
+
translations.push({
|
|
78
|
+
ref: translationRef,
|
|
79
|
+
localeCode,
|
|
80
|
+
namespace,
|
|
81
|
+
abspath,
|
|
82
|
+
exists: true,
|
|
83
|
+
content: JSON.stringify(content)
|
|
84
|
+
});
|
|
83
85
|
}
|
|
84
86
|
return [
|
|
85
87
|
translations,
|
|
86
88
|
errors
|
|
87
89
|
];
|
|
88
90
|
};
|
|
89
|
-
const
|
|
91
|
+
const readAllForCommandTarget = async (target)=>{
|
|
90
92
|
const { type: targetType , context: targetCtx } = target;
|
|
91
93
|
if (!targetCtx.exists) {
|
|
92
|
-
|
|
94
|
+
const subject = targetType === "translationFile" ? "a translation file at" : "translation files in";
|
|
95
|
+
return _core.CliUx.ux.error(`Cannot locate ${subject} \`${targetCtx.abspath}\``);
|
|
93
96
|
}
|
|
94
97
|
switch(targetType){
|
|
95
98
|
case "translationFile":
|
|
@@ -2,9 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: all[name]
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
writeTranslationFile: ()=>writeTranslationFile,
|
|
13
|
+
writeTranslationFiles: ()=>writeTranslationFiles
|
|
8
14
|
});
|
|
9
15
|
const _nodePath = /*#__PURE__*/ _interopRequireWildcard(require("node:path"));
|
|
10
16
|
const _fsExtra = /*#__PURE__*/ _interopRequireWildcard(require("fs-extra"));
|
|
@@ -51,30 +57,36 @@ function _interopRequireWildcard(obj, nodeInterop) {
|
|
|
51
57
|
}
|
|
52
58
|
return newObj;
|
|
53
59
|
}
|
|
54
|
-
const
|
|
60
|
+
const writeTranslationFile = async (translationFileCtx, translation)=>_fsExtra.outputJson(translationFileCtx.abspath, JSON.parse(translation.content), {
|
|
61
|
+
spaces: _json.DOUBLE_SPACES
|
|
62
|
+
});
|
|
63
|
+
const writeTranslationFiles = async (targetDirCtx, translations)=>{
|
|
55
64
|
const backupDirPath = _nodePath.resolve(_const.sandboxDir, (0, _lodash.uniqueId)("backup"));
|
|
56
65
|
try {
|
|
57
66
|
// If the index directory already exists, back it up in the temp sandbox
|
|
58
67
|
// before wiping it clean.
|
|
59
|
-
if (
|
|
60
|
-
await _fsExtra.copy(
|
|
61
|
-
await _fsExtra.
|
|
68
|
+
if (targetDirCtx.exists) {
|
|
69
|
+
await _fsExtra.copy(targetDirCtx.abspath, backupDirPath);
|
|
70
|
+
await _fsExtra.emptyDir(targetDirCtx.abspath);
|
|
62
71
|
}
|
|
63
72
|
// Write given remote translations into the given translations directory path.
|
|
64
73
|
const writeTranslationDirPromises = translations.map(async (translation)=>{
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
74
|
+
// If TranslationDirContext, then that is the locale directory we want
|
|
75
|
+
// to write translation files in; otherwise for translations index
|
|
76
|
+
// directory, we want to nest translation files under each locale dir.
|
|
77
|
+
const localeDirPath = "key" in targetDirCtx ? targetDirCtx.abspath : _nodePath.resolve(targetDirCtx.abspath, translation.locale_code);
|
|
78
|
+
const translationFileCtx = await (0, _helpers.buildTranslationFileCtx)(localeDirPath, translation.locale_code, translation.namespace);
|
|
79
|
+
return writeTranslationFile(translationFileCtx, translation);
|
|
70
80
|
});
|
|
71
81
|
await Promise.all(writeTranslationDirPromises);
|
|
72
82
|
} catch (error) {
|
|
73
83
|
// In case of any error, wipe the index directory that is likely in a bad
|
|
74
84
|
// state then restore the backup if one existed before.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
await _fsExtra.copy(backupDirPath,
|
|
85
|
+
if (targetDirCtx.exists) {
|
|
86
|
+
await _fsExtra.emptyDir(targetDirCtx.abspath);
|
|
87
|
+
await _fsExtra.copy(backupDirPath, targetDirCtx.abspath);
|
|
88
|
+
} else {
|
|
89
|
+
await _fsExtra.remove(targetDirCtx.abspath);
|
|
78
90
|
}
|
|
79
91
|
throw error;
|
|
80
92
|
} finally{
|
|
@@ -11,6 +11,7 @@ function _export(target, all) {
|
|
|
11
11
|
_export(exports, {
|
|
12
12
|
WORKFLOW_JSON: ()=>WORKFLOW_JSON,
|
|
13
13
|
VISUAL_BLOCKS_JSON: ()=>VISUAL_BLOCKS_JSON,
|
|
14
|
+
workflowJsonPath: ()=>workflowJsonPath,
|
|
14
15
|
FILEPATH_MARKER: ()=>FILEPATH_MARKER,
|
|
15
16
|
FILEPATH_MARKED_RE: ()=>FILEPATH_MARKED_RE,
|
|
16
17
|
validateWorkflowKey: ()=>validateWorkflowKey,
|
|
@@ -18,9 +19,11 @@ _export(exports, {
|
|
|
18
19
|
isWorkflowDir: ()=>isWorkflowDir,
|
|
19
20
|
formatCategories: ()=>formatCategories,
|
|
20
21
|
formatStepSummary: ()=>formatStepSummary,
|
|
21
|
-
formatStatus: ()=>formatStatus
|
|
22
|
+
formatStatus: ()=>formatStatus,
|
|
23
|
+
ensureValidCommandTarget: ()=>ensureValidCommandTarget
|
|
22
24
|
});
|
|
23
25
|
const _nodePath = /*#__PURE__*/ _interopRequireWildcard(require("node:path"));
|
|
26
|
+
const _core = require("@oclif/core");
|
|
24
27
|
const _fsExtra = /*#__PURE__*/ _interopRequireWildcard(require("fs-extra"));
|
|
25
28
|
const _lodash = require("lodash");
|
|
26
29
|
const _string = require("../../helpers/string");
|
|
@@ -66,6 +69,7 @@ function _interopRequireWildcard(obj, nodeInterop) {
|
|
|
66
69
|
}
|
|
67
70
|
const WORKFLOW_JSON = "workflow.json";
|
|
68
71
|
const VISUAL_BLOCKS_JSON = "visual_blocks.json";
|
|
72
|
+
const workflowJsonPath = (workflowDirCtx)=>_nodePath.resolve(workflowDirCtx.abspath, WORKFLOW_JSON);
|
|
69
73
|
const FILEPATH_MARKER = "@";
|
|
70
74
|
const FILEPATH_MARKED_RE = new RegExp(`${FILEPATH_MARKER}$`);
|
|
71
75
|
const validateWorkflowKey = (input)=>{
|
|
@@ -77,7 +81,7 @@ const validateWorkflowKey = (input)=>{
|
|
|
77
81
|
return undefined;
|
|
78
82
|
};
|
|
79
83
|
const lsWorkflowJson = async (dirPath)=>{
|
|
80
|
-
const workflowJsonPath = _nodePath.
|
|
84
|
+
const workflowJsonPath = _nodePath.resolve(dirPath, WORKFLOW_JSON);
|
|
81
85
|
const exists = await _fsExtra.pathExists(workflowJsonPath);
|
|
82
86
|
return exists ? workflowJsonPath : undefined;
|
|
83
87
|
};
|
|
@@ -149,3 +153,61 @@ const formatStepSummary = (step)=>{
|
|
|
149
153
|
const formatStatus = (workflow)=>{
|
|
150
154
|
return workflow.active ? "active" : "inactive";
|
|
151
155
|
};
|
|
156
|
+
const ensureValidCommandTarget = async (props, runContext)=>{
|
|
157
|
+
const { args , flags } = props;
|
|
158
|
+
const { commandId , resourceDir: resourceDirCtx , cwd: runCwd } = runContext;
|
|
159
|
+
// If the target resource is a different type than the current resource dir
|
|
160
|
+
// type, error out.
|
|
161
|
+
if (resourceDirCtx && resourceDirCtx.type !== "workflow") {
|
|
162
|
+
return _core.CliUx.ux.error(`Cannot run ${commandId} inside a ${resourceDirCtx.type} directory`);
|
|
163
|
+
}
|
|
164
|
+
// Cannot accept both workflow key arg and --all flag.
|
|
165
|
+
if (flags.all && args.workflowKey) {
|
|
166
|
+
return _core.CliUx.ux.error(`workflowKey arg \`${args.workflowKey}\` cannot also be provided when using --all`);
|
|
167
|
+
}
|
|
168
|
+
// --all flag is given, which means no workflow key arg.
|
|
169
|
+
if (flags.all) {
|
|
170
|
+
// If --all flag used inside a workflow directory, then require a workflows
|
|
171
|
+
// dir path.
|
|
172
|
+
if (resourceDirCtx && !flags["workflows-dir"]) {
|
|
173
|
+
return _core.CliUx.ux.error("Missing required flag workflows-dir");
|
|
174
|
+
}
|
|
175
|
+
// Targeting all workflow dirs in the workflows index dir.
|
|
176
|
+
// TODO: Default to the knock project config first if present before cwd.
|
|
177
|
+
const defaultToCwd = {
|
|
178
|
+
abspath: runCwd,
|
|
179
|
+
exists: true
|
|
180
|
+
};
|
|
181
|
+
const indexDirCtx = flags["workflows-dir"] || defaultToCwd;
|
|
182
|
+
return {
|
|
183
|
+
type: "workflowsIndexDir",
|
|
184
|
+
context: indexDirCtx
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
// Workflow key arg is given, which means no --all flag.
|
|
188
|
+
if (args.workflowKey) {
|
|
189
|
+
if (resourceDirCtx && resourceDirCtx.key !== args.workflowKey) {
|
|
190
|
+
return _core.CliUx.ux.error(`Cannot run ${commandId} \`${args.workflowKey}\` inside another workflow directory:\n${resourceDirCtx.key}`);
|
|
191
|
+
}
|
|
192
|
+
const targetDirPath = resourceDirCtx ? resourceDirCtx.abspath : _nodePath.resolve(runCwd, args.workflowKey);
|
|
193
|
+
const workflowDirCtx = {
|
|
194
|
+
type: "workflow",
|
|
195
|
+
key: args.workflowKey,
|
|
196
|
+
abspath: targetDirPath,
|
|
197
|
+
exists: await isWorkflowDir(targetDirPath)
|
|
198
|
+
};
|
|
199
|
+
return {
|
|
200
|
+
type: "workflowDir",
|
|
201
|
+
context: workflowDirCtx
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
// From this point on, we have neither a workflow key arg nor --all flag.
|
|
205
|
+
// If running inside a workflow directory, then use that workflow directory.
|
|
206
|
+
if (resourceDirCtx) {
|
|
207
|
+
return {
|
|
208
|
+
type: "workflowDir",
|
|
209
|
+
context: resourceDirCtx
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
return _core.CliUx.ux.error("Missing 1 required arg:\nworkflowKey");
|
|
213
|
+
};
|