@super-protocol/sp-cli 0.0.2-beta.1 → 0.0.2-beta.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 +135 -321
- package/dist/commands/account/info.d.ts +21 -0
- package/dist/commands/account/info.js +43 -0
- package/dist/commands/auth/login.d.ts +1 -10
- package/dist/commands/auth/login.js +15 -84
- package/dist/commands/base.d.ts +2 -4
- package/dist/commands/base.js +8 -10
- package/dist/commands/config/add.js +9 -5
- package/dist/commands/config/base.d.ts +4 -3
- package/dist/commands/config/base.js +12 -14
- package/dist/commands/config/create.js +4 -4
- package/dist/commands/config/list.js +2 -2
- package/dist/commands/config/use.js +5 -3
- package/dist/commands/files/download.d.ts +15 -0
- package/dist/commands/files/download.js +53 -0
- package/dist/commands/files/upload.d.ts +18 -0
- package/dist/commands/files/upload.js +77 -0
- package/dist/commands/storage/base.d.ts +5 -0
- package/dist/commands/storage/base.js +113 -2
- package/dist/commands/storage/create.d.ts +0 -4
- package/dist/commands/storage/create.js +0 -116
- package/dist/commands/storage/select.js +12 -10
- package/dist/commands/storage/update.d.ts +0 -2
- package/dist/commands/storage/update.js +35 -87
- package/dist/config/config-file.schema.d.ts +4 -4
- package/dist/config/config-file.schema.js +1 -1
- package/dist/config/config.schema.d.ts +16 -16
- package/dist/config/config.schema.js +1 -10
- package/dist/config/resource.schema.d.ts +31 -0
- package/dist/config/resource.schema.js +14 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +1 -0
- package/dist/lib/container.d.ts +4 -6
- package/dist/lib/container.js +21 -21
- package/dist/managers/account-manager.js +13 -3
- package/dist/managers/config-file-manager.d.ts +1 -1
- package/dist/managers/config-file-manager.js +13 -8
- package/dist/services/auth.service.d.ts +24 -0
- package/dist/services/auth.service.js +93 -0
- package/dist/services/storage.service.d.ts +44 -7
- package/dist/services/storage.service.js +207 -12
- package/dist/utils/helper.d.ts +5 -0
- package/dist/utils/helper.js +22 -0
- package/dist/utils/progress.d.ts +8 -0
- package/dist/utils/progress.js +27 -0
- package/oclif.manifest.json +180 -184
- package/package.json +9 -7
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BaseCommand } from '../base.js';
|
|
2
|
+
export declare class InfoCommand extends BaseCommand<typeof InfoCommand> {
|
|
3
|
+
init(): Promise<void>;
|
|
4
|
+
run(): Promise<{
|
|
5
|
+
address: string;
|
|
6
|
+
balance: string;
|
|
7
|
+
storage: {
|
|
8
|
+
bucket: string;
|
|
9
|
+
createdAt: string;
|
|
10
|
+
id: string;
|
|
11
|
+
isCentralized: boolean;
|
|
12
|
+
prefix: string;
|
|
13
|
+
s3Credentials?: import("@super-protocol/provider-client").components["schemas"]["S3CredentialsResponseDto"];
|
|
14
|
+
storageType: import("@super-protocol/provider-client").components["schemas"]["StorageType"];
|
|
15
|
+
storjCredentials?: import("@super-protocol/provider-client").components["schemas"]["StorJCredentialsResponseDto"];
|
|
16
|
+
updatedAt: string;
|
|
17
|
+
userId: string;
|
|
18
|
+
};
|
|
19
|
+
wallet: string;
|
|
20
|
+
}>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { formatEther } from 'viem';
|
|
2
|
+
import { StorageService } from '../../services/storage.service.js';
|
|
3
|
+
import { BaseCommand } from '../base.js';
|
|
4
|
+
export class InfoCommand extends BaseCommand {
|
|
5
|
+
async init() {
|
|
6
|
+
await super.init();
|
|
7
|
+
await this.container.initProviderClient().initAccountManager().initConfigManager().build();
|
|
8
|
+
}
|
|
9
|
+
async run() {
|
|
10
|
+
const { providerClient } = this.container;
|
|
11
|
+
const storageService = new StorageService(providerClient, this.logger);
|
|
12
|
+
const { data, error } = await providerClient.GET('/api/auth/me');
|
|
13
|
+
if (error) {
|
|
14
|
+
this.error(error.message);
|
|
15
|
+
}
|
|
16
|
+
if (!data) {
|
|
17
|
+
this.error('Failed to retrieve account information');
|
|
18
|
+
}
|
|
19
|
+
const { data: wallet } = await providerClient.GET('/api/users/me/wallet');
|
|
20
|
+
if (!wallet) {
|
|
21
|
+
this.error('Failed to retrieve wallet information');
|
|
22
|
+
}
|
|
23
|
+
const storage = await storageService.getCurrentStorage();
|
|
24
|
+
const balance = formatEther(BigInt(wallet?.teeBalance || '0'), 'wei');
|
|
25
|
+
this.log(`Login: ${data.address}`);
|
|
26
|
+
this.log(`Super Wallet: ${data.internalAddress}`);
|
|
27
|
+
this.log(`Balance: ${balance} SPPI`);
|
|
28
|
+
if (storage.isCentralized) {
|
|
29
|
+
this.log('Storage: Super cloud');
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
this.log('Active storage:');
|
|
33
|
+
this.log(` bucket: ${storage.bucket}`);
|
|
34
|
+
this.log(` prefix: ${storage.prefix}`);
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
address: data.address,
|
|
38
|
+
balance,
|
|
39
|
+
storage,
|
|
40
|
+
wallet: data.internalAddress,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -1,18 +1,9 @@
|
|
|
1
1
|
import { BaseCommand } from '../base.js';
|
|
2
2
|
export default class SpLogin extends BaseCommand<typeof SpLogin> {
|
|
3
|
+
static aliases: string[];
|
|
3
4
|
static description: string;
|
|
4
5
|
static examples: string[];
|
|
5
6
|
checkStorage(): Promise<void>;
|
|
6
|
-
getTokens(nonce: string): Promise<void>;
|
|
7
|
-
getUserNonce(address: string): Promise<{
|
|
8
|
-
error: {
|
|
9
|
-
message: string;
|
|
10
|
-
statusCode: number;
|
|
11
|
-
} | undefined;
|
|
12
|
-
user: {
|
|
13
|
-
nonce?: string;
|
|
14
|
-
} | undefined;
|
|
15
|
-
}>;
|
|
16
7
|
init(): Promise<void>;
|
|
17
8
|
run(): Promise<void>;
|
|
18
9
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AuthService } from '../../services/auth.service.js';
|
|
2
2
|
import { StorageService } from '../../services/storage.service.js';
|
|
3
3
|
import { BaseCommand } from '../base.js';
|
|
4
4
|
export default class SpLogin extends BaseCommand {
|
|
5
|
+
static aliases = ['login'];
|
|
5
6
|
static description = 'Authorization';
|
|
6
7
|
static examples = [
|
|
7
8
|
`<%= config.bin %> <%= command.id %>
|
|
@@ -9,53 +10,13 @@ export default class SpLogin extends BaseCommand {
|
|
|
9
10
|
];
|
|
10
11
|
async checkStorage() {
|
|
11
12
|
await this.container.initProviderClient({ enableAuth: true, enableCookies: true, rebuild: true }).build();
|
|
12
|
-
const {
|
|
13
|
-
const storageService = new StorageService(
|
|
13
|
+
const { providerClient } = this.container;
|
|
14
|
+
const storageService = new StorageService(providerClient, this.logger);
|
|
14
15
|
if (!await storageService.hasStorage()) {
|
|
15
16
|
this.logger.info('Requesting default storage');
|
|
16
|
-
const
|
|
17
|
-
this.logger.info({
|
|
18
|
-
await storageService.saveStorage(
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
async getTokens(nonce) {
|
|
22
|
-
const { accountManager, configManager, providerClient } = this.container;
|
|
23
|
-
const signature = await accountManager.createSign(nonce);
|
|
24
|
-
const { data: tokenResponse, error, } = await providerClient.POST('/api/auth/token', {
|
|
25
|
-
body: {
|
|
26
|
-
address: accountManager.getAddress(),
|
|
27
|
-
provider: 'sp-cli',
|
|
28
|
-
signature,
|
|
29
|
-
},
|
|
30
|
-
});
|
|
31
|
-
if (error) {
|
|
32
|
-
this.logger.error({ err: error }, 'Token exchange failed');
|
|
33
|
-
ux.error('Authorization failed please try again later.');
|
|
34
|
-
}
|
|
35
|
-
const { accessToken } = tokenResponse || {};
|
|
36
|
-
if (!accessToken) {
|
|
37
|
-
this.logger.error({ response: tokenResponse }, 'Unexpected token response');
|
|
38
|
-
ux.error('Provider returned an unexpected token response.');
|
|
39
|
-
}
|
|
40
|
-
await configManager.setCredentials({ accessKey: accessToken });
|
|
41
|
-
this.log('Authorization successful');
|
|
42
|
-
}
|
|
43
|
-
async getUserNonce(address) {
|
|
44
|
-
const { providerClient } = this.container;
|
|
45
|
-
try {
|
|
46
|
-
const { data, error } = await providerClient.GET('/api/users/nonce/{address}', {
|
|
47
|
-
params: {
|
|
48
|
-
path: {
|
|
49
|
-
address,
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
this.logger.debug({ data, error }, 'Getting user nonce');
|
|
54
|
-
return { error, user: data };
|
|
55
|
-
}
|
|
56
|
-
catch (error) {
|
|
57
|
-
this.logger.error({ err: error }, 'Error request nonce');
|
|
58
|
-
ux.error('Connection failure, please try again later');
|
|
17
|
+
const { id, isCentralized, storageType } = await storageService.getCentralizedStorage();
|
|
18
|
+
this.logger.info({ id, isCentralized, storageType }, 'Requested new storage');
|
|
19
|
+
await storageService.saveStorage(id);
|
|
59
20
|
}
|
|
60
21
|
}
|
|
61
22
|
async init() {
|
|
@@ -63,48 +24,17 @@ export default class SpLogin extends BaseCommand {
|
|
|
63
24
|
await this.container
|
|
64
25
|
.initConfigManager()
|
|
65
26
|
.initAccountManager()
|
|
66
|
-
.initProviderClient({ enableAuth: false })
|
|
27
|
+
.initProviderClient({ enableAuth: false, enableCookies: true })
|
|
67
28
|
.build();
|
|
68
29
|
}
|
|
69
30
|
async run() {
|
|
70
|
-
const { accountManager, providerClient } = this.container;
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
this.logger.debug('Nonce error call sign up');
|
|
75
|
-
const { data: nonceResponse, error: signUpError } = await providerClient.POST('/api/auth/sign-up', {
|
|
76
|
-
body: {
|
|
77
|
-
address,
|
|
78
|
-
},
|
|
79
|
-
});
|
|
80
|
-
if (signUpError && signUpError.statusCode === 409) {
|
|
81
|
-
this.logger.debug({ signUpError }, 'Error signing up');
|
|
82
|
-
const { error: nonceError, user } = await this.getUserNonce(address);
|
|
83
|
-
this.logger.debug({ nonceError, user }, 'Requesting nonce again');
|
|
84
|
-
if (user && user.nonce)
|
|
85
|
-
await this.getTokens(user.nonce);
|
|
86
|
-
else
|
|
87
|
-
ux.error('User exists but nonce is unavailable. Please try again or contact support.');
|
|
88
|
-
}
|
|
89
|
-
else if (signUpError) {
|
|
90
|
-
this.logger.error({ signUpError }, 'Sign-up failed');
|
|
91
|
-
ux.error('Sign-up failed. Please try again later.');
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
const nonce = nonceResponse?.nonce;
|
|
95
|
-
if (!nonce) {
|
|
96
|
-
this.logger.error({ response: nonceResponse }, 'Unexpected sign-up response');
|
|
97
|
-
ux.error('Provider did not return a nonce.');
|
|
98
|
-
}
|
|
99
|
-
await this.getTokens(nonce);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
else if (user && user.nonce) {
|
|
103
|
-
this.logger.debug({ user }, 'Requesting for existed user');
|
|
104
|
-
await this.getTokens(user.nonce);
|
|
31
|
+
const { accountManager, configManager, providerClient } = this.container;
|
|
32
|
+
const authService = new AuthService(accountManager, configManager, providerClient, this.logger);
|
|
33
|
+
try {
|
|
34
|
+
await authService.auth();
|
|
105
35
|
}
|
|
106
|
-
|
|
107
|
-
|
|
36
|
+
catch (error) {
|
|
37
|
+
this.error(error, { exit: 1 });
|
|
108
38
|
}
|
|
109
39
|
try {
|
|
110
40
|
await this.checkStorage();
|
|
@@ -113,5 +43,6 @@ export default class SpLogin extends BaseCommand {
|
|
|
113
43
|
this.logger.error({ err: error }, 'Storage initialization failed');
|
|
114
44
|
this.warn('Storage initialization failed. You can set up storage later using "sp storage create" or "sp storage select".');
|
|
115
45
|
}
|
|
46
|
+
this.log('Successfully authorized');
|
|
116
47
|
}
|
|
117
48
|
}
|
package/dist/commands/base.d.ts
CHANGED
|
@@ -4,15 +4,13 @@ import { AppContainer } from '../lib/container.js';
|
|
|
4
4
|
export type CommandFlags<T extends typeof Command> = Interfaces.InferredFlags<T['flags'] & typeof BaseCommand['baseFlags']>;
|
|
5
5
|
export type CommandArgs<T extends typeof Command> = Interfaces.InferredArgs<T['args']>;
|
|
6
6
|
export declare abstract class BaseCommand<T extends typeof Command> extends Command {
|
|
7
|
-
static baseFlags:
|
|
8
|
-
config: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
9
|
-
url: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
10
|
-
};
|
|
7
|
+
static baseFlags: typeof Command.baseFlags;
|
|
11
8
|
static enableJsonFlag: boolean;
|
|
12
9
|
protected args: CommandArgs<T>;
|
|
13
10
|
protected container: AppContainer;
|
|
14
11
|
protected flags: CommandFlags<T>;
|
|
15
12
|
protected logger: pino.BaseLogger;
|
|
16
13
|
constructor(argv: string[], config: Config);
|
|
14
|
+
protected ensurePromptValue<T>(value: symbol | T, errorMessage?: string): T;
|
|
17
15
|
init(): Promise<void>;
|
|
18
16
|
}
|
package/dist/commands/base.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isCancel } from '@clack/prompts';
|
|
1
2
|
import { Command, Flags, } from '@oclif/core';
|
|
2
3
|
import { AppContainer } from '../lib/container.js';
|
|
3
4
|
import logger from '../logger.js';
|
|
@@ -8,11 +9,6 @@ export class BaseCommand extends Command {
|
|
|
8
9
|
required: false,
|
|
9
10
|
summary: 'Specify config file.',
|
|
10
11
|
}),
|
|
11
|
-
url: Flags.string({
|
|
12
|
-
helpGroup: 'GLOBAL',
|
|
13
|
-
required: false,
|
|
14
|
-
summary: 'Specify provider base URL.',
|
|
15
|
-
}),
|
|
16
12
|
};
|
|
17
13
|
static enableJsonFlag = true;
|
|
18
14
|
args;
|
|
@@ -23,14 +19,17 @@ export class BaseCommand extends Command {
|
|
|
23
19
|
super(argv, config);
|
|
24
20
|
this.logger = logger.getPino();
|
|
25
21
|
}
|
|
22
|
+
ensurePromptValue(value, errorMessage = 'Operation cancelled.') {
|
|
23
|
+
if (isCancel(value)) {
|
|
24
|
+
this.error(errorMessage);
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
26
28
|
async init() {
|
|
27
29
|
await super.init();
|
|
28
30
|
const { args, flags } = await this.parse({
|
|
29
31
|
args: this.ctor.args,
|
|
30
|
-
baseFlags:
|
|
31
|
-
...BaseCommand.baseFlags,
|
|
32
|
-
...super.ctor.baseFlags,
|
|
33
|
-
},
|
|
32
|
+
baseFlags: super.ctor.baseFlags,
|
|
34
33
|
enableJsonFlag: this.ctor.enableJsonFlag,
|
|
35
34
|
flags: this.ctor.flags,
|
|
36
35
|
strict: this.ctor.strict,
|
|
@@ -39,7 +38,6 @@ export class BaseCommand extends Command {
|
|
|
39
38
|
this.args = args;
|
|
40
39
|
this.container = AppContainer.container.setupRuntimeConfig({
|
|
41
40
|
configFile: flags.config,
|
|
42
|
-
url: flags.url,
|
|
43
41
|
});
|
|
44
42
|
}
|
|
45
43
|
}
|
|
@@ -48,7 +48,6 @@ export default class ConfigAdd extends BaseConfigCommand {
|
|
|
48
48
|
if (!existsSync(testPath)) {
|
|
49
49
|
return 'File does not exist';
|
|
50
50
|
}
|
|
51
|
-
return true;
|
|
52
51
|
},
|
|
53
52
|
});
|
|
54
53
|
}
|
|
@@ -66,15 +65,20 @@ export default class ConfigAdd extends BaseConfigCommand {
|
|
|
66
65
|
this.log(`Successfully imported configuration: ${displayName}`);
|
|
67
66
|
this.log(`Configuration file: ${importedFileName}`);
|
|
68
67
|
const shouldSwitch = this.flags.yes || await this.selectPrompt({
|
|
69
|
-
choices: [
|
|
70
|
-
{ name: 'Yes', value: true },
|
|
71
|
-
{ name: 'No', value: false },
|
|
72
|
-
],
|
|
73
68
|
message: 'Switch to this configuration now?',
|
|
69
|
+
options: [
|
|
70
|
+
{ label: 'Yes', value: true },
|
|
71
|
+
{ label: 'No', value: false },
|
|
72
|
+
],
|
|
74
73
|
});
|
|
75
74
|
if (shouldSwitch) {
|
|
76
75
|
await this.configFileManager.setCurrentConfig(importedFileName);
|
|
77
76
|
this.log(`Switched to configuration: ${displayName}`);
|
|
77
|
+
await this.container
|
|
78
|
+
.initConfigFileManager(true)
|
|
79
|
+
.initConfigManager(true)
|
|
80
|
+
.initAccountManager(true)
|
|
81
|
+
.build();
|
|
78
82
|
}
|
|
79
83
|
}
|
|
80
84
|
catch (error) {
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import type { Command } from '@oclif/core';
|
|
2
|
-
import {
|
|
2
|
+
import { select, text } from '@clack/prompts';
|
|
3
3
|
import type { ConfigFileManager } from '../../managers/config-file-manager.js';
|
|
4
4
|
import { BaseCommand } from '../base.js';
|
|
5
|
-
type
|
|
5
|
+
type TextOptions = Parameters<typeof text>[0];
|
|
6
6
|
type SelectOptions<T> = Parameters<typeof select<T>>[0];
|
|
7
7
|
export declare abstract class BaseConfigCommand<T extends typeof Command> extends BaseCommand<T> {
|
|
8
|
+
static baseFlags: {};
|
|
8
9
|
protected configFileManager: ConfigFileManager;
|
|
9
10
|
protected displayCurrentConfig(): void;
|
|
10
11
|
init(): Promise<void>;
|
|
11
|
-
protected inputPrompt(options:
|
|
12
|
+
protected inputPrompt(options: TextOptions): Promise<string>;
|
|
12
13
|
protected selectPrompt<Value>(options: SelectOptions<Value>): Promise<Value>;
|
|
13
14
|
}
|
|
14
15
|
export {};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { select, text } from '@clack/prompts';
|
|
2
|
+
import { PROVIDER_URL } from '../../constants.js';
|
|
2
3
|
import { BaseCommand } from '../base.js';
|
|
3
4
|
export class BaseConfigCommand extends BaseCommand {
|
|
5
|
+
static baseFlags = {};
|
|
4
6
|
configFileManager;
|
|
5
7
|
displayCurrentConfig() {
|
|
6
8
|
const current = this.configFileManager.getCurrentConfigFile();
|
|
@@ -20,25 +22,19 @@ export class BaseConfigCommand extends BaseCommand {
|
|
|
20
22
|
this.log(` Provider URL: ${configData.providerUrl}`);
|
|
21
23
|
}
|
|
22
24
|
else {
|
|
23
|
-
this.log(
|
|
25
|
+
this.log(` Provider URL: ${PROVIDER_URL} (using default)`);
|
|
24
26
|
}
|
|
25
27
|
if (configData.auth?.accessKey) {
|
|
26
|
-
this.log(' Authorization:
|
|
28
|
+
this.log(' Authorization: [OK] Configured');
|
|
27
29
|
}
|
|
28
30
|
else {
|
|
29
|
-
this.log(' Authorization:
|
|
31
|
+
this.log(' Authorization: [--] Not configured');
|
|
30
32
|
}
|
|
31
33
|
if (configData.account?.address) {
|
|
32
|
-
this.log(` Account:
|
|
34
|
+
this.log(` Account: [OK] ${configData.account.address}`);
|
|
33
35
|
}
|
|
34
36
|
else {
|
|
35
|
-
this.log(' Account:
|
|
36
|
-
}
|
|
37
|
-
if (configData.cookies) {
|
|
38
|
-
this.log(' Cookies: ✓ Stored');
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
this.log(' Cookies: ✗ None');
|
|
37
|
+
this.log(' Account: [--] Not configured');
|
|
42
38
|
}
|
|
43
39
|
}
|
|
44
40
|
}
|
|
@@ -54,9 +50,11 @@ export class BaseConfigCommand extends BaseCommand {
|
|
|
54
50
|
this.configFileManager = this.container.configFileManager;
|
|
55
51
|
}
|
|
56
52
|
async inputPrompt(options) {
|
|
57
|
-
|
|
53
|
+
const result = await text(options);
|
|
54
|
+
return this.ensurePromptValue(result);
|
|
58
55
|
}
|
|
59
56
|
async selectPrompt(options) {
|
|
60
|
-
|
|
57
|
+
const result = await select(options);
|
|
58
|
+
return this.ensurePromptValue(result);
|
|
61
59
|
}
|
|
62
60
|
}
|
|
@@ -33,11 +33,11 @@ export default class ConfigCreate extends BaseConfigCommand {
|
|
|
33
33
|
this.log(`Provider URL: ${url}`);
|
|
34
34
|
}
|
|
35
35
|
const shouldSwitch = yes || await this.selectPrompt({
|
|
36
|
-
choices: [
|
|
37
|
-
{ name: 'Yes', value: true },
|
|
38
|
-
{ name: 'No', value: false },
|
|
39
|
-
],
|
|
40
36
|
message: 'Switch to this configuration now?',
|
|
37
|
+
options: [
|
|
38
|
+
{ label: 'Yes', value: true },
|
|
39
|
+
{ label: 'No', value: false },
|
|
40
|
+
],
|
|
41
41
|
});
|
|
42
42
|
if (shouldSwitch) {
|
|
43
43
|
await this.configFileManager.setCurrentConfig(fileName);
|
|
@@ -23,10 +23,10 @@ export default class ConfigList extends BaseConfigCommand {
|
|
|
23
23
|
parts.push(`URL: ${configData.providerUrl}`);
|
|
24
24
|
}
|
|
25
25
|
if (configData.auth) {
|
|
26
|
-
parts.push('Auth:
|
|
26
|
+
parts.push('Auth: [OK]');
|
|
27
27
|
}
|
|
28
28
|
if (configData.account) {
|
|
29
|
-
parts.push(
|
|
29
|
+
parts.push(`Account: [OK] ${configData.account.address} `);
|
|
30
30
|
}
|
|
31
31
|
if (parts.length > 0) {
|
|
32
32
|
statusInfo = ` | ${parts.join(', ')}`;
|
|
@@ -6,17 +6,19 @@ export default class ConfigUse extends BaseConfigCommand {
|
|
|
6
6
|
];
|
|
7
7
|
async run() {
|
|
8
8
|
const configs = this.configFileManager.getConfigsWithNames();
|
|
9
|
+
const currentConfig = this.configFileManager.getCurrentConfigFile();
|
|
9
10
|
if (configs.length === 0) {
|
|
10
11
|
this.log('No configurations found');
|
|
11
12
|
this.log('Create a new configuration with: sp config create --name "Config Name"');
|
|
12
13
|
return;
|
|
13
14
|
}
|
|
14
15
|
const selected = await this.selectPrompt({
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
initialValue: currentConfig,
|
|
17
|
+
message: 'Select a configuration:',
|
|
18
|
+
options: configs.map(config => ({
|
|
19
|
+
label: config.name ?? config.file,
|
|
17
20
|
value: config.file,
|
|
18
21
|
})),
|
|
19
|
-
message: 'Select a configuration:',
|
|
20
22
|
});
|
|
21
23
|
await this.configFileManager.setCurrentConfig(selected);
|
|
22
24
|
const selectedConfig = configs.find(c => c.file === selected);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseCommand } from '../base.js';
|
|
2
|
+
export default class FilesDownload extends BaseCommand<typeof FilesDownload> {
|
|
3
|
+
static args: {
|
|
4
|
+
resourceFile: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
+
localDirectory: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static description: string;
|
|
8
|
+
static examples: string[];
|
|
9
|
+
static flags: {
|
|
10
|
+
'maximum-concurrent': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
static help: string;
|
|
13
|
+
init(): Promise<void>;
|
|
14
|
+
run(): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { StorageService } from '../../services/storage.service.js';
|
|
3
|
+
import { createProgressPrinter } from '../../utils/progress.js';
|
|
4
|
+
import { BaseCommand } from '../base.js';
|
|
5
|
+
export default class FilesDownload extends BaseCommand {
|
|
6
|
+
static args = {
|
|
7
|
+
resourceFile: Args.string({ description: 'Path to a resource file', required: true }),
|
|
8
|
+
// eslint-disable-next-line perfectionist/sort-objects
|
|
9
|
+
localDirectory: Args.string({ description: 'Path to save downloaded file', required: true }),
|
|
10
|
+
};
|
|
11
|
+
static description = 'describe the command here';
|
|
12
|
+
static examples = [
|
|
13
|
+
'<%= config.bin %> <%= command.id %> ./resource.json ./pathToDownload ',
|
|
14
|
+
];
|
|
15
|
+
static flags = {
|
|
16
|
+
'maximum-concurrent': Flags.integer({
|
|
17
|
+
default: 1, description: 'Maximum concurrent pieces to upload at once per transfer', max: 1000, min: 1,
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
static help = 'Download and decrypt a file from the remote storage to <localPath> using resource file <resourcePath>';
|
|
21
|
+
async init() {
|
|
22
|
+
await super.init();
|
|
23
|
+
await this.container.initProviderClient({ enableAuth: false }).initConfigManager().build();
|
|
24
|
+
}
|
|
25
|
+
async run() {
|
|
26
|
+
const { args, flags } = await this.parse(FilesDownload);
|
|
27
|
+
const { providerClient } = this.container;
|
|
28
|
+
const storageSerivce = new StorageService(providerClient, this.logger);
|
|
29
|
+
const progress = createProgressPrinter({
|
|
30
|
+
action: 'Download',
|
|
31
|
+
start: 'Downloading: ',
|
|
32
|
+
});
|
|
33
|
+
try {
|
|
34
|
+
await storageSerivce.download({
|
|
35
|
+
downloadPath: args.localDirectory,
|
|
36
|
+
maximumConcurrent: flags['maximum-concurrent'],
|
|
37
|
+
resourcePath: args.resourceFile,
|
|
38
|
+
}, ({ current, key, total }) => {
|
|
39
|
+
progress.advance(key, current / total * 100, `Downloading: ${key} [${current}/${total}]`);
|
|
40
|
+
});
|
|
41
|
+
progress.finish();
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
let reason = '';
|
|
45
|
+
this.logger.error({ err: error }, 'Error trying download');
|
|
46
|
+
if (error instanceof Error) {
|
|
47
|
+
reason = error.message;
|
|
48
|
+
}
|
|
49
|
+
this.error(`Download aborted. Reason: ${reason}`);
|
|
50
|
+
}
|
|
51
|
+
this.log('Download successful completed');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BaseCommand } from '../base.js';
|
|
2
|
+
export default class FilesUpload extends BaseCommand<typeof FilesUpload> {
|
|
3
|
+
static args: {
|
|
4
|
+
path: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
filename: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'maximum-concurrent': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
metadata: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
'skip-encryption': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
sync: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
};
|
|
16
|
+
init(): Promise<void>;
|
|
17
|
+
run(): Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { StorageService } from '../../services/storage.service.js';
|
|
3
|
+
import { createProgressPrinter } from '../../utils/progress.js';
|
|
4
|
+
import { BaseCommand } from '../base.js';
|
|
5
|
+
export default class FilesUpload extends BaseCommand {
|
|
6
|
+
static args = {
|
|
7
|
+
path: Args.string({ description: 'file or directory to upload', required: true }),
|
|
8
|
+
};
|
|
9
|
+
static description = 'describe the command here';
|
|
10
|
+
static examples = [
|
|
11
|
+
'<%= config.bin %> <%= command.id %> ./file.txt',
|
|
12
|
+
];
|
|
13
|
+
static flags = {
|
|
14
|
+
filename: Flags.string({
|
|
15
|
+
description: 'The name of the resulting file/directory in the storage',
|
|
16
|
+
required: false,
|
|
17
|
+
}),
|
|
18
|
+
'maximum-concurrent': Flags.integer({
|
|
19
|
+
default: 1, description: 'Maximum concurrent pieces to upload at once per transfer', max: 1000, min: 1,
|
|
20
|
+
}),
|
|
21
|
+
metadata: Flags.string({
|
|
22
|
+
description: 'Path to a metadata file for adding fields to the resource file',
|
|
23
|
+
required: false,
|
|
24
|
+
}),
|
|
25
|
+
output: Flags.string({
|
|
26
|
+
default: 'resource.json',
|
|
27
|
+
description: 'Path to save resource file that is used to access the uploaded file',
|
|
28
|
+
required: false,
|
|
29
|
+
}),
|
|
30
|
+
'skip-encryption': Flags.boolean({
|
|
31
|
+
default: false,
|
|
32
|
+
description: 'Skip file encryption before upload',
|
|
33
|
+
required: false,
|
|
34
|
+
}),
|
|
35
|
+
sync: Flags.boolean({
|
|
36
|
+
default: false,
|
|
37
|
+
description: 'Sync mode: delete files in target that don\'t exist in source',
|
|
38
|
+
required: false,
|
|
39
|
+
}),
|
|
40
|
+
};
|
|
41
|
+
async init() {
|
|
42
|
+
await super.init();
|
|
43
|
+
await this.container.initProviderClient().initConfigManager().build();
|
|
44
|
+
}
|
|
45
|
+
async run() {
|
|
46
|
+
const { args, flags } = await this.parse(FilesUpload);
|
|
47
|
+
const { providerClient } = this.container;
|
|
48
|
+
const storageSerivce = new StorageService(providerClient, this.logger);
|
|
49
|
+
const progress = createProgressPrinter({
|
|
50
|
+
action: 'Upload',
|
|
51
|
+
start: 'Uploading: ',
|
|
52
|
+
});
|
|
53
|
+
try {
|
|
54
|
+
await storageSerivce.upload({
|
|
55
|
+
localPath: args.path,
|
|
56
|
+
maximumConcurrent: flags['maximum-concurrent'],
|
|
57
|
+
metadataPath: flags.metadata,
|
|
58
|
+
outputPath: flags.output,
|
|
59
|
+
remotePath: flags.filename,
|
|
60
|
+
sync: flags.sync,
|
|
61
|
+
withEncryption: flags['skip-encryption'],
|
|
62
|
+
}, ({ current, key, total }) => {
|
|
63
|
+
progress.advance(key, current / total * 100, `Uploading: ${key} [${current}/${total}]`);
|
|
64
|
+
});
|
|
65
|
+
progress.finish();
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
let reason = '';
|
|
69
|
+
this.logger.error({ err: error }, 'Error trying upload');
|
|
70
|
+
if (error instanceof Error) {
|
|
71
|
+
reason = error.message;
|
|
72
|
+
}
|
|
73
|
+
this.error(`Upload aborted. Reason: ${reason}`);
|
|
74
|
+
}
|
|
75
|
+
this.log('Upload successful completed');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
+
import { AddStorageDto } from '@super-protocol/provider-client';
|
|
2
3
|
import { BaseCommand } from '../../commands/base.js';
|
|
3
4
|
import { StorageService } from '../../services/storage.service.js';
|
|
4
5
|
export declare abstract class BaseStorageCommand<T extends typeof Command> extends BaseCommand<T> {
|
|
5
6
|
protected currentDir: string;
|
|
6
7
|
protected storageService: StorageService;
|
|
7
8
|
init(): Promise<void>;
|
|
9
|
+
protected promptS3Credentials(): Promise<NonNullable<AddStorageDto['s3Credentials']>>;
|
|
10
|
+
protected promptStoragePayload(): Promise<AddStorageDto>;
|
|
11
|
+
protected promptStorJCredentials(): Promise<NonNullable<AddStorageDto['storjCredentials']>>;
|
|
12
|
+
protected validateStoragePayload(payload: Partial<AddStorageDto> | undefined): asserts payload is AddStorageDto;
|
|
8
13
|
}
|