@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
package/bin/dev.cmd ADDED
@@ -0,0 +1,3 @@
1
+ @echo off
2
+
3
+ node --loader ts-node/esm --no-warnings=ExperimentalWarning "%~dp0\dev" %*
package/bin/dev.js ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env -S node --loader ts-node/esm --no-warnings=ExperimentalWarning
2
+
3
+ // eslint-disable-next-line node/shebang
4
+ async function main() {
5
+ const {execute} = await import('@oclif/core')
6
+ await execute({development: true, dir: import.meta.url})
7
+ }
8
+
9
+ await main()
package/bin/run.cmd ADDED
@@ -0,0 +1,3 @@
1
+ @echo off
2
+
3
+ node "%~dp0\run" %*
package/bin/run.js ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+
3
+ async function main() {
4
+ const {execute} = await import('@oclif/core')
5
+ await execute({dir: import.meta.url})
6
+ }
7
+
8
+ await main()
@@ -0,0 +1,43 @@
1
+ import Joi from 'joi';
2
+ export declare class ConfigError extends Error {
3
+ }
4
+ interface BaseProfile {
5
+ address: string;
6
+ accessType: 'google' | 'microsoft' | 'guest';
7
+ accessToken: string;
8
+ }
9
+ interface RootProfile extends Omit<BaseProfile, 'accessType'> {
10
+ accessType: 'root';
11
+ rootCredentials: {
12
+ username: string;
13
+ password: string;
14
+ };
15
+ }
16
+ export type Profile = BaseProfile | RootProfile;
17
+ export declare enum KEYS {
18
+ address = "address",
19
+ accessType = "accessType",
20
+ accessToken = "accessToken",
21
+ rootCredentials_username = "rootCredentials.username",
22
+ rootCredentials_password = "rootCredentials.password"
23
+ }
24
+ export declare function optionDesc(): string[];
25
+ export declare class Config {
26
+ private configFile;
27
+ private profiles;
28
+ constructor(configFile: string);
29
+ private index;
30
+ private addProps;
31
+ private checkKey;
32
+ get(key: string, profileName: string): string;
33
+ set(key: string, value: string, profileName: string): void;
34
+ writeConfigFile(): void;
35
+ getProfileNames(): string[];
36
+ validate(): Joi.ValidationResult;
37
+ getAccess(profileName: string): Promise<{
38
+ address: string;
39
+ accessToken: string;
40
+ }>;
41
+ toString(): string;
42
+ }
43
+ export {};
package/dist/Config.js ADDED
@@ -0,0 +1,233 @@
1
+ /* eslint-disable @typescript-eslint/no-redundant-type-constituents */
2
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
3
+ /* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */
4
+ /* eslint-disable @typescript-eslint/restrict-template-expressions */
5
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
8
+ import Joi from 'joi';
9
+ import YAML, { YAMLParseError } from 'yaml';
10
+ import { checkProfileExists, queryApollo } from './utils.js';
11
+ export class ConfigError extends Error {
12
+ }
13
+ export var KEYS;
14
+ (function (KEYS) {
15
+ KEYS["address"] = "address";
16
+ KEYS["accessType"] = "accessType";
17
+ KEYS["accessToken"] = "accessToken";
18
+ KEYS["rootCredentials_username"] = "rootCredentials.username";
19
+ KEYS["rootCredentials_password"] = "rootCredentials.password";
20
+ })(KEYS || (KEYS = {}));
21
+ function optionDocs() {
22
+ const docs = [];
23
+ for (const v of Object.values(KEYS)) {
24
+ switch (v) {
25
+ case 'address': {
26
+ docs.push({
27
+ key: v,
28
+ description: 'Address and port e.g http://localhost:3999',
29
+ });
30
+ break;
31
+ }
32
+ case 'accessType': {
33
+ docs.push({
34
+ key: v,
35
+ description: 'How to access Apollo. accessType is typically one of: google, microsoft, guest, root. Allowed types depend on your Apollo setup',
36
+ });
37
+ break;
38
+ }
39
+ case 'accessToken': {
40
+ docs.push({
41
+ key: v,
42
+ description: 'Access token. Usually inserted by `apollo login`',
43
+ });
44
+ break;
45
+ }
46
+ case 'rootCredentials.username': {
47
+ docs.push({
48
+ key: v,
49
+ description: 'Username of root account. Only set this for "root" access type',
50
+ });
51
+ break;
52
+ }
53
+ case 'rootCredentials.password': {
54
+ docs.push({
55
+ key: v,
56
+ description: 'Password for root account. Only set this for "root" access type',
57
+ });
58
+ break;
59
+ }
60
+ default: {
61
+ throw new ConfigError(`Unexpected key: ${v}`);
62
+ }
63
+ }
64
+ }
65
+ return docs;
66
+ }
67
+ export function optionDesc() {
68
+ const docs = [];
69
+ for (const x of optionDocs()) {
70
+ docs.push(`- ${x.key}:\n${x.description}`);
71
+ }
72
+ return docs;
73
+ }
74
+ function isValidAddress(address) {
75
+ // const port: string | undefined = address.split(':').pop()
76
+ // if (port === undefined || /^\d+$/.test(port) === false) {
77
+ // return false
78
+ // }
79
+ let url;
80
+ try {
81
+ url = new URL(address);
82
+ }
83
+ catch {
84
+ return false;
85
+ }
86
+ if (url.protocol !== 'http:' && url.protocol !== 'https:') {
87
+ return false;
88
+ }
89
+ return true;
90
+ }
91
+ const profileSchema = Joi.object({
92
+ address: Joi.string()
93
+ .uri({ scheme: /https?/ })
94
+ .required(),
95
+ accessType: Joi.string()
96
+ .valid('google', 'microsoft', 'root', 'guest')
97
+ .required(),
98
+ accessToken: Joi.string(),
99
+ rootCredentials: Joi.object({
100
+ username: Joi.string().required(),
101
+ password: Joi.string().required(),
102
+ }).when('accessType', {
103
+ is: Joi.string().valid('root'),
104
+ // eslint-disable-next-line unicorn/no-thenable
105
+ then: Joi.required(),
106
+ otherwise: Joi.forbidden(),
107
+ }),
108
+ });
109
+ const configSchema = Joi.object().pattern(Joi.string(), profileSchema);
110
+ export class Config {
111
+ configFile;
112
+ profiles = {};
113
+ constructor(configFile) {
114
+ this.configFile = configFile;
115
+ if (fs.existsSync(configFile)) {
116
+ const data = fs.readFileSync(configFile, 'utf8').trim();
117
+ if (data !== '') {
118
+ let config;
119
+ try {
120
+ config = YAML.parse(data);
121
+ }
122
+ catch (error) {
123
+ if (error instanceof YAMLParseError) {
124
+ process.stderr.write('Error: Configuration file is probably invalid yaml format:\n');
125
+ process.stderr.write(error.message);
126
+ }
127
+ else if (error instanceof Error) {
128
+ process.stderr.write('Unexpected error:');
129
+ process.stderr.write(error.message);
130
+ }
131
+ // eslint-disable-next-line unicorn/no-process-exit
132
+ process.exit(1);
133
+ }
134
+ this.profiles = config;
135
+ }
136
+ }
137
+ }
138
+ index(obj, arr, value) {
139
+ if (typeof arr == 'string') {
140
+ return this.index(obj, arr.split('.'), value);
141
+ }
142
+ if (arr.length == 1 && value !== undefined) {
143
+ return (obj[arr[0]] = value);
144
+ }
145
+ if (arr.length === 0) {
146
+ return obj;
147
+ }
148
+ return this.index(obj[arr[0]], arr.slice(1), value);
149
+ }
150
+ addProps(obj, arr, value) {
151
+ // credit https://stackoverflow.com/questions/17643965/how-to-automatically-add-properties-to-an-object-that-is-undefined
152
+ if (typeof arr == 'string') {
153
+ arr = arr.split('.');
154
+ }
155
+ obj[arr[0]] = obj[arr[0]] || {};
156
+ const tmpObj = obj[arr[0]];
157
+ if (arr.length > 1) {
158
+ arr.shift();
159
+ this.addProps(tmpObj, arr, value);
160
+ }
161
+ else if (value !== undefined) {
162
+ obj[arr[0]] = value;
163
+ }
164
+ return obj;
165
+ }
166
+ checkKey(key) {
167
+ for (const x of Object.values(KEYS)) {
168
+ if (x === key) {
169
+ return;
170
+ }
171
+ }
172
+ throw new ConfigError(`Invalid configuration key: "${key}". Valid keys are:\n${Object.values('\n')}`);
173
+ }
174
+ get(key, profileName) {
175
+ this.checkKey(key);
176
+ const profile = this.profiles[profileName];
177
+ if (!profile) {
178
+ // throw new Error(`No profile name "${profileName}" found`)
179
+ return '';
180
+ }
181
+ this.addProps(profile, key);
182
+ const value = this.index(profile, key);
183
+ if (typeof value === 'object' && Object.keys(value).length === 0) {
184
+ // The key is valid but missing from config
185
+ return '';
186
+ }
187
+ return value;
188
+ }
189
+ set(key, value, profileName) {
190
+ this.checkKey(key);
191
+ if (key === KEYS[KEYS.address] && !isValidAddress(value)) {
192
+ throw new ConfigError(`"${value}" is not a valid value for "${key}"`);
193
+ }
194
+ const profile = this.profiles[profileName] ?? {};
195
+ this.profiles[profileName] = profile;
196
+ this.addProps(profile, key, value);
197
+ }
198
+ writeConfigFile() {
199
+ let APOLLO_DISABLE_CONFIG_CREATE = false;
200
+ if (process.env.APOLLO_DISABLE_CONFIG_CREATE !== undefined &&
201
+ process.env.APOLLO_DISABLE_CONFIG_CREATE !== '0') {
202
+ APOLLO_DISABLE_CONFIG_CREATE = true;
203
+ }
204
+ if (APOLLO_DISABLE_CONFIG_CREATE && !fs.existsSync(this.configFile)) {
205
+ throw new ConfigError('Configuration file does not exist yet, please create it as an empty file first.');
206
+ }
207
+ const yml = YAML.stringify(this.profiles);
208
+ fs.mkdirSync(path.dirname(this.configFile), { recursive: true });
209
+ fs.writeFileSync(this.configFile, yml);
210
+ }
211
+ getProfileNames() {
212
+ return Object.keys(this.profiles);
213
+ }
214
+ validate() {
215
+ return configSchema.validate(this.profiles);
216
+ }
217
+ async getAccess(profileName) {
218
+ checkProfileExists(profileName, this);
219
+ const address = this.get('address', profileName);
220
+ if (address === undefined || address.trim() === '') {
221
+ throw new ConfigError(`Profile "${profileName}" has no address. Please run "apollo config" to set it up.`);
222
+ }
223
+ const accessToken = this.get('accessToken', profileName);
224
+ if (accessToken === undefined || accessToken.trim() === '') {
225
+ throw new ConfigError(`Profile "${profileName}" has no access token. Please run "apollo login" to set it up.`);
226
+ }
227
+ await queryApollo(address, accessToken, 'assemblies');
228
+ return { address, accessToken };
229
+ }
230
+ toString() {
231
+ return YAML.stringify(this.profiles);
232
+ }
233
+ }
@@ -0,0 +1,21 @@
1
+ import { Command, Interfaces } from '@oclif/core';
2
+ export type Flags<T extends typeof Command> = Interfaces.InferredFlags<(typeof BaseCommand)['baseFlags'] & T['flags']>;
3
+ export type Args<T extends typeof Command> = Interfaces.InferredArgs<T['args']>;
4
+ export declare abstract class BaseCommand<T extends typeof Command> extends Command {
5
+ static baseFlags: {
6
+ profile: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
7
+ 'config-file': Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
8
+ };
9
+ protected flags: Flags<T>;
10
+ protected args: Args<T>;
11
+ init(): Promise<void>;
12
+ private getConfig;
13
+ getAccess(configFile: string | undefined, profileName: string | undefined): Promise<{
14
+ address: string;
15
+ accessToken: string;
16
+ }>;
17
+ protected catch(err: Error & {
18
+ exitCode?: number;
19
+ }): Promise<unknown>;
20
+ protected finally(_: Error | undefined): Promise<unknown>;
21
+ }
@@ -0,0 +1,62 @@
1
+ import path from 'node:path';
2
+ import { Command, Flags } from '@oclif/core';
3
+ import { Config, ConfigError } from './Config.js';
4
+ import { checkConfigfileExists } from './utils.js';
5
+ export class BaseCommand extends Command {
6
+ static baseFlags = {
7
+ profile: Flags.string({
8
+ description: 'Use credentials from this profile',
9
+ }),
10
+ 'config-file': Flags.string({
11
+ description: 'Use this config file (mostly for testing)',
12
+ }),
13
+ };
14
+ flags;
15
+ args;
16
+ async init() {
17
+ await super.init();
18
+ const { args, flags } = await this.parse({
19
+ flags: this.ctor.flags,
20
+ baseFlags: super.ctor.baseFlags,
21
+ args: this.ctor.args,
22
+ strict: this.ctor.strict,
23
+ });
24
+ this.flags = flags;
25
+ this.args = args;
26
+ }
27
+ getConfig(configFile) {
28
+ if (configFile === undefined) {
29
+ configFile = path.join(this.config.configDir, 'config.yaml');
30
+ }
31
+ checkConfigfileExists(configFile);
32
+ const config = new Config(configFile);
33
+ return config;
34
+ }
35
+ async getAccess(configFile, profileName) {
36
+ const config = this.getConfig(configFile);
37
+ if (profileName === undefined) {
38
+ profileName = process.env.APOLLO_PROFILE ?? 'default';
39
+ }
40
+ try {
41
+ return await config.getAccess(profileName);
42
+ }
43
+ catch (error) {
44
+ if (error instanceof ConfigError) {
45
+ this.logToStderr(error.message);
46
+ this.exit(1);
47
+ }
48
+ else {
49
+ throw error;
50
+ }
51
+ }
52
+ }
53
+ async catch(err) {
54
+ // add any custom logic to handle errors from the command
55
+ // or simply return the parent class error handling
56
+ return super.catch(err);
57
+ }
58
+ async finally(_) {
59
+ // called after run and catch regardless of whether or not the command errored
60
+ return super.finally(_);
61
+ }
62
+ }
@@ -0,0 +1,15 @@
1
+ import { BaseCommand } from '../../baseCommand.js';
2
+ export default class Get extends BaseCommand<typeof Get> {
3
+ static description: string;
4
+ static examples: {
5
+ description: string;
6
+ command: string;
7
+ }[];
8
+ static flags: {
9
+ 'input-file': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
10
+ assembly: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
11
+ index: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
12
+ force: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
13
+ };
14
+ run(): Promise<void>;
15
+ }
@@ -0,0 +1,98 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
2
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
3
+ import * as fs from 'node:fs';
4
+ import * as path from 'node:path';
5
+ import { Flags } from '@oclif/core';
6
+ import { ObjectId } from 'bson';
7
+ import { BaseCommand } from '../../baseCommand.js';
8
+ import { submitAssembly, uploadFile, wrapLines } from '../../utils.js';
9
+ export default class Get extends BaseCommand {
10
+ static description = 'Add new assembly from local or external fasta file';
11
+ static examples = [
12
+ {
13
+ description: wrapLines('From local file:'),
14
+ command: '<%= config.bin %> <%= command.id %> -i genome.fa -a myAssembly',
15
+ },
16
+ {
17
+ description: wrapLines('From external source we also need the URL of the index:'),
18
+ command: '<%= config.bin %> <%= command.id %> -i https://.../genome.fa -x https://.../genome.fa.fai -a myAssembly',
19
+ },
20
+ ];
21
+ static flags = {
22
+ 'input-file': Flags.string({
23
+ char: 'i',
24
+ description: 'Input fasta file',
25
+ required: true,
26
+ }),
27
+ assembly: Flags.string({
28
+ char: 'a',
29
+ description: 'Name for this assembly. Use the file name if omitted',
30
+ }),
31
+ index: Flags.string({
32
+ char: 'x',
33
+ description: 'URL of the index. Required if input is an external source and ignored if input is a local file',
34
+ }),
35
+ force: Flags.boolean({
36
+ char: 'f',
37
+ description: 'Delete existing assembly, if it exists',
38
+ }),
39
+ };
40
+ async run() {
41
+ const { flags } = await this.parse(Get);
42
+ const access = await this.getAccess(flags['config-file'], flags.profile);
43
+ const assemblyName = flags.assembly ?? path.basename(flags['input-file']);
44
+ const isExternal = isValidHttpUrl(flags['input-file']);
45
+ let response;
46
+ if (isExternal) {
47
+ if (flags.index === undefined) {
48
+ this.logToStderr('Please provide the URL to the index of the external fasta file');
49
+ this.exit(1);
50
+ }
51
+ const body = {
52
+ assemblyName,
53
+ typeName: 'AddAssemblyFromExternalChange',
54
+ externalLocation: {
55
+ fa: flags['input-file'],
56
+ fai: flags.index,
57
+ },
58
+ };
59
+ response = (await submitAssembly(access.address, access.accessToken, body, flags.force));
60
+ }
61
+ else {
62
+ if (!isExternal && !fs.existsSync(flags['input-file'])) {
63
+ this.logToStderr(`File ${flags['input-file']} does not exist`);
64
+ this.exit(1);
65
+ }
66
+ try {
67
+ const fileId = await uploadFile(access.address, access.accessToken, flags['input-file'], 'text/x-fasta');
68
+ const body = {
69
+ assemblyName,
70
+ fileId,
71
+ typeName: 'AddAssemblyFromFileChange',
72
+ assembly: new ObjectId().toHexString(),
73
+ };
74
+ response = (await submitAssembly(access.address, access.accessToken, body, flags.force));
75
+ }
76
+ catch (error) {
77
+ this.logToStderr(error.message);
78
+ this.exit(1);
79
+ }
80
+ }
81
+ if (!response.ok) {
82
+ const json = JSON.parse(await response.text());
83
+ this.logToStderr(JSON.stringify(json, null, 2));
84
+ this.exit(1);
85
+ }
86
+ this.exit(0);
87
+ }
88
+ }
89
+ function isValidHttpUrl(x) {
90
+ let url;
91
+ try {
92
+ url = new URL(x);
93
+ }
94
+ catch {
95
+ return false;
96
+ }
97
+ return url.protocol === 'http:' || url.protocol === 'https:';
98
+ }
@@ -0,0 +1,16 @@
1
+ import { BaseCommand } from '../../baseCommand.js';
2
+ export default class AddGff extends BaseCommand<typeof AddGff> {
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 | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
12
+ 'omit-features': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
13
+ force: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
14
+ };
15
+ run(): Promise<void>;
16
+ }
@@ -0,0 +1,76 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
2
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
3
+ import * as fs from 'node:fs';
4
+ import * as path from 'node:path';
5
+ import { Flags } from '@oclif/core';
6
+ import { ObjectId } from 'bson';
7
+ import { BaseCommand } from '../../baseCommand.js';
8
+ import { submitAssembly, uploadFile, wrapLines } from '../../utils.js';
9
+ export default class AddGff extends BaseCommand {
10
+ static summary = 'Add new assembly from gff or gft file';
11
+ static description = wrapLines('The gff file is expected to contain sequences as per gff specifications. Features are also imported by default.');
12
+ static examples = [
13
+ {
14
+ description: 'Import sequences and features:',
15
+ command: '<%= config.bin %> <%= command.id %> -i genome.gff -a myAssembly',
16
+ },
17
+ {
18
+ description: 'Import sequences only:',
19
+ command: '<%= config.bin %> <%= command.id %> -i genome.gff -a myAssembly -o',
20
+ },
21
+ ];
22
+ static flags = {
23
+ 'input-file': Flags.string({
24
+ char: 'i',
25
+ description: 'Input gff or gtf file',
26
+ required: true,
27
+ }),
28
+ assembly: Flags.string({
29
+ char: 'a',
30
+ description: 'Name for this assembly. Use the file name if omitted',
31
+ }),
32
+ 'omit-features': Flags.boolean({
33
+ char: 'o',
34
+ description: 'Do not import features, only upload the sequences',
35
+ }),
36
+ force: Flags.boolean({
37
+ char: 'f',
38
+ description: 'Delete existing assembly, if it exists',
39
+ }),
40
+ };
41
+ async run() {
42
+ const { flags } = await this.parse(AddGff);
43
+ if (!fs.existsSync(flags['input-file'])) {
44
+ this.logToStderr(`File ${flags['input-file']} does not exist`);
45
+ this.exit(1);
46
+ }
47
+ const access = await this.getAccess(flags['config-file'], flags.profile);
48
+ const fileId = await uploadFile(access.address, access.accessToken, flags['input-file'], 'text/x-gff3');
49
+ let typeName = 'AddAssemblyAndFeaturesFromFileChange';
50
+ if (flags['omit-features']) {
51
+ typeName = 'AddAssemblyFromFileChange';
52
+ }
53
+ const assemblyName = flags.assembly ?? path.basename(flags['input-file']);
54
+ let res;
55
+ try {
56
+ const body = {
57
+ assemblyName,
58
+ fileId,
59
+ typeName,
60
+ assembly: new ObjectId().toHexString(),
61
+ };
62
+ res = await submitAssembly(access.address, access.accessToken, body, flags.force);
63
+ }
64
+ catch (error) {
65
+ this.logToStderr(error.message);
66
+ this.exit(1);
67
+ }
68
+ if (!res.ok) {
69
+ const json = JSON.parse(await res.text());
70
+ const message = json['message'];
71
+ this.logToStderr(message);
72
+ this.exit(1);
73
+ }
74
+ this.exit(0);
75
+ }
76
+ }
@@ -0,0 +1,15 @@
1
+ import { BaseCommand } from '../../baseCommand.js';
2
+ export default class Check extends BaseCommand<typeof Check> {
3
+ static summary: string;
4
+ static description: string;
5
+ static examples: {
6
+ description: string;
7
+ command: string;
8
+ }[];
9
+ static flags: {
10
+ assembly: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
11
+ check: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
12
+ delete: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
13
+ };
14
+ run(): Promise<void>;
15
+ }