@apollo-annotation/cli 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/README.md +899 -0
  2. package/bin/dev.cmd +3 -0
  3. package/bin/dev.js +9 -0
  4. package/bin/run.cmd +3 -0
  5. package/bin/run.js +8 -0
  6. package/dist/Config.d.ts +43 -0
  7. package/dist/Config.js +233 -0
  8. package/dist/baseCommand.d.ts +21 -0
  9. package/dist/baseCommand.js +62 -0
  10. package/dist/commands/assembly/add-fasta.d.ts +15 -0
  11. package/dist/commands/assembly/add-fasta.js +98 -0
  12. package/dist/commands/assembly/add-gff.d.ts +16 -0
  13. package/dist/commands/assembly/add-gff.js +76 -0
  14. package/dist/commands/assembly/check.d.ts +15 -0
  15. package/dist/commands/assembly/check.js +148 -0
  16. package/dist/commands/assembly/delete.d.ts +14 -0
  17. package/dist/commands/assembly/delete.js +43 -0
  18. package/dist/commands/assembly/get.d.ts +9 -0
  19. package/dist/commands/assembly/get.js +33 -0
  20. package/dist/commands/assembly/get.test.d.ts +1 -0
  21. package/dist/commands/assembly/get.test.js +50 -0
  22. package/dist/commands/assembly/sequence.d.ts +16 -0
  23. package/dist/commands/assembly/sequence.js +117 -0
  24. package/dist/commands/change/get.d.ts +9 -0
  25. package/dist/commands/change/get.js +35 -0
  26. package/dist/commands/change/get.test.d.ts +1 -0
  27. package/dist/commands/change/get.test.js +22 -0
  28. package/dist/commands/config.d.ts +25 -0
  29. package/dist/commands/config.js +217 -0
  30. package/dist/commands/config.test.d.ts +1 -0
  31. package/dist/commands/config.test.js +188 -0
  32. package/dist/commands/feature/add-child.d.ts +17 -0
  33. package/dist/commands/feature/add-child.js +120 -0
  34. package/dist/commands/feature/check.d.ts +14 -0
  35. package/dist/commands/feature/check.js +97 -0
  36. package/dist/commands/feature/copy.d.ts +17 -0
  37. package/dist/commands/feature/copy.js +110 -0
  38. package/dist/commands/feature/delete.d.ts +11 -0
  39. package/dist/commands/feature/delete.js +99 -0
  40. package/dist/commands/feature/edit-attribute.d.ts +16 -0
  41. package/dist/commands/feature/edit-attribute.js +100 -0
  42. package/dist/commands/feature/edit-coords.d.ts +15 -0
  43. package/dist/commands/feature/edit-coords.js +109 -0
  44. package/dist/commands/feature/edit-type.d.ts +10 -0
  45. package/dist/commands/feature/edit-type.js +70 -0
  46. package/dist/commands/feature/edit.d.ts +13 -0
  47. package/dist/commands/feature/edit.js +81 -0
  48. package/dist/commands/feature/get-id.d.ts +14 -0
  49. package/dist/commands/feature/get-id.js +56 -0
  50. package/dist/commands/feature/get.d.ts +16 -0
  51. package/dist/commands/feature/get.js +87 -0
  52. package/dist/commands/feature/import.d.ts +15 -0
  53. package/dist/commands/feature/import.js +83 -0
  54. package/dist/commands/feature/search.d.ts +14 -0
  55. package/dist/commands/feature/search.js +91 -0
  56. package/dist/commands/login.d.ts +21 -0
  57. package/dist/commands/login.js +206 -0
  58. package/dist/commands/login.test.d.ts +1 -0
  59. package/dist/commands/login.test.js +52 -0
  60. package/dist/commands/logout.d.ts +10 -0
  61. package/dist/commands/logout.js +41 -0
  62. package/dist/commands/logout.test.d.ts +1 -0
  63. package/dist/commands/logout.test.js +67 -0
  64. package/dist/commands/refseq/get.d.ts +13 -0
  65. package/dist/commands/refseq/get.js +44 -0
  66. package/dist/commands/status.d.ts +6 -0
  67. package/dist/commands/status.js +38 -0
  68. package/dist/commands/status.test.d.ts +1 -0
  69. package/dist/commands/status.test.js +54 -0
  70. package/dist/commands/user/get.d.ts +14 -0
  71. package/dist/commands/user/get.js +46 -0
  72. package/dist/commands/user/get.test.d.ts +1 -0
  73. package/dist/commands/user/get.test.js +23 -0
  74. package/dist/index.d.ts +1 -0
  75. package/dist/index.js +1 -0
  76. package/dist/test/fixtures.d.ts +7 -0
  77. package/dist/test/fixtures.js +40 -0
  78. package/dist/utils.d.ts +54 -0
  79. package/dist/utils.js +373 -0
  80. package/oclif.manifest.json +1632 -0
  81. package/package.json +100 -0
