@surelycrm/cli 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/bin/sure-cli.js +97 -15
- package/package.json +1 -1
- package/templates/support-reply.json +5 -0
package/README.md
CHANGED
|
@@ -45,12 +45,14 @@ Configuration is stored in `~/.surecli/config.json`.
|
|
|
45
45
|
|---------|-------------|
|
|
46
46
|
| `sure-cli config` | Show stored configuration |
|
|
47
47
|
| `sure-cli create-customer` | Create a new customer |
|
|
48
|
-
| `sure-cli get-customer --id {guid}` | Get a customer by GUID |
|
|
49
|
-
| `sure-cli get-customer-by-reference --reference {ref}` | Get a customer by reference number |
|
|
48
|
+
| `sure-cli get-customer --id {guid}` | Get a customer by GUID, email, or reference |
|
|
50
49
|
| `sure-cli update-customer --id {guid}` | Update an existing customer |
|
|
51
50
|
| `sure-cli change-status --customer-id {guid} --status-id {guid}` | Change a customer's status |
|
|
52
51
|
| `sure-cli start-workflow --customer-id {guid} --workflow-name {name}` | Start a workflow for a customer |
|
|
53
52
|
| `sure-cli get-customers-by-age --age {age} --comparison {comparison}` | Filter customers by age |
|
|
53
|
+
| `sure-cli get-support-tickets --new` | Get new/open support tickets |
|
|
54
|
+
| `sure-cli get-support-tickets --recently-replied --hours {hours}` | Get recently replied support tickets |
|
|
55
|
+
| `sure-cli reply-to-ticket --id {guid} --message {message}` | Reply to a support ticket |
|
|
54
56
|
|
|
55
57
|
Use `--help` on any command for details.
|
|
56
58
|
|
|
@@ -61,6 +63,7 @@ JSON templates for complex payloads are in the `templates/` directory:
|
|
|
61
63
|
- `customer.json` — customer create/update payload
|
|
62
64
|
- `status-change.json` — status change payload
|
|
63
65
|
- `workflow-start.json` — workflow start payload
|
|
66
|
+
- `support-reply.json` — support ticket reply payload
|
|
64
67
|
|
|
65
68
|
## Documentation
|
|
66
69
|
|
package/bin/sure-cli.js
CHANGED
|
@@ -7,7 +7,7 @@ const { loadConfig, saveConfig, requireConfig } = require('../lib/config');
|
|
|
7
7
|
const { request, handleResponse } = require('../lib/api');
|
|
8
8
|
|
|
9
9
|
const program = new Command();
|
|
10
|
-
program.name('sure-cli').description('CLI wrapper for the SurelyCrm API').version('1.
|
|
10
|
+
program.name('sure-cli').description('CLI wrapper for the SurelyCrm API').version('1.1.0');
|
|
11
11
|
|
|
12
12
|
const TEMPLATES_DIR = path.join(__dirname, '..', 'templates');
|
|
13
13
|
|
|
@@ -107,23 +107,33 @@ program
|
|
|
107
107
|
|
|
108
108
|
program
|
|
109
109
|
.command('get-customer')
|
|
110
|
-
.description('Get a customer by GUID')
|
|
111
|
-
.
|
|
110
|
+
.description('Get a customer by GUID, email address, or reference number')
|
|
111
|
+
.option('--id <guid>', 'Customer GUID')
|
|
112
|
+
.option('--email <email>', 'Customer email address')
|
|
113
|
+
.option('--reference <reference>', 'Customer reference number')
|
|
112
114
|
.action(run(async (options) => {
|
|
113
115
|
const config = requireConfig();
|
|
114
|
-
const id = getRequiredOption(options, 'id');
|
|
115
|
-
const response = await request(config.baseUrl, config.apiKey, 'GET', `Api/customer/${id}`);
|
|
116
|
-
handleResponse(response);
|
|
117
|
-
}));
|
|
118
116
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
117
|
+
const provided = [options.id, options.email, options.reference].filter(Boolean);
|
|
118
|
+
if (provided.length === 0) {
|
|
119
|
+
console.error('One of --id, --email, or --reference is required');
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
if (provided.length > 1) {
|
|
123
|
+
console.error('Only one of --id, --email, or --reference can be provided');
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
let path;
|
|
128
|
+
if (options.id) {
|
|
129
|
+
path = `Api/customer/${options.id}`;
|
|
130
|
+
} else if (options.email) {
|
|
131
|
+
path = `Api/customer/byEmail/${encodeURIComponent(options.email)}`;
|
|
132
|
+
} else {
|
|
133
|
+
path = `Api/customer/reference/${encodeURIComponent(options.reference)}`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const response = await request(config.baseUrl, config.apiKey, 'GET', path);
|
|
127
137
|
handleResponse(response);
|
|
128
138
|
}));
|
|
129
139
|
|
|
@@ -199,4 +209,76 @@ program
|
|
|
199
209
|
handleResponse(response);
|
|
200
210
|
}));
|
|
201
211
|
|
|
212
|
+
program
|
|
213
|
+
.command('get-support-tickets')
|
|
214
|
+
.description('Get support tickets')
|
|
215
|
+
.option('--new', 'Get new/open support tickets')
|
|
216
|
+
.option('--recently-replied', 'Get support tickets with replies in the recent period')
|
|
217
|
+
.option('--hours <hours>', 'Number of hours to look back for recently replied tickets', '24')
|
|
218
|
+
.option('--page <page>', 'Page number', '1')
|
|
219
|
+
.option('--page-size <pageSize>', 'Page size', '25')
|
|
220
|
+
.action(run(async (options) => {
|
|
221
|
+
const config = requireConfig();
|
|
222
|
+
|
|
223
|
+
if (!options.new && !options.recentlyReplied) {
|
|
224
|
+
console.error('Either --new or --recently-replied is required');
|
|
225
|
+
process.exit(1);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (options.new && options.recentlyReplied) {
|
|
229
|
+
console.error('Cannot use both --new and --recently-replied at the same time');
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const params = new URLSearchParams();
|
|
234
|
+
if (options.new) {
|
|
235
|
+
params.append('newTickets', 'true');
|
|
236
|
+
} else if (options.recentlyReplied) {
|
|
237
|
+
params.append('recentlyReplied', 'true');
|
|
238
|
+
params.append('hours', options.hours);
|
|
239
|
+
}
|
|
240
|
+
params.append('page', options.page);
|
|
241
|
+
params.append('pageSize', options.pageSize);
|
|
242
|
+
|
|
243
|
+
const response = await request(config.baseUrl, config.apiKey, 'GET', `Api/support/tickets?${params.toString()}`);
|
|
244
|
+
handleResponse(response);
|
|
245
|
+
}));
|
|
246
|
+
|
|
247
|
+
program
|
|
248
|
+
.command('reply-to-ticket')
|
|
249
|
+
.description('Reply to a support ticket')
|
|
250
|
+
.requiredOption('--id <guid>', 'Support ticket GUID')
|
|
251
|
+
.option('--message <message>', 'Reply message text')
|
|
252
|
+
.option('--template <file>', 'Path to a JSON reply template')
|
|
253
|
+
.option('--data <json>', 'Inline JSON reply payload')
|
|
254
|
+
.option('--internal', 'Mark the reply as internal-only', false)
|
|
255
|
+
.option('--close', 'Close the ticket after replying', false)
|
|
256
|
+
.action(run(async (options) => {
|
|
257
|
+
const config = requireConfig();
|
|
258
|
+
const id = getRequiredOption(options, 'id');
|
|
259
|
+
|
|
260
|
+
let body = parseDataInput(options);
|
|
261
|
+
if (!body) {
|
|
262
|
+
body = loadTemplate('support-reply');
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (options.message) {
|
|
266
|
+
body.message = options.message;
|
|
267
|
+
}
|
|
268
|
+
if (options.internal) {
|
|
269
|
+
body.isInternal = true;
|
|
270
|
+
}
|
|
271
|
+
if (options.close) {
|
|
272
|
+
body.closeAfterReply = true;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (!body.message) {
|
|
276
|
+
console.error('A message is required. Use --message, --template, or --data.');
|
|
277
|
+
process.exit(1);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const response = await request(config.baseUrl, config.apiKey, 'POST', `Api/support/tickets/${id}/reply`, body);
|
|
281
|
+
handleResponse(response);
|
|
282
|
+
}));
|
|
283
|
+
|
|
202
284
|
program.parse();
|
package/package.json
CHANGED