@apollo-annotation/cli 0.3.10 → 0.3.11

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 CHANGED
@@ -16,7 +16,7 @@ $ npm install -g @apollo-annotation/cli
16
16
  $ apollo COMMAND
17
17
  running command...
18
18
  $ apollo (--version)
19
- @apollo-annotation/cli/0.3.10 linux-x64 node-v24.11.1
19
+ @apollo-annotation/cli/0.3.11 linux-x64 node-v24.11.1
20
20
  $ apollo --help [COMMAND]
21
21
  USAGE
22
22
  $ apollo COMMAND
@@ -38,6 +38,7 @@ USAGE
38
38
  - [`apollo change get`](#apollo-change-get)
39
39
  - [`apollo config [KEY] [VALUE]`](#apollo-config-key-value)
40
40
  - [`apollo export gff3 ASSEMBLY`](#apollo-export-gff3-assembly)
41
+ - [`apollo feature add [FEATURE-JSON]`](#apollo-feature-add-feature-json)
41
42
  - [`apollo feature add-child`](#apollo-feature-add-child)
42
43
  - [`apollo feature check`](#apollo-feature-check)
43
44
  - [`apollo feature copy`](#apollo-feature-copy)
@@ -116,7 +117,7 @@ EXAMPLES
116
117
  ```
117
118
 
118
119
  _See code:
119
- [src/commands/assembly/add-from-fasta.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/assembly/add-from-fasta.ts)_
120
+ [src/commands/assembly/add-from-fasta.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/assembly/add-from-fasta.ts)_
120
121
 
121
122
  ## `apollo assembly add-from-gff INPUT-FILE`
122
123
 
@@ -152,7 +153,7 @@ EXAMPLES
152
153
  ```
153
154
 
154
155
  _See code:
155
- [src/commands/assembly/add-from-gff.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/assembly/add-from-gff.ts)_
156
+ [src/commands/assembly/add-from-gff.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/assembly/add-from-gff.ts)_
156
157
 
157
158
  ## `apollo assembly check`
158
159
 
@@ -194,7 +195,7 @@ EXAMPLES
194
195
  ```
195
196
 
196
197
  _See code:
197
- [src/commands/assembly/check.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/assembly/check.ts)_
198
+ [src/commands/assembly/check.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/assembly/check.ts)_
198
199
 
199
200
  ## `apollo assembly delete`
200
201
 
@@ -222,7 +223,7 @@ EXAMPLES
222
223
  ```
223
224
 
224
225
  _See code:
225
- [src/commands/assembly/delete.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/assembly/delete.ts)_
226
+ [src/commands/assembly/delete.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/assembly/delete.ts)_
226
227
 
227
228
  ## `apollo assembly get`
228
229
 
@@ -244,7 +245,7 @@ DESCRIPTION
244
245
  ```
245
246
 
246
247
  _See code:
247
- [src/commands/assembly/get.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/assembly/get.ts)_
248
+ [src/commands/assembly/get.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/assembly/get.ts)_
248
249
 
249
250
  ## `apollo assembly sequence`
250
251
 
@@ -279,7 +280,7 @@ EXAMPLES
279
280
  ```
280
281
 
281
282
  _See code:
282
- [src/commands/assembly/sequence.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/assembly/sequence.ts)_
283
+ [src/commands/assembly/sequence.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/assembly/sequence.ts)_
283
284
 
284
285
  ## `apollo change get`
285
286
 
@@ -303,7 +304,7 @@ DESCRIPTION
303
304
  ```
304
305
 
305
306
  _See code:
306
- [src/commands/change/get.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/change/get.ts)_
307
+ [src/commands/change/get.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/change/get.ts)_
307
308
 
308
309
  ## `apollo config [KEY] [VALUE]`
309
310
 
@@ -355,7 +356,7 @@ EXAMPLES
355
356
  ```
356
357
 
357
358
  _See code:
358
- [src/commands/config.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/config.ts)_
359
+ [src/commands/config.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/config.ts)_
359
360
 
360
361
  ## `apollo export gff3 ASSEMBLY`
361
362
 
@@ -383,7 +384,63 @@ EXAMPLES
383
384
  ```
384
385
 
385
386
  _See code:
386
- [src/commands/export/gff3.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/export/gff3.ts)_
387
+ [src/commands/export/gff3.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/export/gff3.ts)_
388
+
389
+ ## `apollo feature add [FEATURE-JSON]`
390
+
391
+ Add one or more features to Apollo
392
+
393
+ ```
394
+ USAGE
395
+ $ apollo feature add [FEATURE-JSON] [--profile <value>] [--config-file <value>] [-a <value>] [-r <value> -s
396
+ <value> -e <value> -t <value>] [-F <value>]
397
+
398
+ ARGUMENTS
399
+ FEATURE-JSON Inline JSON describing the feature(s) to add. Can also be provided via stdin.
400
+
401
+ FLAGS
402
+ -F, --feature-json-file=<value> File with JSON describing the feature(s) to add
403
+ -a, --assembly=<value> Name or ID of target assembly. Not required if refseq is unique in the database
404
+ -e, --max=<value> End position in target reference sequence
405
+ -r, --refSeq=<value> Name or ID of target reference sequence
406
+ -s, --min=<value> Start position in target reference sequence
407
+ -t, --type=<value> Type of child feature
408
+ --config-file=<value> Use this config file (mostly for testing)
409
+ --profile=<value> Use credentials from this profile
410
+
411
+ DESCRIPTION
412
+ Add one or more features to Apollo
413
+
414
+ A single simple feature can be added using the --min, --max, etc. flags.
415
+
416
+ To add multiple features, features with more details, or features with children, you can pass in JSON via argument or
417
+ stdin or use the --feature-json-file options.
418
+
419
+
420
+ EXAMPLES
421
+ Add a single feature by specifying its location and type
422
+
423
+ $ apollo feature add --assembly hg19 --refSeq chr3 --min 1000 --max 5000 --type remark
424
+
425
+ Add a single feature from inline JSON
426
+
427
+ $ apollo feature add \
428
+ '{"assembly":"<assemblyNameOrId>","refseq":"<refSeqNameOrId>","min":1,"max":100,"type":"<featureType>"}'
429
+
430
+ Add mutilple features from stdin JSON
431
+
432
+ echo '[{"assembly":"<assemblyNameOrId>","refseq":"<refSeqNameOrId>","min":1,"max":100,"type":"<featureType>"},{" \
433
+ assembly":"<assemblyNameOrId>","refseq":"<refSeqNameOrId>","min":101,"max":200,"type":"<featureType>"}]' | \
434
+ apollo feature add
435
+
436
+ Add a feature with children from inline JSON
437
+
438
+ $ apollo feature add '{"assembly":"<assemblyNameOrId>","refseq":"<refSeqNameOrId>","min":1,"max":100,"type":"<fe \
439
+ atureType>","children":[{"min":1,"max":50,"type":"<featureType>"}]}'
440
+ ```
441
+
442
+ _See code:
443
+ [src/commands/feature/add.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/feature/add.ts)_
387
444
 
388
445
  ## `apollo feature add-child`
389
446
 
@@ -414,7 +471,7 @@ EXAMPLES
414
471
  ```
415
472
 
416
473
  _See code:
417
- [src/commands/feature/add-child.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/feature/add-child.ts)_
474
+ [src/commands/feature/add-child.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/feature/add-child.ts)_
418
475
 
419
476
  ## `apollo feature check`
420
477
 
@@ -447,7 +504,7 @@ EXAMPLES
447
504
  ```
448
505
 
449
506
  _See code:
450
- [src/commands/feature/check.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/feature/check.ts)_
507
+ [src/commands/feature/check.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/feature/check.ts)_
451
508
 
452
509
  ## `apollo feature copy`
453
510
 
@@ -478,7 +535,7 @@ EXAMPLES
478
535
  ```
479
536
 
480
537
  _See code:
481
- [src/commands/feature/copy.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/feature/copy.ts)_
538
+ [src/commands/feature/copy.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/feature/copy.ts)_
482
539
 
483
540
  ## `apollo feature delete`
484
541
 
@@ -502,7 +559,7 @@ DESCRIPTION
502
559
  ```
503
560
 
504
561
  _See code:
505
- [src/commands/feature/delete.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/feature/delete.ts)_
562
+ [src/commands/feature/delete.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/feature/delete.ts)_
506
563
 
507
564
  ## `apollo feature edit`
508
565
 
@@ -544,7 +601,7 @@ EXAMPLES
544
601
  ```
545
602
 
546
603
  _See code:
547
- [src/commands/feature/edit.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/feature/edit.ts)_
604
+ [src/commands/feature/edit.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/feature/edit.ts)_
548
605
 
549
606
  ## `apollo feature edit-attribute`
550
607
 
@@ -584,7 +641,7 @@ EXAMPLES
584
641
  ```
585
642
 
586
643
  _See code:
587
- [src/commands/feature/edit-attribute.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/feature/edit-attribute.ts)_
644
+ [src/commands/feature/edit-attribute.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/feature/edit-attribute.ts)_
588
645
 
589
646
  ## `apollo feature edit-coords`
590
647
 
@@ -618,7 +675,7 @@ EXAMPLES
618
675
  ```
619
676
 
620
677
  _See code:
621
- [src/commands/feature/edit-coords.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/feature/edit-coords.ts)_
678
+ [src/commands/feature/edit-coords.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/feature/edit-coords.ts)_
622
679
 
623
680
  ## `apollo feature edit-type`
624
681
 
@@ -642,7 +699,7 @@ DESCRIPTION
642
699
  ```
643
700
 
644
701
  _See code:
645
- [src/commands/feature/edit-type.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/feature/edit-type.ts)_
702
+ [src/commands/feature/edit-type.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/feature/edit-type.ts)_
646
703
 
647
704
  ## `apollo feature get`
648
705
 
@@ -676,7 +733,7 @@ EXAMPLES
676
733
  ```
677
734
 
678
735
  _See code:
679
- [src/commands/feature/get.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/feature/get.ts)_
736
+ [src/commands/feature/get.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/feature/get.ts)_
680
737
 
681
738
  ## `apollo feature get-id`
682
739
 
@@ -704,7 +761,7 @@ EXAMPLES
704
761
  ```
705
762
 
706
763
  _See code:
707
- [src/commands/feature/get-id.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/feature/get-id.ts)_
764
+ [src/commands/feature/get-id.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/feature/get-id.ts)_
708
765
 
709
766
  ## `apollo feature get-indexed-id ID`
710
767
 
@@ -736,7 +793,7 @@ EXAMPLES
736
793
  ```
737
794
 
738
795
  _See code:
739
- [src/commands/feature/get-indexed-id.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/feature/get-indexed-id.ts)_
796
+ [src/commands/feature/get-indexed-id.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/feature/get-indexed-id.ts)_
740
797
 
741
798
  ## `apollo feature import INPUT-FILE`
742
799
 
@@ -767,7 +824,7 @@ EXAMPLES
767
824
  ```
768
825
 
769
826
  _See code:
770
- [src/commands/feature/import.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/feature/import.ts)_
827
+ [src/commands/feature/import.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/feature/import.ts)_
771
828
 
772
829
  ## `apollo feature search`
773
830
 
@@ -818,7 +875,7 @@ EXAMPLES
818
875
  ```
819
876
 
820
877
  _See code:
821
- [src/commands/feature/search.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/feature/search.ts)_
878
+ [src/commands/feature/search.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/feature/search.ts)_
822
879
 
823
880
  ## `apollo file delete`
824
881
 
@@ -845,7 +902,7 @@ EXAMPLES
845
902
  ```
846
903
 
847
904
  _See code:
848
- [src/commands/file/delete.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/file/delete.ts)_
905
+ [src/commands/file/delete.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/file/delete.ts)_
849
906
 
850
907
  ## `apollo file download`
851
908
 
@@ -873,7 +930,7 @@ EXAMPLES
873
930
  ```
874
931
 
875
932
  _See code:
876
- [src/commands/file/download.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/file/download.ts)_
933
+ [src/commands/file/download.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/file/download.ts)_
877
934
 
878
935
  ## `apollo file get`
879
936
 
@@ -900,7 +957,7 @@ EXAMPLES
900
957
  ```
901
958
 
902
959
  _See code:
903
- [src/commands/file/get.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/file/get.ts)_
960
+ [src/commands/file/get.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/file/get.ts)_
904
961
 
905
962
  ## `apollo file upload INPUT-FILE`
906
963
 
@@ -937,7 +994,7 @@ EXAMPLES
937
994
  ```
938
995
 
939
996
  _See code:
940
- [src/commands/file/upload.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/file/upload.ts)_
997
+ [src/commands/file/upload.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/file/upload.ts)_
941
998
 
942
999
  ## `apollo help [COMMANDS]`
943
1000
 
@@ -1003,7 +1060,7 @@ EXAMPLES
1003
1060
  ```
1004
1061
 
1005
1062
  _See code:
1006
- [src/commands/jbrowse/desktop.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/jbrowse/desktop.ts)_
1063
+ [src/commands/jbrowse/desktop.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/jbrowse/desktop.ts)_
1007
1064
 
1008
1065
  ## `apollo jbrowse get-config`
1009
1066
 
@@ -1029,7 +1086,7 @@ EXAMPLES
1029
1086
  ```
1030
1087
 
1031
1088
  _See code:
1032
- [src/commands/jbrowse/get-config.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/jbrowse/get-config.ts)_
1089
+ [src/commands/jbrowse/get-config.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/jbrowse/get-config.ts)_
1033
1090
 
1034
1091
  ## `apollo jbrowse set-config INPUTFILE`
1035
1092
 
@@ -1058,7 +1115,7 @@ EXAMPLES
1058
1115
  ```
1059
1116
 
1060
1117
  _See code:
1061
- [src/commands/jbrowse/set-config.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/jbrowse/set-config.ts)_
1118
+ [src/commands/jbrowse/set-config.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/jbrowse/set-config.ts)_
1062
1119
 
1063
1120
  ## `apollo login`
1064
1121
 
@@ -1097,7 +1154,7 @@ EXAMPLES
1097
1154
  ```
1098
1155
 
1099
1156
  _See code:
1100
- [src/commands/login.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/login.ts)_
1157
+ [src/commands/login.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/login.ts)_
1101
1158
 
1102
1159
  ## `apollo logout`
1103
1160
 
@@ -1127,7 +1184,7 @@ EXAMPLES
1127
1184
  ```
1128
1185
 
1129
1186
  _See code:
1130
- [src/commands/logout.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/logout.ts)_
1187
+ [src/commands/logout.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/logout.ts)_
1131
1188
 
1132
1189
  ## `apollo refseq add-alias INPUT-FILE`
1133
1190
 
@@ -1158,7 +1215,7 @@ EXAMPLES
1158
1215
  ```
1159
1216
 
1160
1217
  _See code:
1161
- [src/commands/refseq/add-alias.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/refseq/add-alias.ts)_
1218
+ [src/commands/refseq/add-alias.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/refseq/add-alias.ts)_
1162
1219
 
1163
1220
  ## `apollo refseq get`
1164
1221
 
@@ -1190,7 +1247,7 @@ EXAMPLES
1190
1247
  ```
1191
1248
 
1192
1249
  _See code:
1193
- [src/commands/refseq/get.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/refseq/get.ts)_
1250
+ [src/commands/refseq/get.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/refseq/get.ts)_
1194
1251
 
1195
1252
  ## `apollo status`
1196
1253
 
@@ -1212,7 +1269,7 @@ DESCRIPTION
1212
1269
  ```
1213
1270
 
1214
1271
  _See code:
1215
- [src/commands/status.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/status.ts)_
1272
+ [src/commands/status.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/status.ts)_
1216
1273
 
1217
1274
  ## `apollo user get`
1218
1275
 
@@ -1248,6 +1305,6 @@ EXAMPLES
1248
1305
  ```
1249
1306
 
1250
1307
  _See code:
1251
- [src/commands/user/get.ts](https://github.com/GMOD/Apollo3/blob/v0.3.10/packages/apollo-cli/src/commands/user/get.ts)_
1308
+ [src/commands/user/get.ts](https://github.com/GMOD/Apollo3/blob/v0.3.11/packages/apollo-cli/src/commands/user/get.ts)_
1252
1309
 
1253
1310
  <!-- commandsstop -->
@@ -0,0 +1,57 @@
1
+ import { type AnnotationFeatureSnapshot } from '@apollo-annotation/mst';
2
+ import { type SerializedAddFeatureChange } from '@apollo-annotation/shared';
3
+ import { type Response } from 'undici';
4
+ import { BaseCommand } from '../../baseCommand.js';
5
+ interface BaseFeatureJSON {
6
+ min: number;
7
+ max: number;
8
+ type: string;
9
+ children?: BaseFeatureJSON[];
10
+ [key: string]: unknown;
11
+ }
12
+ interface FeatureJSON extends BaseFeatureJSON {
13
+ assembly?: string;
14
+ refSeq: string;
15
+ }
16
+ export default class Add extends BaseCommand<typeof Add> {
17
+ static summary: string;
18
+ static description: string;
19
+ static examples: {
20
+ description: string;
21
+ command: string;
22
+ }[];
23
+ static flags: {
24
+ assembly: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
25
+ refSeq: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
26
+ min: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
27
+ max: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
28
+ type: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
29
+ 'feature-json-file': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
30
+ };
31
+ static args: {
32
+ 'feature-json': import("@oclif/core/lib/interfaces/parser.js").Arg<string | undefined, Record<string, unknown>>;
33
+ };
34
+ run(): Promise<void>;
35
+ addFeatureFromJSON(featureJSONString: string): Promise<void>;
36
+ makeFeatureSnapshot(details: FeatureJSON, ids: string[]): AnnotationFeatureSnapshot;
37
+ addFeatureFromFlags(refSeqNameOrId: string, min: number, max: number, type: string, assemblyNameOrId?: string): Promise<void>;
38
+ getAssemblyAndRefSeqIds(refSeqNameOrId: string, assemblyNameOrId?: string): Promise<[string, string]>;
39
+ getAssembly(assemblyNameOrId: string): Promise<{
40
+ _id: string;
41
+ name: string;
42
+ aliases?: string[];
43
+ }>;
44
+ getRefSeq(refSeqNameOrId: string, assemblyId?: string): Promise<{
45
+ _id: string;
46
+ name: string;
47
+ assembly: string;
48
+ aliases?: string[];
49
+ }>;
50
+ submitChange(change: SerializedAddFeatureChange): Promise<void>;
51
+ fetch(endpoint: string, options?: {
52
+ method?: string;
53
+ body?: string;
54
+ headers?: Record<string, string>;
55
+ }): Promise<Response>;
56
+ }
57
+ export {};
@@ -0,0 +1,323 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { Args, Flags } from '@oclif/core';
3
+ import { ObjectId } from 'bson';
4
+ import { fetch } from 'undici';
5
+ import { BaseCommand } from '../../baseCommand.js';
6
+ import { createFetchErrorMessage, localhostToAddress } from '../../utils.js';
7
+ export default class Add extends BaseCommand {
8
+ static summary = 'Add one or more features to Apollo';
9
+ static description = `A single simple feature can be added using the --min, --max, etc. flags.
10
+
11
+ To add multiple features, features with more details, or features with children, you can pass in JSON via argument or stdin or use the --feature-json-file options.
12
+ `;
13
+ static examples = [
14
+ {
15
+ description: 'Add a single feature by specifying its location and type',
16
+ command: '<%= config.bin %> <%= command.id %> --assembly hg19 --refSeq chr3 --min 1000 --max 5000 --type remark',
17
+ },
18
+ {
19
+ description: 'Add a single feature from inline JSON',
20
+ command: '<%= config.bin %> <%= command.id %> \'{"assembly":"<assemblyNameOrId>","refseq":"<refSeqNameOrId>","min":1,"max":100,"type":"<featureType>"}\'',
21
+ },
22
+ {
23
+ description: 'Add mutilple features from stdin JSON',
24
+ command: 'echo \'[{"assembly":"<assemblyNameOrId>","refseq":"<refSeqNameOrId>","min":1,"max":100,"type":"<featureType>"},{"assembly":"<assemblyNameOrId>","refseq":"<refSeqNameOrId>","min":101,"max":200,"type":"<featureType>"}]\' | <%= config.bin %> <%= command.id %>',
25
+ },
26
+ {
27
+ description: 'Add a feature with children from inline JSON',
28
+ command: '<%= config.bin %> <%= command.id %> \'{"assembly":"<assemblyNameOrId>","refseq":"<refSeqNameOrId>","min":1,"max":100,"type":"<featureType>","children":[{"min":1,"max":50,"type":"<featureType>"}]}\'',
29
+ },
30
+ ];
31
+ static flags = {
32
+ assembly: Flags.string({
33
+ char: 'a',
34
+ description: 'Name or ID of target assembly. Not required if refseq is unique in the database',
35
+ }),
36
+ refSeq: Flags.string({
37
+ char: 'r',
38
+ description: 'Name or ID of target reference sequence',
39
+ dependsOn: ['min', 'max', 'type'],
40
+ exclusive: ['feature-json-file'],
41
+ }),
42
+ min: Flags.integer({
43
+ char: 's',
44
+ description: 'Start position in target reference sequence',
45
+ dependsOn: ['refSeq', 'max', 'type'],
46
+ exclusive: ['feature-json-file'],
47
+ }),
48
+ max: Flags.integer({
49
+ char: 'e',
50
+ description: 'End position in target reference sequence',
51
+ dependsOn: ['refSeq', 'min', 'type'],
52
+ exclusive: ['feature-json-file'],
53
+ }),
54
+ type: Flags.string({
55
+ char: 't',
56
+ description: 'Type of child feature',
57
+ dependsOn: ['refSeq', 'min', 'max'],
58
+ exclusive: ['feature-json-file'],
59
+ }),
60
+ 'feature-json-file': Flags.file({
61
+ char: 'F',
62
+ description: 'File with JSON describing the feature(s) to add',
63
+ exists: true,
64
+ }),
65
+ };
66
+ static args = {
67
+ 'feature-json': Args.string({
68
+ description: 'Inline JSON describing the feature(s) to add. Can also be provided via stdin.',
69
+ }),
70
+ };
71
+ async run() {
72
+ const { args, flags } = this;
73
+ const { 'feature-json': featureJSONString } = args;
74
+ const { assembly, refSeq, min, max, type, 'feature-json-file': featureJSONFile, } = flags;
75
+ if (featureJSONString) {
76
+ if (assembly !== undefined ||
77
+ refSeq !== undefined ||
78
+ min !== undefined ||
79
+ max !== undefined ||
80
+ type !== undefined ||
81
+ featureJSONFile !== undefined) {
82
+ this.error('Cannot use the following flags when providing a feature JSON: --assembly, --refSeq, --min, --max, --type, --feature-json-file');
83
+ }
84
+ await this.addFeatureFromJSON(featureJSONString);
85
+ return;
86
+ }
87
+ if (featureJSONFile) {
88
+ const fileText = await readFile(featureJSONFile, 'utf8');
89
+ await this.addFeatureFromJSON(fileText);
90
+ return;
91
+ }
92
+ if (refSeq === undefined ||
93
+ min === undefined ||
94
+ max === undefined ||
95
+ type === undefined) {
96
+ this.error('Must provide all of: --refSeq, --min, --max, and --type');
97
+ }
98
+ await this.addFeatureFromFlags(refSeq, min, max, type, assembly);
99
+ }
100
+ async addFeatureFromJSON(featureJSONString) {
101
+ let featureJSON;
102
+ try {
103
+ featureJSON = parseFeatureJSON(featureJSONString);
104
+ }
105
+ catch (error) {
106
+ this.logToStderr('Error: feature JSON is not valid');
107
+ if (error instanceof Error || typeof error === 'string') {
108
+ this.error(error);
109
+ }
110
+ throw error;
111
+ }
112
+ if (Array.isArray(featureJSON)) {
113
+ const firstFeature = featureJSON.at(0);
114
+ if (!firstFeature) {
115
+ throw new Error('Feature array is empty');
116
+ }
117
+ const { assembly, refSeq } = firstFeature;
118
+ if (!featureJSON.every((feature) => feature.assembly === assembly)) {
119
+ throw new Error('Cannot add features to multiple assemblies at the same time');
120
+ }
121
+ const [assemblyId] = await this.getAssemblyAndRefSeqIds(refSeq, assembly);
122
+ const changedIds = [];
123
+ const changes = await Promise.all(featureJSON.map(async (singleFeatureJSON) => {
124
+ const { children, assembly, refSeq, ...rest } = singleFeatureJSON;
125
+ const refSeqDocument = await this.getRefSeq(refSeq);
126
+ return {
127
+ addedFeature: this.makeFeatureSnapshot({
128
+ assembly: assemblyId,
129
+ refSeq: refSeqDocument._id,
130
+ ...rest,
131
+ }, changedIds),
132
+ };
133
+ }));
134
+ const change = {
135
+ changedIds,
136
+ typeName: 'AddFeatureChange',
137
+ assembly: assemblyId,
138
+ changes,
139
+ };
140
+ return this.submitChange(change);
141
+ }
142
+ const { assembly, refSeq, ...rest } = featureJSON;
143
+ const [assemblyId, refSeqId] = await this.getAssemblyAndRefSeqIds(refSeq, assembly);
144
+ const changedIds = [];
145
+ const details = {
146
+ addedFeature: this.makeFeatureSnapshot({
147
+ assembly: assemblyId,
148
+ refSeq: refSeqId,
149
+ ...rest,
150
+ }, changedIds),
151
+ };
152
+ const change = {
153
+ changedIds,
154
+ typeName: 'AddFeatureChange',
155
+ assembly: assemblyId,
156
+ ...details,
157
+ };
158
+ return this.submitChange(change);
159
+ }
160
+ makeFeatureSnapshot(details, ids) {
161
+ const { children, ...rest } = details;
162
+ let childrenDetails = undefined;
163
+ if (children) {
164
+ childrenDetails = {};
165
+ const { refSeq } = rest;
166
+ for (const child of children) {
167
+ const childDetails = this.makeFeatureSnapshot({ refSeq, ...child }, ids);
168
+ childrenDetails[childDetails._id] = childDetails;
169
+ }
170
+ }
171
+ const _id = new ObjectId().toHexString();
172
+ ids.push(_id);
173
+ return {
174
+ _id,
175
+ ...rest,
176
+ ...(childrenDetails ? { children: childrenDetails } : {}),
177
+ };
178
+ }
179
+ async addFeatureFromFlags(refSeqNameOrId, min, max, type, assemblyNameOrId) {
180
+ const [assemblyId, refSeqId] = await this.getAssemblyAndRefSeqIds(refSeqNameOrId, assemblyNameOrId);
181
+ const changedIds = [];
182
+ const details = {
183
+ addedFeature: this.makeFeatureSnapshot({ refSeq: refSeqId, min: min - 1, max, type }, changedIds),
184
+ };
185
+ const change = {
186
+ changedIds,
187
+ typeName: 'AddFeatureChange',
188
+ assembly: assemblyId,
189
+ ...details,
190
+ };
191
+ return this.submitChange(change);
192
+ }
193
+ async getAssemblyAndRefSeqIds(refSeqNameOrId, assemblyNameOrId) {
194
+ const refSeqIsObjectId = ObjectId.isValid(refSeqNameOrId);
195
+ const assemblyIsObjectId = assemblyNameOrId
196
+ ? ObjectId.isValid(assemblyNameOrId)
197
+ : false;
198
+ if (assemblyNameOrId && assemblyIsObjectId && refSeqIsObjectId) {
199
+ return [assemblyNameOrId, refSeqNameOrId];
200
+ }
201
+ if (refSeqIsObjectId) {
202
+ if (assemblyNameOrId) {
203
+ this.warn('Ignoring provided --assembly because it is not an ID');
204
+ }
205
+ const refSeqDocument = await this.getRefSeq(refSeqNameOrId);
206
+ return [refSeqDocument.assembly, refSeqNameOrId];
207
+ }
208
+ if (!assemblyNameOrId) {
209
+ this.error(`If provided refSeq (${refSeqNameOrId}) is not an ID, assembly must also be provided`);
210
+ }
211
+ const assemblyDocument = await this.getAssembly(assemblyNameOrId);
212
+ const refSeqDocument = await this.getRefSeq(refSeqNameOrId, assemblyDocument._id);
213
+ return [assemblyDocument._id, refSeqDocument._id];
214
+ }
215
+ async getAssembly(assemblyNameOrId) {
216
+ if (ObjectId.isValid(assemblyNameOrId)) {
217
+ const response = await this.fetch(`assemblies/${assemblyNameOrId}`);
218
+ if (!response.ok) {
219
+ const errorMessage = await createFetchErrorMessage(response, `Could not find assembly: "${assemblyNameOrId}"`);
220
+ this.error(errorMessage);
221
+ }
222
+ return response.json();
223
+ }
224
+ const response = await this.fetch('assemblies');
225
+ if (!response.ok) {
226
+ const errorMessage = await createFetchErrorMessage(response, `Could not find assembly: "${assemblyNameOrId}"`);
227
+ this.error(errorMessage);
228
+ }
229
+ const assemblies = (await response.json());
230
+ for (const assembly of assemblies) {
231
+ if (assembly.name === assemblyNameOrId ||
232
+ assembly.aliases?.includes(assemblyNameOrId)) {
233
+ return assembly;
234
+ }
235
+ }
236
+ throw new Error(`Could not find assembly: "${assemblyNameOrId}"`);
237
+ }
238
+ async getRefSeq(refSeqNameOrId, assemblyId) {
239
+ if (ObjectId.isValid(refSeqNameOrId)) {
240
+ const response = await this.fetch(`refSeqs/${refSeqNameOrId}`);
241
+ if (!response.ok) {
242
+ const errorMessage = await createFetchErrorMessage(response, `Could not find refSeq: "${refSeqNameOrId}"`);
243
+ this.error(errorMessage);
244
+ }
245
+ return response.json();
246
+ }
247
+ let endpoint = 'refSeqs';
248
+ if (assemblyId) {
249
+ const searchParams = new URLSearchParams({ assembly: assemblyId });
250
+ endpoint = `${endpoint}?${searchParams.toString()}`;
251
+ }
252
+ const response = await this.fetch(endpoint);
253
+ if (!response.ok) {
254
+ const errorMessage = await createFetchErrorMessage(response, `Could not find refSeq: "${refSeqNameOrId}"`);
255
+ this.error(errorMessage);
256
+ }
257
+ const refSeqs = (await response.json());
258
+ for (const refSeq of refSeqs) {
259
+ if (refSeq.name === refSeqNameOrId ||
260
+ refSeq.aliases?.includes(refSeqNameOrId)) {
261
+ return refSeq;
262
+ }
263
+ }
264
+ throw new Error(`Could not find refSeq: "${refSeqNameOrId}"`);
265
+ }
266
+ async submitChange(change) {
267
+ const options = { method: 'POST', body: JSON.stringify(change) };
268
+ const response = await this.fetch('changes', options);
269
+ if (!response.ok) {
270
+ const errorMessage = await createFetchErrorMessage(response, 'Could not add feature');
271
+ this.error(errorMessage);
272
+ }
273
+ this.log(await response.text());
274
+ }
275
+ async fetch(endpoint, options) {
276
+ const { address, accessToken } = await this.getAccess();
277
+ const url = new URL(localhostToAddress(`${address}/${endpoint}`));
278
+ const optionsWithAuth = {
279
+ ...options,
280
+ headers: {
281
+ authorization: `Bearer ${accessToken}`,
282
+ 'Content-Type': 'application/json',
283
+ ...options?.headers,
284
+ },
285
+ };
286
+ return fetch(url, optionsWithAuth);
287
+ }
288
+ }
289
+ function parseFeatureJSON(featureJSONString) {
290
+ const featureJSON = JSON.parse(featureJSONString);
291
+ if (Array.isArray(featureJSON)) {
292
+ return featureJSON.map((feature) => {
293
+ assertFeatureIsValid(feature, true);
294
+ return feature;
295
+ });
296
+ }
297
+ assertFeatureIsValid(featureJSON, true);
298
+ return featureJSON;
299
+ }
300
+ function assertFeatureIsValid(feature, topLevel = false) {
301
+ if (typeof feature !== 'object' ||
302
+ feature === null ||
303
+ Array.isArray(feature)) {
304
+ throw new TypeError(`Feature is not a key-value record: '${JSON.stringify(feature)}'`);
305
+ }
306
+ for (const attribute of ['min', 'max', 'type']) {
307
+ if (!(attribute in feature)) {
308
+ throw new Error(`Feature does not contain "${attribute}": '${JSON.stringify(feature)}'`);
309
+ }
310
+ }
311
+ if (topLevel && !('refSeq' in feature)) {
312
+ throw new Error(`Top-level feature does not contain "refSeq": '${JSON.stringify(feature)}'`);
313
+ }
314
+ if ('children' in feature) {
315
+ const { children } = feature;
316
+ if (!Array.isArray(children)) {
317
+ throw new TypeError(`"children" is not an array of features '${JSON.stringify(feature)}'`);
318
+ }
319
+ for (const child of children) {
320
+ assertFeatureIsValid(child);
321
+ }
322
+ }
323
+ }
package/dist/test/test.js CHANGED
@@ -554,6 +554,75 @@ void describe('Test CLI', () => {
554
554
  out = JSON.parse(p.stdout);
555
555
  assert.strictEqual(out.length, 1);
556
556
  assert.ok(out.at(0)?.type === 'gene');
557
+ // Gets feature and child feature that were added manually (not imported)
558
+ p = new Shell(`${apollo} feature add ${P} <<EOF
559
+ {
560
+ "assembly": "vv1",
561
+ "refSeq": "ctgA",
562
+ "min": 301,
563
+ "max": 310,
564
+ "type": "match",
565
+ "attributes": {"gff_id": ["match1"]},
566
+ "children": [
567
+ {
568
+ "min": 301,
569
+ "max": 305,
570
+ "type": "match_part",
571
+ "attributes": {"gff_id": ["matchPart1"]}
572
+ }
573
+ ]
574
+ }
575
+ EOF`);
576
+ p = new Shell(`${apollo} feature get-indexed-id ${P} match1 -a vv1`);
577
+ out = JSON.parse(p.stdout);
578
+ assert.strictEqual(out.length, 1);
579
+ assert.ok(p.stdout.includes('match1'));
580
+ p = new Shell(`${apollo} feature get-indexed-id ${P} matchPart1 -a vv1`);
581
+ out = JSON.parse(p.stdout);
582
+ assert.strictEqual(out.length, 1);
583
+ assert.ok(p.stdout.includes('matchPart1'));
584
+ // Doesn't get child feature after it was deleted
585
+ const idToDelete = out[0]._id;
586
+ new Shell(`${apollo} feature delete ${P} -i ${idToDelete}`);
587
+ p = new Shell(`${apollo} feature get-indexed-id ${P} matchPart1 -a vv1`);
588
+ assert.deepStrictEqual(p.stdout.trim(), '[]');
589
+ // Gets feature after ID was manually added
590
+ p = new Shell(`${apollo} feature add ${P} <<EOF
591
+ {
592
+ "assembly": "vv1",
593
+ "refSeq": "ctgA",
594
+ "min": 311,
595
+ "max": 320,
596
+ "type": "match"
597
+ }
598
+ EOF`);
599
+ out = JSON.parse(p.stdout);
600
+ const { assembly, changes } = out;
601
+ const { _id, refSeq } = changes[0].addedFeature;
602
+ new Shell(`${apollo} feature edit-attribute ${P} -i ${_id} -a gff_id -v match2`);
603
+ p = new Shell(`${apollo} feature get-indexed-id ${P} match2 -a vv1`);
604
+ out = JSON.parse(p.stdout);
605
+ assert.strictEqual(out.length, 1);
606
+ assert.ok(p.stdout.includes('match2'));
607
+ // Gets child featuer after it was added with an ID
608
+ // add-child CLI command doesn't support adding attributes yet, so we'll
609
+ // manually do it with curl for testing for neow
610
+ p = new Shell(`${apollo} config ${P} accessToken`);
611
+ const token = p.stdout.trim();
612
+ const newChildFeatureID = '69408088d502fc21aea1bb0a';
613
+ new Shell(`curl -X POST http://127.0.0.1:3999/changes -d '{"typeName":"AddFeatureChange","changedIds":["${newChildFeatureID}"],"assembly":"${assembly}","addedFeature":{"_id":"${newChildFeatureID}","refSeq":"${refSeq}","min":311,"max":315,"type":"match_part","attributes":{"gff_id":["matchPart2"]}},"parentFeatureId":"${_id}"}' -H "Content-Type: application/json" -H "Authorization: Bearer ${token}"`);
614
+ p = new Shell(`${apollo} feature get-indexed-id ${P} matchPart2 -a vv1`);
615
+ out = JSON.parse(p.stdout);
616
+ assert.strictEqual(out.length, 1);
617
+ assert.ok(p.stdout.includes('matchPart2'));
618
+ // Doesn't get feature or child after IDs were manually removed
619
+ new Shell(`${apollo} feature edit-attribute ${P} -i ${_id} -a gff_id -d`);
620
+ const childId = out[0]._id;
621
+ new Shell(`${apollo} feature edit-attribute ${P} -i ${childId} -a gff_id -d`);
622
+ p = new Shell(`${apollo} feature get-indexed-id ${P} match2 -a vv1`);
623
+ assert.deepStrictEqual(p.stdout.trim(), '[]');
624
+ p = new Shell(`${apollo} feature get-indexed-id ${P} matchPart2 -a vv1`);
625
+ assert.deepStrictEqual(p.stdout.trim(), '[]');
557
626
  });
558
627
  void globalThis.itName('Delete features', () => {
559
628
  new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a vv1 -f`);
@@ -570,6 +639,75 @@ void describe('Test CLI', () => {
570
639
  p = new Shell(`${apollo} feature delete ${P} --force -i ${fid}`);
571
640
  assert.strictEqual(p.returncode, 0);
572
641
  });
642
+ void globalThis.itName('Add features', () => {
643
+ let p = new Shell(`${apollo} assembly add-from-fasta ${P} test_data/tiny.fasta.gz -a tiny -f`);
644
+ let out = JSON.parse(p.stdout);
645
+ const assemblyId = out._id;
646
+ p = new Shell(`${apollo} feature get ${P} -a tiny`);
647
+ assert.deepStrictEqual(p.stdout.trim(), '[]');
648
+ // Can add a feature using flags
649
+ p = new Shell(`${apollo} feature add ${P} -a tiny -r ctgA -s 1 -e 10 -t remark`);
650
+ out = JSON.parse(p.stdout);
651
+ p = new Shell(`${apollo} feature get ${P} -a tiny`);
652
+ out = JSON.parse(p.stdout);
653
+ assert.strictEqual(out.length, 1);
654
+ const refSeqId = out[0].refSeq;
655
+ // Can add a feature using assembly and refSeq ids
656
+ p = new Shell(`${apollo} feature add ${P} -a ${assemblyId} -r ${refSeqId} -s 11 -e 20 -t remark`);
657
+ p = new Shell(`${apollo} feature get ${P} -a ${assemblyId}`);
658
+ out = JSON.parse(p.stdout);
659
+ assert.strictEqual(out.length, 2);
660
+ // Can add a feature using JSON arg
661
+ p = new Shell(`${apollo} feature add ${P} '{"assembly":"${assemblyId}","refSeq":"${refSeqId}","min":21,"max":30,"type":"remark"}'`);
662
+ p = new Shell(`${apollo} feature get ${P} -a ${assemblyId}`);
663
+ out = JSON.parse(p.stdout);
664
+ assert.strictEqual(out.length, 3);
665
+ // Can add a feature using JSON from stdin
666
+ p = new Shell(`${apollo} feature add ${P} <<EOF
667
+ {
668
+ "assembly": "${assemblyId}",
669
+ "refSeq": "${refSeqId}",
670
+ "min": 31,
671
+ "max": 40,
672
+ "type": "remark"
673
+ }
674
+ EOF`);
675
+ p = new Shell(`${apollo} feature get ${P} -a ${assemblyId}`);
676
+ out = JSON.parse(p.stdout);
677
+ assert.strictEqual(out.length, 4);
678
+ // Can add a feature using JSON from a file
679
+ fs.writeFileSync('test_data/tmp.json', `{"assembly":"${assemblyId}","refSeq":"${refSeqId}","min":41,"max":50,"type":"remark"}\n`);
680
+ p = new Shell(`${apollo} feature add ${P} --feature-json-file test_data/tmp.json`);
681
+ fs.unlinkSync('test_data/tmp.json');
682
+ p = new Shell(`${apollo} feature get ${P} -a ${assemblyId}`);
683
+ out = JSON.parse(p.stdout);
684
+ assert.strictEqual(out.length, 5);
685
+ // Can add multiple features using JSON
686
+ p = new Shell(`${apollo} feature add ${P} '[{"assembly":"${assemblyId}","refSeq":"${refSeqId}","min":51,"max":60,"type":"remark"},{"assembly":"${assemblyId}","refSeq":"${refSeqId}","min":61,"max":70,"type":"remark"}]'`);
687
+ p = new Shell(`${apollo} feature get ${P} -a ${assemblyId}`);
688
+ out = JSON.parse(p.stdout);
689
+ assert.strictEqual(out.length, 7);
690
+ // Can add a feature with children from JSON
691
+ p = new Shell(`${apollo} feature add ${P} '{"assembly":"${assemblyId}","refSeq":"${refSeqId}","min":71,"max":80,"type":"match","children":[{"min":71,"max":75,"type":"match_part"}]}'`);
692
+ p = new Shell(`${apollo} feature get ${P} -a ${assemblyId} -r ${refSeqId} -s 71 -e 80`);
693
+ out = JSON.parse(p.stdout);
694
+ let feature = out.at(0);
695
+ assert.strictEqual(Object.keys(feature?.children).length, 1);
696
+ // Can add a feature with attributes from JSON
697
+ p = new Shell(`${apollo} feature add ${P} '{"assembly":"${assemblyId}","refSeq":"${refSeqId}","min":81,"max":90,"type":"remark","attributes":{"key1":["val1"]}}'`);
698
+ p = new Shell(`${apollo} feature get ${P} -a ${assemblyId} -r ${refSeqId} -s 81 -e 90`);
699
+ out = JSON.parse(p.stdout);
700
+ feature = out.at(0);
701
+ assert.strictEqual(feature?.attributes?.key1?.[0], 'val1');
702
+ // Can add a feature with children from JSON
703
+ p = new Shell(`${apollo} feature add ${P} '{"assembly":"${assemblyId}","refSeq":"${refSeqId}","min":91,"max":100,"type":"match","children":[{"min":91,"max":95,"type":"match_part","attributes":{"key2":["val2"]}}]}'`);
704
+ p = new Shell(`${apollo} feature get ${P} -a ${assemblyId} -r ${refSeqId} -s 91 -e 100`);
705
+ out = JSON.parse(p.stdout);
706
+ feature = out.at(0);
707
+ const keys = Object.keys(feature?.children);
708
+ assert.strictEqual(keys.length, 1);
709
+ assert.strictEqual(feature.children[keys[0]].attributes.key2[0], 'val2');
710
+ });
573
711
  void globalThis.itName('Add child features', () => {
574
712
  new Shell(`${apollo} assembly add-from-gff ${P} test_data/tiny.fasta.gff3 -a vv1 -f`);
575
713
  let p = new Shell(`${apollo} feature search ${P} -a vv1 -t contig`);
@@ -684,6 +684,51 @@
684
684
  "sequence.js"
685
685
  ]
686
686
  },
687
+ "change:get": {
688
+ "aliases": [],
689
+ "args": {},
690
+ "description": "Return the change log in json format. Note that when an assembly is deleted the link between common name and ID is lost (it can still be recovered by inspecting the change log but at present this task is left to the user). In such cases you need to use the assembly ID.",
691
+ "flags": {
692
+ "profile": {
693
+ "description": "Use credentials from this profile",
694
+ "name": "profile",
695
+ "hasDynamicHelp": false,
696
+ "multiple": false,
697
+ "type": "option"
698
+ },
699
+ "config-file": {
700
+ "description": "Use this config file (mostly for testing)",
701
+ "name": "config-file",
702
+ "hasDynamicHelp": false,
703
+ "multiple": false,
704
+ "type": "option"
705
+ },
706
+ "assembly": {
707
+ "char": "a",
708
+ "description": "Get changes only for these assembly names or IDs (but see description)",
709
+ "name": "assembly",
710
+ "hasDynamicHelp": false,
711
+ "multiple": true,
712
+ "type": "option"
713
+ }
714
+ },
715
+ "hasDynamicHelp": false,
716
+ "hiddenAliases": [],
717
+ "id": "change:get",
718
+ "pluginAlias": "@apollo-annotation/cli",
719
+ "pluginName": "@apollo-annotation/cli",
720
+ "pluginType": "core",
721
+ "strict": true,
722
+ "summary": "Get list of changes",
723
+ "enableJsonFlag": false,
724
+ "isESM": true,
725
+ "relativePath": [
726
+ "dist",
727
+ "commands",
728
+ "change",
729
+ "get.js"
730
+ ]
731
+ },
687
732
  "export:gff3": {
688
733
  "aliases": [],
689
734
  "args": {
@@ -738,10 +783,16 @@
738
783
  "gff3.js"
739
784
  ]
740
785
  },
741
- "change:get": {
786
+ "feature:add-child": {
742
787
  "aliases": [],
743
788
  "args": {},
744
- "description": "Return the change log in json format. Note that when an assembly is deleted the link between common name and ID is lost (it can still be recovered by inspecting the change log but at present this task is left to the user). In such cases you need to use the assembly ID.",
789
+ "description": "See the other commands under `apollo feature` to retrive the parent ID of interest and to populate the child feature with attributes.",
790
+ "examples": [
791
+ {
792
+ "description": "Add an exon at genomic coordinates 10..20 to this feature ID:",
793
+ "command": "<%= config.bin %> <%= command.id %> -i 660...73f -t exon -s 10 -e 20"
794
+ }
795
+ ],
745
796
  "flags": {
746
797
  "profile": {
747
798
  "description": "Use credentials from this profile",
@@ -757,40 +808,85 @@
757
808
  "multiple": false,
758
809
  "type": "option"
759
810
  },
760
- "assembly": {
761
- "char": "a",
762
- "description": "Get changes only for these assembly names or IDs (but see description)",
763
- "name": "assembly",
811
+ "feature-id": {
812
+ "char": "i",
813
+ "description": "Add a child to this feature ID; use - to read it from stdin",
814
+ "name": "feature-id",
815
+ "default": "-",
764
816
  "hasDynamicHelp": false,
765
- "multiple": true,
817
+ "multiple": false,
818
+ "type": "option"
819
+ },
820
+ "start": {
821
+ "char": "s",
822
+ "description": "Start coordinate of the child feature (1-based)",
823
+ "name": "start",
824
+ "required": true,
825
+ "hasDynamicHelp": false,
826
+ "multiple": false,
827
+ "type": "option"
828
+ },
829
+ "end": {
830
+ "char": "e",
831
+ "description": "End coordinate of the child feature (1-based)",
832
+ "name": "end",
833
+ "required": true,
834
+ "hasDynamicHelp": false,
835
+ "multiple": false,
836
+ "type": "option"
837
+ },
838
+ "type": {
839
+ "char": "t",
840
+ "description": "Type of child feature",
841
+ "name": "type",
842
+ "required": true,
843
+ "hasDynamicHelp": false,
844
+ "multiple": false,
766
845
  "type": "option"
767
846
  }
768
847
  },
769
848
  "hasDynamicHelp": false,
770
849
  "hiddenAliases": [],
771
- "id": "change:get",
850
+ "id": "feature:add-child",
772
851
  "pluginAlias": "@apollo-annotation/cli",
773
852
  "pluginName": "@apollo-annotation/cli",
774
853
  "pluginType": "core",
775
854
  "strict": true,
776
- "summary": "Get list of changes",
855
+ "summary": "Add a child feature (e.g. add an exon to an mRNA)",
777
856
  "enableJsonFlag": false,
778
857
  "isESM": true,
779
858
  "relativePath": [
780
859
  "dist",
781
860
  "commands",
782
- "change",
783
- "get.js"
861
+ "feature",
862
+ "add-child.js"
784
863
  ]
785
864
  },
786
- "feature:add-child": {
865
+ "feature:add": {
787
866
  "aliases": [],
788
- "args": {},
789
- "description": "See the other commands under `apollo feature` to retrive the parent ID of interest and to populate the child feature with attributes.",
867
+ "args": {
868
+ "feature-json": {
869
+ "description": "Inline JSON describing the feature(s) to add. Can also be provided via stdin.",
870
+ "name": "feature-json"
871
+ }
872
+ },
873
+ "description": "A single simple feature can be added using the --min, --max, etc. flags.\n\nTo add multiple features, features with more details, or features with children, you can pass in JSON via argument or stdin or use the --feature-json-file options.\n",
790
874
  "examples": [
791
875
  {
792
- "description": "Add an exon at genomic coordinates 10..20 to this feature ID:",
793
- "command": "<%= config.bin %> <%= command.id %> -i 660...73f -t exon -s 10 -e 20"
876
+ "description": "Add a single feature by specifying its location and type",
877
+ "command": "<%= config.bin %> <%= command.id %> --assembly hg19 --refSeq chr3 --min 1000 --max 5000 --type remark"
878
+ },
879
+ {
880
+ "description": "Add a single feature from inline JSON",
881
+ "command": "<%= config.bin %> <%= command.id %> '{\"assembly\":\"<assemblyNameOrId>\",\"refseq\":\"<refSeqNameOrId>\",\"min\":1,\"max\":100,\"type\":\"<featureType>\"}'"
882
+ },
883
+ {
884
+ "description": "Add mutilple features from stdin JSON",
885
+ "command": "echo '[{\"assembly\":\"<assemblyNameOrId>\",\"refseq\":\"<refSeqNameOrId>\",\"min\":1,\"max\":100,\"type\":\"<featureType>\"},{\"assembly\":\"<assemblyNameOrId>\",\"refseq\":\"<refSeqNameOrId>\",\"min\":101,\"max\":200,\"type\":\"<featureType>\"}]' | <%= config.bin %> <%= command.id %>"
886
+ },
887
+ {
888
+ "description": "Add a feature with children from inline JSON",
889
+ "command": "<%= config.bin %> <%= command.id %> '{\"assembly\":\"<assemblyNameOrId>\",\"refseq\":\"<refSeqNameOrId>\",\"min\":1,\"max\":100,\"type\":\"<featureType>\",\"children\":[{\"min\":1,\"max\":50,\"type\":\"<featureType>\"}]}'"
794
890
  }
795
891
  ],
796
892
  "flags": {
@@ -808,38 +904,82 @@
808
904
  "multiple": false,
809
905
  "type": "option"
810
906
  },
811
- "feature-id": {
812
- "char": "i",
813
- "description": "Add a child to this feature ID; use - to read it from stdin",
814
- "name": "feature-id",
815
- "default": "-",
907
+ "assembly": {
908
+ "char": "a",
909
+ "description": "Name or ID of target assembly. Not required if refseq is unique in the database",
910
+ "name": "assembly",
816
911
  "hasDynamicHelp": false,
817
912
  "multiple": false,
818
913
  "type": "option"
819
914
  },
820
- "start": {
915
+ "refSeq": {
916
+ "char": "r",
917
+ "dependsOn": [
918
+ "min",
919
+ "max",
920
+ "type"
921
+ ],
922
+ "description": "Name or ID of target reference sequence",
923
+ "exclusive": [
924
+ "feature-json-file"
925
+ ],
926
+ "name": "refSeq",
927
+ "hasDynamicHelp": false,
928
+ "multiple": false,
929
+ "type": "option"
930
+ },
931
+ "min": {
821
932
  "char": "s",
822
- "description": "Start coordinate of the child feature (1-based)",
823
- "name": "start",
824
- "required": true,
933
+ "dependsOn": [
934
+ "refSeq",
935
+ "max",
936
+ "type"
937
+ ],
938
+ "description": "Start position in target reference sequence",
939
+ "exclusive": [
940
+ "feature-json-file"
941
+ ],
942
+ "name": "min",
825
943
  "hasDynamicHelp": false,
826
944
  "multiple": false,
827
945
  "type": "option"
828
946
  },
829
- "end": {
947
+ "max": {
830
948
  "char": "e",
831
- "description": "End coordinate of the child feature (1-based)",
832
- "name": "end",
833
- "required": true,
949
+ "dependsOn": [
950
+ "refSeq",
951
+ "min",
952
+ "type"
953
+ ],
954
+ "description": "End position in target reference sequence",
955
+ "exclusive": [
956
+ "feature-json-file"
957
+ ],
958
+ "name": "max",
834
959
  "hasDynamicHelp": false,
835
960
  "multiple": false,
836
961
  "type": "option"
837
962
  },
838
963
  "type": {
839
964
  "char": "t",
965
+ "dependsOn": [
966
+ "refSeq",
967
+ "min",
968
+ "max"
969
+ ],
840
970
  "description": "Type of child feature",
971
+ "exclusive": [
972
+ "feature-json-file"
973
+ ],
841
974
  "name": "type",
842
- "required": true,
975
+ "hasDynamicHelp": false,
976
+ "multiple": false,
977
+ "type": "option"
978
+ },
979
+ "feature-json-file": {
980
+ "char": "F",
981
+ "description": "File with JSON describing the feature(s) to add",
982
+ "name": "feature-json-file",
843
983
  "hasDynamicHelp": false,
844
984
  "multiple": false,
845
985
  "type": "option"
@@ -847,19 +987,19 @@
847
987
  },
848
988
  "hasDynamicHelp": false,
849
989
  "hiddenAliases": [],
850
- "id": "feature:add-child",
990
+ "id": "feature:add",
851
991
  "pluginAlias": "@apollo-annotation/cli",
852
992
  "pluginName": "@apollo-annotation/cli",
853
993
  "pluginType": "core",
854
994
  "strict": true,
855
- "summary": "Add a child feature (e.g. add an exon to an mRNA)",
995
+ "summary": "Add one or more features to Apollo",
856
996
  "enableJsonFlag": false,
857
997
  "isESM": true,
858
998
  "relativePath": [
859
999
  "dist",
860
1000
  "commands",
861
1001
  "feature",
862
- "add-child.js"
1002
+ "add.js"
863
1003
  ]
864
1004
  },
865
1005
  "feature:check": {
@@ -2259,5 +2399,5 @@
2259
2399
  ]
2260
2400
  }
2261
2401
  },
2262
- "version": "0.3.10"
2402
+ "version": "0.3.11"
2263
2403
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apollo-annotation/cli",
3
- "version": "0.3.10",
3
+ "version": "0.3.11",
4
4
  "description": "Command line interface for the Apollo annotation server",
5
5
  "repository": {
6
6
  "type": "git",
@@ -89,8 +89,8 @@
89
89
  "yaml": "^2.3.4"
90
90
  },
91
91
  "devDependencies": {
92
- "@apollo-annotation/mst": "^0.3.10",
93
- "@apollo-annotation/shared": "^0.3.10",
92
+ "@apollo-annotation/mst": "^0.3.11",
93
+ "@apollo-annotation/shared": "^0.3.11",
94
94
  "@istanbuljs/esm-loader-hook": "^0.2.0",
95
95
  "@istanbuljs/nyc-config-typescript": "^1.0.2",
96
96
  "@oclif/test": "^3.1.3",