@cyberismo/cli 0.0.17 → 0.0.19
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/index.js +264 -210
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +539 -314
package/src/index.ts
CHANGED
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import {
|
|
15
|
+
import { constants, existsSync } from 'node:fs';
|
|
16
|
+
import { access, lstat, readFile } from 'node:fs/promises';
|
|
16
17
|
import { resolve } from 'node:path';
|
|
17
18
|
|
|
18
19
|
import { Argument, Command, Option } from 'commander';
|
|
@@ -138,62 +139,6 @@ const nameGuideline =
|
|
|
138
139
|
const pathGuideline =
|
|
139
140
|
'Path to the project root. Mandatory if not running inside a project tree.';
|
|
140
141
|
|
|
141
|
-
const additionalHelpForCreate = `Sub-command help:
|
|
142
|
-
create attachment <cardKey> <filename>, where
|
|
143
|
-
<cardKey> is card key of a card to have the attachment,
|
|
144
|
-
<filename> is attachment filename.
|
|
145
|
-
|
|
146
|
-
create card <template> [cardKey], where
|
|
147
|
-
<template> Template to use. You can list the templates in a project with "show templates" command.
|
|
148
|
-
[cardKey] Parent card's card key. If defined, new card will be created as a child card to that card.
|
|
149
|
-
|
|
150
|
-
create cardType <name> <workflow>, where
|
|
151
|
-
<name> Name for cardType. ${nameGuideline}
|
|
152
|
-
<workflow> Workflow for the card type. You can list workflows in a project with "show workflows" command.
|
|
153
|
-
|
|
154
|
-
create fieldType <name> <dataType>, where
|
|
155
|
-
<name> Name for fieldType. ${nameGuideline}
|
|
156
|
-
<dataType> Type of field. You can list field types in a project with "show fieldTypes" command.
|
|
157
|
-
|
|
158
|
-
create graphModel <name>, where
|
|
159
|
-
<name> Name for graph model. ${nameGuideline}
|
|
160
|
-
|
|
161
|
-
create graphView <name>, where
|
|
162
|
-
<name> Name for graph view. ${nameGuideline}
|
|
163
|
-
|
|
164
|
-
create label <cardKey> <labelName>, where
|
|
165
|
-
<cardKey> Card key of the label
|
|
166
|
-
<labelName> Name for the new label
|
|
167
|
-
|
|
168
|
-
create link <source> <destination> <linkType> [description], where
|
|
169
|
-
<source> Source card key of the link
|
|
170
|
-
<destination> Destination card key of the link
|
|
171
|
-
<linkType> Link type to create
|
|
172
|
-
[description] Link description
|
|
173
|
-
|
|
174
|
-
create linkType <name>, where
|
|
175
|
-
<name> Name for linkType. ${nameGuideline}
|
|
176
|
-
|
|
177
|
-
create project <name> <prefix> <path>, where
|
|
178
|
-
<name> Name of the project.
|
|
179
|
-
<prefix> Prefix for the project.
|
|
180
|
-
<path> Path where to create the project
|
|
181
|
-
|
|
182
|
-
create report <name>, where
|
|
183
|
-
<name> Name for report. ${nameGuideline}
|
|
184
|
-
|
|
185
|
-
create template <name> [content], where
|
|
186
|
-
<name> Name for template. ${nameGuideline}
|
|
187
|
-
[content] If empty, template is created with default values. Template content must conform to schema "templateSchema.json"
|
|
188
|
-
|
|
189
|
-
create workflow <name> [content], where
|
|
190
|
-
<name> Name for workflow. ${nameGuideline}
|
|
191
|
-
[content] If empty, workflow is created with default values. Workflow content must conform to schema "workflowSchema.json"
|
|
192
|
-
|
|
193
|
-
create <resourceName> [content], where
|
|
194
|
-
<resourceName> Name of the resource (e.g. <prefix>/<type>/<identifier>)
|
|
195
|
-
[content] If empty, resource is created with default values. Content must conform to its resource schema.`;
|
|
196
|
-
|
|
197
142
|
const additionalHelpForRemove = `Sub-command help:
|
|
198
143
|
remove attachment <cardKey> <filename>, where
|
|
199
144
|
<cardKey> is card key of the owning card,
|
|
@@ -256,6 +201,20 @@ const contextOption = new Option(
|
|
|
256
201
|
.choices(validContexts)
|
|
257
202
|
.default('app');
|
|
258
203
|
|
|
204
|
+
const pathOption = new Option('-p, --project-path <path>', pathGuideline);
|
|
205
|
+
|
|
206
|
+
// Custom Command class with pathOption pre-configured
|
|
207
|
+
class CommandWithPath extends Command {
|
|
208
|
+
createCommand(name?: string): CommandWithPath {
|
|
209
|
+
return new CommandWithPath(name);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
constructor(name?: string) {
|
|
213
|
+
super(name);
|
|
214
|
+
this.addOption(pathOption);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
259
218
|
// Main CLI program.
|
|
260
219
|
program
|
|
261
220
|
.name('cyberismo')
|
|
@@ -272,7 +231,10 @@ program
|
|
|
272
231
|
.default('fatal'),
|
|
273
232
|
);
|
|
274
233
|
|
|
275
|
-
const addCmd =
|
|
234
|
+
const addCmd = new CommandWithPath('add').description(
|
|
235
|
+
'Add items to the project',
|
|
236
|
+
);
|
|
237
|
+
program.addCommand(addCmd);
|
|
276
238
|
|
|
277
239
|
// Add card to a template
|
|
278
240
|
addCmd
|
|
@@ -287,7 +249,6 @@ addCmd
|
|
|
287
249
|
'Card type to use for the new card. \nYou can list the card types in a project with "show cardTypes" command.',
|
|
288
250
|
)
|
|
289
251
|
.argument('[cardKey]', "Parent card's card key")
|
|
290
|
-
.option('-p, --project-path [path]', `${pathGuideline}`)
|
|
291
252
|
.option('-r, --repeat <quantity>', 'Add multiple cards to a template')
|
|
292
253
|
.action(
|
|
293
254
|
async (
|
|
@@ -312,7 +273,6 @@ addCmd
|
|
|
312
273
|
'<location>',
|
|
313
274
|
'Hub URL. Default hub can be added by using "default"',
|
|
314
275
|
)
|
|
315
|
-
.option('-p, --project-path [path]', `${pathGuideline}`)
|
|
316
276
|
.action(async (location: string, options: CommandOptions<'add'>) => {
|
|
317
277
|
if (location === 'default') {
|
|
318
278
|
location = DEFAULT_HUB;
|
|
@@ -325,9 +285,10 @@ addCmd
|
|
|
325
285
|
handleResponse(result);
|
|
326
286
|
});
|
|
327
287
|
|
|
328
|
-
const calculate =
|
|
329
|
-
|
|
330
|
-
|
|
288
|
+
const calculate = new CommandWithPath('calc').description(
|
|
289
|
+
'Used for running logic programs',
|
|
290
|
+
);
|
|
291
|
+
program.addCommand(calculate);
|
|
331
292
|
|
|
332
293
|
calculate
|
|
333
294
|
.command('generate')
|
|
@@ -337,7 +298,6 @@ calculate
|
|
|
337
298
|
'Path to an output file. Command writes the logic program to this file.',
|
|
338
299
|
)
|
|
339
300
|
.argument('[query]', 'Query to run')
|
|
340
|
-
.option('-p, --project-path [path]', `${pathGuideline}`)
|
|
341
301
|
.action(
|
|
342
302
|
async (
|
|
343
303
|
destination: string,
|
|
@@ -358,7 +318,6 @@ calculate
|
|
|
358
318
|
.description('Run a logic program')
|
|
359
319
|
.argument('<filePath>', 'Path to the logic program')
|
|
360
320
|
.addOption(contextOption)
|
|
361
|
-
.option('-p, --project-path [path]', `${pathGuideline}`)
|
|
362
321
|
.action(async (filePath: string, options: CommandOptions<'calc'>) => {
|
|
363
322
|
const result = await commandHandler.command(
|
|
364
323
|
Cmd.calc,
|
|
@@ -368,120 +327,231 @@ calculate
|
|
|
368
327
|
handleResponse(result);
|
|
369
328
|
});
|
|
370
329
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
)
|
|
330
|
+
const createCmd = new CommandWithPath('create').description(
|
|
331
|
+
'Create cards, resources and other project items',
|
|
332
|
+
);
|
|
333
|
+
program.addCommand(createCmd);
|
|
334
|
+
|
|
335
|
+
// Create attachment subcommand
|
|
336
|
+
createCmd
|
|
337
|
+
.command('attachment')
|
|
338
|
+
.description('Create an attachment for a card')
|
|
339
|
+
.argument('<cardKey>', 'Card key of the card to attach to')
|
|
340
|
+
.argument('<filename>', 'Path to the file to attach')
|
|
341
|
+
.action(
|
|
342
|
+
async (
|
|
343
|
+
cardKey: string,
|
|
344
|
+
filename: string,
|
|
345
|
+
options: CommandOptions<'create'>,
|
|
346
|
+
) => {
|
|
347
|
+
const result = await commandHandler.command(
|
|
348
|
+
Cmd.create,
|
|
349
|
+
['attachment', cardKey, filename],
|
|
350
|
+
Object.assign({}, options, program.opts()),
|
|
351
|
+
);
|
|
352
|
+
handleResponse(result);
|
|
353
|
+
},
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
// Create card subcommand
|
|
357
|
+
createCmd
|
|
358
|
+
.command('card')
|
|
359
|
+
.description('Create a card from a template')
|
|
379
360
|
.argument(
|
|
380
|
-
'
|
|
381
|
-
'
|
|
361
|
+
'<template>',
|
|
362
|
+
'Template to use. You can list templates with "show templates" command',
|
|
382
363
|
)
|
|
383
364
|
.argument(
|
|
384
|
-
'[
|
|
385
|
-
'
|
|
365
|
+
'[parentCardKey]',
|
|
366
|
+
"Parent card's card key. If defined, new card will be created as a child",
|
|
386
367
|
)
|
|
368
|
+
.action(
|
|
369
|
+
async (
|
|
370
|
+
template: string,
|
|
371
|
+
parentCardKey: string | undefined,
|
|
372
|
+
options: CommandOptions<'create'>,
|
|
373
|
+
) => {
|
|
374
|
+
const result = await commandHandler.command(
|
|
375
|
+
Cmd.create,
|
|
376
|
+
['card', template, parentCardKey].filter(Boolean) as string[],
|
|
377
|
+
Object.assign({}, options, program.opts()),
|
|
378
|
+
);
|
|
379
|
+
handleResponse(result);
|
|
380
|
+
},
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
// Create cardType subcommand
|
|
384
|
+
createCmd
|
|
385
|
+
.command('cardType')
|
|
386
|
+
.description('Create a new card type')
|
|
387
|
+
.argument('<name>', `Name for card type. ${nameGuideline}`)
|
|
387
388
|
.argument(
|
|
388
|
-
'
|
|
389
|
-
'
|
|
389
|
+
'<workflow>',
|
|
390
|
+
'Workflow for the card type. You can list workflows with "show workflows" command',
|
|
390
391
|
)
|
|
392
|
+
.action(
|
|
393
|
+
async (
|
|
394
|
+
name: string,
|
|
395
|
+
workflow: string,
|
|
396
|
+
options: CommandOptions<'create'>,
|
|
397
|
+
) => {
|
|
398
|
+
const result = await commandHandler.command(
|
|
399
|
+
Cmd.create,
|
|
400
|
+
['cardType', name, workflow],
|
|
401
|
+
Object.assign({}, options, program.opts()),
|
|
402
|
+
);
|
|
403
|
+
handleResponse(result);
|
|
404
|
+
},
|
|
405
|
+
);
|
|
406
|
+
|
|
407
|
+
// Create fieldType subcommand
|
|
408
|
+
createCmd
|
|
409
|
+
.command('fieldType')
|
|
410
|
+
.description('Create a new field type')
|
|
411
|
+
.argument('<name>', `Name for field type. ${nameGuideline}`)
|
|
391
412
|
.argument(
|
|
392
|
-
'
|
|
393
|
-
'
|
|
394
|
-
)
|
|
395
|
-
.addHelpText('after', additionalHelpForCreate)
|
|
396
|
-
.option('-p, --project-path [path]', `${pathGuideline}`)
|
|
397
|
-
.option(
|
|
398
|
-
'-s, --skipModuleImport',
|
|
399
|
-
'Skip importing modules when creating a project',
|
|
413
|
+
'<dataType>',
|
|
414
|
+
'Type of field. You can list field types with "show fieldTypes" command',
|
|
400
415
|
)
|
|
401
416
|
.action(
|
|
402
417
|
async (
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
parameter1: string,
|
|
406
|
-
parameter2: string,
|
|
407
|
-
parameter3: string,
|
|
418
|
+
name: string,
|
|
419
|
+
dataType: string,
|
|
408
420
|
options: CommandOptions<'create'>,
|
|
409
421
|
) => {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
422
|
+
const result = await commandHandler.command(
|
|
423
|
+
Cmd.create,
|
|
424
|
+
['fieldType', name, dataType],
|
|
425
|
+
Object.assign({}, options, program.opts()),
|
|
426
|
+
);
|
|
427
|
+
handleResponse(result);
|
|
428
|
+
},
|
|
429
|
+
);
|
|
415
430
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
431
|
+
// Create graphModel subcommand
|
|
432
|
+
createCmd
|
|
433
|
+
.command('graphModel')
|
|
434
|
+
.description('Create a new graph model')
|
|
435
|
+
.argument('<name>', `Name for graph model. ${nameGuideline}`)
|
|
436
|
+
.action(async (name: string, options: CommandOptions<'create'>) => {
|
|
437
|
+
const result = await commandHandler.command(
|
|
438
|
+
Cmd.create,
|
|
439
|
+
['graphModel', name],
|
|
440
|
+
Object.assign({}, options, program.opts()),
|
|
441
|
+
);
|
|
442
|
+
handleResponse(result);
|
|
443
|
+
});
|
|
422
444
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
445
|
+
// Create graphView subcommand
|
|
446
|
+
createCmd
|
|
447
|
+
.command('graphView')
|
|
448
|
+
.description('Create a new graph view')
|
|
449
|
+
.argument('<name>', `Name for graph view. ${nameGuideline}`)
|
|
450
|
+
.action(async (name: string, options: CommandOptions<'create'>) => {
|
|
451
|
+
const result = await commandHandler.command(
|
|
452
|
+
Cmd.create,
|
|
453
|
+
['graphView', name],
|
|
454
|
+
Object.assign({}, options, program.opts()),
|
|
455
|
+
);
|
|
456
|
+
handleResponse(result);
|
|
457
|
+
});
|
|
432
458
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
459
|
+
// Create label subcommand
|
|
460
|
+
createCmd
|
|
461
|
+
.command('label')
|
|
462
|
+
.description('Create a label on a card')
|
|
463
|
+
.argument('<cardKey>', 'Card key')
|
|
464
|
+
.argument('<labelName>', 'Name for the new label')
|
|
465
|
+
.action(
|
|
466
|
+
async (
|
|
467
|
+
cardKey: string,
|
|
468
|
+
labelName: string,
|
|
469
|
+
options: CommandOptions<'create'>,
|
|
470
|
+
) => {
|
|
471
|
+
const result = await commandHandler.command(
|
|
472
|
+
Cmd.create,
|
|
473
|
+
['label', cardKey, labelName],
|
|
474
|
+
Object.assign({}, options, program.opts()),
|
|
475
|
+
);
|
|
476
|
+
handleResponse(result);
|
|
477
|
+
},
|
|
478
|
+
);
|
|
438
479
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
480
|
+
// Create link subcommand
|
|
481
|
+
createCmd
|
|
482
|
+
.command('link')
|
|
483
|
+
.description('Create a link between two cards')
|
|
484
|
+
.argument('<source>', 'Source card key')
|
|
485
|
+
.argument('<destination>', 'Destination card key')
|
|
486
|
+
.argument('<linkType>', 'Link type to create')
|
|
487
|
+
.argument('[description]', 'Optional link description')
|
|
488
|
+
.action(
|
|
489
|
+
async (
|
|
490
|
+
source: string,
|
|
491
|
+
destination: string,
|
|
492
|
+
linkType: string,
|
|
493
|
+
description: string | undefined,
|
|
494
|
+
options: CommandOptions<'create'>,
|
|
495
|
+
) => {
|
|
496
|
+
const result = await commandHandler.command(
|
|
497
|
+
Cmd.create,
|
|
498
|
+
['link', source, destination, linkType, description].filter(
|
|
499
|
+
Boolean,
|
|
500
|
+
) as string[],
|
|
501
|
+
Object.assign({}, options, program.opts()),
|
|
502
|
+
);
|
|
503
|
+
handleResponse(result);
|
|
504
|
+
},
|
|
505
|
+
);
|
|
454
506
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
507
|
+
// Create linkType subcommand
|
|
508
|
+
createCmd
|
|
509
|
+
.command('linkType')
|
|
510
|
+
.description('Create a new link type')
|
|
511
|
+
.argument('<name>', `Name for link type. ${nameGuideline}`)
|
|
512
|
+
.action(async (name: string, options: CommandOptions<'create'>) => {
|
|
513
|
+
const result = await commandHandler.command(
|
|
514
|
+
Cmd.create,
|
|
515
|
+
['linkType', name],
|
|
516
|
+
Object.assign({}, options, program.opts()),
|
|
517
|
+
);
|
|
518
|
+
handleResponse(result);
|
|
519
|
+
});
|
|
464
520
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
521
|
+
// Create project subcommand
|
|
522
|
+
createCmd
|
|
523
|
+
.command('project')
|
|
524
|
+
.description('Create a new project')
|
|
525
|
+
.argument('<name>', 'Project name')
|
|
526
|
+
.argument('<prefix>', 'Project prefix')
|
|
527
|
+
.argument('<path>', 'Path where to create the project')
|
|
528
|
+
.argument('[category]', 'Project category (optional)')
|
|
529
|
+
.argument('[description]', 'Project description (optional)')
|
|
530
|
+
.option(
|
|
531
|
+
'-s, --skipModuleImport',
|
|
532
|
+
'Skip importing modules when creating a project',
|
|
533
|
+
)
|
|
534
|
+
.action(
|
|
535
|
+
async (
|
|
536
|
+
name: string,
|
|
537
|
+
prefix: string,
|
|
538
|
+
path: string,
|
|
539
|
+
category: string | undefined,
|
|
540
|
+
description: string | undefined,
|
|
541
|
+
options: CommandOptions<'create'>,
|
|
542
|
+
) => {
|
|
543
|
+
// Project path must be set to 'options' when creating a project
|
|
544
|
+
options.projectPath = path;
|
|
472
545
|
const commandOptions = Object.assign({}, options, program.opts());
|
|
546
|
+
|
|
473
547
|
const result = await commandHandler.command(
|
|
474
548
|
Cmd.create,
|
|
475
|
-
[
|
|
549
|
+
['project', name, prefix, path, category || '', description || ''],
|
|
476
550
|
commandOptions,
|
|
477
551
|
);
|
|
478
552
|
|
|
479
|
-
// Post-handling after creating a new project
|
|
480
|
-
if (
|
|
481
|
-
type === 'project' &&
|
|
482
|
-
!commandOptions.skipModuleImport &&
|
|
483
|
-
result.statusCode === 200
|
|
484
|
-
) {
|
|
553
|
+
// Post-handling after creating a new project
|
|
554
|
+
if (!commandOptions.skipModuleImport && result.statusCode === 200) {
|
|
485
555
|
try {
|
|
486
556
|
// add default hub
|
|
487
557
|
await commandHandler.command(
|
|
@@ -528,25 +598,115 @@ program
|
|
|
528
598
|
},
|
|
529
599
|
);
|
|
530
600
|
|
|
531
|
-
//
|
|
532
|
-
|
|
533
|
-
.command('
|
|
534
|
-
.description('
|
|
535
|
-
.argument('<
|
|
536
|
-
.
|
|
537
|
-
.action(async (cardKey: string, options: CommandOptions<'edit'>) => {
|
|
601
|
+
// Create report subcommand
|
|
602
|
+
createCmd
|
|
603
|
+
.command('report')
|
|
604
|
+
.description('Create a new report')
|
|
605
|
+
.argument('<name>', `Name for report. ${nameGuideline}`)
|
|
606
|
+
.action(async (name: string, options: CommandOptions<'create'>) => {
|
|
538
607
|
const result = await commandHandler.command(
|
|
539
|
-
Cmd.
|
|
540
|
-
[
|
|
608
|
+
Cmd.create,
|
|
609
|
+
['report', name],
|
|
541
610
|
Object.assign({}, options, program.opts()),
|
|
542
611
|
);
|
|
543
612
|
handleResponse(result);
|
|
544
613
|
});
|
|
545
614
|
|
|
615
|
+
// Create template subcommand
|
|
616
|
+
createCmd
|
|
617
|
+
.command('template')
|
|
618
|
+
.description('Create a new template')
|
|
619
|
+
.argument('<name>', `Name for template. ${nameGuideline}`)
|
|
620
|
+
.argument(
|
|
621
|
+
'[content]',
|
|
622
|
+
'Template content. If empty, template is created with default values. Must conform to templateSchema.json',
|
|
623
|
+
)
|
|
624
|
+
.action(
|
|
625
|
+
async (
|
|
626
|
+
name: string,
|
|
627
|
+
content: string | undefined,
|
|
628
|
+
options: CommandOptions<'create'>,
|
|
629
|
+
) => {
|
|
630
|
+
const result = await commandHandler.command(
|
|
631
|
+
Cmd.create,
|
|
632
|
+
['template', name, content].filter(Boolean) as string[],
|
|
633
|
+
Object.assign({}, options, program.opts()),
|
|
634
|
+
);
|
|
635
|
+
handleResponse(result);
|
|
636
|
+
},
|
|
637
|
+
);
|
|
638
|
+
|
|
639
|
+
// Create workflow subcommand
|
|
640
|
+
createCmd
|
|
641
|
+
.command('workflow')
|
|
642
|
+
.description('Create a new workflow')
|
|
643
|
+
.argument('<name>', `Name for workflow. ${nameGuideline}`)
|
|
644
|
+
.argument(
|
|
645
|
+
'[content]',
|
|
646
|
+
'Workflow content. If empty, workflow is created with default values. Must conform to workflowSchema.json',
|
|
647
|
+
)
|
|
648
|
+
.action(
|
|
649
|
+
async (
|
|
650
|
+
name: string,
|
|
651
|
+
content: string | undefined,
|
|
652
|
+
options: CommandOptions<'create'>,
|
|
653
|
+
) => {
|
|
654
|
+
const result = await commandHandler.command(
|
|
655
|
+
Cmd.create,
|
|
656
|
+
['workflow', name, content].filter(Boolean) as string[],
|
|
657
|
+
Object.assign({}, options, program.opts()),
|
|
658
|
+
);
|
|
659
|
+
handleResponse(result);
|
|
660
|
+
},
|
|
661
|
+
);
|
|
662
|
+
|
|
663
|
+
// Create new resource subcommand
|
|
664
|
+
createCmd
|
|
665
|
+
.command('resource')
|
|
666
|
+
.description('Create a new resource')
|
|
667
|
+
.argument(
|
|
668
|
+
'<resourceName>',
|
|
669
|
+
'Resource name (e.g. <prefix>/<type>/<identifier>)',
|
|
670
|
+
)
|
|
671
|
+
.argument(
|
|
672
|
+
'[content]',
|
|
673
|
+
'Resource content. If empty, resource is created with default values. Must conform to its resource schema',
|
|
674
|
+
)
|
|
675
|
+
.action(
|
|
676
|
+
async (
|
|
677
|
+
resourceName: string,
|
|
678
|
+
content: string | undefined,
|
|
679
|
+
options: CommandOptions<'create'>,
|
|
680
|
+
) => {
|
|
681
|
+
const result = await commandHandler.command(
|
|
682
|
+
Cmd.create,
|
|
683
|
+
[resourceName, content].filter(Boolean) as string[],
|
|
684
|
+
Object.assign({}, options, program.opts()),
|
|
685
|
+
);
|
|
686
|
+
handleResponse(result);
|
|
687
|
+
},
|
|
688
|
+
);
|
|
689
|
+
|
|
690
|
+
// Edit command
|
|
691
|
+
const editCmd = new CommandWithPath('edit')
|
|
692
|
+
.description('Edit a card')
|
|
693
|
+
.argument('<cardKey>', 'Card key of card');
|
|
694
|
+
program.addCommand(editCmd);
|
|
695
|
+
editCmd.action(async (cardKey: string, options: CommandOptions<'edit'>) => {
|
|
696
|
+
const result = await commandHandler.command(
|
|
697
|
+
Cmd.edit,
|
|
698
|
+
[cardKey],
|
|
699
|
+
Object.assign({}, options, program.opts()),
|
|
700
|
+
);
|
|
701
|
+
handleResponse(result);
|
|
702
|
+
});
|
|
703
|
+
|
|
546
704
|
// Export command
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
705
|
+
const exportCmd = new CommandWithPath('export').description(
|
|
706
|
+
'Export a project or a card',
|
|
707
|
+
);
|
|
708
|
+
program.addCommand(exportCmd);
|
|
709
|
+
exportCmd
|
|
550
710
|
.addArgument(
|
|
551
711
|
new Argument('<format>', 'Export format').choices(
|
|
552
712
|
Object.values(ExportFormats),
|
|
@@ -557,7 +717,6 @@ program
|
|
|
557
717
|
'[cardKey]',
|
|
558
718
|
'Export a specific card by card key. If omitted, exports the whole site.',
|
|
559
719
|
)
|
|
560
|
-
.option('-p, --project-path [path]', `${pathGuideline}`)
|
|
561
720
|
.option(
|
|
562
721
|
'-r, --recursive',
|
|
563
722
|
'Export cards under the specified card recursively',
|
|
@@ -637,15 +796,14 @@ program
|
|
|
637
796
|
},
|
|
638
797
|
);
|
|
639
798
|
|
|
640
|
-
const fetchCmd =
|
|
641
|
-
.
|
|
642
|
-
|
|
643
|
-
|
|
799
|
+
const fetchCmd = new CommandWithPath('fetch').description(
|
|
800
|
+
'Retrieve external data to local file system.',
|
|
801
|
+
);
|
|
802
|
+
program.addCommand(fetchCmd);
|
|
644
803
|
|
|
645
804
|
fetchCmd
|
|
646
805
|
.command('hubs')
|
|
647
806
|
.description('Retrieves module lists from hubs')
|
|
648
|
-
.option('-p, --project-path [path]', `${pathGuideline}`)
|
|
649
807
|
.action(async (options: CommandOptions<'fetch'>) => {
|
|
650
808
|
const result = await commandHandler.command(
|
|
651
809
|
Cmd.fetch,
|
|
@@ -655,10 +813,10 @@ fetchCmd
|
|
|
655
813
|
handleResponse(result);
|
|
656
814
|
});
|
|
657
815
|
|
|
658
|
-
const importCmd =
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
816
|
+
const importCmd = new CommandWithPath('import').description(
|
|
817
|
+
'Import modules and data into the project',
|
|
818
|
+
);
|
|
819
|
+
program.addCommand(importCmd);
|
|
662
820
|
|
|
663
821
|
// Import module
|
|
664
822
|
importCmd
|
|
@@ -675,7 +833,6 @@ importCmd
|
|
|
675
833
|
'[useCredentials]',
|
|
676
834
|
'When using git URL uses credentials for cloning. Default: false',
|
|
677
835
|
)
|
|
678
|
-
.option('-p, --project-path [path]', `${pathGuideline}`)
|
|
679
836
|
.action(
|
|
680
837
|
async (
|
|
681
838
|
source: string,
|
|
@@ -763,9 +920,8 @@ importCmd
|
|
|
763
920
|
.argument('<csvFile>', 'File to import from')
|
|
764
921
|
.argument(
|
|
765
922
|
'[cardKey]',
|
|
766
|
-
'
|
|
923
|
+
'Parent card key. If defined, cards are created as children of this card',
|
|
767
924
|
)
|
|
768
|
-
.option('-p, --project-path [path]', `${pathGuideline}`)
|
|
769
925
|
.action(
|
|
770
926
|
async (
|
|
771
927
|
csvFile: string,
|
|
@@ -781,9 +937,80 @@ importCmd
|
|
|
781
937
|
},
|
|
782
938
|
);
|
|
783
939
|
|
|
784
|
-
//
|
|
940
|
+
// Migrate command
|
|
785
941
|
program
|
|
786
|
-
.command('
|
|
942
|
+
.command('migrate')
|
|
943
|
+
.description('Migrate project schema to a newer version.')
|
|
944
|
+
.argument(
|
|
945
|
+
'[version]',
|
|
946
|
+
'Target schema version. If not provided, migrates to the latest version. Can only migrate one version at a time when specified.',
|
|
947
|
+
)
|
|
948
|
+
.option('-p, --project-path [path]', `${pathGuideline}`)
|
|
949
|
+
.option(
|
|
950
|
+
'-b, --backup <directory>',
|
|
951
|
+
'Create a backup before migration in the specified directory. Directory must exist.',
|
|
952
|
+
)
|
|
953
|
+
.option(
|
|
954
|
+
'-t, --timeout <minutes>',
|
|
955
|
+
'Timeout for migration in minutes (default: 2 minutes)',
|
|
956
|
+
'2',
|
|
957
|
+
)
|
|
958
|
+
.action(async (version: string, options: CommandOptions<'migrate'>) => {
|
|
959
|
+
if (version) {
|
|
960
|
+
const versionNumber = parseInt(version);
|
|
961
|
+
if (isNaN(versionNumber)) {
|
|
962
|
+
console.error(`Error: migration version is not a number: '${version}'`);
|
|
963
|
+
process.exit(1);
|
|
964
|
+
}
|
|
965
|
+
if (versionNumber <= 0) {
|
|
966
|
+
console.error(
|
|
967
|
+
`Error: migration version must be above zero: '${version}'`,
|
|
968
|
+
);
|
|
969
|
+
process.exit(1);
|
|
970
|
+
}
|
|
971
|
+
if (options.backup) {
|
|
972
|
+
options.backup = resolve(options.backup.toString().trim());
|
|
973
|
+
if (!existsSync(options.backup)) {
|
|
974
|
+
console.error(
|
|
975
|
+
`Error: Backup directory does not exist: ${options.backup}`,
|
|
976
|
+
);
|
|
977
|
+
process.exit(1);
|
|
978
|
+
}
|
|
979
|
+
try {
|
|
980
|
+
await access(options.backup, constants.W_OK);
|
|
981
|
+
} catch {
|
|
982
|
+
console.error(
|
|
983
|
+
`Error: Cannot write to backup directory: ${options.backup}`,
|
|
984
|
+
);
|
|
985
|
+
process.exit(1);
|
|
986
|
+
}
|
|
987
|
+
if (!(await lstat(options.backup)).isDirectory()) {
|
|
988
|
+
console.error(`Error: Backup directory is a file: ${options.backup}`);
|
|
989
|
+
process.exit(1);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
if (options.timeout !== undefined) {
|
|
995
|
+
const timeoutMinutes = Number(options.timeout);
|
|
996
|
+
if (isNaN(timeoutMinutes) || timeoutMinutes <= 0) {
|
|
997
|
+
console.error(`Error: Timeout must be a positive number`);
|
|
998
|
+
process.exit(1);
|
|
999
|
+
}
|
|
1000
|
+
// Convert minutes to milliseconds
|
|
1001
|
+
options.timeout = timeoutMinutes * 60 * 1000;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
const result = await commandHandler.command(
|
|
1005
|
+
Cmd.migrate,
|
|
1006
|
+
[version],
|
|
1007
|
+
Object.assign({}, options, program.opts()),
|
|
1008
|
+
);
|
|
1009
|
+
handleResponse(result);
|
|
1010
|
+
});
|
|
1011
|
+
|
|
1012
|
+
// Move command
|
|
1013
|
+
const moveCmd = new CommandWithPath('move')
|
|
787
1014
|
.description(
|
|
788
1015
|
'Moves a card from root to under another card, from under another card to root, or from under a one card to another.',
|
|
789
1016
|
)
|
|
@@ -791,22 +1018,22 @@ program
|
|
|
791
1018
|
.argument(
|
|
792
1019
|
'[destination]',
|
|
793
1020
|
'Destination Card key where "source" is moved to. If moving to root, use "root"',
|
|
794
|
-
)
|
|
795
|
-
.option('-p, --project-path [path]', `${pathGuideline}`)
|
|
796
|
-
.action(
|
|
797
|
-
async (
|
|
798
|
-
source: string,
|
|
799
|
-
destination: string,
|
|
800
|
-
options: CommandOptions<'move'>,
|
|
801
|
-
) => {
|
|
802
|
-
const result = await commandHandler.command(
|
|
803
|
-
Cmd.move,
|
|
804
|
-
[source, destination],
|
|
805
|
-
Object.assign({}, options, program.opts()),
|
|
806
|
-
);
|
|
807
|
-
handleResponse(result);
|
|
808
|
-
},
|
|
809
1021
|
);
|
|
1022
|
+
program.addCommand(moveCmd);
|
|
1023
|
+
moveCmd.action(
|
|
1024
|
+
async (
|
|
1025
|
+
source: string,
|
|
1026
|
+
destination: string,
|
|
1027
|
+
options: CommandOptions<'move'>,
|
|
1028
|
+
) => {
|
|
1029
|
+
const result = await commandHandler.command(
|
|
1030
|
+
Cmd.move,
|
|
1031
|
+
[source, destination],
|
|
1032
|
+
Object.assign({}, options, program.opts()),
|
|
1033
|
+
);
|
|
1034
|
+
handleResponse(result);
|
|
1035
|
+
},
|
|
1036
|
+
);
|
|
810
1037
|
|
|
811
1038
|
program
|
|
812
1039
|
.command('preview')
|
|
@@ -819,10 +1046,10 @@ program
|
|
|
819
1046
|
await previewSite(dir || '.', true);
|
|
820
1047
|
});
|
|
821
1048
|
|
|
822
|
-
const rank =
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
1049
|
+
const rank = new CommandWithPath('rank').description(
|
|
1050
|
+
'Manage card ranking and ordering',
|
|
1051
|
+
);
|
|
1052
|
+
program.addCommand(rank);
|
|
826
1053
|
|
|
827
1054
|
rank
|
|
828
1055
|
.command('card')
|
|
@@ -834,7 +1061,6 @@ rank
|
|
|
834
1061
|
'<afterCardKey>',
|
|
835
1062
|
'Card key of the card that the card should be after. Use "first" to rank the card first.',
|
|
836
1063
|
)
|
|
837
|
-
.option('-p, --project-path [path]', `${pathGuideline}`)
|
|
838
1064
|
.action(
|
|
839
1065
|
async (
|
|
840
1066
|
cardKey: string,
|
|
@@ -857,9 +1083,8 @@ rank
|
|
|
857
1083
|
)
|
|
858
1084
|
.argument(
|
|
859
1085
|
'[parentCardKey]',
|
|
860
|
-
'if null, rebalance the whole project, otherwise rebalance only the direct children
|
|
1086
|
+
'if null, rebalance the whole project, otherwise rebalance only the direct children',
|
|
861
1087
|
)
|
|
862
|
-
.option('-p, --project-path [path]', `${pathGuideline}`)
|
|
863
1088
|
.action(async (cardKey: string, options: CommandOptions<'rank'>) => {
|
|
864
1089
|
const result = await commandHandler.command(
|
|
865
1090
|
Cmd.rank,
|
|
@@ -870,9 +1095,11 @@ rank
|
|
|
870
1095
|
});
|
|
871
1096
|
|
|
872
1097
|
// Remove command
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
1098
|
+
const removeCmd = new CommandWithPath('remove').description(
|
|
1099
|
+
'Remove cards, resources and other project items',
|
|
1100
|
+
);
|
|
1101
|
+
program.addCommand(removeCmd);
|
|
1102
|
+
removeCmd
|
|
876
1103
|
.argument(
|
|
877
1104
|
'<type>',
|
|
878
1105
|
`removable types: '${Parser.listTargets('remove').join("', '")}', or resource name (e.g. <prefix>/<type>/<identifier>)`,
|
|
@@ -891,7 +1118,6 @@ program
|
|
|
891
1118
|
'Depends on context; see below for specific remove operation',
|
|
892
1119
|
)
|
|
893
1120
|
.addHelpText('after', additionalHelpForRemove)
|
|
894
|
-
.option('-p, --project-path [path]', `${pathGuideline}`)
|
|
895
1121
|
.action(
|
|
896
1122
|
async (
|
|
897
1123
|
type: string,
|
|
@@ -942,25 +1168,23 @@ program
|
|
|
942
1168
|
);
|
|
943
1169
|
|
|
944
1170
|
// Rename command
|
|
945
|
-
|
|
946
|
-
.command('rename')
|
|
1171
|
+
const renameCmd = new CommandWithPath('rename')
|
|
947
1172
|
.description(
|
|
948
1173
|
'Change project prefix and rename all the content with the new prefix',
|
|
949
1174
|
)
|
|
950
|
-
.argument('<to>', 'New project prefix')
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1175
|
+
.argument('<to>', 'New project prefix');
|
|
1176
|
+
program.addCommand(renameCmd);
|
|
1177
|
+
renameCmd.action(async (to: string, options: CommandOptions<'rename'>) => {
|
|
1178
|
+
const result = await commandHandler.command(
|
|
1179
|
+
Cmd.rename,
|
|
1180
|
+
[to],
|
|
1181
|
+
Object.assign({}, options, program.opts()),
|
|
1182
|
+
);
|
|
1183
|
+
handleResponse(result);
|
|
1184
|
+
});
|
|
960
1185
|
|
|
961
1186
|
// Report command
|
|
962
|
-
|
|
963
|
-
.command('report')
|
|
1187
|
+
const reportCmd = new CommandWithPath('report')
|
|
964
1188
|
.description('Runs a report')
|
|
965
1189
|
.argument(
|
|
966
1190
|
'<parameters>',
|
|
@@ -970,27 +1194,29 @@ program
|
|
|
970
1194
|
'[output]',
|
|
971
1195
|
'Optional output file; if omitted output will be directed to stdout',
|
|
972
1196
|
)
|
|
973
|
-
.addOption(contextOption)
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
1197
|
+
.addOption(contextOption);
|
|
1198
|
+
program.addCommand(reportCmd);
|
|
1199
|
+
reportCmd.action(
|
|
1200
|
+
async (
|
|
1201
|
+
parameters: string,
|
|
1202
|
+
output: string,
|
|
1203
|
+
options: CommandOptions<'report'>,
|
|
1204
|
+
) => {
|
|
1205
|
+
const result = await commandHandler.command(
|
|
1206
|
+
Cmd.report,
|
|
1207
|
+
[parameters, output],
|
|
1208
|
+
Object.assign({}, options, program.opts()),
|
|
1209
|
+
);
|
|
1210
|
+
handleResponse(result);
|
|
1211
|
+
},
|
|
1212
|
+
);
|
|
989
1213
|
|
|
990
1214
|
// Show command
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
1215
|
+
const showCmd = new CommandWithPath('show').description(
|
|
1216
|
+
'Shows details from a project',
|
|
1217
|
+
);
|
|
1218
|
+
program.addCommand(showCmd);
|
|
1219
|
+
showCmd
|
|
994
1220
|
.argument(
|
|
995
1221
|
'<type>',
|
|
996
1222
|
`details can be seen from: ${Parser.listTargets('show').join(', ')}`,
|
|
@@ -1008,7 +1234,6 @@ program
|
|
|
1008
1234
|
'-a --showAll',
|
|
1009
1235
|
'Show all modules, irregardless if it has been imported or not. Only with "show importableModules"',
|
|
1010
1236
|
)
|
|
1011
|
-
.option('-p, --project-path [path]', `${pathGuideline}`)
|
|
1012
1237
|
.option(
|
|
1013
1238
|
'-u --show-use',
|
|
1014
1239
|
'Show where resource is used. Only used with resources, otherwise will be ignored.',
|
|
@@ -1035,34 +1260,35 @@ program
|
|
|
1035
1260
|
});
|
|
1036
1261
|
|
|
1037
1262
|
// Transition command
|
|
1038
|
-
|
|
1039
|
-
.command('transition')
|
|
1263
|
+
const transitionCmd = new CommandWithPath('transition')
|
|
1040
1264
|
.description('Transition a card to the specified state')
|
|
1041
1265
|
.argument('<cardKey>', 'card key of a card')
|
|
1042
1266
|
.argument(
|
|
1043
1267
|
'<transition>',
|
|
1044
1268
|
'Workflow state transition that is done.\nYou can list the workflows in a project with "show workflows" command.\nYou can see the available transitions with "show workflow <name>" command.',
|
|
1045
|
-
)
|
|
1046
|
-
.option('-p, --project-path [path]', `${pathGuideline}`)
|
|
1047
|
-
.action(
|
|
1048
|
-
async (
|
|
1049
|
-
cardKey: string,
|
|
1050
|
-
transition: string,
|
|
1051
|
-
options: CommandOptions<'transition'>,
|
|
1052
|
-
) => {
|
|
1053
|
-
const result = await commandHandler.command(
|
|
1054
|
-
Cmd.transition,
|
|
1055
|
-
[cardKey, transition],
|
|
1056
|
-
Object.assign({}, options, program.opts()),
|
|
1057
|
-
);
|
|
1058
|
-
handleResponse(result);
|
|
1059
|
-
},
|
|
1060
1269
|
);
|
|
1270
|
+
program.addCommand(transitionCmd);
|
|
1271
|
+
transitionCmd.action(
|
|
1272
|
+
async (
|
|
1273
|
+
cardKey: string,
|
|
1274
|
+
transition: string,
|
|
1275
|
+
options: CommandOptions<'transition'>,
|
|
1276
|
+
) => {
|
|
1277
|
+
const result = await commandHandler.command(
|
|
1278
|
+
Cmd.transition,
|
|
1279
|
+
[cardKey, transition],
|
|
1280
|
+
Object.assign({}, options, program.opts()),
|
|
1281
|
+
);
|
|
1282
|
+
handleResponse(result);
|
|
1283
|
+
},
|
|
1284
|
+
);
|
|
1061
1285
|
|
|
1062
1286
|
// Update command
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1287
|
+
const updateCmd = new CommandWithPath('update').description(
|
|
1288
|
+
'Update resource details',
|
|
1289
|
+
);
|
|
1290
|
+
program.addCommand(updateCmd);
|
|
1291
|
+
updateCmd
|
|
1066
1292
|
.argument('<resourceName>', 'Resource name')
|
|
1067
1293
|
.argument(
|
|
1068
1294
|
'<operation>',
|
|
@@ -1075,10 +1301,9 @@ program
|
|
|
1075
1301
|
'When using "change" define new value for detail.\nWhen using "remove" provide optional replacement value for removed value',
|
|
1076
1302
|
)
|
|
1077
1303
|
.option(
|
|
1078
|
-
'-m, --mapping-file
|
|
1304
|
+
'-m, --mapping-file <path>',
|
|
1079
1305
|
'Path to JSON file containing workflow state mapping (only used when changing workflow)',
|
|
1080
1306
|
)
|
|
1081
|
-
.option('-p, --project-path [path]', `${pathGuideline}`)
|
|
1082
1307
|
.addHelpText('after', additionalHelpForUpdate)
|
|
1083
1308
|
.action(
|
|
1084
1309
|
async (
|
|
@@ -1099,14 +1324,14 @@ program
|
|
|
1099
1324
|
);
|
|
1100
1325
|
|
|
1101
1326
|
// Updates all modules, or specific named module in the project.
|
|
1102
|
-
|
|
1103
|
-
.command('update-modules')
|
|
1327
|
+
const updateModulesCmd = new CommandWithPath('update-modules')
|
|
1104
1328
|
.description(
|
|
1105
1329
|
'Updates to latest versions either all modules or a specific module',
|
|
1106
1330
|
)
|
|
1107
|
-
.argument('[moduleName]', 'Module name')
|
|
1108
|
-
|
|
1109
|
-
|
|
1331
|
+
.argument('[moduleName]', 'Module name');
|
|
1332
|
+
program.addCommand(updateModulesCmd);
|
|
1333
|
+
updateModulesCmd.action(
|
|
1334
|
+
async (moduleName, options: CommandOptions<'updateModules'>) => {
|
|
1110
1335
|
const result = await commandHandler.command(
|
|
1111
1336
|
Cmd.updateModules,
|
|
1112
1337
|
[moduleName],
|
|
@@ -1114,66 +1339,66 @@ program
|
|
|
1114
1339
|
credentials(),
|
|
1115
1340
|
);
|
|
1116
1341
|
handleResponse(result);
|
|
1117
|
-
}
|
|
1342
|
+
},
|
|
1343
|
+
);
|
|
1118
1344
|
|
|
1119
1345
|
// Validate command
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1346
|
+
const validateCmd = new CommandWithPath('validate').description(
|
|
1347
|
+
'Validate project structure',
|
|
1348
|
+
);
|
|
1349
|
+
program.addCommand(validateCmd);
|
|
1350
|
+
validateCmd.action(async (options: CommandOptions<'validate'>) => {
|
|
1351
|
+
const result = await commandHandler.command(
|
|
1352
|
+
Cmd.validate,
|
|
1353
|
+
[],
|
|
1354
|
+
Object.assign({}, options, program.opts()),
|
|
1355
|
+
);
|
|
1356
|
+
handleResponse(result);
|
|
1357
|
+
});
|
|
1132
1358
|
|
|
1133
1359
|
// Start app command.
|
|
1134
1360
|
// If there are validation errors, user is prompted to continue or not.
|
|
1135
1361
|
// There is 10 sec timeout on the prompt. If user does not reply, then
|
|
1136
1362
|
// it is assumed that validation errors do not matter and application
|
|
1137
1363
|
// start is resumed.
|
|
1138
|
-
|
|
1139
|
-
.command('app')
|
|
1364
|
+
const appCmd = new CommandWithPath('app')
|
|
1140
1365
|
.description(
|
|
1141
1366
|
'Starts the cyberismo app, accessible with a web browser at http://localhost:3000',
|
|
1142
1367
|
)
|
|
1143
1368
|
.option(
|
|
1144
1369
|
'-w, --watch-resource-changes',
|
|
1145
1370
|
'Project watches changes in .cards folder resources',
|
|
1146
|
-
)
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1371
|
+
);
|
|
1372
|
+
program.addCommand(appCmd);
|
|
1373
|
+
appCmd.action(async (options: CommandOptions<'start'>) => {
|
|
1374
|
+
// validate project
|
|
1375
|
+
const result = await commandHandler.command(
|
|
1376
|
+
Cmd.validate,
|
|
1377
|
+
[],
|
|
1378
|
+
Object.assign({}, options, program.opts()),
|
|
1379
|
+
);
|
|
1380
|
+
if (!result.message) {
|
|
1381
|
+
program.error('Expected validation result, but got none');
|
|
1382
|
+
return;
|
|
1383
|
+
}
|
|
1384
|
+
if (result.message !== 'Project structure validated') {
|
|
1385
|
+
truncateMessage(result.message).forEach((item) => console.error(item));
|
|
1386
|
+
console.error('\n'); // The output looks nicer with one extra row.
|
|
1387
|
+
result.message = '';
|
|
1388
|
+
const userConfirmation = await confirm(
|
|
1389
|
+
{
|
|
1390
|
+
message: 'There are validation errors. Do you want to continue?',
|
|
1391
|
+
},
|
|
1392
|
+
{ signal: AbortSignal.timeout(10000), clearPromptOnDone: true },
|
|
1393
|
+
).catch((error) => {
|
|
1394
|
+
return error.name === 'AbortPromptError';
|
|
1395
|
+
});
|
|
1396
|
+
if (!userConfirmation) {
|
|
1397
|
+
handleResponse(result);
|
|
1157
1398
|
return;
|
|
1158
1399
|
}
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
result.message = '';
|
|
1163
|
-
const userConfirmation = await confirm(
|
|
1164
|
-
{
|
|
1165
|
-
message: 'There are validation errors. Do you want to continue?',
|
|
1166
|
-
},
|
|
1167
|
-
{ signal: AbortSignal.timeout(10000), clearPromptOnDone: true },
|
|
1168
|
-
).catch((error) => {
|
|
1169
|
-
return error.name === 'AbortPromptError';
|
|
1170
|
-
});
|
|
1171
|
-
if (!userConfirmation) {
|
|
1172
|
-
handleResponse(result);
|
|
1173
|
-
return;
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
await startServer(await commandHandler.getProjectPath(options.projectPath));
|
|
1177
|
-
});
|
|
1400
|
+
}
|
|
1401
|
+
await startServer(await commandHandler.getProjectPath(options.projectPath));
|
|
1402
|
+
});
|
|
1178
1403
|
|
|
1179
1404
|
export default program;
|