@super-protocol/sp-cli 0.0.2-beta.1 → 0.0.2-beta.2
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 +53 -61
- package/dist/commands/account/info.d.ts +21 -0
- package/dist/commands/account/info.js +43 -0
- package/dist/commands/auth/login.d.ts +0 -10
- package/dist/commands/auth/login.js +13 -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/storage/base.js +2 -2
- package/dist/commands/storage/create.js +35 -35
- package/dist/commands/storage/select.js +10 -8
- package/dist/commands/storage/update.js +53 -48
- package/dist/lib/container.d.ts +4 -6
- package/dist/lib/container.js +21 -21
- package/dist/managers/account-manager.js +12 -2
- package/dist/managers/config-file-manager.d.ts +1 -1
- package/dist/managers/config-file-manager.js +12 -7
- package/dist/services/auth.service.d.ts +24 -0
- package/dist/services/auth.service.js +93 -0
- package/dist/services/storage.service.d.ts +17 -4
- package/dist/services/storage.service.js +72 -6
- package/oclif.manifest.json +39 -200
- package/package.json +3 -2
|
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { confirm, password } from '@
|
|
7
|
+
import { confirm, isCancel, password } from '@clack/prompts';
|
|
8
8
|
import { ux } from '@oclif/core';
|
|
9
9
|
import { Value } from '@sinclair/typebox/value';
|
|
10
10
|
import { Retryable } from 'typescript-retry-decorator';
|
|
@@ -69,6 +69,9 @@ export class AccountManager {
|
|
|
69
69
|
const ask = await confirm({
|
|
70
70
|
message: 'Do you want to create new one?',
|
|
71
71
|
});
|
|
72
|
+
if (isCancel(ask)) {
|
|
73
|
+
ux.error('Operation cancelled.', { exit: 1 });
|
|
74
|
+
}
|
|
72
75
|
if (ask) {
|
|
73
76
|
await this.promptAccount();
|
|
74
77
|
}
|
|
@@ -81,8 +84,15 @@ export class AccountManager {
|
|
|
81
84
|
const askPrivateKey = await confirm({
|
|
82
85
|
message: 'Do you want to input privateKey?',
|
|
83
86
|
});
|
|
87
|
+
if (isCancel(askPrivateKey)) {
|
|
88
|
+
ux.error('Operation cancelled.', { exit: 1 });
|
|
89
|
+
}
|
|
84
90
|
if (askPrivateKey) {
|
|
85
|
-
const
|
|
91
|
+
const privateKeyInput = await password({ message: 'Please input your privateKey for using in account' });
|
|
92
|
+
if (isCancel(privateKeyInput)) {
|
|
93
|
+
ux.error('Operation cancelled.', { exit: 1 });
|
|
94
|
+
}
|
|
95
|
+
const privateKey = privateKeyInput.trim();
|
|
86
96
|
try {
|
|
87
97
|
const account = await this.createFromKey(privateKey);
|
|
88
98
|
ux.stdout('Your privateKey will be used in config. Keypair created');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { confirm, select } from '@
|
|
1
|
+
import { confirm, isCancel, select } from '@clack/prompts';
|
|
2
2
|
import { ux } from '@oclif/core';
|
|
3
3
|
import { Value } from '@sinclair/typebox/value';
|
|
4
4
|
import * as fs from 'node:fs';
|
|
@@ -78,22 +78,27 @@ export class ConfigFileManager {
|
|
|
78
78
|
configToDelete = config.file;
|
|
79
79
|
}
|
|
80
80
|
else {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
const selection = await this.selectPrompt({
|
|
82
|
+
message: 'Select configuration to delete:',
|
|
83
|
+
options: configs.map(config => ({
|
|
84
|
+
label: config.name,
|
|
84
85
|
value: config.file,
|
|
85
86
|
})),
|
|
86
|
-
message: 'Select configuration to delete:',
|
|
87
87
|
});
|
|
88
|
+
if (isCancel(selection)) {
|
|
89
|
+
this.ux.stdout('Deletion cancelled');
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
configToDelete = selection;
|
|
88
93
|
}
|
|
89
94
|
const configToDeleteData = configs.find(c => c.file === configToDelete);
|
|
90
95
|
const displayName = configToDeleteData?.name || configToDelete;
|
|
91
96
|
if (!force) {
|
|
92
97
|
const confirmed = await this.confirmPrompt({
|
|
93
|
-
|
|
98
|
+
initialValue: false,
|
|
94
99
|
message: `Are you sure you want to delete configuration "${displayName}"?`,
|
|
95
100
|
});
|
|
96
|
-
if (!confirmed) {
|
|
101
|
+
if (isCancel(confirmed) || !confirmed) {
|
|
97
102
|
this.ux.stdout('Deletion cancelled');
|
|
98
103
|
return;
|
|
99
104
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ProviderClient } from '@super-protocol/provider-client';
|
|
2
|
+
import pino from 'pino';
|
|
3
|
+
import { AccountManager } from '../managers/account-manager.js';
|
|
4
|
+
import { ConfigManager } from '../managers/config-manager.js';
|
|
5
|
+
export declare class AuthError extends Error {
|
|
6
|
+
}
|
|
7
|
+
export declare class AuthService {
|
|
8
|
+
private readonly accountManager;
|
|
9
|
+
private readonly configManager;
|
|
10
|
+
private readonly providerClient;
|
|
11
|
+
private readonly logger;
|
|
12
|
+
constructor(accountManager: AccountManager, configManager: ConfigManager, providerClient: ProviderClient, logger: pino.BaseLogger);
|
|
13
|
+
auth(): Promise<void>;
|
|
14
|
+
getTokens(nonce: string): Promise<void>;
|
|
15
|
+
getUserNonce(address: string): Promise<{
|
|
16
|
+
error: {
|
|
17
|
+
message: string;
|
|
18
|
+
statusCode: number;
|
|
19
|
+
} | undefined;
|
|
20
|
+
user: {
|
|
21
|
+
nonce?: string;
|
|
22
|
+
} | undefined;
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export class AuthError extends Error {
|
|
2
|
+
}
|
|
3
|
+
export class AuthService {
|
|
4
|
+
accountManager;
|
|
5
|
+
configManager;
|
|
6
|
+
providerClient;
|
|
7
|
+
logger;
|
|
8
|
+
constructor(accountManager, configManager, providerClient, logger) {
|
|
9
|
+
this.accountManager = accountManager;
|
|
10
|
+
this.configManager = configManager;
|
|
11
|
+
this.providerClient = providerClient;
|
|
12
|
+
this.logger = logger;
|
|
13
|
+
}
|
|
14
|
+
async auth() {
|
|
15
|
+
const address = this.accountManager.getAddress();
|
|
16
|
+
const { error: nonceError, user } = await this.getUserNonce(address);
|
|
17
|
+
if (nonceError && nonceError.statusCode === 404) {
|
|
18
|
+
this.logger.debug('Nonce error call sign up');
|
|
19
|
+
const { data: nonceResponse, error: signUpError } = await this.providerClient.POST('/api/auth/sign-up', {
|
|
20
|
+
body: {
|
|
21
|
+
address,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
if (signUpError && signUpError.statusCode === 409) {
|
|
25
|
+
this.logger.debug({ signUpError }, 'Error signing up');
|
|
26
|
+
const { error: nonceError, user } = await this.getUserNonce(address);
|
|
27
|
+
this.logger.debug({ nonceError, user }, 'Requesting nonce again');
|
|
28
|
+
if (user && user.nonce) {
|
|
29
|
+
await this.getTokens(user.nonce);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
throw new AuthError('User exists but nonce is unavailable. Please try again or contact support.');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else if (signUpError) {
|
|
36
|
+
this.logger.error({ signUpError }, 'Sign-up failed');
|
|
37
|
+
throw new AuthError('Sign-up failed. Please try again later.');
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
const nonce = nonceResponse?.nonce;
|
|
41
|
+
if (!nonce) {
|
|
42
|
+
this.logger.error({ response: nonceResponse }, 'Unexpected sign-up response');
|
|
43
|
+
throw new AuthError('Provider did not return a nonce.');
|
|
44
|
+
}
|
|
45
|
+
await this.getTokens(nonce);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else if (user && user.nonce) {
|
|
49
|
+
this.logger.debug({ user }, 'Requesting for existed user');
|
|
50
|
+
await this.getTokens(user.nonce);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
throw new AuthError('Unable to retrieve authentication nonce. Please try again later or contact support if the issue persists.');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async getTokens(nonce) {
|
|
57
|
+
const signature = await this.accountManager.createSign(nonce);
|
|
58
|
+
const { data: tokenResponse, error, } = await this.providerClient.POST('/api/auth/token', {
|
|
59
|
+
body: {
|
|
60
|
+
address: this.accountManager.getAddress(),
|
|
61
|
+
provider: 'sp-cli',
|
|
62
|
+
signature,
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
if (error) {
|
|
66
|
+
this.logger.error({ err: error }, 'Token exchange failed');
|
|
67
|
+
throw new AuthError(error.message);
|
|
68
|
+
}
|
|
69
|
+
const { accessToken } = tokenResponse || {};
|
|
70
|
+
if (!accessToken) {
|
|
71
|
+
this.logger.error({ response: tokenResponse }, 'Unexpected token response');
|
|
72
|
+
throw new AuthError('Provider returned an unexpected token response.');
|
|
73
|
+
}
|
|
74
|
+
await this.configManager.setCredentials({ accessKey: accessToken });
|
|
75
|
+
}
|
|
76
|
+
async getUserNonce(address) {
|
|
77
|
+
try {
|
|
78
|
+
const { data, error } = await this.providerClient.GET('/api/users/nonce/{address}', {
|
|
79
|
+
params: {
|
|
80
|
+
path: {
|
|
81
|
+
address,
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
this.logger.debug({ data, error }, 'Getting user nonce');
|
|
86
|
+
return { error, user: data };
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
this.logger.error({ err: error }, 'Error request nonce');
|
|
90
|
+
throw new AuthError('Connection failure, please try again later');
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { AddStorageDto, ProviderClient, StorageResponseDto, UpdateStorageDto } from '@super-protocol/provider-client';
|
|
2
2
|
import pino from 'pino';
|
|
3
|
-
import { IConfigManager } from '../interfaces/config-manager.interface.js';
|
|
4
3
|
export declare class StorageError extends Error {
|
|
5
4
|
}
|
|
6
5
|
export declare class StoragesEmptyError extends StorageError {
|
|
@@ -9,12 +8,26 @@ export declare class StorageCreateError extends StorageError {
|
|
|
9
8
|
}
|
|
10
9
|
export declare class StorageUpdateError extends StorageError {
|
|
11
10
|
}
|
|
11
|
+
export declare class StorageGetError extends StorageError {
|
|
12
|
+
}
|
|
12
13
|
export declare class StorageService {
|
|
13
|
-
private readonly configManager;
|
|
14
14
|
private readonly providerClient;
|
|
15
15
|
private readonly logger;
|
|
16
|
-
constructor(
|
|
16
|
+
constructor(providerClient: ProviderClient, logger: pino.BaseLogger);
|
|
17
17
|
createStorage(storage: AddStorageDto): Promise<StorageResponseDto>;
|
|
18
|
+
getCentralizedStorage(): Promise<{
|
|
19
|
+
bucket: string;
|
|
20
|
+
createdAt: string;
|
|
21
|
+
id: string;
|
|
22
|
+
isCentralized: boolean;
|
|
23
|
+
prefix: string;
|
|
24
|
+
s3Credentials?: import("@super-protocol/provider-client").components["schemas"]["S3CredentialsResponseDto"];
|
|
25
|
+
storageType: import("@super-protocol/provider-client").components["schemas"]["StorageType"];
|
|
26
|
+
storjCredentials?: import("@super-protocol/provider-client").components["schemas"]["StorJCredentialsResponseDto"];
|
|
27
|
+
updatedAt: string;
|
|
28
|
+
userId: string;
|
|
29
|
+
} | undefined>;
|
|
30
|
+
getCurrentStorage(): Promise<StorageResponseDto>;
|
|
18
31
|
hasStorage(): Promise<boolean>;
|
|
19
32
|
initStorage(): Promise<{
|
|
20
33
|
bucket: string;
|
|
@@ -28,7 +41,7 @@ export declare class StorageService {
|
|
|
28
41
|
updatedAt: string;
|
|
29
42
|
userId: string;
|
|
30
43
|
}>;
|
|
31
|
-
|
|
44
|
+
requestStorages(): Promise<StorageResponseDto[]>;
|
|
32
45
|
saveStorage(selectedStorage: string): Promise<void>;
|
|
33
46
|
updateStorage(id: string, storage: UpdateStorageDto): Promise<StorageResponseDto>;
|
|
34
47
|
}
|
|
@@ -7,12 +7,12 @@ export class StorageCreateError extends StorageError {
|
|
|
7
7
|
}
|
|
8
8
|
export class StorageUpdateError extends StorageError {
|
|
9
9
|
}
|
|
10
|
+
export class StorageGetError extends StorageError {
|
|
11
|
+
}
|
|
10
12
|
export class StorageService {
|
|
11
|
-
configManager;
|
|
12
13
|
providerClient;
|
|
13
14
|
logger;
|
|
14
|
-
constructor(
|
|
15
|
-
this.configManager = configManager;
|
|
15
|
+
constructor(providerClient, logger) {
|
|
16
16
|
this.providerClient = providerClient;
|
|
17
17
|
this.logger = logger;
|
|
18
18
|
}
|
|
@@ -39,8 +39,55 @@ export class StorageService {
|
|
|
39
39
|
throw error_;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
+
async getCentralizedStorage() {
|
|
43
|
+
const storages = await this.requestStorages();
|
|
44
|
+
return storages.find(storage => storage.isCentralized);
|
|
45
|
+
}
|
|
46
|
+
async getCurrentStorage() {
|
|
47
|
+
try {
|
|
48
|
+
const { data, error } = await this.providerClient.GET('/api/user-settings');
|
|
49
|
+
if (error) {
|
|
50
|
+
throw new StorageGetError('Error getting storage');
|
|
51
|
+
}
|
|
52
|
+
const { activeStorageId } = data || {};
|
|
53
|
+
const storages = await this.requestStorages();
|
|
54
|
+
const storage = storages.find(storage => storage.id === activeStorageId);
|
|
55
|
+
if (!storage) {
|
|
56
|
+
throw new StorageError('Selected storage not found please select storage first');
|
|
57
|
+
}
|
|
58
|
+
return storage;
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
this.logger.error({ err: error }, 'Failed to get current storage');
|
|
62
|
+
const error_ = error instanceof StorageError ? error : new ProviderClientError('Request failed please try again later');
|
|
63
|
+
throw error_;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
42
66
|
async hasStorage() {
|
|
43
|
-
|
|
67
|
+
try {
|
|
68
|
+
const { data, error } = await this.providerClient.GET('/api/user-settings');
|
|
69
|
+
if (error && error.statusCode === 404) {
|
|
70
|
+
const storage = await this.getCentralizedStorage();
|
|
71
|
+
if (storage) {
|
|
72
|
+
await this.saveStorage(storage.id);
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
if (error) {
|
|
78
|
+
this.logger.error({ err: error }, 'Error checking storage');
|
|
79
|
+
throw new StorageError(`Error request storage ${error}`);
|
|
80
|
+
}
|
|
81
|
+
if (!data) {
|
|
82
|
+
throw new StorageError('Error request storage');
|
|
83
|
+
}
|
|
84
|
+
return Boolean(data.activeStorageId);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
this.logger.error({ err: error }, 'Storage initialization failed');
|
|
88
|
+
const error_ = error instanceof StorageError ? error : new ProviderClientError('Request failed please try again later');
|
|
89
|
+
throw error_;
|
|
90
|
+
}
|
|
44
91
|
}
|
|
45
92
|
async initStorage() {
|
|
46
93
|
this.logger.info('Requesting storage initialization');
|
|
@@ -50,6 +97,10 @@ export class StorageService {
|
|
|
50
97
|
this.logger.error({ err: result.error }, 'Failed to initialize storage');
|
|
51
98
|
throw new StorageCreateError(result.error.message);
|
|
52
99
|
}
|
|
100
|
+
if (!result.data) {
|
|
101
|
+
this.logger.error('Provider returned empty storage initialization response');
|
|
102
|
+
throw new StorageCreateError('Incorrect response');
|
|
103
|
+
}
|
|
53
104
|
this.logger.info('Storage initialized successfully');
|
|
54
105
|
return result.data;
|
|
55
106
|
}
|
|
@@ -59,7 +110,7 @@ export class StorageService {
|
|
|
59
110
|
throw error_;
|
|
60
111
|
}
|
|
61
112
|
}
|
|
62
|
-
async
|
|
113
|
+
async requestStorages() {
|
|
63
114
|
let data;
|
|
64
115
|
this.logger.info('Requesting available storages');
|
|
65
116
|
try {
|
|
@@ -84,7 +135,22 @@ export class StorageService {
|
|
|
84
135
|
}
|
|
85
136
|
async saveStorage(selectedStorage) {
|
|
86
137
|
this.logger.info({ selectedStorage }, 'Saving selected storage');
|
|
87
|
-
|
|
138
|
+
try {
|
|
139
|
+
const { data, error } = await this.providerClient.POST('/api/user-settings', {
|
|
140
|
+
body: {
|
|
141
|
+
activeStorageId: selectedStorage,
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
if (error) {
|
|
145
|
+
throw new StorageError(`User settings request error ${error?.message}`);
|
|
146
|
+
}
|
|
147
|
+
this.logger.info({ selectedStorage: data?.activeStorageId }, 'Selected storage saved successfully');
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
this.logger.error({ err: error }, 'Failed to save selected storage');
|
|
151
|
+
const error_ = error instanceof StorageError ? error : new ProviderClientError('Request failed please try again later');
|
|
152
|
+
throw error_;
|
|
153
|
+
}
|
|
88
154
|
}
|
|
89
155
|
async updateStorage(id, storage) {
|
|
90
156
|
this.logger.info({ storageId: id }, 'Updating storage');
|