@swell/cli 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/app-command.js +1 -1
  2. package/dist/commands/api/delete.js +4 -1
  3. package/dist/commands/api/get.js +1 -0
  4. package/dist/commands/api/index.js +4 -1
  5. package/dist/commands/api/post.js +1 -0
  6. package/dist/commands/api/put.js +1 -0
  7. package/dist/commands/app/init.d.ts +8 -7
  8. package/dist/commands/app/init.js +36 -18
  9. package/dist/commands/app/pull.js +2 -2
  10. package/dist/commands/app/push.js +2 -2
  11. package/dist/commands/app/version.d.ts +1 -0
  12. package/dist/commands/app/version.js +14 -4
  13. package/dist/commands/create/app.d.ts +8 -4
  14. package/dist/commands/create/app.js +68 -51
  15. package/dist/commands/create/content.d.ts +5 -6
  16. package/dist/commands/create/content.js +21 -37
  17. package/dist/commands/create/function.d.ts +6 -7
  18. package/dist/commands/create/function.js +94 -31
  19. package/dist/commands/create/index.js +8 -0
  20. package/dist/commands/create/model.d.ts +5 -6
  21. package/dist/commands/create/model.js +21 -33
  22. package/dist/commands/create/notification.d.ts +9 -9
  23. package/dist/commands/create/notification.js +117 -95
  24. package/dist/commands/create/setting.d.ts +21 -0
  25. package/dist/commands/create/setting.js +120 -0
  26. package/dist/commands/create/tests.d.ts +4 -5
  27. package/dist/commands/create/tests.js +8 -11
  28. package/dist/commands/create/webhook.d.ts +22 -0
  29. package/dist/commands/create/webhook.js +176 -0
  30. package/dist/commands/schema.d.ts +1 -0
  31. package/dist/commands/schema.js +51 -5
  32. package/dist/commands/theme/init.d.ts +8 -4
  33. package/dist/commands/theme/init.js +21 -8
  34. package/dist/create-app-command.d.ts +1 -0
  35. package/dist/create-app-command.js +15 -10
  36. package/dist/create-config-command.js +2 -2
  37. package/dist/help/custom-help.d.ts +89 -0
  38. package/dist/help/custom-help.js +337 -0
  39. package/dist/help/types.d.ts +75 -0
  40. package/dist/help/types.js +1 -0
  41. package/dist/lib/apps/app-config.js +2 -2
  42. package/dist/lib/apps/index.d.ts +2 -1
  43. package/dist/lib/apps/index.js +21 -5
  44. package/dist/lib/apps/paths.js +7 -6
  45. package/dist/lib/create/notification.d.ts +1 -0
  46. package/dist/lib/create/schemas.d.ts +1 -0
  47. package/dist/lib/create/schemas.js +1 -0
  48. package/dist/lib/create/setting.d.ts +15 -0
  49. package/dist/lib/create/setting.js +27 -0
  50. package/dist/lib/create/tests/templates/env-dts.js +1 -0
  51. package/dist/lib/create/tests/templates/swell-client.js +2 -0
  52. package/dist/lib/create/tests/templates/tsconfig.js +2 -0
  53. package/dist/lib/create/tests/templates/vitest-config.js +1 -0
  54. package/dist/lib/create/webhook.d.ts +32 -0
  55. package/dist/lib/create/webhook.js +52 -0
  56. package/dist/swell-api-command.d.ts +14 -0
  57. package/dist/swell-api-command.js +113 -7
  58. package/oclif.manifest.json +609 -259
  59. package/package.json +2 -1
@@ -7,65 +7,127 @@ import { toFunctionFileName } from '../../lib/create/index.js';
7
7
  const PERMITTED_TRIGGERS = ['cron', 'model', 'route'];