@@ -0,0 +1,110 @@
1
+ import { Flags } from '@oclif/core';
2
+ import { ObjectId } from 'bson';
3
+ import { fetch } from 'undici';
4
+ import { BaseCommand } from '../../baseCommand.js';
5
+ import { createFetchErrorMessage, getAssemblyFromRefseq, getFeatureById, getRefseqId, localhostToAddress, wrapLines, } from '../../utils.js';
6
+ export default class Copy extends BaseCommand {
7
+ static summary = 'Copy a feature to another location';
8
+ static description = wrapLines('The feature may be copied to the same or to a different assembly. \
9
+ he destination reference sequence may be selected by name only if unique in the database or by name and assembly or by identifier.');
10
+ static examples = [
11
+ {
12
+ description: 'Copy this feature ID to chr1:100 in assembly hg38:',
13
+ command: '<%= config.bin %> <%= command.id %> -i 6605826fbd0eee691f83e73f -r chr1 -s 100 -a hg38',
14
+ },
15
+ ];
16
+ static flags = {
17
+ 'feature-id': Flags.string({
18
+ char: 'i',
19
+ default: '-',
20
+ description: 'Feature ID to copy to; use - to read it from stdin',
21
+ }),
22
+ refseq: Flags.string({
23
+ char: 'r',
24
+ description: 'Name or ID of target reference sequence',
25
+ required: true,
26
+ }),
27
+ start: Flags.integer({
28
+ char: 's',
29
+ description: 'Start position in target reference sequence',
30
+ required: true,
31
+ }),
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
+ required: false,
36
+ }),
37
+ };
38
+ async run() {
39
+ const { flags } = await this.parse(Copy);
40
+ if (flags.start <= 0) {
41
+ this.logToStderr('Start coordinate must be greater than 0');
42
+ this.exit(1);
43
+ }
44
+ const access = await this.getAccess(flags['config-file'], flags.profile);
45
+ const response = await getFeatureById(access.address, access.accessToken, flags['feature-id']);
46
+ if (!response.ok) {
47
+ const errorMessage = await createFetchErrorMessage(response, 'getFeatureById failed');
48
+ throw new Error(errorMessage);
49
+ }
50
+ const feature = (await response.json());
51
+ let refseqIds = [];
52
+ try {
53
+ refseqIds = await getRefseqId(access.address, access.accessToken, flags.refseq, flags.assembly);
54
+ }
55
+ catch (error) {
56
+ this.logToStderr(error.message);
57
+ this.exit(1);
58
+ }
59
+ if (refseqIds.length === 0) {
60
+ this.logToStderr('No reference sequence found');
61
+ this.exit(1);
62
+ }
63
+ const [refseq] = refseqIds;
64
+ const assembly = await getAssemblyFromRefseq(access.address, access.accessToken, refseq);
65
+ const newId = new ObjectId().toHexString();
66
+ const rescopy = await this.copyFeature(access.address, access.accessToken, feature, refseq, flags.start, assembly, newId);
67
+ if (!rescopy.ok) {
68
+ const message = feature['message'];
69
+ this.logToStderr(message);
70
+ this.exit(1);
71
+ }
72
+ this.exit(0);
73
+ }
74
+ async copyFeature(address, accessToken, feature, refseq, start, assembly, newId) {
75
+ const featureLen = feature['end'] -
76
+ feature['start'];
77
+ const change = {
78
+ typeName: 'AddFeatureChange',
79
+ changedIds: [newId],
80
+ assembly,
81
+ addedFeature: {
82
+ _id: newId,
83
+ refSeq: refseq,
84
+ start: start - 1,
85
+ end: start + featureLen - 1,
86
+ type: feature['type'],
87
+ attributes: feature['attributes'],
88
+ discontinuousLocations: feature['discontinuousLocations'],
89
+ strand: feature['strand'],
90
+ },
91
+ copyFeature: true,
92
+ allIds: [newId],
93
+ };
94
+ const url = new URL(localhostToAddress(`${address}/changes`));
95
+ const auth = {
96
+ method: 'POST',
97
+ body: JSON.stringify(change),
98
+ headers: {
99
+ authorization: `Bearer ${accessToken}`,
100
+ 'Content-Type': 'application/json',
101
+ },
102
+ };
103
+ const response = await fetch(url, auth);
104
+ if (!response.ok) {
105
+ const errorMessage = await createFetchErrorMessage(response, 'copyFeature failed');
106
+ throw new Error(errorMessage);
107
+ }
108
+ return response;
109
+ }
110
+ }
@@ -0,0 +1,11 @@
1
+ import { BaseCommand } from '../../baseCommand.js';
2
+ export default class Delete extends BaseCommand<typeof Delete> {
3
+ static summary: string;
4
+ static description: string;
5
+ static flags: {
6
+ 'feature-id': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string[], import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
7
+ force: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
8
+ 'dry-run': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
9
+ };
10
+ run(): Promise<void>;
11
+ }
@@ -0,0 +1,99 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */
2
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
3
+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
4
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
5
+ import { Flags } from '@oclif/core';
6
+ import { fetch } from 'undici';
7
+ import { BaseCommand } from '../../baseCommand.js';
8
+ import { createFetchErrorMessage, getFeatureById, idReader, localhostToAddress, wrapLines, } from '../../utils.js';
9
+ async function deleteFeature(address, accessToken, feature) {
10
+ const changeJson = {
11
+ typeName: 'DeleteFeatureChange',
12
+ changedIds: [feature],
13
+ assembly: feature['assembly'],
14
+ deletedFeature: {
15
+ _id: feature['_id'],
16
+ gffId: feature['gffId'],
17
+ refSeq: feature['refSeq'],
18
+ type: feature['type'],
19
+ start: feature['start'],
20
+ end: feature['end'],
21
+ discontinuousLocations: feature['discontinuousLocations'],
22
+ score: feature['score'],
23
+ attributes: feature['attributes'],
24
+ },
25
+ };
26
+ const url = new URL(localhostToAddress(`${address}/changes`));
27
+ const auth = {
28
+ method: 'POST',
29
+ body: JSON.stringify(changeJson),
30
+ headers: {
31
+ authorization: `Bearer ${accessToken}`,
32
+ 'Content-Type': 'application/json',
33
+ },
34
+ };
35
+ const response = await fetch(url, auth);
36
+ if (!response.ok) {
37
+ const errorMessage = await createFetchErrorMessage(response, 'deleteFeature failed');
38
+ throw new Error(errorMessage);
39
+ }
40
+ return response;
41
+ }
42
+ export default class Delete extends BaseCommand {
43
+ static summary = 'Delete one or more features by ID';
44
+ static description = wrapLines('Note that deleting a child feature after deleting its parent will result in an error unless you set -f/--force.');
45
+ static flags = {
46
+ 'feature-id': Flags.string({
47
+ char: 'i',
48
+ default: ['-'],
49
+ description: 'Feature IDs to delete',
50
+ multiple: true,
51
+ }),
52
+ force: Flags.boolean({
53
+ char: 'f',
54
+ description: 'Ignore non-existing features',
55
+ }),
56
+ 'dry-run': Flags.boolean({
57
+ char: 'n',
58
+ description: 'Only show what would be delete',
59
+ }),
60
+ };
61
+ async run() {
62
+ const { flags } = await this.parse(Delete);
63
+ const tmpIds = idReader(flags['feature-id']);
64
+ const featureIds = new Set();
65
+ for (const x of tmpIds) {
66
+ featureIds.add(x);
67
+ }
68
+ const access = await this.getAccess(flags['config-file'], flags.profile);
69
+ for (const featureId of featureIds) {
70
+ const response = await getFeatureById(access.address, access.accessToken, featureId);
71
+ if (response.status === 404 && flags.force) {
72
+ continue;
73
+ }
74
+ if (!response.ok) {
75
+ const errorMessage = await createFetchErrorMessage(response, 'getFeatureById failed');
76
+ throw new Error(errorMessage);
77
+ }
78
+ const feature = JSON.parse(await response.text());
79
+ if (!response.ok) {
80
+ const message = feature['message'];
81
+ this.logToStderr(message);
82
+ this.exit(1);
83
+ }
84
+ if (flags['dry-run']) {
85
+ this.log(feature);
86
+ }
87
+ else {
88
+ const delFet = await deleteFeature(access.address, access.accessToken, feature);
89
+ if (!delFet.ok) {
90
+ const json = (await delFet.json());
91
+ const message = json['message'];
92
+ this.logToStderr(message);
93
+ this.exit(1);
94
+ }
95
+ }
96
+ }
97
+ this.exit(0);
98
+ }
99
+ }
@@ -0,0 +1,16 @@
1
+ import { BaseCommand } from '../../baseCommand.js';
2
+ export default class EditAttibute extends BaseCommand<typeof EditAttibute> {
3
+ static summary: string;
4
+ static description: string;
5
+ static examples: {
6
+ description: string;
7
+ command: string;
8
+ }[];
9
+ static flags: {
10
+ 'feature-id': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
11
+ attribute: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
12
+ value: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
13
+ delete: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
14
+ };
15
+ run(): Promise<void>;
16
+ }
@@ -0,0 +1,100 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */
2
+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
3
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
4
+ import { Flags } from '@oclif/core';
5
+ import { fetch } from 'undici';
6
+ import { BaseCommand } from '../../baseCommand.js';
7
+ import { createFetchErrorMessage, getAssemblyFromRefseq, getFeatureById, idReader, localhostToAddress, wrapLines, } from '../../utils.js';
8
+ export default class EditAttibute extends BaseCommand {
9
+ static summary = 'Add, edit, or view a feature attribute';
10
+ static description = wrapLines('Be aware that there is no checking whether attributes names and values are valid. \
11
+ For example, you can create non-unique ID attributes or you can set gene ontology terms to non-existing terms');
12
+ static examples = [
13
+ {
14
+ description: 'Add attribute "domains" with a list of values:',
15
+ command: '<%= config.bin %> <%= command.id %> -i 66...3f -a domains -v ABC PLD',
16
+ },
17
+ {
18
+ description: 'Print values in "domains" as json array:',
19
+ command: '<%= config.bin %> <%= command.id %> -i 66...3f -a domains',
20
+ },
21
+ {
22
+ description: 'Delete attribute "domains"',
23
+ command: '<%= config.bin %> <%= command.id %> -i 66...3f -a domains -d',
24
+ },
25
+ ];
26
+ static flags = {
27
+ 'feature-id': Flags.string({
28
+ char: 'i',
29
+ default: '-',
30
+ description: 'Feature ID to edit or "-" to read it from stdin',
31
+ }),
32
+ attribute: Flags.string({
33
+ char: 'a',
34
+ required: true,
35
+ description: 'Attribute key to add or edit',
36
+ }),
37
+ value: Flags.string({
38
+ char: 'v',
39
+ multiple: true,
40
+ description: 'New attribute value. Separated mutliple values by space to them as a list. If unset return current value',
41
+ }),
42
+ delete: Flags.boolean({
43
+ char: 'd',
44
+ description: 'Delete this attribute',
45
+ }),
46
+ };
47
+ async run() {
48
+ const { flags } = await this.parse(EditAttibute);
49
+ if (flags.delete && flags.value) {
50
+ this.logToStderr('Error: Options --delete and --value are mutually exclusive');
51
+ this.exit(1);
52
+ }
53
+ const ff = idReader([flags['feature-id']]);
54
+ if (ff.length !== 1) {
55
+ this.logToStderr(`Expected only one feature identifier. Got ${ff.length}`);
56
+ }
57
+ const [featureId] = ff;
58
+ const access = await this.getAccess(flags['config-file'], flags.profile);
59
+ const response = await getFeatureById(access.address, access.accessToken, featureId);
60
+ if (!response.ok) {
61
+ const errorMessage = await createFetchErrorMessage(response, 'getFeatureById failed');
62
+ throw new Error(errorMessage);
63
+ }
64
+ const featureJson = JSON.parse(await response.text());
65
+ if (flags.value === undefined && !flags.delete) {
66
+ this.log(JSON.stringify(featureJson.attributes[flags.attribute]));
67
+ this.exit(0);
68
+ }
69
+ if (flags.delete) {
70
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
71
+ delete featureJson.attributes[flags.attribute];
72
+ }
73
+ else {
74
+ featureJson.attributes[flags.attribute] = flags.value;
75
+ }
76
+ const assembly = await getAssemblyFromRefseq(access.address, access.accessToken, featureJson['refSeq']);
77
+ const changeJson = {
78
+ typeName: 'FeatureAttributeChange',
79
+ changedIds: [featureId],
80
+ assembly,
81
+ featureId,
82
+ attributes: featureJson.attributes,
83
+ };
84
+ const url = new URL(localhostToAddress(`${access.address}/changes`));
85
+ const auth = {
86
+ method: 'POST',
87
+ body: JSON.stringify(changeJson),
88
+ headers: {
89
+ authorization: `Bearer ${access.accessToken}`,
90
+ 'Content-Type': 'application/json',
91
+ },
92
+ };
93
+ const res = await fetch(url, auth);
94
+ if (!res.ok) {
95
+ const errorMessage = await createFetchErrorMessage(res, 'edit-attribute failed');
96
+ throw new Error(errorMessage);
97
+ }
98
+ this.exit(0);
99
+ }
100
+ }
@@ -0,0 +1,15 @@
1
+ import { BaseCommand } from '../../baseCommand.js';
2
+ export default class Get extends BaseCommand<typeof Get> {
3
+ static summary: string;
4
+ static description: string;
5
+ static examples: {
6
+ description: string;
7
+ command: string;
8
+ }[];
9
+ static flags: {
10
+ 'feature-id': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
11
+ start: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
12
+ end: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
13
+ };
14
+ run(): Promise<void>;
15
+ }
@@ -0,0 +1,109 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
2
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */
3
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
4
+ import { Flags } from '@oclif/core';
5
+ import { fetch } from 'undici';
6
+ import { BaseCommand } from '../../baseCommand.js';
7
+ import { createFetchErrorMessage, getAssemblyFromRefseq, getFeatureById, idReader, localhostToAddress, wrapLines, } from '../../utils.js';
8
+ export default class Get extends BaseCommand {
9
+ static summary = 'Edit feature start and/or end coordinates';
10
+ static description = wrapLines("If editing a child feature that new coordinates must be within the parent's coordinates.\
11
+ To get the identifier of the feature to edit consider using `apollo feature get` or `apollo feature search`");
12
+ static examples = [
13
+ {
14
+ description: 'Edit start and end:',
15
+ command: '<%= config.bin %> <%= command.id %> -i abc...xyz -s 10 -e 1000',
16
+ },
17
+ {
18
+ description: 'Edit end and leave start as it is:',
19
+ command: '<%= config.bin %> <%= command.id %> -i abc...xyz -e 2000',
20
+ },
21
+ ];
22
+ static flags = {
23
+ 'feature-id': Flags.string({
24
+ char: 'i',
25
+ default: '-',
26
+ description: 'Feature ID to edit or "-" to read it from stdin',
27
+ }),
28
+ start: Flags.integer({
29
+ char: 's',
30
+ description: 'New start coordinate (1-based)',
31
+ }),
32
+ end: Flags.integer({
33
+ char: 'e',
34
+ description: 'New end coordinate (1-based)',
35
+ }),
36
+ };
37
+ async run() {
38
+ const { flags } = await this.parse(Get);
39
+ if (flags.start === undefined && flags.end === undefined) {
40
+ this.logToStderr('Please provide new start and/or end coordinates to edit');
41
+ this.exit(1);
42
+ }
43
+ if (flags.start !== undefined && flags.start <= 0) {
44
+ this.logToStderr('Coordinates must be greater than 0');
45
+ this.exit(1);
46
+ }
47
+ if (flags.start !== undefined &&
48
+ flags.end !== undefined &&
49
+ flags.end < flags.start) {
50
+ this.logToStderr('Error: The new end coordinate is lower than the new start coordinate');
51
+ this.exit(1);
52
+ }
53
+ if (flags.start !== undefined) {
54
+ flags.start -= 1;
55
+ }
56
+ const ff = idReader([flags['feature-id']]);
57
+ if (ff.length !== 1) {
58
+ this.logToStderr(`Expected only one feature identifier. Got ${ff.length}`);
59
+ }
60
+ const [featureId] = ff;
61
+ const access = await this.getAccess(flags['config-file'], flags.profile);
62
+ const response = await getFeatureById(access.address, access.accessToken, featureId);
63
+ if (!response.ok) {
64
+ const errorMessage = await createFetchErrorMessage(response, 'getFeatureById failed');
65
+ throw new Error(errorMessage);
66
+ }
67
+ const featureJson = JSON.parse(await response.text());
68
+ const assembly = await getAssemblyFromRefseq(access.address, access.accessToken, featureJson['refSeq']);
69
+ const currentEnd = featureJson['end'];
70
+ let edit = ['Start', 'End'];
71
+ if (flags.start !== undefined && flags.start > currentEnd) {
72
+ // Edit End first so you avoid an intermediate start > end
73
+ edit = ['End', 'Start'];
74
+ }
75
+ for (const coord of edit) {
76
+ const currentStart = featureJson['start'];
77
+ if (coord === 'Start' &&
78
+ (flags.start === undefined || flags.start === currentStart)) {
79
+ continue;
80
+ }
81
+ else if (coord === 'End' &&
82
+ (flags.end === undefined || flags.end === currentEnd)) {
83
+ continue;
84
+ }
85
+ const changeJson = {
86
+ typeName: `Location${coord}Change`,
87
+ changedIds: [featureId],
88
+ assembly,
89
+ featureId,
90
+ [`old${coord}`]: featureJson[coord.toLowerCase()],
91
+ [`new${coord}`]: flags[coord.toLowerCase()],
92
+ };
93
+ const url = new URL(localhostToAddress(`${access.address}/changes`));
94
+ const auth = {
95
+ method: 'POST',
96
+ body: JSON.stringify(changeJson),
97
+ headers: {
98
+ authorization: `Bearer ${access.accessToken}`,
99
+ 'Content-Type': 'application/json',
100
+ },
101
+ };
102
+ const response = await fetch(url, auth);
103
+ if (!response.ok) {
104
+ const errorMessage = await createFetchErrorMessage(response, 'edit-coords failed');
105
+ throw new Error(errorMessage);
106
+ }
107
+ }
108
+ }
109
+ }
@@ -0,0 +1,10 @@
1
+ import { BaseCommand } from '../../baseCommand.js';
2
+ export default class Get extends BaseCommand<typeof Get> {
3
+ static summary: string;
4
+ static description: string;
5
+ static flags: {
6
+ 'feature-id': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
7
+ type: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
8
+ };
9
+ run(): Promise<void>;
10
+ }
@@ -0,0 +1,70 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */
2
+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
3
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
4
+ import { Flags } from '@oclif/core';
5
+ import { fetch } from 'undici';
6
+ import { BaseCommand } from '../../baseCommand.js';
7
+ import { createFetchErrorMessage, getAssemblyFromRefseq, getFeatureById, idReader, localhostToAddress, wrapLines, } from '../../utils.js';
8
+ export default class Get extends BaseCommand {
9
+ static summary = 'Edit or view feature type';
10
+ static description = wrapLines('Feature type is column 3 in gff format.\
11
+ It must be a valid sequence ontology term although but the valifdity of the new term is not checked.');
12
+ static flags = {
13
+ 'feature-id': Flags.string({
14
+ char: 'i',
15
+ default: '-',
16
+ description: 'Feature ID to edit or "-" to read it from stdin',
17
+ }),
18
+ type: Flags.string({
19
+ char: 't',
20
+ description: 'Assign feature to this type. If unset return the current type',
21
+ }),
22
+ };
23
+ async run() {
24
+ const { flags } = await this.parse(Get);
25
+ const ff = idReader([flags['feature-id']]);
26
+ if (ff.length !== 1) {
27
+ this.logToStderr(`Expected only one feature identifier. Got ${ff.length}`);
28
+ }
29
+ const [featureId] = ff;
30
+ const access = await this.getAccess(flags['config-file'], flags.profile);
31
+ const response = await getFeatureById(access.address, access.accessToken, featureId);
32
+ if (!response.ok) {
33
+ const errorMessage = await createFetchErrorMessage(response, 'getFeatureById failed');
34
+ throw new Error(errorMessage);
35
+ }
36
+ const featureJson = JSON.parse(await response.text());
37
+ const currentType = featureJson['type'];
38
+ if (flags.type === undefined) {
39
+ this.log(currentType);
40
+ this.exit(0);
41
+ }
42
+ if (flags.type === currentType) {
43
+ this.logToStderr(`NOTE: Feature ${featureId} is already of type "${flags.type}"`);
44
+ this.exit(0);
45
+ }
46
+ const assembly = await getAssemblyFromRefseq(access.address, access.accessToken, featureJson['refSeq']);
47
+ const changeJson = {
48
+ typeName: 'TypeChange',
49
+ changedIds: [featureId],
50
+ assembly,
51
+ featureId,
52
+ oldType: currentType,
53
+ newType: flags.type,
54
+ };
55
+ const url = new URL(localhostToAddress(`${access.address}/changes`));
56
+ const auth = {
57
+ method: 'POST',
58
+ body: JSON.stringify(changeJson),
59
+ headers: {
60
+ authorization: `Bearer ${access.accessToken}`,
61
+ 'Content-Type': 'application/json',
62
+ },
63
+ };
64
+ const res = await fetch(url, auth);
65
+ if (!res.ok) {
66
+ const errorMessage = await createFetchErrorMessage(res, 'edit-type failed');
67
+ throw new Error(errorMessage);
68
+ }
69
+ }
70
+ }
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from '../../baseCommand.js';
2
+ export default class Get extends BaseCommand<typeof Get> {
3
+ static summary: string;
4
+ static description: string;
5
+ static examples: {
6
+ description: string;
7
+ command: string;
8
+ }[];
9
+ static flags: {
10
+ 'json-input': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,81 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
2
+ import * as fs from 'node:fs';
3
+ import { Flags } from '@oclif/core';
4
+ import { fetch } from 'undici';
5
+ import { BaseCommand } from '../../baseCommand.js';
6
+ import { createFetchErrorMessage, localhostToAddress, wrapLines, } from '../../utils.js';
7
+ export default class Get extends BaseCommand {
8
+ static summary = 'Edit features using an appropiate json input';
9
+ static description = wrapLines(`Edit a feature by submitting a json input with all the required attributes for Apollo to process it. This is a very low level command which most users probably do not need.
10
+
11
+ Input may be a json string or a json file and it may be an array of changes. This is an example input for editing feature type:
12
+
13
+ {
14
+ "typeName": "TypeChange",
15
+ "changedIds": [
16
+ "6613f7d22c957525d631b1cc"
17
+ ],
18
+ "assembly": "6613f7d1360321540a11e5ed",
19
+ "featureId": "6613f7d22c957525d631b1cc",
20
+ "oldType": "BAC",
21
+ "newType": "G_quartet"
22
+ }`);
23
+ static examples = [
24
+ {
25
+ description: 'Editing by passing a json to stdin:',
26
+ command: 'echo \'{"typeName": ... "newType": "G_quartet"}\' | <%= config.bin %> <%= command.id %> -j -',
27
+ },
28
+ ];
29
+ static flags = {
30
+ 'json-input': Flags.string({
31
+ char: 'j',
32
+ default: '-',
33
+ description: 'Json string or json file or "-" to read json from stdin',
34
+ }),
35
+ };
36
+ async run() {
37
+ const { flags } = await this.parse(Get);
38
+ let jsonStr = flags['json-input'];
39
+ if (flags['json-input'] === '-') {
40
+ jsonStr = fs.readFileSync(process.stdin.fd).toString();
41
+ }
42
+ else if (fs.existsSync(flags['json-input'])) {
43
+ jsonStr = fs.readFileSync(flags['json-input']).toString();
44
+ }
45
+ let json;
46
+ try {
47
+ json = JSON.parse(jsonStr);
48
+ if (!Array.isArray(json)) {
49
+ json = [json];
50
+ }
51
+ }
52
+ catch (error) {
53
+ if (error instanceof Error) {
54
+ this.logToStderr(`Error parsing json input:\n${error.message}`);
55
+ this.exit(1);
56
+ }
57
+ else {
58
+ throw error;
59
+ }
60
+ }
61
+ const access = await this.getAccess(flags['config-file'], flags.profile);
62
+ for (const change of json) {
63
+ const str = JSON.stringify(change);
64
+ const url = new URL(localhostToAddress(`${access.address}/changes`));
65
+ const auth = {
66
+ method: 'POST',
67
+ body: str,
68
+ headers: {
69
+ authorization: `Bearer ${access.accessToken}`,
70
+ 'Content-Type': 'application/json',
71
+ },
72
+ };
73
+ const response = await fetch(url, auth);
74
+ if (!response.ok) {
75
+ const errorMessage = await createFetchErrorMessage(response, 'edit failed');
76
+ throw new Error(errorMessage);
77
+ }
78
+ }
79
+ this.exit(0);
80
+ }
81
+ }
@@ -0,0 +1,14 @@
1
+ import { BaseCommand } from '../../baseCommand.js';
2
+ export default class Get extends BaseCommand<typeof Get> {
3
+ static summary: string;
4
+ static description: string;
5
+ static examples: {
6
+ description: string;
7
+ command: string;
8
+ }[];
9
+ static flags: {
10
+ 'feature-id': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string[], import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
11
+ };
12
+ run(): Promise<void>;
13
+ private getFeatureId;
14
+ }