@knocklabs/cli 0.3.1 → 1.0.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 +343 -55
- package/dist/commands/branch/delete.js +4 -1
- package/dist/commands/branch/merge.js +82 -0
- package/dist/commands/channel/list.js +73 -0
- package/dist/commands/environment/list.js +73 -0
- package/dist/commands/guide/new.js +276 -0
- package/dist/commands/guide/open.js +106 -0
- package/dist/commands/guide/pull.js +5 -6
- package/dist/commands/guide/push.js +1 -1
- package/dist/commands/guide/validate.js +1 -1
- package/dist/commands/init.js +108 -0
- package/dist/commands/layout/new.js +228 -0
- package/dist/commands/layout/open.js +106 -0
- package/dist/commands/layout/pull.js +5 -6
- package/dist/commands/layout/push.js +1 -1
- package/dist/commands/layout/validate.js +1 -1
- package/dist/commands/message-type/new.js +228 -0
- package/dist/commands/message-type/open.js +106 -0
- package/dist/commands/message-type/pull.js +5 -6
- package/dist/commands/message-type/push.js +1 -1
- package/dist/commands/message-type/validate.js +1 -1
- package/dist/commands/partial/new.js +274 -0
- package/dist/commands/partial/open.js +106 -0
- package/dist/commands/partial/pull.js +5 -6
- package/dist/commands/partial/push.js +1 -1
- package/dist/commands/partial/validate.js +1 -1
- package/dist/commands/pull.js +7 -2
- package/dist/commands/push.js +6 -4
- package/dist/commands/translation/pull.js +1 -1
- package/dist/commands/translation/push.js +1 -1
- package/dist/commands/translation/validate.js +1 -1
- package/dist/commands/workflow/new.js +179 -54
- package/dist/commands/workflow/open.js +106 -0
- package/dist/commands/workflow/pull.js +6 -8
- package/dist/commands/workflow/push.js +1 -1
- package/dist/commands/workflow/validate.js +1 -1
- package/dist/lib/api-v1.js +23 -2
- package/dist/lib/auth.js +1 -1
- package/dist/lib/base-command.js +18 -15
- package/dist/lib/helpers/project-config.js +158 -0
- package/dist/lib/helpers/request.js +1 -2
- package/dist/lib/helpers/string.js +4 -4
- package/dist/lib/helpers/typegen.js +1 -1
- package/dist/lib/marshal/email-layout/generator.js +152 -0
- package/dist/lib/marshal/email-layout/helpers.js +6 -9
- package/dist/lib/marshal/email-layout/index.js +1 -0
- package/dist/lib/marshal/email-layout/writer.js +15 -3
- package/dist/lib/marshal/guide/generator.js +163 -0
- package/dist/lib/marshal/guide/helpers.js +6 -10
- package/dist/lib/marshal/guide/index.js +1 -0
- package/dist/lib/marshal/guide/writer.js +5 -9
- package/dist/lib/marshal/message-type/generator.js +139 -0
- package/dist/lib/marshal/message-type/helpers.js +6 -10
- package/dist/lib/marshal/message-type/index.js +1 -0
- package/dist/lib/marshal/message-type/writer.js +5 -1
- package/dist/lib/marshal/partial/generator.js +159 -0
- package/dist/lib/marshal/partial/helpers.js +6 -10
- package/dist/lib/marshal/partial/index.js +1 -0
- package/dist/lib/marshal/partial/writer.js +3 -0
- package/dist/lib/marshal/translation/helpers.js +6 -10
- package/dist/lib/marshal/translation/processor.isomorphic.js +4 -4
- package/dist/lib/marshal/translation/writer.js +2 -2
- package/dist/lib/marshal/workflow/generator.js +175 -19
- package/dist/lib/marshal/workflow/helpers.js +7 -10
- package/dist/lib/run-context/loader.js +5 -0
- package/dist/lib/templates.js +131 -0
- package/dist/lib/urls.js +16 -0
- package/oclif.manifest.json +1446 -547
- package/package.json +11 -9
|
@@ -12,6 +12,9 @@ _export(exports, {
|
|
|
12
12
|
get pruneLayoutsIndexDir () {
|
|
13
13
|
return pruneLayoutsIndexDir;
|
|
14
14
|
},
|
|
15
|
+
get writeEmailLayoutDirFromBundle () {
|
|
16
|
+
return writeEmailLayoutDirFromBundle;
|
|
17
|
+
},
|
|
15
18
|
get writeEmailLayoutDirFromData () {
|
|
16
19
|
return writeEmailLayoutDirFromData;
|
|
17
20
|
},
|
|
@@ -82,18 +85,27 @@ const writeEmailLayoutDirFromData = async (emailLayoutDirCtx, remoteEmailLayout,
|
|
|
82
85
|
withExtractedFiles: true
|
|
83
86
|
}) : [];
|
|
84
87
|
const bundle = (0, _processorisomorphic.buildEmailLayoutDirBundle)(remoteEmailLayout, localEmailLayout, withSchema ? EMAIL_LAYOUT_SCHEMA : undefined);
|
|
88
|
+
return writeEmailLayoutDirFromBundle(emailLayoutDirCtx, bundle);
|
|
89
|
+
};
|
|
90
|
+
/*
|
|
91
|
+
* A lower level write function that takes a constructed email layout dir bundle
|
|
92
|
+
* and writes it into a layout directory on a local file system.
|
|
93
|
+
*
|
|
94
|
+
* It does not make any assumptions about how the email layout directory bundle was
|
|
95
|
+
* built; for example, it can be from parsing the layout data fetched from
|
|
96
|
+
* the Knock API, or built manually for scaffolding purposes.
|
|
97
|
+
*/ const writeEmailLayoutDirFromBundle = async (emailLayoutDirCtx, emailLayoutDirBundle)=>{
|
|
85
98
|
const backupDirPath = _nodepath.default.resolve(_const.sandboxDir, (0, _lodash.uniqueId)("backup"));
|
|
86
99
|
try {
|
|
87
|
-
// We store a backup in case there's an error.
|
|
88
100
|
if (emailLayoutDirCtx.exists) {
|
|
89
101
|
await _fsextra.copy(emailLayoutDirCtx.abspath, backupDirPath);
|
|
90
102
|
await _fsextra.emptyDir(emailLayoutDirCtx.abspath);
|
|
91
103
|
}
|
|
92
|
-
const promises = Object.entries(
|
|
104
|
+
const promises = Object.entries(emailLayoutDirBundle).map(([relpath, fileContent])=>{
|
|
93
105
|
const filePath = _nodepath.default.resolve(emailLayoutDirCtx.abspath, relpath);
|
|
94
106
|
return relpath === _processorisomorphic.LAYOUT_JSON ? _fsextra.outputJson(filePath, fileContent, {
|
|
95
107
|
spaces: _json.DOUBLE_SPACES
|
|
96
|
-
}) : _fsextra.outputFile(filePath, fileContent);
|
|
108
|
+
}) : _fsextra.outputFile(filePath, fileContent !== null && fileContent !== void 0 ? fileContent : "");
|
|
97
109
|
});
|
|
98
110
|
await Promise.all(promises);
|
|
99
111
|
} catch (error) {
|
|
@@ -0,0 +1,163 @@
|
|
|
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 generateGuideDir () {
|
|
13
|
+
return generateGuideDir;
|
|
14
|
+
},
|
|
15
|
+
get generateGuideFromTemplate () {
|
|
16
|
+
return generateGuideFromTemplate;
|
|
17
|
+
},
|
|
18
|
+
get scaffoldGuideDirBundle () {
|
|
19
|
+
return scaffoldGuideDirBundle;
|
|
20
|
+
},
|
|
21
|
+
get scaffoldValuesFromSchema () {
|
|
22
|
+
return scaffoldValuesFromSchema;
|
|
23
|
+
},
|
|
24
|
+
get validateGuideKey () {
|
|
25
|
+
return validateGuideKey;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
const _string = require("../../helpers/string");
|
|
29
|
+
const _templates = /*#__PURE__*/ _interop_require_wildcard(require("../../templates"));
|
|
30
|
+
const _processorisomorphic = require("./processor.isomorphic");
|
|
31
|
+
const _reader = require("./reader");
|
|
32
|
+
const _writer = require("./writer");
|
|
33
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
34
|
+
if (typeof WeakMap !== "function") return null;
|
|
35
|
+
var cacheBabelInterop = new WeakMap();
|
|
36
|
+
var cacheNodeInterop = new WeakMap();
|
|
37
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
38
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
39
|
+
})(nodeInterop);
|
|
40
|
+
}
|
|
41
|
+
function _interop_require_wildcard(obj, nodeInterop) {
|
|
42
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
43
|
+
return obj;
|
|
44
|
+
}
|
|
45
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
46
|
+
return {
|
|
47
|
+
default: obj
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
51
|
+
if (cache && cache.has(obj)) {
|
|
52
|
+
return cache.get(obj);
|
|
53
|
+
}
|
|
54
|
+
var newObj = {
|
|
55
|
+
__proto__: null
|
|
56
|
+
};
|
|
57
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
58
|
+
for(var key in obj){
|
|
59
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
60
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
61
|
+
if (desc && (desc.get || desc.set)) {
|
|
62
|
+
Object.defineProperty(newObj, key, desc);
|
|
63
|
+
} else {
|
|
64
|
+
newObj[key] = obj[key];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
newObj.default = obj;
|
|
69
|
+
if (cache) {
|
|
70
|
+
cache.set(obj, newObj);
|
|
71
|
+
}
|
|
72
|
+
return newObj;
|
|
73
|
+
}
|
|
74
|
+
const validateGuideKey = (input)=>{
|
|
75
|
+
if (!(0, _string.checkSlugifiedFormat)(input, {
|
|
76
|
+
onlyLowerCase: true
|
|
77
|
+
})) {
|
|
78
|
+
return "must include only lowercase alphanumeric, dash, or underscore characters";
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
};
|
|
82
|
+
const scaffoldValuesFromSchema = (fields)=>{
|
|
83
|
+
const values = {};
|
|
84
|
+
for (const field of fields){
|
|
85
|
+
switch(field.type){
|
|
86
|
+
case "text":
|
|
87
|
+
case "textarea":
|
|
88
|
+
case "markdown":
|
|
89
|
+
values[field.key] = "";
|
|
90
|
+
break;
|
|
91
|
+
case "boolean":
|
|
92
|
+
values[field.key] = false;
|
|
93
|
+
break;
|
|
94
|
+
case "select":
|
|
95
|
+
case "multi_select":
|
|
96
|
+
values[field.key] = null;
|
|
97
|
+
break;
|
|
98
|
+
case "button":
|
|
99
|
+
values[field.key] = {
|
|
100
|
+
text: "",
|
|
101
|
+
action: ""
|
|
102
|
+
};
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return values;
|
|
107
|
+
};
|
|
108
|
+
const scaffoldGuideDirBundle = (attrs)=>{
|
|
109
|
+
const { name, messageType, variantKey = "default" } = attrs;
|
|
110
|
+
// Find the selected variant or default to the first one
|
|
111
|
+
const variant = messageType.variants.find((v)=>v.key === variantKey) || messageType.variants[0];
|
|
112
|
+
if (!variant) {
|
|
113
|
+
throw new Error(`Message type ${messageType.key} has no variants available`);
|
|
114
|
+
}
|
|
115
|
+
// Scaffold values from the variant's field schema
|
|
116
|
+
const values = scaffoldValuesFromSchema(variant.fields);
|
|
117
|
+
const guideJson = {
|
|
118
|
+
name,
|
|
119
|
+
steps: [
|
|
120
|
+
{
|
|
121
|
+
ref: "step_1",
|
|
122
|
+
schema_key: messageType.key,
|
|
123
|
+
schema_variant_key: variant.key,
|
|
124
|
+
values
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
};
|
|
128
|
+
return {
|
|
129
|
+
[_processorisomorphic.GUIDE_JSON]: guideJson
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
const generateGuideDir = async (guideDirCtx, attrs)=>{
|
|
133
|
+
const bundle = scaffoldGuideDirBundle(attrs);
|
|
134
|
+
return (0, _writer.writeGuideDirFromBundle)(guideDirCtx, bundle);
|
|
135
|
+
};
|
|
136
|
+
const generateGuideFromTemplate = async (guideDirCtx, templateString, attrs)=>{
|
|
137
|
+
let tempDir;
|
|
138
|
+
try {
|
|
139
|
+
// Download the template directory into a temp directory
|
|
140
|
+
tempDir = await _templates.downloadTemplate(templateString);
|
|
141
|
+
// Create a guide directory context for the temp directory
|
|
142
|
+
const tempGuideDirCtx = {
|
|
143
|
+
type: "guide",
|
|
144
|
+
key: "temp",
|
|
145
|
+
abspath: tempDir,
|
|
146
|
+
exists: true
|
|
147
|
+
};
|
|
148
|
+
// Read the guide.json from the temp directory we downloaded
|
|
149
|
+
const [guide, errors] = await (0, _reader.readGuideDir)(tempGuideDirCtx, {
|
|
150
|
+
withExtractedFiles: true
|
|
151
|
+
});
|
|
152
|
+
if (errors.length > 0 || !guide) {
|
|
153
|
+
throw new Error(`Invalid guide template: ${errors.join(", ")}`);
|
|
154
|
+
}
|
|
155
|
+
// Modify the guide data with the new attributes
|
|
156
|
+
guide.name = attrs.name;
|
|
157
|
+
// Finally, we write the guide into the target guide directory
|
|
158
|
+
(0, _writer.writeGuideDirFromData)(guideDirCtx, guide);
|
|
159
|
+
return;
|
|
160
|
+
} finally{
|
|
161
|
+
await _templates.cleanupTempDir(tempDir);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
@@ -42,6 +42,7 @@ const _core = require("@oclif/core");
|
|
|
42
42
|
const _fsextra = /*#__PURE__*/ _interop_require_wildcard(require("fs-extra"));
|
|
43
43
|
const _lodash = require("lodash");
|
|
44
44
|
const _quicktypecore = require("quicktype-core");
|
|
45
|
+
const _projectconfig = require("../../helpers/project-config");
|
|
45
46
|
const _processorisomorphic = require("./processor.isomorphic");
|
|
46
47
|
function _getRequireWildcardCache(nodeInterop) {
|
|
47
48
|
if (typeof WeakMap !== "function") return null;
|
|
@@ -107,7 +108,7 @@ const lsGuideJson = async (dirPath)=>{
|
|
|
107
108
|
return exists ? guideJsonPath : undefined;
|
|
108
109
|
};
|
|
109
110
|
const isGuideDir = async (dirPath)=>Boolean(await lsGuideJson(dirPath));
|
|
110
|
-
const ensureValidCommandTarget = async (props, runContext)=>{
|
|
111
|
+
const ensureValidCommandTarget = async (props, runContext, projectConfig)=>{
|
|
111
112
|
const { args, flags } = props;
|
|
112
113
|
const { commandId, resourceDir: resourceDirCtx, cwd: runCwd } = runContext;
|
|
113
114
|
// If the target resource is a different type than the current resource dir
|
|
@@ -119,6 +120,8 @@ const ensureValidCommandTarget = async (props, runContext)=>{
|
|
|
119
120
|
if (flags.all && args.guideKey) {
|
|
120
121
|
return _core.ux.error(`guideKey arg \`${args.guideKey}\` cannot also be provided when using --all`);
|
|
121
122
|
}
|
|
123
|
+
// Default to knock project config first if present, otherwise cwd.
|
|
124
|
+
const guidesIndexDirCtx = await (0, _projectconfig.resolveResourceDir)(projectConfig, "guide", runCwd);
|
|
122
125
|
// --all flag is given, which means no guide key arg.
|
|
123
126
|
if (flags.all) {
|
|
124
127
|
// If --all flag used inside a guide directory, then require a guides
|
|
@@ -126,16 +129,9 @@ const ensureValidCommandTarget = async (props, runContext)=>{
|
|
|
126
129
|
if (resourceDirCtx && !flags["guides-dir"]) {
|
|
127
130
|
return _core.ux.error("Missing required flag guides-dir");
|
|
128
131
|
}
|
|
129
|
-
// Targeting all guide dirs in the guides index dir.
|
|
130
|
-
// TODO: Default to the knock project config first if present before cwd.
|
|
131
|
-
const defaultToCwd = {
|
|
132
|
-
abspath: runCwd,
|
|
133
|
-
exists: true
|
|
134
|
-
};
|
|
135
|
-
const indexDirCtx = flags["guides-dir"] || defaultToCwd;
|
|
136
132
|
return {
|
|
137
133
|
type: "guidesIndexDir",
|
|
138
|
-
context:
|
|
134
|
+
context: flags["guides-dir"] || guidesIndexDirCtx
|
|
139
135
|
};
|
|
140
136
|
}
|
|
141
137
|
// Guide key arg is given, which means no --all flag.
|
|
@@ -143,7 +139,7 @@ const ensureValidCommandTarget = async (props, runContext)=>{
|
|
|
143
139
|
if (resourceDirCtx && resourceDirCtx.key !== args.guideKey) {
|
|
144
140
|
return _core.ux.error(`Cannot run ${commandId} \`${args.guideKey}\` inside another guide directory:\n${resourceDirCtx.key}`);
|
|
145
141
|
}
|
|
146
|
-
const targetDirPath = resourceDirCtx ? resourceDirCtx.abspath : _nodepath.resolve(
|
|
142
|
+
const targetDirPath = resourceDirCtx ? resourceDirCtx.abspath : _nodepath.resolve(guidesIndexDirCtx.abspath, args.guideKey);
|
|
147
143
|
const guideDirCtx = {
|
|
148
144
|
type: "guide",
|
|
149
145
|
key: args.guideKey,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
+
_export_star(require("./generator"), exports);
|
|
5
6
|
_export_star(require("./helpers"), exports);
|
|
6
7
|
_export_star(require("./processor.isomorphic"), exports);
|
|
7
8
|
_export_star(require("./reader"), exports);
|
|
@@ -12,6 +12,9 @@ _export(exports, {
|
|
|
12
12
|
get pruneGuidesIndexDir () {
|
|
13
13
|
return pruneGuidesIndexDir;
|
|
14
14
|
},
|
|
15
|
+
get writeGuideDirFromBundle () {
|
|
16
|
+
return writeGuideDirFromBundle;
|
|
17
|
+
},
|
|
15
18
|
get writeGuideDirFromData () {
|
|
16
19
|
return writeGuideDirFromData;
|
|
17
20
|
},
|
|
@@ -79,14 +82,7 @@ const writeGuideDirFromData = async (guideDirCtx, remoteGuide, options)=>{
|
|
|
79
82
|
const bundle = (0, _processorisomorphic.buildGuideDirBundle)(remoteGuide, localGuide, withSchema ? GUIDE_SCHEMA : undefined);
|
|
80
83
|
return writeGuideDirFromBundle(guideDirCtx, bundle);
|
|
81
84
|
};
|
|
82
|
-
|
|
83
|
-
* A lower level write function that takes a constructed guide dir bundle
|
|
84
|
-
* and writes it into a guide directory on a local file system.
|
|
85
|
-
*
|
|
86
|
-
* It does not make any assumptions about how the guide directory bundle was
|
|
87
|
-
* built; for example, it can be from parsing the guide data fetched from
|
|
88
|
-
* the Knock API, or built manually for scaffolding purposes.
|
|
89
|
-
*/ const writeGuideDirFromBundle = async (guideDirCtx, guideDirBundle)=>{
|
|
85
|
+
const writeGuideDirFromBundle = async (guideDirCtx, guideDirBundle)=>{
|
|
90
86
|
const backupDirPath = _nodepath.resolve(_const.sandboxDir, (0, _lodash.uniqueId)("backup"));
|
|
91
87
|
try {
|
|
92
88
|
if (guideDirCtx.exists) {
|
|
@@ -97,7 +93,7 @@ const writeGuideDirFromData = async (guideDirCtx, remoteGuide, options)=>{
|
|
|
97
93
|
const filePath = _nodepath.resolve(guideDirCtx.abspath, relpath);
|
|
98
94
|
return relpath === _processorisomorphic.GUIDE_JSON ? _fsextra.outputJson(filePath, fileContent, {
|
|
99
95
|
spaces: _json.DOUBLE_SPACES
|
|
100
|
-
}) : _fsextra.outputFile(filePath,
|
|
96
|
+
}) : _fsextra.outputFile(filePath, typeof fileContent === "string" ? fileContent : "");
|
|
101
97
|
});
|
|
102
98
|
await Promise.all(promises);
|
|
103
99
|
} catch (error) {
|
|
@@ -0,0 +1,139 @@
|
|
|
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 generateMessageTypeDir () {
|
|
13
|
+
return generateMessageTypeDir;
|
|
14
|
+
},
|
|
15
|
+
get generateMessageTypeFromTemplate () {
|
|
16
|
+
return generateMessageTypeFromTemplate;
|
|
17
|
+
},
|
|
18
|
+
get scaffoldMessageTypeDirBundle () {
|
|
19
|
+
return scaffoldMessageTypeDirBundle;
|
|
20
|
+
},
|
|
21
|
+
get validateMessageTypeKey () {
|
|
22
|
+
return validateMessageTypeKey;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
const _lodash = require("lodash");
|
|
26
|
+
const _string = require("../../helpers/string");
|
|
27
|
+
const _templates = /*#__PURE__*/ _interop_require_wildcard(require("../../templates"));
|
|
28
|
+
const _constisomorphic = require("../shared/const.isomorphic");
|
|
29
|
+
const _processorisomorphic = require("./processor.isomorphic");
|
|
30
|
+
const _reader = require("./reader");
|
|
31
|
+
const _writer = require("./writer");
|
|
32
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
33
|
+
if (typeof WeakMap !== "function") return null;
|
|
34
|
+
var cacheBabelInterop = new WeakMap();
|
|
35
|
+
var cacheNodeInterop = new WeakMap();
|
|
36
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
37
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
38
|
+
})(nodeInterop);
|
|
39
|
+
}
|
|
40
|
+
function _interop_require_wildcard(obj, nodeInterop) {
|
|
41
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
42
|
+
return obj;
|
|
43
|
+
}
|
|
44
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
45
|
+
return {
|
|
46
|
+
default: obj
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
50
|
+
if (cache && cache.has(obj)) {
|
|
51
|
+
return cache.get(obj);
|
|
52
|
+
}
|
|
53
|
+
var newObj = {
|
|
54
|
+
__proto__: null
|
|
55
|
+
};
|
|
56
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
57
|
+
for(var key in obj){
|
|
58
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
59
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
60
|
+
if (desc && (desc.get || desc.set)) {
|
|
61
|
+
Object.defineProperty(newObj, key, desc);
|
|
62
|
+
} else {
|
|
63
|
+
newObj[key] = obj[key];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
newObj.default = obj;
|
|
68
|
+
if (cache) {
|
|
69
|
+
cache.set(obj, newObj);
|
|
70
|
+
}
|
|
71
|
+
return newObj;
|
|
72
|
+
}
|
|
73
|
+
const validateMessageTypeKey = (input)=>{
|
|
74
|
+
if (!(0, _string.checkSlugifiedFormat)(input, {
|
|
75
|
+
onlyLowerCase: true
|
|
76
|
+
})) {
|
|
77
|
+
return "must include only lowercase alphanumeric, dash, or underscore characters";
|
|
78
|
+
}
|
|
79
|
+
return undefined;
|
|
80
|
+
};
|
|
81
|
+
/*
|
|
82
|
+
* Returns the default scaffolded preview content.
|
|
83
|
+
*/ const defaultPreviewContent = ()=>{
|
|
84
|
+
return `{{ name }}`;
|
|
85
|
+
};
|
|
86
|
+
/*
|
|
87
|
+
* Scaffolds a new message type directory bundle with default content.
|
|
88
|
+
*/ const scaffoldMessageTypeDirBundle = (attrs)=>{
|
|
89
|
+
const previewFilePath = "preview.txt";
|
|
90
|
+
const defaultPreview = defaultPreviewContent();
|
|
91
|
+
const messageTypeJson = {
|
|
92
|
+
name: attrs.name,
|
|
93
|
+
description: "",
|
|
94
|
+
variants: [
|
|
95
|
+
{
|
|
96
|
+
key: "default",
|
|
97
|
+
name: "Default",
|
|
98
|
+
fields: []
|
|
99
|
+
}
|
|
100
|
+
],
|
|
101
|
+
[`preview${_constisomorphic.FILEPATH_MARKER}`]: previewFilePath
|
|
102
|
+
};
|
|
103
|
+
return {
|
|
104
|
+
[_processorisomorphic.MESSAGE_TYPE_JSON]: messageTypeJson,
|
|
105
|
+
[previewFilePath]: defaultPreview
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
const generateMessageTypeDir = async (messageTypeDirCtx, attrs)=>{
|
|
109
|
+
const bundle = scaffoldMessageTypeDirBundle(attrs);
|
|
110
|
+
return (0, _writer.writeMessageTypeDirFromBundle)(messageTypeDirCtx, bundle);
|
|
111
|
+
};
|
|
112
|
+
const generateMessageTypeFromTemplate = async (messageTypeDirCtx, templateString, attrs)=>{
|
|
113
|
+
let tempDir;
|
|
114
|
+
try {
|
|
115
|
+
// Download the template directory into a temp directory
|
|
116
|
+
tempDir = await _templates.downloadTemplate(templateString);
|
|
117
|
+
// Create a message type directory context for the temp directory
|
|
118
|
+
const tempMessageTypeDirCtx = {
|
|
119
|
+
type: "message_type",
|
|
120
|
+
key: "temp",
|
|
121
|
+
abspath: tempDir,
|
|
122
|
+
exists: true
|
|
123
|
+
};
|
|
124
|
+
// Read the message_type.json from the temp directory we downloaded
|
|
125
|
+
const [messageType, errors] = await (0, _reader.readMessageTypeDir)(tempMessageTypeDirCtx, {
|
|
126
|
+
withExtractedFiles: true
|
|
127
|
+
});
|
|
128
|
+
if (errors.length > 0 || !messageType) {
|
|
129
|
+
throw new Error(`Invalid message type template: ${errors.join(", ")}`);
|
|
130
|
+
}
|
|
131
|
+
// Modify the message type data with the new attributes
|
|
132
|
+
const messageTypeData = (0, _lodash.cloneDeep)(messageType);
|
|
133
|
+
messageTypeData.name = attrs.name;
|
|
134
|
+
// Finally, we write the message type into the target message type directory
|
|
135
|
+
await (0, _writer.writeMessageTypeDirFromData)(messageTypeDirCtx, messageTypeData);
|
|
136
|
+
} finally{
|
|
137
|
+
await _templates.cleanupTempDir(tempDir);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
@@ -25,6 +25,7 @@ _export(exports, {
|
|
|
25
25
|
const _nodepath = /*#__PURE__*/ _interop_require_wildcard(require("node:path"));
|
|
26
26
|
const _core = require("@oclif/core");
|
|
27
27
|
const _fsextra = /*#__PURE__*/ _interop_require_wildcard(require("fs-extra"));
|
|
28
|
+
const _projectconfig = require("../../helpers/project-config");
|
|
28
29
|
const _processorisomorphic = require("./processor.isomorphic");
|
|
29
30
|
function _getRequireWildcardCache(nodeInterop) {
|
|
30
31
|
if (typeof WeakMap !== "function") return null;
|
|
@@ -74,7 +75,7 @@ const lsMessageTypeJson = async (dirPath)=>{
|
|
|
74
75
|
return exists ? messageTypeJsonPath : undefined;
|
|
75
76
|
};
|
|
76
77
|
const isMessageTypeDir = async (dirPath)=>Boolean(await lsMessageTypeJson(dirPath));
|
|
77
|
-
const ensureValidCommandTarget = async (props, runContext)=>{
|
|
78
|
+
const ensureValidCommandTarget = async (props, runContext, projectConfig)=>{
|
|
78
79
|
const { args, flags } = props;
|
|
79
80
|
const { commandId, resourceDir: resourceDirCtx, cwd: runCwd } = runContext;
|
|
80
81
|
// If the target resource is a different type than the current resource dir
|
|
@@ -86,6 +87,8 @@ const ensureValidCommandTarget = async (props, runContext)=>{
|
|
|
86
87
|
if (flags.all && args.messageTypeKey) {
|
|
87
88
|
return _core.ux.error(`messageTypeKey arg \`${args.messageTypeKey}\` cannot also be provided when using --all`);
|
|
88
89
|
}
|
|
90
|
+
// Default to knock project config first if present, otherwise cwd.
|
|
91
|
+
const messageTypesIndexDirCtx = await (0, _projectconfig.resolveResourceDir)(projectConfig, "message_type", runCwd);
|
|
89
92
|
// --all flag is given, which means no message type key arg.
|
|
90
93
|
if (flags.all) {
|
|
91
94
|
// If --all flag used inside a message type directory, then require a message
|
|
@@ -93,16 +96,9 @@ const ensureValidCommandTarget = async (props, runContext)=>{
|
|
|
93
96
|
if (resourceDirCtx && !flags["message-types-dir"]) {
|
|
94
97
|
return _core.ux.error("Missing required flag message-types-dir");
|
|
95
98
|
}
|
|
96
|
-
// Targeting all message type dirs in the message types index dir.
|
|
97
|
-
// TODO: Default to the knock project config first if present before cwd.
|
|
98
|
-
const defaultToCwd = {
|
|
99
|
-
abspath: runCwd,
|
|
100
|
-
exists: true
|
|
101
|
-
};
|
|
102
|
-
const indexDirCtx = flags["message-types-dir"] || defaultToCwd;
|
|
103
99
|
return {
|
|
104
100
|
type: "messageTypesIndexDir",
|
|
105
|
-
context:
|
|
101
|
+
context: flags["message-types-dir"] || messageTypesIndexDirCtx
|
|
106
102
|
};
|
|
107
103
|
}
|
|
108
104
|
// Message type key arg is given, which means no --all flag.
|
|
@@ -110,7 +106,7 @@ const ensureValidCommandTarget = async (props, runContext)=>{
|
|
|
110
106
|
if (resourceDirCtx && resourceDirCtx.key !== args.messageTypeKey) {
|
|
111
107
|
return _core.ux.error(`Cannot run ${commandId} \`${args.messageTypeKey}\` inside another message type directory:\n${resourceDirCtx.key}`);
|
|
112
108
|
}
|
|
113
|
-
const targetDirPath = resourceDirCtx ? resourceDirCtx.abspath : _nodepath.resolve(
|
|
109
|
+
const targetDirPath = resourceDirCtx ? resourceDirCtx.abspath : _nodepath.resolve(messageTypesIndexDirCtx.abspath, args.messageTypeKey);
|
|
114
110
|
const messageTypeDirCtx = {
|
|
115
111
|
type: "message_type",
|
|
116
112
|
key: args.messageTypeKey,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
+
_export_star(require("./generator"), exports);
|
|
5
6
|
_export_star(require("./helpers"), exports);
|
|
6
7
|
_export_star(require("./processor.isomorphic"), exports);
|
|
7
8
|
_export_star(require("./reader"), exports);
|
|
@@ -12,6 +12,9 @@ _export(exports, {
|
|
|
12
12
|
get pruneMessageTypesIndexDir () {
|
|
13
13
|
return pruneMessageTypesIndexDir;
|
|
14
14
|
},
|
|
15
|
+
get writeMessageTypeDirFromBundle () {
|
|
16
|
+
return writeMessageTypeDirFromBundle;
|
|
17
|
+
},
|
|
15
18
|
get writeMessageTypeDirFromData () {
|
|
16
19
|
return writeMessageTypeDirFromData;
|
|
17
20
|
},
|
|
@@ -94,10 +97,11 @@ const writeMessageTypeDirFromData = async (messageTypeDirCtx, remoteMessageType,
|
|
|
94
97
|
await _fsextra.emptyDir(messageTypeDirCtx.abspath);
|
|
95
98
|
}
|
|
96
99
|
const promises = Object.entries(messageTypeDirBundle).map(([relpath, fileContent])=>{
|
|
100
|
+
var _fileContent_toString;
|
|
97
101
|
const filePath = _nodepath.resolve(messageTypeDirCtx.abspath, relpath);
|
|
98
102
|
return relpath === _processorisomorphic.MESSAGE_TYPE_JSON ? _fsextra.outputJson(filePath, fileContent, {
|
|
99
103
|
spaces: _json.DOUBLE_SPACES
|
|
100
|
-
}) : _fsextra.outputFile(filePath, fileContent !== null &&
|
|
104
|
+
}) : _fsextra.outputFile(filePath, (_fileContent_toString = fileContent.toString()) !== null && _fileContent_toString !== void 0 ? _fileContent_toString : "");
|
|
101
105
|
});
|
|
102
106
|
await Promise.all(promises);
|
|
103
107
|
} catch (error) {
|
|
@@ -0,0 +1,159 @@
|
|
|
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 generatePartialDir () {
|
|
13
|
+
return generatePartialDir;
|
|
14
|
+
},
|
|
15
|
+
get generatePartialFromTemplate () {
|
|
16
|
+
return generatePartialFromTemplate;
|
|
17
|
+
},
|
|
18
|
+
get scaffoldPartialDirBundle () {
|
|
19
|
+
return scaffoldPartialDirBundle;
|
|
20
|
+
},
|
|
21
|
+
get validatePartialKey () {
|
|
22
|
+
return validatePartialKey;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
const _lodash = require("lodash");
|
|
26
|
+
const _string = require("../../helpers/string");
|
|
27
|
+
const _templates = /*#__PURE__*/ _interop_require_wildcard(require("../../templates"));
|
|
28
|
+
const _constisomorphic = require("../shared/const.isomorphic");
|
|
29
|
+
const _processorisomorphic = require("./processor.isomorphic");
|
|
30
|
+
const _reader = require("./reader");
|
|
31
|
+
const _types = require("./types");
|
|
32
|
+
const _writer = require("./writer");
|
|
33
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
34
|
+
if (typeof WeakMap !== "function") return null;
|
|
35
|
+
var cacheBabelInterop = new WeakMap();
|
|
36
|
+
var cacheNodeInterop = new WeakMap();
|
|
37
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
38
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
39
|
+
})(nodeInterop);
|
|
40
|
+
}
|
|
41
|
+
function _interop_require_wildcard(obj, nodeInterop) {
|
|
42
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
43
|
+
return obj;
|
|
44
|
+
}
|
|
45
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
46
|
+
return {
|
|
47
|
+
default: obj
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
51
|
+
if (cache && cache.has(obj)) {
|
|
52
|
+
return cache.get(obj);
|
|
53
|
+
}
|
|
54
|
+
var newObj = {
|
|
55
|
+
__proto__: null
|
|
56
|
+
};
|
|
57
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
58
|
+
for(var key in obj){
|
|
59
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
60
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
61
|
+
if (desc && (desc.get || desc.set)) {
|
|
62
|
+
Object.defineProperty(newObj, key, desc);
|
|
63
|
+
} else {
|
|
64
|
+
newObj[key] = obj[key];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
newObj.default = obj;
|
|
69
|
+
if (cache) {
|
|
70
|
+
cache.set(obj, newObj);
|
|
71
|
+
}
|
|
72
|
+
return newObj;
|
|
73
|
+
}
|
|
74
|
+
const validatePartialKey = (input)=>{
|
|
75
|
+
if (!(0, _string.checkSlugifiedFormat)(input, {
|
|
76
|
+
onlyLowerCase: true
|
|
77
|
+
})) {
|
|
78
|
+
return "must include only lowercase alphanumeric, dash, or underscore characters";
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
};
|
|
82
|
+
/*
|
|
83
|
+
* Maps the partial type to the correct file extension.
|
|
84
|
+
*/ const partialTypeToFileExt = (type)=>{
|
|
85
|
+
switch(type){
|
|
86
|
+
case _types.PartialType.Html:
|
|
87
|
+
return "html";
|
|
88
|
+
case _types.PartialType.Json:
|
|
89
|
+
return "json";
|
|
90
|
+
case _types.PartialType.Markdown:
|
|
91
|
+
return "md";
|
|
92
|
+
case _types.PartialType.Text:
|
|
93
|
+
default:
|
|
94
|
+
return "txt";
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
/*
|
|
98
|
+
* Returns the default scaffolded content for a partial based on its type.
|
|
99
|
+
*/ const defaultContentForType = (type)=>{
|
|
100
|
+
switch(type){
|
|
101
|
+
case _types.PartialType.Html:
|
|
102
|
+
return "<div>{{ content }}</div>";
|
|
103
|
+
case _types.PartialType.Json:
|
|
104
|
+
return "{}";
|
|
105
|
+
case _types.PartialType.Markdown:
|
|
106
|
+
return "**{{ content }}**";
|
|
107
|
+
case _types.PartialType.Text:
|
|
108
|
+
default:
|
|
109
|
+
return "{{ content }}";
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
/*
|
|
113
|
+
* Scaffolds a new partial directory bundle with default content.
|
|
114
|
+
*/ const scaffoldPartialDirBundle = (attrs)=>{
|
|
115
|
+
const fileExt = partialTypeToFileExt(attrs.type);
|
|
116
|
+
const contentFilePath = `content.${fileExt}`;
|
|
117
|
+
const defaultContent = defaultContentForType(attrs.type);
|
|
118
|
+
const partialJson = {
|
|
119
|
+
name: attrs.name,
|
|
120
|
+
type: attrs.type,
|
|
121
|
+
[`content${_constisomorphic.FILEPATH_MARKER}`]: contentFilePath
|
|
122
|
+
};
|
|
123
|
+
return {
|
|
124
|
+
[_processorisomorphic.PARTIAL_JSON]: partialJson,
|
|
125
|
+
[contentFilePath]: defaultContent
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
const generatePartialDir = async (partialDirCtx, attrs)=>{
|
|
129
|
+
const bundle = scaffoldPartialDirBundle(attrs);
|
|
130
|
+
return (0, _writer.writePartialDirFromBundle)(partialDirCtx, bundle);
|
|
131
|
+
};
|
|
132
|
+
const generatePartialFromTemplate = async (partialDirCtx, templateString, attrs)=>{
|
|
133
|
+
let tempDir;
|
|
134
|
+
try {
|
|
135
|
+
// Download the template directory into a temp directory
|
|
136
|
+
tempDir = await _templates.downloadTemplate(templateString);
|
|
137
|
+
// Create a partial directory context for the temp directory
|
|
138
|
+
const tempPartialDirCtx = {
|
|
139
|
+
type: "partial",
|
|
140
|
+
key: "temp",
|
|
141
|
+
abspath: tempDir,
|
|
142
|
+
exists: true
|
|
143
|
+
};
|
|
144
|
+
// Read the partial.json from the temp directory we downloaded
|
|
145
|
+
const [partial, errors] = await (0, _reader.readPartialDir)(tempPartialDirCtx, {
|
|
146
|
+
withExtractedFiles: true
|
|
147
|
+
});
|
|
148
|
+
if (errors.length > 0 || !partial) {
|
|
149
|
+
throw new Error(`Invalid partial template: ${errors.join(", ")}`);
|
|
150
|
+
}
|
|
151
|
+
// Modify the partial data with the new attributes
|
|
152
|
+
const partialData = (0, _lodash.cloneDeep)(partial);
|
|
153
|
+
partialData.name = attrs.name;
|
|
154
|
+
// Finally, we write the partial into the target partial directory
|
|
155
|
+
await (0, _writer.writePartialDirFromData)(partialDirCtx, partialData);
|
|
156
|
+
} finally{
|
|
157
|
+
await _templates.cleanupTempDir(tempDir);
|
|
158
|
+
}
|
|
159
|
+
};
|