8
8
  export default class CreateFunction extends CreateConfigCommand {
9
9
  static args = {
10
- functionName: Args.string({
11
- description: 'function name, used in an http route if applicable',
10
+ name: Args.string({
11
+ default: '',
12
+ description: 'Filename with extension (e.g., my-func.ts)',
12
13
  }),
13
14
  trigger: Args.string({
14
- description: `function trigger type`,
15
+ default: '',
16
+ description: 'cron | model | route',
15
17
  options: PERMITTED_TRIGGERS,
16
18
  }),
17
19
  };
18
- static description = `This command assists in generating functions scripts. CLI will prompt for values when flags are not present.`;
19
20
  static examples = [
20
- {
21
- command: 'swell create function',
22
- description: 'Create function script interactively.',
23
- },
24
- {
25
- command: 'swell create function orders-subscriptions-created.ts model --events order.created,subscription.created',
26
- description: 'Specify model event trigger of the function.',
27
- },
28
- {
29
- command: 'swell create function get-frontend-data.ts route --route public',
30
- description: 'Specify public API access.',
31
- },
32
- {
33
- command: 'swell create function process-metrics.ts cron --schedule "0 0 * * *"',
34
- description: 'Specify schedule of the cron function.',
35
- },
21
+ '$ swell create function',
22
+ '$ swell create function order-handler.ts model -e order.created,order.updated -y',
23
+ '$ swell create function cleanup.ts cron -s "0 0 * * *" -y',
24
+ '$ swell create function api-endpoint.ts route -r public -y',
36
25
  ];
26
+ static helpMeta = {
27
+ usageDirect: '<name> <trigger> [...] -y',
28
+ variantSection: {
29
+ title: 'TRIGGER OPTIONS',
30
+ variants: [
31
+ {
32
+ name: 'model',
33
+ flag: '-e, --events=<value>',
34
+ description: 'Model events (e.g., order.created,order.updated)',
35
+ },
36
+ {
37
+ name: 'cron',
38
+ flag: '-s, --schedule=<value>',
39
+ description: 'Cron expression (e.g., "0 0 * * *")',
40
+ },
41
+ {
42
+ name: 'route',
43
+ flag: '-r, --route=<option>',
44
+ description: 'Access: public (default) | private',
45
+ },
46
+ ],
47
+ },
48
+ variantFlags: ['events', 'schedule', 'route'],
49
+ };
37
50
  static flags = {
38
51
  description: Flags.string({
39
52
  char: 'd',
40
53
  default: '',
41
- description: 'function description',
54
+ description: 'Description',
42
55
  }),
43
56
  events: Flags.string({
44
57
  char: 'e',
45
58
  default: '',
46
- description: 'list of data model events used with model trigger, delimited by commas',
59
+ description: 'Model events (e.g., order.created,order.updated)',
47
60
  }),
48
61
  overwrite: Flags.boolean({
49
62
  default: false,
50
- description: 'overwrite existing function file',
63
+ description: 'Overwrite existing file',
51
64
  }),
52
65
  route: Flags.string({
53
66
  char: 'r',
54
- default: 'public',
55
- description: 'access type used with route trigger',
67
+ default: '',
68
+ description: 'Access: public | private',
56
69
  options: ['public', 'private'],
57
70
  }),
58
71
  schedule: Flags.string({
59
72
  char: 's',
60
73
  default: '',
61
- description: 'crontab value used with cron trigger',
74
+ description: 'Cron expression (e.g., "0 0 * * *")',
75
+ }),
76
+ yes: Flags.boolean({
77
+ char: 'y',
78
+ description: 'Skip prompts, require all arguments',
62
79
  }),
63
80
  };
64
- static summary = 'Initialize a functions script in JavaScript or TypeScript.';
81
+ static summary = 'Create a serverless function in JavaScript or TypeScript.';
65
82
  createType = ConfigType.FUNCTION;
66
83
  async run() {
67
84
  const { args, flags } = await this.parse(CreateFunction);
68
- const { functionName, trigger } = args;
85
+ const confirmYes = Boolean(flags.yes);
86
+ // NON-INTERACTIVE PATH
87
+ if (confirmYes) {
88
+ // Validate name argument
89
+ if (!args.name) {
90
+ this.error('Missing required argument for non-interactive mode: NAME\n\nExample: swell create function my-func.ts model -e order.created -y', { exit: 1 });
91
+ }
92
+ // Validate trigger argument
93
+ if (!args.trigger) {
94
+ this.error('Missing required argument for non-interactive mode: TRIGGER\n\nValid triggers: cron, model, route\n\nExample: swell create function my-func.ts model -e order.created -y', { exit: 1 });
95
+ }
96
+ // Validate filename has extension
97
+ const language = args.name.endsWith('.ts')
98
+ ? 'ts'
99
+ : args.name.endsWith('.js')
100
+ ? 'js'
101
+ : null;
102
+ if (!language) {
103
+ this.error('Function name must end with .ts or .js extension\n\nExample: swell create function my-func.ts model -e order.created -y', { exit: 1 });
104
+ }
105
+ const trigger = args.trigger;
106
+ // Validate trigger-specific requirements
107
+ if (trigger === 'model' && !flags.events) {
108
+ this.error('Missing required flag for model trigger: --events\n\nExample: swell create function my-func.ts model -e order.created,order.updated -y', { exit: 1 });
109
+ }
110
+ if (trigger === 'cron' && !flags.schedule) {
111
+ this.error('Missing required flag for cron trigger: --schedule\n\nExample: swell create function my-func.ts cron -s "0 0 * * *" -y', { exit: 1 });
112
+ }
113
+ // Build params with defaults
114
+ const writeFunctionFileParams = {
115
+ description: flags.description || '',
116
+ events: flags.events || '',
117
+ extension: undefined,
118
+ functionName: args.name,
119
+ language,
120
+ route: flags.route || 'public',
121
+ schedule: flags.schedule || '',
122
+ trigger,
123
+ };
124
+ // Write file without confirmation
125
+ await this.writeFunctionFile(writeFunctionFileParams, flags.overwrite,
126
+ /* shouldConfirm */ false);
127
+ return;
128
+ }
129
+ // INTERACTIVE PATH
130
+ const { name: functionName, trigger } = args;
69
131
  const { description, events, overwrite, route, schedule } = flags;
70
132
  let writeFunctionFileParams = {
71
133
  description,
@@ -85,7 +147,8 @@ export default class CreateFunction extends CreateConfigCommand {
85
147
  ...writeFunctionFileParams,
86
148
  ...(await this.gatherInput(writeFunctionFileParams)),
87
149
  };
88
- await this.writeFunctionFile(writeFunctionFileParams, overwrite);
150
+ await this.writeFunctionFile(writeFunctionFileParams, overwrite,
151
+ /* shouldConfirm */ true);
89
152
  }
90
153
  async gatherInput(params) {
91
154
  // Check if there are any extensions in the app configuration
@@ -193,7 +256,7 @@ export default class CreateFunction extends CreateConfigCommand {
193
256
  trigger,
194
257
  };
195
258
  }
196
- async writeFunctionFile({ description, events, extension, functionName, language, route, schedule, trigger, }, overwrite) {
259
+ async writeFunctionFile({ description, events, extension, functionName, language, route, schedule, trigger, }, overwrite, shouldConfirm = true) {
197
260
  const fileName = toFunctionFileName(functionName);
198
261
  await this.createFile({
199
262
  extension: language,
@@ -208,6 +271,6 @@ export default class CreateFunction extends CreateConfigCommand {
208
271
  trigger,
209
272
  }),
210
273
  fileName,
211
- }, overwrite);
274
+ }, overwrite, shouldConfirm);
212
275
  }
213
276
  }
@@ -26,10 +26,18 @@ export default class Create extends Command {
26
26
  name: 'Notification',
27
27
  value: 'notification',
28
28
  },
29
+ {
30
+ name: 'Setting',
31
+ value: 'setting',
32
+ },
29
33
  {
30
34
  name: 'Tests',
31
35
  value: 'tests',
32
36
  },
37
+ {
38
+ name: 'Webhook',
39
+ value: 'webhook',
40
+ },
33
41
  ],
