@knocklabs/cli 0.1.0-rc.4 → 0.1.3
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 +172 -77
- package/dist/commands/commit/index.js +6 -3
- package/dist/commands/commit/promote.js +5 -2
- package/dist/commands/knock.js +102 -0
- package/dist/commands/ping.js +2 -4
- package/dist/commands/translation/get.js +128 -0
- package/dist/commands/translation/list.js +57 -9
- package/dist/commands/translation/pull.js +72 -21
- package/dist/commands/translation/push.js +23 -12
- package/dist/commands/translation/validate.js +12 -8
- package/dist/commands/whoami.js +31 -0
- package/dist/commands/workflow/activate.js +19 -8
- package/dist/commands/workflow/get.js +14 -10
- package/dist/commands/workflow/list.js +7 -3
- package/dist/commands/workflow/new.js +4 -5
- package/dist/commands/workflow/pull.js +18 -10
- package/dist/commands/workflow/push.js +60 -47
- package/dist/commands/workflow/run.js +58 -0
- package/dist/commands/workflow/validate.js +52 -48
- package/dist/lib/api-v1.js +32 -5
- package/dist/lib/base-command.js +8 -4
- package/dist/lib/helpers/flag.js +12 -1
- package/dist/lib/helpers/page.js +7 -2
- package/dist/lib/helpers/request.js +1 -1
- package/dist/lib/helpers/ux.js +2 -2
- package/dist/lib/marshal/translation/helpers.js +21 -7
- 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 +26 -16
- package/dist/lib/marshal/workflow/helpers.js +64 -2
- package/dist/lib/marshal/workflow/reader.js +62 -0
- package/dist/lib/run-context/helpers.js +2 -2
- package/oclif.manifest.json +281 -24
- package/package.json +25 -19
|
@@ -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.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,32 +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.emptyDir(
|
|
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
|
-
if (
|
|
76
|
-
await _fsExtra.emptyDir(
|
|
77
|
-
await _fsExtra.copy(backupDirPath,
|
|
85
|
+
if (targetDirCtx.exists) {
|
|
86
|
+
await _fsExtra.emptyDir(targetDirCtx.abspath);
|
|
87
|
+
await _fsExtra.copy(backupDirPath, targetDirCtx.abspath);
|
|
78
88
|
} else {
|
|
79
|
-
await _fsExtra.remove(
|
|
89
|
+
await _fsExtra.remove(targetDirCtx.abspath);
|
|
80
90
|
}
|
|
81
91
|
throw error;
|
|
82
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.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.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.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.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.ux.error("Missing 1 required arg:\nworkflowKey");
|
|
213
|
+
};
|
|
@@ -10,10 +10,12 @@ function _export(target, all) {
|
|
|
10
10
|
}
|
|
11
11
|
_export(exports, {
|
|
12
12
|
readWorkflowDir: ()=>readWorkflowDir,
|
|
13
|
+
readAllForCommandTarget: ()=>readAllForCommandTarget,
|
|
13
14
|
checkIfValidExtractedFilePathFormat: ()=>checkIfValidExtractedFilePathFormat,
|
|
14
15
|
readExtractedFileSync: ()=>readExtractedFileSync
|
|
15
16
|
});
|
|
16
17
|
const _nodePath = /*#__PURE__*/ _interopRequireWildcard(require("node:path"));
|
|
18
|
+
const _core = require("@oclif/core");
|
|
17
19
|
const _fsExtra = /*#__PURE__*/ _interopRequireWildcard(require("fs-extra"));
|
|
18
20
|
const _lodash = require("lodash");
|
|
19
21
|
const _error = require("../../helpers/error");
|
|
@@ -247,3 +249,63 @@ const readWorkflowDir = async (workflowDirCtx, opts = {})=>{
|
|
|
247
249
|
[]
|
|
248
250
|
];
|
|
249
251
|
};
|
|
252
|
+
/*
|
|
253
|
+
* For the given list of workflow directory contexts, read each workflow dir and
|
|
254
|
+
* return workflow directory data.
|
|
255
|
+
*/ const readWorkflowDirs = async (workflowDirCtxs, opts = {})=>{
|
|
256
|
+
const workflows = [];
|
|
257
|
+
const errors = [];
|
|
258
|
+
for (const workflowDirCtx of workflowDirCtxs){
|
|
259
|
+
// eslint-disable-next-line no-await-in-loop
|
|
260
|
+
const [workflow, readErrors] = await readWorkflowDir(workflowDirCtx, opts);
|
|
261
|
+
if (readErrors.length > 0) {
|
|
262
|
+
const workflowJsonPath = _nodePath.resolve(workflowDirCtx.abspath, _helpers.WORKFLOW_JSON);
|
|
263
|
+
const e = new _error.SourceError((0, _error.formatErrors)(readErrors), workflowJsonPath);
|
|
264
|
+
errors.push(e);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
workflows.push({
|
|
268
|
+
...workflowDirCtx,
|
|
269
|
+
content: workflow
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
return [
|
|
273
|
+
workflows,
|
|
274
|
+
errors
|
|
275
|
+
];
|
|
276
|
+
};
|
|
277
|
+
const readAllForCommandTarget = async (target, opts = {})=>{
|
|
278
|
+
const { type: targetType , context: targetCtx } = target;
|
|
279
|
+
if (!targetCtx.exists) {
|
|
280
|
+
const subject = targetType === "workflowDir" ? "a workflow directory at" : "workflow directories in";
|
|
281
|
+
return _core.ux.error(`Cannot locate ${subject} \`${targetCtx.abspath}\``);
|
|
282
|
+
}
|
|
283
|
+
switch(targetType){
|
|
284
|
+
case "workflowDir":
|
|
285
|
+
{
|
|
286
|
+
return readWorkflowDirs([
|
|
287
|
+
targetCtx
|
|
288
|
+
], opts);
|
|
289
|
+
}
|
|
290
|
+
case "workflowsIndexDir":
|
|
291
|
+
{
|
|
292
|
+
const dirents = await _fsExtra.readdir(targetCtx.abspath, {
|
|
293
|
+
withFileTypes: true
|
|
294
|
+
});
|
|
295
|
+
const promises = dirents.map(async (dirent)=>{
|
|
296
|
+
const abspath = _nodePath.resolve(targetCtx.abspath, dirent.name);
|
|
297
|
+
const workflowDirCtx = {
|
|
298
|
+
type: "workflow",
|
|
299
|
+
key: dirent.name,
|
|
300
|
+
abspath,
|
|
301
|
+
exists: await (0, _helpers.isWorkflowDir)(abspath)
|
|
302
|
+
};
|
|
303
|
+
return workflowDirCtx;
|
|
304
|
+
});
|
|
305
|
+
const workflowDirCtxs = (await Promise.all(promises)).filter((workflowDirCtx)=>workflowDirCtx.exists);
|
|
306
|
+
return readWorkflowDirs(workflowDirCtxs, opts);
|
|
307
|
+
}
|
|
308
|
+
default:
|
|
309
|
+
throw new Error(`Invalid workflow command target: ${target}`);
|
|
310
|
+
}
|
|
311
|
+
};
|
|
@@ -11,7 +11,7 @@ const ensureResourceDirForTarget = (resourceDirCtx, target)=>{
|
|
|
11
11
|
// If the target resource is a different type than the current resource dir
|
|
12
12
|
// type, error out.
|
|
13
13
|
if (resourceDirCtx.type !== target.type) {
|
|
14
|
-
return _core.
|
|
14
|
+
return _core.ux.error(`Cannot run ${target.commandId} inside a ${resourceDirCtx.type} directory`);
|
|
15
15
|
}
|
|
16
16
|
// If the resource key was not provided with the command, then infer from the
|
|
17
17
|
// current resource directory context.
|
|
@@ -23,5 +23,5 @@ const ensureResourceDirForTarget = (resourceDirCtx, target)=>{
|
|
|
23
23
|
if (target.key === resourceDirCtx.key) {
|
|
24
24
|
return resourceDirCtx;
|
|
25
25
|
}
|
|
26
|
-
return _core.
|
|
26
|
+
return _core.ux.error(`Cannot run ${target.commandId} \`${target.key}\` inside another ${resourceDirCtx.type} directory:\n${resourceDirCtx.key}`);
|
|
27
27
|
};
|