@apollo-annotation/cli 0.1.18 → 0.1.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/README.md +118 -56
- package/bin/dev.js +2 -2
- package/bin/run.js +2 -2
- package/dist/ApolloConf.js +1 -0
- package/dist/baseCommand.js +4 -3
- package/dist/commands/assembly/add-fasta.js +0 -1
- package/dist/commands/assembly/add-gff.js +0 -1
- package/dist/commands/assembly/get.test.js +3 -3
- package/dist/commands/assembly/sequence.js +4 -10
- package/dist/commands/change/get.test.js +1 -1
- package/dist/commands/config.js +1 -1
- package/dist/commands/feature/add-child.js +12 -14
- package/dist/commands/feature/check.js +5 -5
- package/dist/commands/feature/copy.js +7 -10
- package/dist/commands/feature/delete.js +9 -15
- package/dist/commands/feature/edit-attribute.js +12 -6
- package/dist/commands/feature/edit-coords.js +31 -16
- package/dist/commands/feature/edit-type.js +2 -6
- package/dist/commands/feature/edit.js +0 -1
- package/dist/commands/feature/get-id.js +0 -1
- package/dist/commands/feature/get.js +0 -1
- package/dist/commands/feature/import.js +20 -33
- package/dist/commands/feature/search.js +1 -1
- package/dist/commands/login.js +1 -1
- package/dist/commands/logout.js +1 -1
- package/dist/commands/refseq/add-alias.d.ts +14 -0
- package/dist/commands/refseq/add-alias.js +72 -0
- package/dist/commands/status.js +1 -1
- package/dist/commands/user/get.test.js +1 -1
- package/dist/test/fixtures.js +2 -2
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +59 -28
- package/oclif.manifest.json +107 -46
- package/package.json +10 -3
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
3
1
|
import { Flags } from '@oclif/core';
|
|
4
2
|
import { fetch } from 'undici';
|
|
5
3
|
import { BaseCommand } from '../../baseCommand.js';
|
|
@@ -7,18 +5,15 @@ import { createFetchErrorMessage, getFeatureById, idReader, localhostToAddress,
|
|
|
7
5
|
async function deleteFeature(address, accessToken, feature) {
|
|
8
6
|
const changeJson = {
|
|
9
7
|
typeName: 'DeleteFeatureChange',
|
|
10
|
-
changedIds: [feature],
|
|
11
|
-
assembly:
|
|
8
|
+
changedIds: [feature._id],
|
|
9
|
+
assembly: '111222333444555666777888', // Use a placeholder objectId (i.e. some 24 chars)
|
|
12
10
|
deletedFeature: {
|
|
13
|
-
_id: feature
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
discontinuousLocations: feature['discontinuousLocations'],
|
|
20
|
-
score: feature['score'],
|
|
21
|
-
attributes: feature['attributes'],
|
|
11
|
+
_id: feature._id,
|
|
12
|
+
refSeq: feature.refSeq,
|
|
13
|
+
type: feature.type,
|
|
14
|
+
min: feature.min,
|
|
15
|
+
max: feature.max,
|
|
16
|
+
attributes: feature.attributes,
|
|
22
17
|
},
|
|
23
18
|
};
|
|
24
19
|
const url = new URL(localhostToAddress(`${address}/changes`));
|
|
@@ -75,7 +70,7 @@ export default class Delete extends BaseCommand {
|
|
|
75
70
|
}
|
|
76
71
|
const feature = JSON.parse(await res.text());
|
|
77
72
|
if (flags['dry-run']) {
|
|
78
|
-
this.log(feature);
|
|
73
|
+
this.log(JSON.stringify(feature, null, 2));
|
|
79
74
|
}
|
|
80
75
|
else {
|
|
81
76
|
const delFet = await deleteFeature(access.address, access.accessToken, feature);
|
|
@@ -85,6 +80,5 @@ export default class Delete extends BaseCommand {
|
|
|
85
80
|
}
|
|
86
81
|
}
|
|
87
82
|
}
|
|
88
|
-
this.exit(0);
|
|
89
83
|
}
|
|
90
84
|
}
|
|
@@ -1,6 +1,3 @@
|
|
|
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
1
|
import { Flags } from '@oclif/core';
|
|
5
2
|
import { fetch } from 'undici';
|
|
6
3
|
import { BaseCommand } from '../../baseCommand.js';
|
|
@@ -61,6 +58,9 @@ export default class EditAttibute extends BaseCommand {
|
|
|
61
58
|
throw new Error(errorMessage);
|
|
62
59
|
}
|
|
63
60
|
const featureJson = JSON.parse(await response.text());
|
|
61
|
+
if (featureJson.attributes === undefined) {
|
|
62
|
+
featureJson.attributes = {};
|
|
63
|
+
}
|
|
64
64
|
if (flags.value === undefined && !flags.delete) {
|
|
65
65
|
this.log(JSON.stringify(featureJson.attributes[flags.attribute]));
|
|
66
66
|
return;
|
|
@@ -72,13 +72,20 @@ export default class EditAttibute extends BaseCommand {
|
|
|
72
72
|
else {
|
|
73
73
|
featureJson.attributes[flags.attribute] = flags.value;
|
|
74
74
|
}
|
|
75
|
-
const assembly = await getAssemblyFromRefseq(access.address, access.accessToken, featureJson
|
|
75
|
+
const assembly = await getAssemblyFromRefseq(access.address, access.accessToken, featureJson.refSeq);
|
|
76
|
+
const attrs = {};
|
|
77
|
+
for (const [key, val] of Object.entries(featureJson.attributes)) {
|
|
78
|
+
if (!val) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
attrs[key] = [...val];
|
|
82
|
+
}
|
|
76
83
|
const changeJson = {
|
|
77
84
|
typeName: 'FeatureAttributeChange',
|
|
78
85
|
changedIds: [featureId],
|
|
79
86
|
assembly,
|
|
80
87
|
featureId,
|
|
81
|
-
attributes:
|
|
88
|
+
attributes: attrs,
|
|
82
89
|
};
|
|
83
90
|
const url = new URL(localhostToAddress(`${access.address}/changes`));
|
|
84
91
|
const auth = {
|
|
@@ -94,6 +101,5 @@ export default class EditAttibute extends BaseCommand {
|
|
|
94
101
|
const errorMessage = await createFetchErrorMessage(res, 'edit-attribute failed');
|
|
95
102
|
throw new Error(errorMessage);
|
|
96
103
|
}
|
|
97
|
-
this.exit(0);
|
|
98
104
|
}
|
|
99
105
|
}
|
|
@@ -1,6 +1,3 @@
|
|
|
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
1
|
import { Flags } from '@oclif/core';
|
|
5
2
|
import { fetch } from 'undici';
|
|
6
3
|
import { BaseCommand } from '../../baseCommand.js';
|
|
@@ -62,15 +59,15 @@ export default class Get extends BaseCommand {
|
|
|
62
59
|
throw new Error(errorMessage);
|
|
63
60
|
}
|
|
64
61
|
const featureJson = JSON.parse(await res.text());
|
|
65
|
-
const assembly = await getAssemblyFromRefseq(access.address, access.accessToken, featureJson
|
|
66
|
-
const currentEnd = featureJson
|
|
62
|
+
const assembly = await getAssemblyFromRefseq(access.address, access.accessToken, featureJson.refSeq);
|
|
63
|
+
const currentEnd = featureJson.max;
|
|
67
64
|
let edit = ['Start', 'End'];
|
|
68
65
|
if (flags.start !== undefined && flags.start > currentEnd) {
|
|
69
|
-
// Edit End first so you avoid an intermediate start > end
|
|
66
|
+
// Edit End (Max) first so you avoid an intermediate start > end
|
|
70
67
|
edit = ['End', 'Start'];
|
|
71
68
|
}
|
|
72
69
|
for (const coord of edit) {
|
|
73
|
-
const currentStart = featureJson
|
|
70
|
+
const currentStart = featureJson.min;
|
|
74
71
|
if (coord === 'Start' &&
|
|
75
72
|
(flags.start === undefined || flags.start === currentStart)) {
|
|
76
73
|
continue;
|
|
@@ -79,18 +76,36 @@ export default class Get extends BaseCommand {
|
|
|
79
76
|
(flags.end === undefined || flags.end === currentEnd)) {
|
|
80
77
|
continue;
|
|
81
78
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
79
|
+
let body;
|
|
80
|
+
if (coord === 'Start' && flags.start !== undefined) {
|
|
81
|
+
const oldCoord = featureJson.min;
|
|
82
|
+
body = {
|
|
83
|
+
typeName: 'LocationStartChange',
|
|
84
|
+
changedIds: [featureId],
|
|
85
|
+
assembly,
|
|
86
|
+
featureId,
|
|
87
|
+
['oldStart']: oldCoord,
|
|
88
|
+
['newStart']: flags.start,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
else if (coord === 'End' && flags.end !== undefined) {
|
|
92
|
+
const oldCoord = featureJson.max;
|
|
93
|
+
body = {
|
|
94
|
+
typeName: 'LocationEndChange',
|
|
95
|
+
changedIds: [featureId],
|
|
96
|
+
assembly,
|
|
97
|
+
featureId,
|
|
98
|
+
['oldEnd']: oldCoord,
|
|
99
|
+
['newEnd']: flags.end,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
throw new Error(`Unexpected coordinate name: "${coord}"`);
|
|
104
|
+
}
|
|
90
105
|
const url = new URL(localhostToAddress(`${access.address}/changes`));
|
|
91
106
|
const auth = {
|
|
92
107
|
method: 'POST',
|
|
93
|
-
body: JSON.stringify(
|
|
108
|
+
body: JSON.stringify(body),
|
|
94
109
|
headers: {
|
|
95
110
|
authorization: `Bearer ${access.accessToken}`,
|
|
96
111
|
'Content-Type': 'application/json',
|
|
@@ -1,6 +1,3 @@
|
|
|
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
1
|
import { Flags } from '@oclif/core';
|
|
5
2
|
import { fetch } from 'undici';
|
|
6
3
|
import { BaseCommand } from '../../baseCommand.js';
|
|
@@ -34,7 +31,7 @@ export default class Get extends BaseCommand {
|
|
|
34
31
|
throw new Error(errorMessage);
|
|
35
32
|
}
|
|
36
33
|
const featureJson = JSON.parse(await response.text());
|
|
37
|
-
const currentType = featureJson
|
|
34
|
+
const currentType = featureJson.type;
|
|
38
35
|
if (flags.type === undefined) {
|
|
39
36
|
this.log(currentType);
|
|
40
37
|
return;
|
|
@@ -43,7 +40,7 @@ export default class Get extends BaseCommand {
|
|
|
43
40
|
this.logToStderr(`NOTE: Feature ${featureId} is already of type "${flags.type}"`);
|
|
44
41
|
return;
|
|
45
42
|
}
|
|
46
|
-
const assembly = await getAssemblyFromRefseq(access.address, access.accessToken, featureJson
|
|
43
|
+
const assembly = await getAssemblyFromRefseq(access.address, access.accessToken, featureJson.refSeq);
|
|
47
44
|
const changeJson = {
|
|
48
45
|
typeName: 'TypeChange',
|
|
49
46
|
changedIds: [featureId],
|
|
@@ -66,6 +63,5 @@ export default class Get extends BaseCommand {
|
|
|
66
63
|
const errorMessage = await createFetchErrorMessage(res, 'edit-type failed');
|
|
67
64
|
throw new Error(errorMessage);
|
|
68
65
|
}
|
|
69
|
-
this.exit(0);
|
|
70
66
|
}
|
|
71
67
|
}
|
|
@@ -33,7 +33,6 @@ export default class Get extends BaseCommand {
|
|
|
33
33
|
results.push(res);
|
|
34
34
|
}
|
|
35
35
|
this.log(JSON.stringify(results, null, 2));
|
|
36
|
-
this.exit(0);
|
|
37
36
|
}
|
|
38
37
|
async getFeatureId(address, token, featureId) {
|
|
39
38
|
const url = new URL(localhostToAddress(`${address}/features/${featureId}`));
|
|
@@ -50,7 +50,6 @@ export default class Get extends BaseCommand {
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
this.log(JSON.stringify(results, null, 2));
|
|
53
|
-
this.exit(0);
|
|
54
53
|
}
|
|
55
54
|
async getFeatures(address, token, refSeq, start, end) {
|
|
56
55
|
const url = new URL(localhostToAddress(`${address}/features/getFeatures`));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
2
|
import { Flags } from '@oclif/core';
|
|
3
|
-
import { fetch } from 'undici';
|
|
3
|
+
import { Agent, fetch } from 'undici';
|
|
4
4
|
import { BaseCommand } from '../../baseCommand.js';
|
|
5
5
|
import { convertAssemblyNameToId, createFetchErrorMessage, localhostToAddress, uploadFile, } from '../../utils.js';
|
|
6
6
|
export default class Import extends BaseCommand {
|
|
@@ -39,39 +39,26 @@ export default class Import extends BaseCommand {
|
|
|
39
39
|
this.error(`Assembly "${flags.assembly}" does not exist. Perhaps you want to create this assembly first`);
|
|
40
40
|
}
|
|
41
41
|
const uploadId = await uploadFile(access.address, access.accessToken, flags['input-file'], 'text/x-gff3');
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
const body = {
|
|
43
|
+
typeName: 'AddFeaturesFromFileChange',
|
|
44
|
+
assembly: assembly[0],
|
|
45
|
+
fileId: uploadId,
|
|
46
|
+
deleteExistingFeatures: flags['delete-existing'],
|
|
47
|
+
};
|
|
48
|
+
const auth = {
|
|
49
|
+
method: 'POST',
|
|
50
|
+
body: JSON.stringify(body),
|
|
51
|
+
headers: {
|
|
52
|
+
Authorization: `Bearer ${access.accessToken}`,
|
|
53
|
+
'Content-Type': 'application/json',
|
|
54
|
+
},
|
|
55
|
+
dispatcher: new Agent({ headersTimeout: 60 * 60 * 1000 }),
|
|
56
|
+
};
|
|
57
|
+
const url = new URL(localhostToAddress(`${access.address}/changes`));
|
|
58
|
+
const response = await fetch(url, auth);
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
const errorMessage = await createFetchErrorMessage(response, 'importFeatures failed');
|
|
45
61
|
throw new Error(errorMessage);
|
|
46
62
|
}
|
|
47
|
-
this.exit(0);
|
|
48
63
|
}
|
|
49
64
|
}
|
|
50
|
-
async function importFeatures(address, accessToken, assembly, fileId, deleteExistingFeatures) {
|
|
51
|
-
const body = {
|
|
52
|
-
typeName: 'AddFeaturesFromFileChange',
|
|
53
|
-
assembly,
|
|
54
|
-
fileId,
|
|
55
|
-
deleteExistingFeatures,
|
|
56
|
-
};
|
|
57
|
-
const controller = new AbortController();
|
|
58
|
-
setTimeout(() => {
|
|
59
|
-
controller.abort();
|
|
60
|
-
}, 24 * 60 * 60 * 1000);
|
|
61
|
-
const auth = {
|
|
62
|
-
method: 'POST',
|
|
63
|
-
body: JSON.stringify(body),
|
|
64
|
-
headers: {
|
|
65
|
-
Authorization: `Bearer ${accessToken}`,
|
|
66
|
-
'Content-Type': 'application/json',
|
|
67
|
-
},
|
|
68
|
-
signal: controller.signal,
|
|
69
|
-
};
|
|
70
|
-
const url = new URL(localhostToAddress(`${address}/changes`));
|
|
71
|
-
const response = await fetch(url, auth);
|
|
72
|
-
if (!response.ok) {
|
|
73
|
-
const errorMessage = await createFetchErrorMessage(response, 'importFeatures failed');
|
|
74
|
-
throw new Error(errorMessage);
|
|
75
|
-
}
|
|
76
|
-
return response;
|
|
77
|
-
}
|
|
@@ -73,7 +73,7 @@ export default class Search extends BaseCommand {
|
|
|
73
73
|
if (flags.assembly === undefined) {
|
|
74
74
|
const asm = await queryApollo(access.address, access.accessToken, 'assemblies');
|
|
75
75
|
for (const x of (await asm.json())) {
|
|
76
|
-
assemblyIds.push(x
|
|
76
|
+
assemblyIds.push(x._id);
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
else {
|
package/dist/commands/login.js
CHANGED
|
@@ -55,7 +55,7 @@ export default class Login extends BaseCommand {
|
|
|
55
55
|
const { flags } = await this.parse(Login);
|
|
56
56
|
let configFile = flags['config-file'];
|
|
57
57
|
if (configFile === undefined) {
|
|
58
|
-
configFile = path.join(this.config.configDir, 'config.
|
|
58
|
+
configFile = path.join(this.config.configDir, 'config.yml');
|
|
59
59
|
}
|
|
60
60
|
let profileName = flags.profile;
|
|
61
61
|
if (profileName === undefined) {
|
package/dist/commands/logout.js
CHANGED
|
@@ -23,7 +23,7 @@ export default class Logout extends BaseCommand {
|
|
|
23
23
|
}
|
|
24
24
|
let configFile = flags['config-file'];
|
|
25
25
|
if (configFile === undefined) {
|
|
26
|
-
configFile = path.join(this.config.configDir, 'config.
|
|
26
|
+
configFile = path.join(this.config.configDir, 'config.yml');
|
|
27
27
|
}
|
|
28
28
|
basicCheckConfig(configFile, profileName);
|
|
29
29
|
const config = new ApolloConf(configFile);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseCommand } from '../../baseCommand.js';
|
|
2
|
+
export default class AddRefNameAlias extends BaseCommand<typeof AddRefNameAlias> {
|
|
3
|
+
static summary: string;
|
|
4
|
+
static description: string;
|
|
5
|
+
static examples: {
|
|
6
|
+
description: string;
|
|
7
|
+
command: string;
|
|
8
|
+
}[];
|
|
9
|
+
static flags: {
|
|
10
|
+
'input-file': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
11
|
+
assembly: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import { Agent, fetch } from 'undici';
|
|
3
|
+
import { Flags } from '@oclif/core';
|
|
4
|
+
import { BaseCommand } from '../../baseCommand.js';
|
|
5
|
+
import { createFetchErrorMessage, localhostToAddress, queryApollo, wrapLines, } from '../../utils.js';
|
|
6
|
+
import { ConfigError } from '../../ApolloConf.js';
|
|
7
|
+
export default class AddRefNameAlias extends BaseCommand {
|
|
8
|
+
static summary = 'Add reference name aliases from a file';
|
|
9
|
+
static description = wrapLines('Reference name aliasing is a process to make chromosomes that are named slightly differently but which refer to the same thing render properly. This command reads a file with reference name aliases and adds them to the database.');
|
|
10
|
+
static examples = [
|
|
11
|
+
{
|
|
12
|
+
description: 'Add reference name aliases:',
|
|
13
|
+
command: '<%= config.bin %> <%= command.id %> -i alias.txt -a myAssembly',
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
static flags = {
|
|
17
|
+
'input-file': Flags.string({
|
|
18
|
+
char: 'i',
|
|
19
|
+
description: 'Input refname alias file',
|
|
20
|
+
required: true,
|
|
21
|
+
}),
|
|
22
|
+
assembly: Flags.string({
|
|
23
|
+
char: 'a',
|
|
24
|
+
description: 'Name for this assembly.',
|
|
25
|
+
required: true,
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
28
|
+
async run() {
|
|
29
|
+
const { flags } = await this.parse(AddRefNameAlias);
|
|
30
|
+
if (!fs.existsSync(flags['input-file'])) {
|
|
31
|
+
this.error(`File ${flags['input-file']} does not exist`);
|
|
32
|
+
}
|
|
33
|
+
const access = await this.getAccess(flags['config-file'], flags.profile);
|
|
34
|
+
const filehandle = await fs.promises.open(flags['input-file']);
|
|
35
|
+
const fileContent = await filehandle.readFile({ encoding: 'utf8' });
|
|
36
|
+
await filehandle.close();
|
|
37
|
+
const lines = fileContent.split('\n');
|
|
38
|
+
const refNameAliases = [];
|
|
39
|
+
for (const line of lines) {
|
|
40
|
+
const [refName, ...aliases] = line.split('\t');
|
|
41
|
+
refNameAliases.push({ refName, aliases });
|
|
42
|
+
}
|
|
43
|
+
const assemblies = await queryApollo(access.address, access.accessToken, 'assemblies');
|
|
44
|
+
const json = (await assemblies.json());
|
|
45
|
+
const assembly = json.find((x) => 'name' in x && x.name === flags.assembly);
|
|
46
|
+
const assemblyId = assembly && '_id' in assembly ? assembly._id : undefined;
|
|
47
|
+
if (!assemblyId) {
|
|
48
|
+
this.error(`Assembly ${flags.assembly} not found`);
|
|
49
|
+
}
|
|
50
|
+
const change = {
|
|
51
|
+
typeName: 'AddRefSeqAliasesChange',
|
|
52
|
+
assembly: assemblyId,
|
|
53
|
+
refSeqAliases: refNameAliases,
|
|
54
|
+
};
|
|
55
|
+
const auth = {
|
|
56
|
+
method: 'POST',
|
|
57
|
+
body: JSON.stringify(change),
|
|
58
|
+
headers: {
|
|
59
|
+
Authorization: `Bearer ${access.accessToken}`,
|
|
60
|
+
'Content-Type': 'application/json',
|
|
61
|
+
},
|
|
62
|
+
dispatcher: new Agent({ headersTimeout: 60 * 60 * 1000 }),
|
|
63
|
+
};
|
|
64
|
+
const url = new URL(localhostToAddress(`${access.address}/changes`));
|
|
65
|
+
const response = await fetch(url, auth);
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
const errorMessage = await createFetchErrorMessage(response, 'Failed to add reference name aliases');
|
|
68
|
+
throw new ConfigError(errorMessage);
|
|
69
|
+
}
|
|
70
|
+
this.log(`Reference name aliases added successfully to assembly ${flags.assembly}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
package/dist/commands/status.js
CHANGED
|
@@ -15,7 +15,7 @@ export default class Status extends BaseCommand {
|
|
|
15
15
|
}
|
|
16
16
|
let configFile = flags['config-file'];
|
|
17
17
|
if (configFile === undefined) {
|
|
18
|
-
configFile = path.join(this.config.configDir, 'config.
|
|
18
|
+
configFile = path.join(this.config.configDir, 'config.yml');
|
|
19
19
|
}
|
|
20
20
|
basicCheckConfig(configFile, profileName);
|
|
21
21
|
const config = new ApolloConf(configFile);
|
|
@@ -7,7 +7,7 @@ const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
|
7
7
|
// TODO: Need valid token
|
|
8
8
|
describe.skip('apollo user get: Get users as YAML string', () => {
|
|
9
9
|
before(() => {
|
|
10
|
-
copyFile(`${TEST_DATA_DIR}/complete_config.
|
|
10
|
+
copyFile(`${TEST_DATA_DIR}/complete_config.yml`, CONFIG_FILE, VERBOSE);
|
|
11
11
|
});
|
|
12
12
|
after(() => {
|
|
13
13
|
fs.rmSync(CONFIG_FILE);
|
package/dist/test/fixtures.js
CHANGED
|
@@ -4,8 +4,8 @@ import path from 'node:path';
|
|
|
4
4
|
export const TEST_DATA_DIR = path.resolve('test_data');
|
|
5
5
|
export const VERBOSE = false;
|
|
6
6
|
export const CONFIG_DIR = path.join(os.homedir(), '.config', 'apollo-cli');
|
|
7
|
-
export const CONFIG_FILE = path.join(CONFIG_DIR, 'config.
|
|
8
|
-
const CONFIG_BAK = path.join(TEST_DATA_DIR, 'original.config.
|
|
7
|
+
export const CONFIG_FILE = path.join(CONFIG_DIR, 'config.yml');
|
|
8
|
+
const CONFIG_BAK = path.join(TEST_DATA_DIR, 'original.config.yml.bak');
|
|
9
9
|
function renameFile(src, dest, verbose = true) {
|
|
10
10
|
if (fs.existsSync(dest)) {
|
|
11
11
|
throw new Error(`File ${dest} already exists`);
|
package/dist/utils.d.ts
CHANGED
|
@@ -48,7 +48,7 @@ interface bodyExternalFile {
|
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
50
|
export declare function submitAssembly(address: string, accessToken: string, body: bodyLocalFile | bodyExternalFile, force: boolean): Promise<Response>;
|
|
51
|
-
export declare function uploadFile(address: string, accessToken: string, file: string, type: string): Promise<
|
|
51
|
+
export declare function uploadFile(address: string, accessToken: string, file: string, type: string): Promise<never>;
|
|
52
52
|
export declare function wrapLines(s: string, length?: number): string;
|
|
53
53
|
export declare function idReader(input: string[], removeDuplicates?: boolean): string[];
|
|
54
54
|
export {};
|
package/dist/utils.js
CHANGED
|
@@ -7,7 +7,9 @@ import * as crypto from 'node:crypto';
|
|
|
7
7
|
import * as fs from 'node:fs';
|
|
8
8
|
import * as os from 'node:os';
|
|
9
9
|
import * as path from 'node:path';
|
|
10
|
-
import {
|
|
10
|
+
import { Transform, pipeline, } from 'node:stream';
|
|
11
|
+
import { SingleBar } from 'cli-progress';
|
|
12
|
+
import { Agent, fetch } from 'undici';
|
|
11
13
|
import { ApolloConf, ConfigError } from './ApolloConf.js';
|
|
12
14
|
const CONFIG_PATH = path.resolve(os.homedir(), '.clirc');
|
|
13
15
|
export const CLI_SERVER_ADDRESS = 'http://127.0.0.1:5657';
|
|
@@ -61,6 +63,7 @@ export async function deleteAssembly(address, accessToken, assemblyId) {
|
|
|
61
63
|
Authorization: `Bearer ${accessToken}`,
|
|
62
64
|
'Content-Type': 'application/json',
|
|
63
65
|
},
|
|
66
|
+
dispatcher: new Agent({ headersTimeout: 60 * 60 * 1000 }),
|
|
64
67
|
};
|
|
65
68
|
const url = new URL(localhostToAddress(`${address}/changes`));
|
|
66
69
|
const response = await fetch(url, auth);
|
|
@@ -78,7 +81,7 @@ export async function getAssembly(address, accessToken, assemblyNameOrId) {
|
|
|
78
81
|
const assemblies = (await res.json());
|
|
79
82
|
let assemblyObj = {};
|
|
80
83
|
for (const x of assemblies) {
|
|
81
|
-
if (x
|
|
84
|
+
if (x._id === assemblyId[0]) {
|
|
82
85
|
assemblyObj = JSON.parse(JSON.stringify(x));
|
|
83
86
|
break;
|
|
84
87
|
}
|
|
@@ -128,11 +131,11 @@ export async function getRefseqId(address, accessToken, refseqNameOrId, inAssemb
|
|
|
128
131
|
}
|
|
129
132
|
async function checkNameToIdDict(address, accessToken) {
|
|
130
133
|
const asm = await queryApollo(address, accessToken, 'checks/types');
|
|
131
|
-
const ja = (await asm.json());
|
|
134
|
+
const ja = (await asm.json()); // Not sure if CheckResultSnapshot is the right interface
|
|
132
135
|
const nameToId = {};
|
|
133
136
|
for (const x of ja) {
|
|
134
|
-
const name = x['name']
|
|
135
|
-
nameToId[name] = x['_id']
|
|
137
|
+
const { _id, name } = x; // x['name' as keyof typeof x]
|
|
138
|
+
nameToId[name] = _id; // x['_id' as keyof typeof x]
|
|
136
139
|
}
|
|
137
140
|
return nameToId;
|
|
138
141
|
}
|
|
@@ -267,10 +270,6 @@ export async function submitAssembly(address, accessToken, body, force) {
|
|
|
267
270
|
}
|
|
268
271
|
}
|
|
269
272
|
}
|
|
270
|
-
const controller = new AbortController();
|
|
271
|
-
setTimeout(() => {
|
|
272
|
-
controller.abort();
|
|
273
|
-
}, 24 * 60 * 60 * 1000);
|
|
274
273
|
const auth = {
|
|
275
274
|
method: 'POST',
|
|
276
275
|
body: JSON.stringify(body),
|
|
@@ -278,7 +277,7 @@ export async function submitAssembly(address, accessToken, body, force) {
|
|
|
278
277
|
Authorization: `Bearer ${accessToken}`,
|
|
279
278
|
'Content-Type': 'application/json',
|
|
280
279
|
},
|
|
281
|
-
|
|
280
|
+
dispatcher: new Agent({ headersTimeout: 60 * 60 * 1000 }),
|
|
282
281
|
};
|
|
283
282
|
const url = new URL(localhostToAddress(`${address}/changes`));
|
|
284
283
|
const response = await fetch(url, auth);
|
|
@@ -288,32 +287,64 @@ export async function submitAssembly(address, accessToken, body, force) {
|
|
|
288
287
|
}
|
|
289
288
|
return response;
|
|
290
289
|
}
|
|
290
|
+
class ProgressTransform extends Transform {
|
|
291
|
+
size = 0;
|
|
292
|
+
progressBar;
|
|
293
|
+
constructor(opts) {
|
|
294
|
+
super(opts);
|
|
295
|
+
this.progressBar = opts.progressBar;
|
|
296
|
+
}
|
|
297
|
+
_transform(chunk, _encoding, callback) {
|
|
298
|
+
this.size += chunk.length;
|
|
299
|
+
this.progressBar.update(this.size);
|
|
300
|
+
callback(null, chunk);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
291
303
|
export async function uploadFile(address, accessToken, file, type) {
|
|
292
|
-
const
|
|
293
|
-
const
|
|
294
|
-
const
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
304
|
+
const filehandle = await fs.promises.open(file);
|
|
305
|
+
const { size } = await filehandle.stat();
|
|
306
|
+
const stream = filehandle.createReadStream();
|
|
307
|
+
const progressBar = new SingleBar({ etaBuffer: 100_000_000 });
|
|
308
|
+
const progressTransform = new ProgressTransform({ progressBar });
|
|
309
|
+
const body = pipeline(stream, progressTransform, (error) => {
|
|
310
|
+
if (error) {
|
|
311
|
+
progressBar.stop();
|
|
312
|
+
console.error('Error processing file.', error);
|
|
313
|
+
throw error;
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
const init = {
|
|
299
317
|
method: 'POST',
|
|
300
|
-
body
|
|
318
|
+
body,
|
|
319
|
+
duplex: 'half',
|
|
301
320
|
headers: {
|
|
302
321
|
Authorization: `Bearer ${accessToken}`,
|
|
322
|
+
'Content-Type': type,
|
|
323
|
+
'Content-Length': String(size),
|
|
303
324
|
},
|
|
304
|
-
dispatcher: new Agent({
|
|
305
|
-
keepAliveTimeout: 10 * 60 * 1000,
|
|
306
|
-
keepAliveMaxTimeout: 10 * 60 * 1000, // 10 minutes
|
|
307
|
-
}),
|
|
325
|
+
dispatcher: new Agent({ headersTimeout: 60 * 60 * 1000 }),
|
|
308
326
|
};
|
|
327
|
+
const fileName = path.basename(file);
|
|
309
328
|
const url = new URL(localhostToAddress(`${address}/files`));
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
329
|
+
url.searchParams.set('name', fileName);
|
|
330
|
+
url.searchParams.set('type', type);
|
|
331
|
+
progressBar.start(size, 0);
|
|
332
|
+
try {
|
|
333
|
+
const response = await fetch(url, init);
|
|
334
|
+
if (!response.ok) {
|
|
335
|
+
const errorMessage = await createFetchErrorMessage(response, 'uploadFile failed');
|
|
336
|
+
throw new ConfigError(errorMessage);
|
|
337
|
+
}
|
|
338
|
+
const json = (await response.json());
|
|
339
|
+
return json['_id'];
|
|
340
|
+
}
|
|
341
|
+
catch (error) {
|
|
342
|
+
console.error(error);
|
|
343
|
+
throw error;
|
|
344
|
+
}
|
|
345
|
+
finally {
|
|
346
|
+
progressBar.stop();
|
|
314
347
|
}
|
|
315
|
-
const json = (await response.json());
|
|
316
|
-
return json['_id'];
|
|
317
348
|
}
|
|
318
349
|
/* Wrap text to max `length` per line */
|
|
319
350
|
export function wrapLines(s, length) {
|