34
42
  message: 'What do you want to create?',
35
43
  });
@@ -1,19 +1,18 @@
1
1
  import { CreateCollectionCommand } from '../../create-collection-command.js';
2
+ import { HelpMeta } from '../../help/types.js';
2
3
  import { ConfigType } from '../../lib/apps/index.js';
3
4
  export default class CreateModel extends CreateCollectionCommand {
4
5
  static args: {
5
6
  collection: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
6
7
  };
7
8
  static description: string;
8
- static examples: {
9
- command: string;
10
- description: string;
11
- }[];
9
+ static examples: string[];
10
+ static helpMeta: HelpMeta;
12
11
  static flags: {
12
+ label: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
13
13
  description: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
14
- events: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
15
14
  fields: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
16
- label: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
15
+ events: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
17
16
  overwrite: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
18
17
  yes: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
19
18
  };
@@ -9,58 +9,46 @@ export default class CreateModel extends CreateCollectionCommand {
9
9
  static args = {
10
10
  collection: Args.string({
11
11
  default: '',
12
- description: 'collection ID to create or apply to, e.g., products (required with -y)',
12
+ description: 'Collection ID to create or extend (e.g., products)',
13
13
  }),
14
14
  };
15
- static description = `Interactive mode: choose to create a new collection or extend an existing standard collection. The CLI will propose a list of standard collections you can extend.
16
-
17
- Non-interactive (-y): provide COLLECTION explicitly. To discover standard collections first, run: swell inspect models.`;
15
+ static description = 'Interactive mode lets you choose to create a new collection or extend a standard one.\nTo discover standard collections: swell inspect models';
18
16
  static examples = [
19
- {
20
- command: 'swell create model',
21
- description: 'Create data model configuration interactively',
22
- },
23
- {
24
- command: 'swell create model products -y',
25
- description: 'Apply configuration to a standard collection (non-interactive)',
26
- },
27
- {
28
- command: 'swell create model visitors -e created,updated -f title:string,photo:image -l "Visitors" -d "" -y',
29
- description: 'Create custom collection with explicit fields (non-interactive)',
30
- },
31
- {
32
- command: 'swell inspect models',
33
- description: 'List standard collections available for extending',
34
- },
17
+ '$ swell create model',
18
+ '$ swell create model products -y',
19
+ '$ swell create model visitors -f title:string,photo:string -l "Visitors" -y',
35
20
  ];
21
+ static helpMeta = {
22
+ usageDirect: '<collection> [...] -y',
23
+ };
36
24
  static flags = {
25
+ label: Flags.string({
26
+ char: 'l',
27
+ default: '',
28
+ description: 'Display label (default: capitalized collection)',
29
+ }),
37
30
  description: Flags.string({
38
31
  char: 'd',
39
32
  default: '',
40
- description: 'data model description',
41
- }),
42
- events: Flags.string({
43
- char: 'e',
44
- default: 'created,updated,deleted',
45
- description: 'comma-separated events - valid: created, updated, deleted',
33
+ description: 'Description',
46
34
  }),
47
35
  fields: Flags.string({
48
36
  char: 'f',
49
37
  default: '',
50
- description: 'comma-separated id:type pairs (e.g., title:string, price:currency). Types: collection, currency, image, int, link, string',
38
+ description: 'Fields as id:type pairs (e.g., title:string,price:currency)',
51
39
  }),
52
- label: Flags.string({
53
- char: 'l',
54
- default: '',
55
- description: 'display label for the model (defaults to capitalized collection name)',
40
+ events: Flags.string({
41
+ char: 'e',
42
+ default: 'created,updated,deleted',
43
+ description: 'Events to track (default: created,updated,deleted)',
56
44
  }),
57
45
  overwrite: Flags.boolean({
58
46
  default: false,
59
- description: 'overwrite existing data model configuration file (use with -y to force overwrite)',
47
+ description: 'Overwrite existing file',
60
48
  }),
61
49
  yes: Flags.boolean({
62
50
  char: 'y',
63
- description: 'accept all default values; non-interactive, never prompts; errors if required values are missing',
51
+ description: 'Skip prompts, require all arguments',
64
52
  }),
65
53
  };
66
54
  static summary = 'Create or extend a data model configuration in the models folder.';
@@ -1,22 +1,22 @@
1
1
  import { CreateConfigCommand } from '../../create-config-command.js';
2
+ import { HelpMeta } from '../../help/types.js';
2
3
  import { ConfigType } from '../../lib/apps/index.js';
3
4
  export default class CreateNotification extends CreateConfigCommand {
4
5
  static args: {
5
- model: import("@oclif/core/lib/interfaces/parser.js").Arg<string | undefined, Record<string, unknown>>;
6
- name: import("@oclif/core/lib/interfaces/parser.js").Arg<string | undefined, Record<string, unknown>>;
6
+ name: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
7
7
  };
8
8
  static description: string;
9
- static examples: {
10
- command: string;
11
- description: string;
12
- }[];
9
+ static examples: string[];
10
+ static helpMeta: HelpMeta;
13
11
  static flags: {
14
- admin: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
15
- description: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
12
+ model: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
16
13
  event: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
14
+ subject: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
15
+ description: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
16
+ admin: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
17
17
  once: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
18
18
  overwrite: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
19
- subject: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
19
+ yes: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
20
20
  };
21
21
  static summary: string;
22
22
  createType: ConfigType;
@@ -1,92 +1,111 @@
1
1
  import { input, select } from '@inquirer/prompts';
2
2
  import { Args, Flags } from '@oclif/core';
3
- import { capitalize, singularize } from 'inflection';
3
+ import { singularize } from 'inflection';
4
4
  import { CreateConfigCommand } from '../../create-config-command.js';
5
5
  import { ConfigType } from '../../lib/apps/index.js';
6
6
  import { toFileName, toNotificationLabel } from '../../lib/create/index.js';
7
+ import { SCHEMAS } from '../../lib/create/schemas.js';
7
8
  export default class CreateNotification extends CreateConfigCommand {
8
9
  static args = {
9
- model: Args.string({
10
- description: 'data model to trigger the notification by',
11
- }),
12
10
  name: Args.string({
13
- description: 'internal name for the notification',
11
+ default: '',
12
+ description: 'Notification name (e.g., order-paid)',
14
13
  }),
15
14
  };
16
- static description = `This command assists in generating notifications configuration files. This CLI command will prompt for values when flags are not present.`;
15
+ static description = 'Create notification files and configuration in the notifications folder.';
17
16
  static examples = [
18
- {
19
- command: 'swell create notification',
20
- description: 'Create notification configuration interactively.',
21
- },
22
- {
23
- command: 'swell create notification subscriptions confirmed --event subscription.created --once --s "Your subscription has been confirmed" -d "Send a confirmation email when subscription is created"',
24
- description: 'Specify the model, name, event, subject, and description.',
25
- },
26
- {
27
- command: 'swell create notification orders paid --event paid"',
28
- description: 'Specify the event to trigger the notification.',
29
- },
17
+ '$ swell create notification',
18
+ '$ swell create notification order-paid -m orders -y',
19
+ '$ swell create notification order-paid -m orders -e created -s "Order Paid" --admin --once -y',
30
20
  ];
21
+ static helpMeta = {
22
+ usageDirect: '<name> -m <model> [...] -y',
23
+ };
31
24
  static flags = {
32
- admin: Flags.boolean({
33
- char: 'a',
34
- description: 'indicate when the notification is sent to store admins only',
35
- }),
36
- description: Flags.string({
37
- char: 'd',
25
+ model: Flags.string({
26
+ char: 'm',
38
27
  default: '',
39
- description: 'notification description',
28
+ description: 'Triggering model (required with -y)',
40
29
  }),
41
30
  event: Flags.string({
42
31
  char: 'e',
43
32
  default: '',
44
- description: 'data model event to trigger the notification event, i.e. created',
33
+ description: 'Triggering event (default: created)',
34
+ }),
35
+ subject: Flags.string({
36
+ char: 's',
37
+ default: '',
38
+ description: 'Email subject',
39
+ }),
40
+ description: Flags.string({
41
+ char: 'd',
42
+ default: '',
43
+ description: 'Description',
44
+ }),
45
+ admin: Flags.boolean({
46
+ char: 'a',
47
+ description: 'Send to store admins only',
45
48
  }),
46
49
  once: Flags.boolean({
47
50
  char: 'o',
48
- description: 'indicate the notification should be sent only once when conditions are met, instead of repeating',
51
+ description: 'Send only once when conditions met',
49
52
  }),
50
53
  overwrite: Flags.boolean({
51
- description: 'overwrite existing notification configuration file',
54
+ default: false,
55
+ description: 'Overwrite existing file',
52
56
  }),
53
- subject: Flags.string({
54
- char: 's',
55
- default: '',
56
- description: 'notification email subject',
57
+ yes: Flags.boolean({
58
+ char: 'y',
59
+ description: 'Skip prompts, require all arguments',
57
60
  }),
58
61
  };
59
- static summary = 'Initialize notification files and configuration with properties in the notifications folder.';
62
+ static summary = 'Create notification files and configuration in the notifications folder.';
60
63
  createType = ConfigType.NOTIFICATION;
61
64
  async run() {
62
65
  const { args, flags } = await this.parse(CreateNotification);
63
- if (args.model && args.name) {
64
- await this.writeNotificationFile({
65
- admin: flags.admin,
66
- description: flags.description,
67
- event: flags.event,
68
- model: args.model,
69
- name: `${singularize(args.model)}-${args.name.replace(singularize(args.model), '')}`,
70
- once: flags.once,
71
- subject: flags.subject,
72
- }, false);
73
- }
74
- else {
75
- let { admin } = flags;
76
- if (admin === undefined) {
77
- const choice = await select({
78
- choices: [
79
- { name: 'Admins', value: 'admin' },
80
- { name: 'Customers', value: 'customer' },
81
- ],
82
- message: 'Who will be notified?',
83
- });
84
- if (choice === 'admin') {
85
- admin = true;
86
- }
66
+ const confirmYes = Boolean(flags.yes);
67
+ // NON-INTERACTIVE PATH
68
+ if (confirmYes) {
69
+ // Validate NAME argument
70
+ if (!args.name) {
71
+ this.error('Missing required argument for non-interactive mode: NAME\n\nExample: swell create notification order-paid -m orders -y', { exit: 1 });
87
72
  }
73
+ // Validate --model flag
74
+ if (!flags.model) {
75
+ this.error('Missing required flag for non-interactive mode: --model\n\nExample: swell create notification order-paid -m orders -y', { exit: 1 });
76
+ }
77
+ // Build with defaults
78
+ const name = toFileName(args.name);
79
+ const { model, event: eventFlag, subject: subjectFlag, description: descFlag, admin: adminFlag, once: onceFlag, overwrite, } = flags;
80
+ const event = eventFlag || 'created';
81
+ const subject = subjectFlag || toNotificationLabel(name);
82
+ const description = descFlag || '';
83
+ const admin = adminFlag || false;
84
+ const once = onceFlag || false;
85
+ await this.writeNotificationFile({ admin, description, event, model, name, once, subject }, overwrite,
86
+ /* shouldConfirm */ false);
87
+ return;
88
+ }
89
+ // INTERACTIVE PATH
90
+ let name = args.name;
91
+ let model = flags.model;
92
+ const { event: eventFlag, description: descFlag, subject: subjectFlag, overwrite, } = flags;
93
+ // Prompt for admin if not provided
94
+ let { admin } = flags;
95
+ if (admin === undefined) {
96
+ const choice = await select({
97
+ choices: [
98
+ { name: 'Admins', value: 'admin' },
99
+ { name: 'Customers', value: 'customer' },
100
+ ],
101
+ message: 'Who will be notified?',
102
+ });
103
+ admin = choice === 'admin';
104
+ }
105
+ // Prompt for model if not provided
106
+ if (!model) {
88
107
  const collections = await this.getCollectionOptions();
89
- const model = await select({
108
+ model = await select({
90
109
  choices: collections.map((collectionName) => ({
91
110
  name: collectionName,
92
111
  value: collectionName,
@@ -95,46 +114,52 @@ export default class CreateNotification extends CreateConfigCommand {
95
114
  message: 'Which model will trigger the notification?',
96
115
  pageSize: 25,
97
116
  });
98
- const event = await input({
117
+ }
118
+ // Prompt for event if not provided
119
+ const event = eventFlag ||
120
+ (await input({
99
121
  default: 'created',
100
122
  message: 'Event to trigger the notification',
123
+ }));
124
+ // Prompt for name if not provided
125
+ if (!name) {
126
+ name = await input({
127
+ default: `${singularize(model)}-${event}`,
128
+ message: 'Name of the notification',
129
+ });
130
+ }
131
+ name = toFileName(name);
132
+ // Prompt for description if not provided
133
+ const description = descFlag ||
134
+ (await input({
135
+ default: `Notify ${admin ? 'admin' : 'customer'} when ${singularize(model)}...`,
136
+ message: 'Describe what the notification does',
137
+ }));
138
+ // Prompt for once if not provided
139
+ let { once } = flags;
140
+ if (once === undefined) {
141
+ once = await select({
142
+ choices: [
143
+ { name: 'Every time conditions are met', value: false },
144
+ { name: 'Only the first time conditions are met', value: true },
145
+ ],
146
+ message: 'When should we send this notification?',
101
147
  });
102
- const answers = {
103
- description: await input({
104
- default: `Notify ${admin ? 'admin' : 'customer'} when ${singularize(model)}...`,
105
- message: 'Describe what the notification does',
106
- }),
107
- name: await input({
108
- default: `${singularize(model)}-${event}`,
109
- message: 'Name of the notification',
110
- }),
111
- once: await select({
112
- choices: [
113
- {
114
- name: 'Every time conditions are met',
115
- value: false,
116
- },
117
- {
118
- name: 'Only the first time conditions are met',
119
- value: true,
120
- },
121
- ],
122
- message: 'When should we send this notification?',
123
- }),
124
- subject: await input({
125
- default: `Something happened with ${model}`,
126
- message: 'Subject of the notification email',
127
- }),
128
- };
129
- const { description, name, once, subject } = answers;
130
- await this.writeNotificationFile({ admin, description, event, model, name, once, subject }, false);
131
148
  }
149
+ // Prompt for subject if not provided
150
+ const subject = subjectFlag ||
151
+ (await input({
152
+ default: toNotificationLabel(name),
153
+ message: 'Subject of the notification email',
154
+ }));
155
+ await this.writeNotificationFile({ admin, description, event, model, name, once, subject }, overwrite,
156
+ /* shouldConfirm */ true);
132
157
  }
133
- async writeNotificationFile({ admin, description, event, model, name, once, subject, }, overwrite) {
134
- const label = [name].map((val) => capitalize(val).trim()).join(' ');
135
- const fileName = toFileName(label);
158
+ async writeNotificationFile({ admin, description, event, model, name, once, subject, }, overwrite, shouldConfirm = true) {
159
+ const fileName = toFileName(name);
136
160
  const noteLabel = toNotificationLabel(name);
137
161
  const fileBody = {
162
+ $schema: SCHEMAS.NOTIFICATION,
138
163
  collection: model,
139
164
  conditions: {},
140
165
  event: event || 'created',
@@ -157,10 +182,7 @@ export default class CreateNotification extends CreateConfigCommand {
157
182
  expand: [],
158
183
  };
159
184
  fileBody.sample = {};
160
- const jsonCreated = await this.createFile({
161
- fileBody,
162
- fileName,
163
- }, overwrite);
185
+ const jsonCreated = await this.createFile({ fileBody, fileName }, overwrite, shouldConfirm);
164
186
  if (jsonCreated) {
165
187
  await this.createFile({ extension: 'tpl', fileBody: '\n', fileName }, overwrite, false);
166
188
  }
@@ -0,0 +1,21 @@
1
+ import { CreateConfigCommand } from '../../create-config-command.js';
2
+ import { HelpMeta } from '../../help/types.js';
3
+ import { ConfigType } from '../../lib/apps/index.js';
4
+ export default class CreateSetting extends CreateConfigCommand {
5
+ static args: {
6
+ name: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static description: string;
9
+ static examples: string[];
10
+ static helpMeta: HelpMeta;
11
+ static flags: {
12
+ label: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
13
+ description: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
14
+ fields: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
15
+ overwrite: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
16
+ yes: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
17
+ };
18
+ static summary: string;
19
+ createType: ConfigType;
20
+ run(): Promise<void>;
21
+ }