@knocklabs/cli 0.3.0 → 1.0.0-rc.1

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.
Files changed (68) hide show
  1. package/README.md +505 -162
  2. package/dist/commands/branch/create.js +0 -2
  3. package/dist/commands/branch/delete.js +4 -3
  4. package/dist/commands/branch/exit.js +0 -2
  5. package/dist/commands/branch/list.js +0 -2
  6. package/dist/commands/branch/merge.js +82 -0
  7. package/dist/commands/branch/switch.js +0 -2
  8. package/dist/commands/channel/list.js +73 -0
  9. package/dist/commands/environment/list.js +73 -0
  10. package/dist/commands/guide/new.js +276 -0
  11. package/dist/commands/guide/pull.js +5 -6
  12. package/dist/commands/guide/push.js +1 -1
  13. package/dist/commands/guide/validate.js +1 -1
  14. package/dist/commands/init.js +108 -0
  15. package/dist/commands/layout/new.js +228 -0
  16. package/dist/commands/layout/pull.js +5 -6
  17. package/dist/commands/layout/push.js +1 -1
  18. package/dist/commands/layout/validate.js +1 -1
  19. package/dist/commands/message-type/new.js +228 -0
  20. package/dist/commands/message-type/pull.js +5 -6
  21. package/dist/commands/message-type/push.js +1 -1
  22. package/dist/commands/message-type/validate.js +1 -1
  23. package/dist/commands/partial/new.js +274 -0
  24. package/dist/commands/partial/pull.js +5 -6
  25. package/dist/commands/partial/push.js +1 -1
  26. package/dist/commands/partial/validate.js +1 -1
  27. package/dist/commands/pull.js +7 -2
  28. package/dist/commands/push.js +6 -4
  29. package/dist/commands/translation/pull.js +1 -1
  30. package/dist/commands/translation/push.js +1 -1
  31. package/dist/commands/translation/validate.js +1 -1
  32. package/dist/commands/workflow/new.js +179 -54
  33. package/dist/commands/workflow/pull.js +6 -8
  34. package/dist/commands/workflow/push.js +1 -1
  35. package/dist/commands/workflow/validate.js +1 -1
  36. package/dist/lib/api-v1.js +23 -2
  37. package/dist/lib/auth.js +1 -1
  38. package/dist/lib/base-command.js +18 -15
  39. package/dist/lib/helpers/flag.js +0 -2
  40. package/dist/lib/helpers/project-config.js +158 -0
  41. package/dist/lib/helpers/request.js +1 -2
  42. package/dist/lib/helpers/string.js +4 -4
  43. package/dist/lib/helpers/typegen.js +1 -1
  44. package/dist/lib/marshal/email-layout/generator.js +152 -0
  45. package/dist/lib/marshal/email-layout/helpers.js +6 -9
  46. package/dist/lib/marshal/email-layout/index.js +1 -0
  47. package/dist/lib/marshal/email-layout/writer.js +15 -3
  48. package/dist/lib/marshal/guide/generator.js +163 -0
  49. package/dist/lib/marshal/guide/helpers.js +6 -10
  50. package/dist/lib/marshal/guide/index.js +1 -0
  51. package/dist/lib/marshal/guide/writer.js +5 -9
  52. package/dist/lib/marshal/message-type/generator.js +139 -0
  53. package/dist/lib/marshal/message-type/helpers.js +6 -10
  54. package/dist/lib/marshal/message-type/index.js +1 -0
  55. package/dist/lib/marshal/message-type/writer.js +5 -1
  56. package/dist/lib/marshal/partial/generator.js +159 -0
  57. package/dist/lib/marshal/partial/helpers.js +6 -10
  58. package/dist/lib/marshal/partial/index.js +1 -0
  59. package/dist/lib/marshal/partial/writer.js +3 -0
  60. package/dist/lib/marshal/translation/helpers.js +6 -10
  61. package/dist/lib/marshal/translation/processor.isomorphic.js +4 -4
  62. package/dist/lib/marshal/translation/writer.js +2 -2
  63. package/dist/lib/marshal/workflow/generator.js +175 -19
  64. package/dist/lib/marshal/workflow/helpers.js +7 -10
  65. package/dist/lib/run-context/loader.js +5 -0
  66. package/dist/lib/templates.js +131 -0
  67. package/oclif.manifest.json +826 -266
  68. package/package.json +14 -9
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return Init;
9
+ }
10
+ });
11
+ const _nodepath = /*#__PURE__*/ _interop_require_wildcard(require("node:path"));
12
+ const _enquirer = /*#__PURE__*/ _interop_require_default(require("enquirer"));
13
+ const _fsextra = /*#__PURE__*/ _interop_require_wildcard(require("fs-extra"));
14
+ const _basecommand = /*#__PURE__*/ _interop_require_default(require("../lib/base-command"));
15
+ const _projectconfig = require("../lib/helpers/project-config");
16
+ function _define_property(obj, key, value) {
17
+ if (key in obj) {
18
+ Object.defineProperty(obj, key, {
19
+ value: value,
20
+ enumerable: true,
21
+ configurable: true,
22
+ writable: true
23
+ });
24
+ } else {
25
+ obj[key] = value;
26
+ }
27
+ return obj;
28
+ }
29
+ function _interop_require_default(obj) {
30
+ return obj && obj.__esModule ? obj : {
31
+ default: obj
32
+ };
33
+ }
34
+ function _getRequireWildcardCache(nodeInterop) {
35
+ if (typeof WeakMap !== "function") return null;
36
+ var cacheBabelInterop = new WeakMap();
37
+ var cacheNodeInterop = new WeakMap();
38
+ return (_getRequireWildcardCache = function(nodeInterop) {
39
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
40
+ })(nodeInterop);
41
+ }
42
+ function _interop_require_wildcard(obj, nodeInterop) {
43
+ if (!nodeInterop && obj && obj.__esModule) {
44
+ return obj;
45
+ }
46
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
47
+ return {
48
+ default: obj
49
+ };
50
+ }
51
+ var cache = _getRequireWildcardCache(nodeInterop);
52
+ if (cache && cache.has(obj)) {
53
+ return cache.get(obj);
54
+ }
55
+ var newObj = {
56
+ __proto__: null
57
+ };
58
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
59
+ for(var key in obj){
60
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
61
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
62
+ if (desc && (desc.get || desc.set)) {
63
+ Object.defineProperty(newObj, key, desc);
64
+ } else {
65
+ newObj[key] = obj[key];
66
+ }
67
+ }
68
+ }
69
+ newObj.default = obj;
70
+ if (cache) {
71
+ cache.set(obj, newObj);
72
+ }
73
+ return newObj;
74
+ }
75
+ class Init extends _basecommand.default {
76
+ async run() {
77
+ const configPath = _nodepath.resolve(process.cwd(), _projectconfig.PROJECT_CONFIG_FILE_NAME);
78
+ // 1. Check if knock.json already exists
79
+ const configExists = await _fsextra.pathExists(configPath);
80
+ if (configExists) {
81
+ this.error(`A ${_projectconfig.PROJECT_CONFIG_FILE_NAME} file already exists in this directory. Aborting.`);
82
+ }
83
+ // 2. Prompt user for the knock directory location
84
+ const { knockDir } = await _enquirer.default.prompt({
85
+ type: "input",
86
+ name: "knockDir",
87
+ message: "Where do you want to store your Knock resources?",
88
+ initial: ".knock"
89
+ });
90
+ // 3. Create the knock directory and resource subdirectories
91
+ const knockDirPath = _nodepath.resolve(process.cwd(), knockDir);
92
+ await _fsextra.ensureDir(knockDirPath);
93
+ // 4. Write the knock.json configuration file
94
+ await _fsextra.outputJson(configPath, {
95
+ $schema: "https://schemas.knock.app/cli/knock.json",
96
+ knockDir
97
+ }, {
98
+ spaces: 2
99
+ });
100
+ this.log(`‣ Successfully initialized Knock project at ${process.cwd()}`);
101
+ this.log(`‣ Resources directory: ${knockDir}`);
102
+ }
103
+ constructor(...args){
104
+ super(...args), _define_property(this, "requiresAuth", false);
105
+ }
106
+ }
107
+ _define_property(Init, "summary", "Initialize a new Knock project with a knock.json configuration file.");
108
+ _define_property(Init, "description", "Creates a knock.json configuration file in the current directory " + "to store project-level settings like the knock resources directory.");
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return EmailLayoutNew;
9
+ }
10
+ });
11
+ const _nodepath = /*#__PURE__*/ _interop_require_wildcard(require("node:path"));
12
+ const _core = require("@oclif/core");
13
+ const _enquirer = require("enquirer");
14
+ const _basecommand = /*#__PURE__*/ _interop_require_default(require("../../lib/base-command"));
15
+ const _const = require("../../lib/helpers/const");
16
+ const _flag = /*#__PURE__*/ _interop_require_wildcard(require("../../lib/helpers/flag"));
17
+ const _projectconfig = require("../../lib/helpers/project-config");
18
+ const _string = require("../../lib/helpers/string");
19
+ const _ux = require("../../lib/helpers/ux");
20
+ const _emaillayout = /*#__PURE__*/ _interop_require_wildcard(require("../../lib/marshal/email-layout"));
21
+ const _runcontext = require("../../lib/run-context");
22
+ const _push = /*#__PURE__*/ _interop_require_default(require("./push"));
23
+ function _define_property(obj, key, value) {
24
+ if (key in obj) {
25
+ Object.defineProperty(obj, key, {
26
+ value: value,
27
+ enumerable: true,
28
+ configurable: true,
29
+ writable: true
30
+ });
31
+ } else {
32
+ obj[key] = value;
33
+ }
34
+ return obj;
35
+ }
36
+ function _interop_require_default(obj) {
37
+ return obj && obj.__esModule ? obj : {
38
+ default: obj
39
+ };
40
+ }
41
+ function _getRequireWildcardCache(nodeInterop) {
42
+ if (typeof WeakMap !== "function") return null;
43
+ var cacheBabelInterop = new WeakMap();
44
+ var cacheNodeInterop = new WeakMap();
45
+ return (_getRequireWildcardCache = function(nodeInterop) {
46
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
47
+ })(nodeInterop);
48
+ }
49
+ function _interop_require_wildcard(obj, nodeInterop) {
50
+ if (!nodeInterop && obj && obj.__esModule) {
51
+ return obj;
52
+ }
53
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
54
+ return {
55
+ default: obj
56
+ };
57
+ }
58
+ var cache = _getRequireWildcardCache(nodeInterop);
59
+ if (cache && cache.has(obj)) {
60
+ return cache.get(obj);
61
+ }
62
+ var newObj = {
63
+ __proto__: null
64
+ };
65
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
66
+ for(var key in obj){
67
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
68
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
69
+ if (desc && (desc.get || desc.set)) {
70
+ Object.defineProperty(newObj, key, desc);
71
+ } else {
72
+ newObj[key] = obj[key];
73
+ }
74
+ }
75
+ }
76
+ newObj.default = obj;
77
+ if (cache) {
78
+ cache.set(obj, newObj);
79
+ }
80
+ return newObj;
81
+ }
82
+ class EmailLayoutNew extends _basecommand.default {
83
+ async run() {
84
+ const { flags } = this.props;
85
+ const { resourceDir } = this.runContext;
86
+ // 1. Ensure we aren't in any existing resource directory already.
87
+ if (resourceDir) {
88
+ return this.error(`Cannot create a new email layout inside an existing ${resourceDir.type} directory`);
89
+ }
90
+ // 2. Prompt for name and key if not provided
91
+ let name = flags.name;
92
+ let key = flags.key;
93
+ if (!name) {
94
+ const nameResponse = await (0, _enquirer.prompt)({
95
+ type: "input",
96
+ name: "name",
97
+ message: "Email layout name",
98
+ validate: (value)=>{
99
+ if (!value || value.trim().length === 0) {
100
+ return "Email layout name is required";
101
+ }
102
+ return true;
103
+ }
104
+ });
105
+ name = nameResponse.name;
106
+ }
107
+ if (!key) {
108
+ const keyResponse = await (0, _enquirer.prompt)({
109
+ type: "input",
110
+ name: "key",
111
+ message: "Email layout key (immutable slug)",
112
+ initial: (0, _string.slugify)(name),
113
+ validate: (value)=>{
114
+ if (!value || value.trim().length === 0) {
115
+ return "Email layout key is required";
116
+ }
117
+ const keyError = _emaillayout.validateEmailLayoutKey(value);
118
+ if (keyError) {
119
+ return `Invalid email layout key: ${keyError}`;
120
+ }
121
+ return true;
122
+ }
123
+ });
124
+ key = keyResponse.key;
125
+ }
126
+ // Validate the email layout key
127
+ const emailLayoutKeyError = _emaillayout.validateEmailLayoutKey(key);
128
+ if (emailLayoutKeyError) {
129
+ return this.error(`Invalid email layout key \`${key}\` (${emailLayoutKeyError})`);
130
+ }
131
+ const emailLayoutDirCtx = await this.getEmailLayoutDirContext(key);
132
+ const promptMessage = emailLayoutDirCtx.exists ? `Found \`${emailLayoutDirCtx.key}\` at ${emailLayoutDirCtx.abspath}, overwrite?` : `Create a new email layout directory \`${emailLayoutDirCtx.key}\` at ${emailLayoutDirCtx.abspath}?`;
133
+ // Check if the email layout directory already exists, and prompt to confirm if not.
134
+ const input = flags.force || await (0, _ux.promptToConfirm)(promptMessage);
135
+ if (!input) return;
136
+ // Generate the email layout either from a template or from scratch
137
+ await (flags.template ? this.fromTemplate(emailLayoutDirCtx, name, flags.template) : this.fromScratch(emailLayoutDirCtx, name));
138
+ if (flags.push) {
139
+ _ux.spinner.start("‣ Pushing email layout to Knock");
140
+ try {
141
+ await _push.default.run([
142
+ key
143
+ ]);
144
+ } catch (error) {
145
+ this.error(`Failed to push email layout to Knock: ${error}`);
146
+ } finally{
147
+ _ux.spinner.stop();
148
+ }
149
+ }
150
+ this.log(`‣ Successfully created email layout \`${key}\``);
151
+ }
152
+ async fromTemplate(emailLayoutDirCtx, name, templateString) {
153
+ // When being called from the template string, we want to try and generate
154
+ // the email layout from the provided template.
155
+ _ux.spinner.start(`‣ Generating email layout from template \`${templateString}\``);
156
+ try {
157
+ await _emaillayout.generateEmailLayoutFromTemplate(emailLayoutDirCtx, templateString, {
158
+ name
159
+ });
160
+ } catch (error) {
161
+ this.error(`Failed to generate email layout from template: ${error}`);
162
+ } finally{
163
+ _ux.spinner.stop();
164
+ }
165
+ }
166
+ async fromScratch(emailLayoutDirCtx, name) {
167
+ // Generate the email layout directory with scaffolded content
168
+ await _emaillayout.generateEmailLayoutDir(emailLayoutDirCtx, {
169
+ name
170
+ });
171
+ }
172
+ async getEmailLayoutDirContext(emailLayoutKey) {
173
+ const { resourceDir, cwd: runCwd } = this.runContext;
174
+ // Inside an existing resource dir, use it if valid for the target email layout.
175
+ if (resourceDir) {
176
+ const target = {
177
+ commandId: _basecommand.default.id,
178
+ type: "email_layout",
179
+ key: emailLayoutKey
180
+ };
181
+ return (0, _runcontext.ensureResourceDirForTarget)(resourceDir, target);
182
+ }
183
+ // Default to knock project config first if present, otherwise cwd.
184
+ const dirCtx = await (0, _projectconfig.resolveResourceDir)(this.projectConfig, "email_layout", runCwd);
185
+ // Not inside any existing email layout directory, which means either create a
186
+ // new email layout directory in the cwd, or update it if there is one already.
187
+ if (emailLayoutKey) {
188
+ const dirPath = _nodepath.resolve(dirCtx.abspath, emailLayoutKey);
189
+ const exists = await _emaillayout.isEmailLayoutDir(dirPath);
190
+ return {
191
+ type: "email_layout",
192
+ key: emailLayoutKey,
193
+ abspath: dirPath,
194
+ exists
195
+ };
196
+ }
197
+ // Not in any email layout directory, nor an email layout key arg was given so error.
198
+ return this.error("Missing 1 required arg:\nemailLayoutKey");
199
+ }
200
+ }
201
+ _define_property(EmailLayoutNew, "summary", "Create a new email layout with a minimal configuration.");
202
+ _define_property(EmailLayoutNew, "flags", {
203
+ name: _core.Flags.string({
204
+ summary: "The name of the email layout",
205
+ char: "n"
206
+ }),
207
+ key: _core.Flags.string({
208
+ summary: "The key of the email layout",
209
+ char: "k"
210
+ }),
211
+ environment: _core.Flags.string({
212
+ summary: "The environment to create the email layout in. Defaults to development.",
213
+ default: _const.KnockEnv.Development
214
+ }),
215
+ branch: _flag.branch,
216
+ force: _core.Flags.boolean({
217
+ summary: "Force the creation of the email layout directory without confirmation."
218
+ }),
219
+ push: _core.Flags.boolean({
220
+ summary: "Whether or not to push the email layout to Knock after creation.",
221
+ default: false,
222
+ char: "p"
223
+ }),
224
+ template: _core.Flags.string({
225
+ summary: "The template to use for the email layout. Should be `email-layouts/{key}`."
226
+ })
227
+ });
228
+ _define_property(EmailLayoutNew, "args", {});
@@ -16,6 +16,7 @@ const _error = require("../../lib/helpers/error");
16
16
  const _flag = /*#__PURE__*/ _interop_require_wildcard(require("../../lib/helpers/flag"));
