@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.
- package/dist/app-command.js +1 -1
- package/dist/commands/api/delete.js +4 -1
- package/dist/commands/api/get.js +1 -0
- package/dist/commands/api/index.js +4 -1
- package/dist/commands/api/post.js +1 -0
- package/dist/commands/api/put.js +1 -0
- package/dist/commands/app/init.d.ts +8 -7
- package/dist/commands/app/init.js +36 -18
- package/dist/commands/app/pull.js +2 -2
- package/dist/commands/app/push.js +2 -2
- package/dist/commands/app/version.d.ts +1 -0
- package/dist/commands/app/version.js +14 -4
- package/dist/commands/create/app.d.ts +8 -4
- package/dist/commands/create/app.js +68 -51
- package/dist/commands/create/content.d.ts +5 -6
- package/dist/commands/create/content.js +21 -37
- package/dist/commands/create/function.d.ts +6 -7
- package/dist/commands/create/function.js +94 -31
- package/dist/commands/create/index.js +8 -0
- package/dist/commands/create/model.d.ts +5 -6
- package/dist/commands/create/model.js +21 -33
- package/dist/commands/create/notification.d.ts +9 -9
- package/dist/commands/create/notification.js +117 -95
- package/dist/commands/create/setting.d.ts +21 -0
- package/dist/commands/create/setting.js +120 -0
- package/dist/commands/create/tests.d.ts +4 -5
- package/dist/commands/create/tests.js +8 -11
- package/dist/commands/create/webhook.d.ts +22 -0
- package/dist/commands/create/webhook.js +176 -0
- package/dist/commands/schema.d.ts +1 -0
- package/dist/commands/schema.js +51 -5
- package/dist/commands/theme/init.d.ts +8 -4
- package/dist/commands/theme/init.js +21 -8
- package/dist/create-app-command.d.ts +1 -0
- package/dist/create-app-command.js +15 -10
- package/dist/create-config-command.js +2 -2
- package/dist/help/custom-help.d.ts +89 -0
- package/dist/help/custom-help.js +337 -0
- package/dist/help/types.d.ts +75 -0
- package/dist/help/types.js +1 -0
- package/dist/lib/apps/app-config.js +2 -2
- package/dist/lib/apps/index.d.ts +2 -1
- package/dist/lib/apps/index.js +21 -5
- package/dist/lib/apps/paths.js +7 -6
- package/dist/lib/create/notification.d.ts +1 -0
- package/dist/lib/create/schemas.d.ts +1 -0
- package/dist/lib/create/schemas.js +1 -0
- package/dist/lib/create/setting.d.ts +15 -0
- package/dist/lib/create/setting.js +27 -0
- package/dist/lib/create/tests/templates/env-dts.js +1 -0
- package/dist/lib/create/tests/templates/swell-client.js +2 -0
- package/dist/lib/create/tests/templates/tsconfig.js +2 -0
- package/dist/lib/create/tests/templates/vitest-config.js +1 -0
- package/dist/lib/create/webhook.d.ts +32 -0
- package/dist/lib/create/webhook.js +52 -0
- package/dist/swell-api-command.d.ts +14 -0
- package/dist/swell-api-command.js +113 -7
- package/oclif.manifest.json +609 -259
- 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
|
-
|
|
11
|
-
|
|
10
|
+
name: Args.string({
|
|
11
|
+
default: '',
|
|
12
|
+
description: 'Filename with extension (e.g., my-func.ts)',
|
|
12
13
|
}),
|
|
13
14
|
trigger: Args.string({
|
|
14
|
-
|
|
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
|
-
|
|
22
|
-
|
|
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: '
|
|
54
|
+
description: 'Description',
|
|
42
55
|
}),
|
|
43
56
|
events: Flags.string({
|
|
44
57
|
char: 'e',
|
|
45
58
|
default: '',
|
|
46
|
-
description: '
|
|
59
|
+
description: 'Model events (e.g., order.created,order.updated)',
|
|
47
60
|
}),
|
|
48
61
|
overwrite: Flags.boolean({
|
|
49
62
|
default: false,
|
|
50
|
-
description: '
|
|
63
|
+
description: 'Overwrite existing file',
|
|
51
64
|
}),
|
|
52
65
|
route: Flags.string({
|
|
53
66
|
char: 'r',
|
|
54
|
-
default: '
|
|
55
|
-
description: '
|
|
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: '
|
|
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 = '
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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: '
|
|
12
|
+
description: 'Collection ID to create or extend (e.g., products)',
|
|
13
13
|
}),
|
|
14
14
|
};
|
|
15
|
-
static description =
|
|
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
|
-
|
|
21
|
-
|
|
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: '
|
|
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: '
|
|
38
|
+
description: 'Fields as id:type pairs (e.g., title:string,price:currency)',
|
|
51
39
|
}),
|
|
52
|
-
|
|
53
|
-
char: '
|
|
54
|
-
default: '',
|
|
55
|
-
description: '
|
|
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: '
|
|
47
|
+
description: 'Overwrite existing file',
|
|
60
48
|
}),
|
|
61
49
|
yes: Flags.boolean({
|
|
62
50
|
char: 'y',
|
|
63
|
-
description: '
|
|
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
|
-
|
|
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
|
-
|
|
11
|
-
description: string;
|
|
12
|
-
}[];
|
|
9
|
+
static examples: string[];
|
|
10
|
+
static helpMeta: HelpMeta;
|
|
13
11
|
static flags: {
|
|
14
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
11
|
+
default: '',
|
|
12
|
+
description: 'Notification name (e.g., order-paid)',
|
|
14
13
|
}),
|
|
15
14
|
};
|
|
16
|
-
static description =
|
|
15
|
+
static description = 'Create notification files and configuration in the notifications folder.';
|
|
17
16
|
static examples = [
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
33
|
-
char: '
|
|
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: '
|
|
28
|
+
description: 'Triggering model (required with -y)',
|
|
40
29
|
}),
|
|
41
30
|
event: Flags.string({
|
|
42
31
|
char: 'e',
|
|
43
32
|
default: '',
|
|
44
|
-
description: '
|
|
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: '
|
|
51
|
+
description: 'Send only once when conditions met',
|
|
49
52
|
}),
|
|
50
53
|
overwrite: Flags.boolean({
|
|
51
|
-
|
|
54
|
+
default: false,
|
|
55
|
+
description: 'Overwrite existing file',
|
|
52
56
|
}),
|
|
53
|
-
|
|
54
|
-
char: '
|
|
55
|
-
|
|
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 = '
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
+
}
|