17
17
  const _objectisomorphic = require("../../lib/helpers/object.isomorphic");
18
18
  const _page = require("../../lib/helpers/page");
19
+ const _projectconfig = require("../../lib/helpers/project-config");
19
20
  const _request = require("../../lib/helpers/request");
20
21
  const _ux = require("../../lib/helpers/ux");
21
22
  const _emaillayout = /*#__PURE__*/ _interop_require_wildcard(require("../../lib/marshal/email-layout"));
@@ -119,11 +120,8 @@ class EmailLayoutPull extends _basecommand.default {
119
120
  // Pull all email layouts
120
121
  async pullAllEmailLayouts() {
121
122
  const { flags } = this.props;
122
- const defaultToCwd = {
123
- abspath: this.runContext.cwd,
124
- exists: true
125
- };
126
- const targetDirCtx = flags["layouts-dir"] || defaultToCwd;
123
+ const layoutsIndexDirCtx = await (0, _projectconfig.resolveResourceDir)(this.projectConfig, "email_layout", this.runContext.cwd);
124
+ const targetDirCtx = flags["layouts-dir"] || layoutsIndexDirCtx;
127
125
  const prompt = targetDirCtx.exists ? `Pull latest layouts into ${targetDirCtx.abspath}?\n This will overwrite the contents of this directory.` : `Create a new layouts directory at ${targetDirCtx.abspath}?`;
128
126
  const input = flags.force || await (0, _ux.promptToConfirm)(prompt);
129
127
  if (!input) return;
@@ -171,10 +169,11 @@ class EmailLayoutPull extends _basecommand.default {
171
169
  };
172
170
  return (0, _runcontext.ensureResourceDirForTarget)(resourceDir, target);
173
171
  }
172
+ const layoutsIndexDirCtx = await (0, _projectconfig.resolveResourceDir)(this.projectConfig, "email_layout", runCwd);
174
173
  // Not inside any existing email layout directory, which means either create a
175
174
  // new email layout directory in the cwd, or update it if there is one already.
176
175
  if (emailLayoutKey) {
177
- const dirPath = _nodepath.resolve(runCwd, emailLayoutKey);
176
+ const dirPath = _nodepath.resolve(layoutsIndexDirCtx.abspath, emailLayoutKey);
178
177
  const exists = await _emaillayout.isEmailLayoutDir(dirPath);
179
178
  return {
180
179
  type: "email_layout",
@@ -83,7 +83,7 @@ class EmailLayoutPush extends _basecommand.default {
83
83
  async run() {
84
84
  const { flags } = this.props;
85
85
  // 1. First read all layout directories found for the given command.
86
- const target = await _emaillayout.ensureValidCommandTarget(this.props, this.runContext);
86
+ const target = await _emaillayout.ensureValidCommandTarget(this.props, this.runContext, this.projectConfig);
87
87
  const [layouts, readErrors] = await _emaillayout.readAllForCommandTarget(target, {
88
88
  withExtractedFiles: true
89
89
  });
@@ -80,7 +80,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
80
80
  class EmailLayoutValidate extends _basecommand.default {
81
81
  async run() {
82
82
  // 1. Read all layout directories found for the given command.
83
- const target = await _emaillayout.ensureValidCommandTarget(this.props, this.runContext);
83
+ const target = await _emaillayout.ensureValidCommandTarget(this.props, this.runContext, this.projectConfig);
84
84
  const [layouts, readErrors] = await _emaillayout.readAllForCommandTarget(target, {
85
85
  withExtractedFiles: true
86
86
  });
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return MessageTypeNew;
9
+ }
10
+ });
11
+ const _nodepath = /*#__PURE__*/ _interop_require_wildcard(require("node:path"));
12
+ const _core = require("@oclif/core");
13
+ const _enquirer = require("enquirer");
14
+ const _basecommand = /*#__PURE__*/ _interop_require_default(require("../../lib/base-command"));
15
+ const _const = require("../../lib/helpers/const");
16
+ const _flag = /*#__PURE__*/ _interop_require_wildcard(require("../../lib/helpers/flag"));
17
+ const _projectconfig = require("../../lib/helpers/project-config");
18
+ const _string = require("../../lib/helpers/string");
19
+ const _ux = require("../../lib/helpers/ux");
20
+ const _messagetype = /*#__PURE__*/ _interop_require_wildcard(require("../../lib/marshal/message-type"));
21
+ const _runcontext = require("../../lib/run-context");
22
+ const _push = /*#__PURE__*/ _interop_require_default(require("./push"));
23
+ function _define_property(obj, key, value) {
24
+ if (key in obj) {
25
+ Object.defineProperty(obj, key, {
26
+ value: value,
27
+ enumerable: true,
28
+ configurable: true,
29
+ writable: true
30
+ });
31
+ } else {
32
+ obj[key] = value;
33
+ }
34
+ return obj;
35
+ }
36
+ function _interop_require_default(obj) {
37
+ return obj && obj.__esModule ? obj : {
38
+ default: obj
39
+ };
40
+ }
41
+ function _getRequireWildcardCache(nodeInterop) {
42
+ if (typeof WeakMap !== "function") return null;
43
+ var cacheBabelInterop = new WeakMap();
44
+ var cacheNodeInterop = new WeakMap();
45
+ return (_getRequireWildcardCache = function(nodeInterop) {
46
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
47
+ })(nodeInterop);
48
+ }
49
+ function _interop_require_wildcard(obj, nodeInterop) {
50
+ if (!nodeInterop && obj && obj.__esModule) {
51
+ return obj;
52
+ }
53
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
54
+ return {
55
+ default: obj
56
+ };
57
+ }
58
+ var cache = _getRequireWildcardCache(nodeInterop);
59
+ if (cache && cache.has(obj)) {
60
+ return cache.get(obj);
61
+ }
62
+ var newObj = {
63
+ __proto__: null
64
+ };
65
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
66
+ for(var key in obj){
67
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
68
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
69
+ if (desc && (desc.get || desc.set)) {
70
+ Object.defineProperty(newObj, key, desc);
71
+ } else {
72
+ newObj[key] = obj[key];
73
+ }
74
+ }
75
+ }
76
+ newObj.default = obj;
77
+ if (cache) {
78
+ cache.set(obj, newObj);
79
+ }
80
+ return newObj;
81
+ }
82
+ class MessageTypeNew extends _basecommand.default {
83
+ async run() {
84
+ const { flags } = this.props;
85
+ const { resourceDir } = this.runContext;
86
+ // 1. Ensure we aren't in any existing resource directory already.
87
+ if (resourceDir) {
88
+ return this.error(`Cannot create a new message type inside an existing ${resourceDir.type} directory`);
89
+ }
90
+ // 2. Prompt for name and key if not provided
91
+ let name = flags.name;
92
+ let key = flags.key;
93
+ if (!name) {
94
+ const nameResponse = await (0, _enquirer.prompt)({
95
+ type: "input",
96
+ name: "name",
97
+ message: "Message type name",
98
+ validate: (value)=>{
99
+ if (!value || value.trim().length === 0) {
100
+ return "Message type name is required";
101
+ }
102
+ return true;
103
+ }
104
+ });
105
+ name = nameResponse.name;
106
+ }
107
+ if (!key) {
108
+ const keyResponse = await (0, _enquirer.prompt)({
109
+ type: "input",
110
+ name: "key",
111
+ message: "Message type key (immutable slug)",
112
+ initial: (0, _string.slugify)(name),
113
+ validate: (value)=>{
114
+ if (!value || value.trim().length === 0) {
115
+ return "Message type key is required";
116
+ }
117
+ const keyError = _messagetype.validateMessageTypeKey(value);
118
+ if (keyError) {
119
+ return `Invalid message type key: ${keyError}`;
120
+ }
121
+ return true;
122
+ }
123
+ });
124
+ key = keyResponse.key;
125
+ }
126
+ // Validate the message type key
127
+ const messageTypeKeyError = _messagetype.validateMessageTypeKey(key);
128
+ if (messageTypeKeyError) {
129
+ return this.error(`Invalid message type key \`${key}\` (${messageTypeKeyError})`);
130
+ }
131
+ const messageTypeDirCtx = await this.getMessageTypeDirContext(key);
132
+ const promptMessage = messageTypeDirCtx.exists ? `Found \`${messageTypeDirCtx.key}\` at ${messageTypeDirCtx.abspath}, overwrite?` : `Create a new message type directory \`${messageTypeDirCtx.key}\` at ${messageTypeDirCtx.abspath}?`;
133
+ // Check if the message type directory already exists, and prompt to confirm if not.
134
+ const input = flags.force || await (0, _ux.promptToConfirm)(promptMessage);
135
+ if (!input) return;
136
+ // Generate the message type either from a template or from scratch
137
+ await (flags.template ? this.fromTemplate(messageTypeDirCtx, name, flags.template) : this.fromScratch(messageTypeDirCtx, name));
138
+ if (flags.push) {
139
+ _ux.spinner.start("‣ Pushing message type to Knock");
140
+ try {
141
+ await _push.default.run([
142
+ key
143
+ ]);
144
+ } catch (error) {
145
+ this.error(`Failed to push message type to Knock: ${error}`);
146
+ } finally{
147
+ _ux.spinner.stop();
148
+ }
149
+ }
150
+ this.log(`‣ Successfully created message type \`${key}\``);
151
+ }
152
+ async fromTemplate(messageTypeDirCtx, name, templateString) {
153
+ // When being called from the template string, we want to try and generate
154
+ // the message type from the provided template.
155
+ _ux.spinner.start(`‣ Generating message type from template \`${templateString}\``);
156
+ try {
157
+ await _messagetype.generateMessageTypeFromTemplate(messageTypeDirCtx, templateString, {
158
+ name
159
+ });
160
+ } catch (error) {
161
+ this.error(`Failed to generate message type from template: ${error}`);
162
+ } finally{
163
+ _ux.spinner.stop();
164
+ }
165
+ }
166
+ async fromScratch(messageTypeDirCtx, name) {
167
+ // Generate the message type directory with scaffolded content
168
+ await _messagetype.generateMessageTypeDir(messageTypeDirCtx, {
169
+ name
170
+ });
171
+ }
172
+ async getMessageTypeDirContext(messageTypeKey) {
173
+ const { resourceDir, cwd: runCwd } = this.runContext;
174
+ // Inside an existing resource dir, use it if valid for the target message type.
175
+ if (resourceDir) {
176
+ const target = {
177
+ commandId: _basecommand.default.id,
178
+ type: "message_type",
179
+ key: messageTypeKey
180
+ };
181
+ return (0, _runcontext.ensureResourceDirForTarget)(resourceDir, target);
182
+ }
183
+ // Default to knock project config first if present, otherwise cwd.
184
+ const dirCtx = await (0, _projectconfig.resolveResourceDir)(this.projectConfig, "message_type", runCwd);
185
+ // Not inside any existing message type directory, which means either create a
186
+ // new message type directory in the cwd, or update it if there is one already.
187
+ if (messageTypeKey) {
188
+ const dirPath = _nodepath.resolve(dirCtx.abspath, messageTypeKey);
189
+ const exists = await _messagetype.isMessageTypeDir(dirPath);
190
+ return {
191
+ type: "message_type",
192
+ key: messageTypeKey,
193
+ abspath: dirPath,
194
+ exists
195
+ };
196
+ }
197
+ // Not in any message type directory, nor a message type key arg was given so error.
198
+ return this.error("Missing 1 required arg:\nmessageTypeKey");
199
+ }
200
+ }
201
+ _define_property(MessageTypeNew, "summary", "Create a new message type with a minimal configuration.");
202
+ _define_property(MessageTypeNew, "flags", {
203
+ name: _core.Flags.string({
204
+ summary: "The name of the message type",
205
+ char: "n"
206
+ }),
207
+ key: _core.Flags.string({
208
+ summary: "The key of the message type",
209
+ char: "k"
210
+ }),
211
+ environment: _core.Flags.string({
212
+ summary: "The environment to create the message type in. Defaults to development.",
213
+ default: _const.KnockEnv.Development
214
+ }),
215
+ branch: _flag.branch,
216
+ force: _core.Flags.boolean({
217
+ summary: "Force the creation of the message type directory without confirmation."
218
+ }),
219
+ push: _core.Flags.boolean({
220
+ summary: "Whether or not to push the message type to Knock after creation.",
221
+ default: false,
222
+ char: "p"
223
+ }),
224
+ template: _core.Flags.string({
225
+ summary: "The template to use for the message type. Should be `message-types/{key}`."
226
+ })
227
+ });
228
+ _define_property(MessageTypeNew, "args", {});
@@ -16,6 +16,7 @@ const _error = require("../../lib/helpers/error");
16
16
  const _flag = /*#__PURE__*/ _interop_require_wildcard(require("../../lib/helpers/flag"));
17
17
  const _objectisomorphic = require("../../lib/helpers/object.isomorphic");
18
18
  const _page = require("../../lib/helpers/page");
19
+ const _projectconfig = require("../../lib/helpers/project-config");
19
20
  const _request = require("../../lib/helpers/request");
20
21
  const _ux = require("../../lib/helpers/ux");
21
22
  const _messagetype = /*#__PURE__*/ _interop_require_wildcard(require("../../lib/marshal/message-type"));
@@ -122,6 +123,7 @@ class MessageTypePull extends _basecommand.default {
122
123
  async getMessageTypeDirContext() {
123
124
  const { messageTypeKey } = this.props.args;
124
125
  const { resourceDir, cwd: runCwd } = this.runContext;
126
+ const messageTypesIndexDirCtx = await (0, _projectconfig.resolveResourceDir)(this.projectConfig, "message_type", runCwd);
125
127
  // Inside an existing resource dir, use it if valid for the target message
126
128
  // type.
127
129
  if (resourceDir) {
@@ -136,7 +138,7 @@ class MessageTypePull extends _basecommand.default {
136
138
  // a new message type directory in the cwd, or update it if there is one
137
139
  // already.
138
140
  if (messageTypeKey) {
139
- const dirPath = _nodepath.resolve(runCwd, messageTypeKey);
141
+ const dirPath = _nodepath.resolve(messageTypesIndexDirCtx.abspath, messageTypeKey);
140
142
  const exists = await _messagetype.isMessageTypeDir(dirPath);
141
143
  return {
142
144
  type: "message_type",
@@ -153,11 +155,8 @@ class MessageTypePull extends _basecommand.default {
153
155
  * Pull all message types
154
156
  */ async pullAllMessageTypes() {
155
157
  const { flags } = this.props;
156
- const defaultToCwd = {
157
- abspath: this.runContext.cwd,
158
- exists: true
159
- };
160
- const targetDirCtx = flags["message-types-dir"] || defaultToCwd;
158
+ const messageTypesIndexDirCtx = await (0, _projectconfig.resolveResourceDir)(this.projectConfig, "message_type", this.runContext.cwd);
159
+ const targetDirCtx = flags["message-types-dir"] || messageTypesIndexDirCtx;
161
160
  const prompt = targetDirCtx.exists ? `Pull latest message types into ${targetDirCtx.abspath}?\n This will overwrite the contents of this directory.` : `Create a new message types directory at ${targetDirCtx.abspath}?`;
162
161
  const input = flags.force || await (0, _ux.promptToConfirm)(prompt);
163
162
  if (!input) return;
@@ -83,7 +83,7 @@ class MessageTypePush extends _basecommand.default {
83
83
  async run() {
84
84
  const { flags } = this.props;
85
85
  // 1. First read all message type directories found for the given command.
86
- const target = await _messagetype.ensureValidCommandTarget(this.props, this.runContext);
86
+ const target = await _messagetype.ensureValidCommandTarget(this.props, this.runContext, this.projectConfig);
87
87
  const [messageTypes, readErrors] = await _messagetype.readAllForCommandTarget(target, {
88
88
  withExtractedFiles: true
89
89
  });
@@ -80,7 +80,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
80
80
  class MessageTypeValidate extends _basecommand.default {
81
81
  async run() {
82
82
  // 1. Read all message type directories found for the given command.
83
- const target = await _messagetype.ensureValidCommandTarget(this.props, this.runContext);
83
+ const target = await _messagetype.ensureValidCommandTarget(this.props, this.runContext, this.projectConfig);
84
84
  const [messageTypes, readErrors] = await _messagetype.readAllForCommandTarget(target, {
85
85
  withExtractedFiles: true
86
86
  });