@super-protocol/sp-cli 0.0.6 → 0.0.7
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 +97 -229
- package/dist/commands/account/base.d.ts +20 -0
- package/dist/commands/account/base.js +49 -0
- package/dist/commands/{config/delete.d.ts → account/forget.d.ts} +5 -2
- package/dist/commands/{config/delete.js → account/forget.js} +12 -5
- package/dist/commands/account/get-sppi.d.ts +2 -2
- package/dist/commands/account/get-sppi.js +8 -13
- package/dist/commands/account/info.d.ts +5 -2
- package/dist/commands/account/info.js +53 -3
- package/dist/commands/account/list.d.ts +9 -0
- package/dist/commands/{config → account}/list.js +16 -9
- package/dist/commands/account/login.d.ts +35 -0
- package/dist/commands/account/login.js +254 -0
- package/dist/commands/account/switch.d.ts +12 -0
- package/dist/commands/account/switch.js +40 -0
- package/dist/commands/base.d.ts +4 -3
- package/dist/commands/base.js +3 -1
- package/dist/commands/files/download.js +13 -5
- package/dist/commands/files/upload.js +11 -7
- package/dist/commands/storage/base.d.ts +2 -2
- package/dist/commands/storage/create.js +1 -1
- package/dist/commands/storage/select.js +3 -5
- package/dist/commands/storage/show.js +2 -4
- package/dist/commands/storage/update.js +31 -14
- package/dist/commands/workflows/extend-lease.d.ts +1 -1
- package/dist/commands/workflows/extend-lease.js +19 -10
- package/dist/config/config-file.schema.d.ts +1 -2
- package/dist/config/config-file.schema.js +0 -1
- package/dist/config/config.schema.d.ts +1 -1
- package/dist/errors.d.ts +2 -0
- package/dist/errors.js +2 -0
- package/dist/hooks/finally/shutdown-blockchain.d.ts +1 -1
- package/dist/hooks/finally/shutdown-blockchain.js +1 -1
- package/dist/hooks/finally/unlock-config.d.ts +3 -0
- package/dist/hooks/finally/unlock-config.js +5 -0
- package/dist/hooks/init/init-container.d.ts +1 -1
- package/dist/hooks/init/init-container.js +2 -3
- package/dist/hooks/init/lock-config.d.ts +3 -0
- package/dist/hooks/init/lock-config.js +19 -0
- package/dist/hooks/prerun/auth.d.ts +3 -0
- package/dist/hooks/prerun/auth.js +70 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/interfaces/account-manager.interface.d.ts +1 -1
- package/dist/interfaces/config-manager.interface.d.ts +2 -2
- package/dist/lib/cli-instance-lock.d.ts +2 -0
- package/dist/lib/cli-instance-lock.js +37 -0
- package/dist/lib/container.d.ts +6 -4
- package/dist/lib/container.js +108 -38
- package/dist/logger.d.ts +1 -1
- package/dist/logger.js +4 -1
- package/dist/managers/account-manager.d.ts +7 -8
- package/dist/managers/account-manager.js +20 -45
- package/dist/managers/config-file-manager.d.ts +6 -7
- package/dist/managers/config-file-manager.js +35 -32
- package/dist/managers/config-manager.d.ts +5 -5
- package/dist/managers/config-manager.js +5 -2
- package/dist/middlewares/auth-middleware.d.ts +1 -1
- package/dist/services/auth.service.d.ts +10 -15
- package/dist/services/auth.service.js +71 -5
- package/dist/services/storage.service.d.ts +3 -3
- package/dist/services/storage.service.js +46 -19
- package/dist/utils/helper.d.ts +1 -0
- package/dist/utils/helper.js +15 -1
- package/oclif.manifest.json +258 -399
- package/package.json +17 -24
- package/dist/commands/auth/login.d.ts +0 -12
- package/dist/commands/auth/login.js +0 -50
- package/dist/commands/auth/me.d.ts +0 -5
- package/dist/commands/auth/me.js +0 -16
- package/dist/commands/config/add.d.ts +0 -13
- package/dist/commands/config/add.js +0 -73
- package/dist/commands/config/base.d.ts +0 -16
- package/dist/commands/config/base.js +0 -78
- package/dist/commands/config/create.d.ts +0 -11
- package/dist/commands/config/create.js +0 -41
- package/dist/commands/config/index.d.ts +0 -6
- package/dist/commands/config/index.js +0 -22
- package/dist/commands/config/list.d.ts +0 -6
- package/dist/commands/config/show.d.ts +0 -6
- package/dist/commands/config/show.js +0 -10
- package/dist/commands/config/use.d.ts +0 -6
- package/dist/commands/config/use.js +0 -27
package/dist/lib/container.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
1
2
|
import { createProviderClient, loggerMiddleware, requestIdMiddleware, } from '@super-protocol/provider-client';
|
|
2
3
|
import { BlockchainConnector } from '@super-protocol/sdk-js';
|
|
3
|
-
import path from 'node:path';
|
|
4
4
|
import { PROVIDER_URL } from '../constants.js';
|
|
5
5
|
import logger from '../logger.js';
|
|
6
|
-
import { AccountManager, ConfigFileManager, ConfigManager
|
|
6
|
+
import { AccountManager, ConfigFileManager, ConfigManager } from '../managers/index.js';
|
|
7
7
|
import { createAuthMiddleware } from '../middlewares/auth-middleware.js';
|
|
8
8
|
import { createCookieMiddleware } from '../middlewares/cookies-middleware.js';
|
|
9
9
|
export class AppContainer {
|
|
@@ -14,9 +14,10 @@ export class AppContainer {
|
|
|
14
14
|
_configFileManager;
|
|
15
15
|
_configManager;
|
|
16
16
|
_providerClient;
|
|
17
|
-
|
|
17
|
+
providerClientOptions;
|
|
18
18
|
initQueue = new Map();
|
|
19
19
|
logger;
|
|
20
|
+
providerClientInitToken = 0;
|
|
20
21
|
runtimeConfigFile;
|
|
21
22
|
constructor(cwdDir, oclifConfig) {
|
|
22
23
|
this.cwdDir = cwdDir;
|
|
@@ -60,16 +61,19 @@ export class AppContainer {
|
|
|
60
61
|
return this._providerClient;
|
|
61
62
|
}
|
|
62
63
|
async build() {
|
|
63
|
-
await Promise.all(this.
|
|
64
|
+
await Promise.all(this.initQueue.values());
|
|
64
65
|
return this;
|
|
65
66
|
}
|
|
66
67
|
initAccountManager(rebuild = true) {
|
|
67
68
|
this.initConfigManager(rebuild);
|
|
68
69
|
return this.queueInit('accountManager', async () => {
|
|
69
|
-
await this.waitFor('configManager');
|
|
70
|
-
if (this._accountManager) {
|
|
70
|
+
await this.waitFor('configManager', { required: true });
|
|
71
|
+
if (this._accountManager && !rebuild) {
|
|
71
72
|
return;
|
|
72
73
|
}
|
|
74
|
+
if (rebuild) {
|
|
75
|
+
this._accountManager = undefined;
|
|
76
|
+
}
|
|
73
77
|
this.logger.info('Initializing account manager');
|
|
74
78
|
const accountManager = new AccountManager(this.configManager, this.logger);
|
|
75
79
|
await accountManager.init();
|
|
@@ -79,11 +83,11 @@ export class AppContainer {
|
|
|
79
83
|
initBlockchainConnector() {
|
|
80
84
|
this.initConfigManager();
|
|
81
85
|
return this.queueInit('blockchainConnector', async () => {
|
|
82
|
-
await this.waitFor('configManager');
|
|
86
|
+
await this.waitFor('configManager', { required: true });
|
|
83
87
|
let blockchainConfig = await this.configManager.get('blockchain');
|
|
84
88
|
if (!blockchainConfig) {
|
|
85
|
-
await this.
|
|
86
|
-
const { data, error } = await
|
|
89
|
+
const client = await this.getProviderClientForBootstrap();
|
|
90
|
+
const { data, error } = await client.GET('/api/config');
|
|
87
91
|
if (error || !data) {
|
|
88
92
|
throw new Error('Could not get configuration from provider');
|
|
89
93
|
}
|
|
@@ -99,9 +103,12 @@ export class AppContainer {
|
|
|
99
103
|
}
|
|
100
104
|
initConfigFileManager(rebuild = false) {
|
|
101
105
|
return this.queueInit('configFileManager', async () => {
|
|
102
|
-
if (this._configFileManager) {
|
|
106
|
+
if (this._configFileManager && !rebuild) {
|
|
103
107
|
return;
|
|
104
108
|
}
|
|
109
|
+
if (rebuild) {
|
|
110
|
+
this._configFileManager = undefined;
|
|
111
|
+
}
|
|
105
112
|
const configFileManager = new ConfigFileManager(this.oclifConfig.configDir, this.logger, {
|
|
106
113
|
runtimeConfigFile: this.runtimeConfigFile,
|
|
107
114
|
});
|
|
@@ -112,10 +119,13 @@ export class AppContainer {
|
|
|
112
119
|
initConfigManager(rebuild = false) {
|
|
113
120
|
this.initConfigFileManager(rebuild);
|
|
114
121
|
return this.queueInit('configManager', async () => {
|
|
115
|
-
await this.waitFor('configFileManager');
|
|
116
|
-
if (this._configManager) {
|
|
122
|
+
await this.waitFor('configFileManager', { required: true });
|
|
123
|
+
if (this._configManager && !rebuild) {
|
|
117
124
|
return;
|
|
118
125
|
}
|
|
126
|
+
if (rebuild) {
|
|
127
|
+
this._configManager = undefined;
|
|
128
|
+
}
|
|
119
129
|
const configFilePath = await this.configFileManager.getCurrentConfigPath();
|
|
120
130
|
if (!configFilePath) {
|
|
121
131
|
throw new Error('Config file not found');
|
|
@@ -126,14 +136,30 @@ export class AppContainer {
|
|
|
126
136
|
this._configManager = configManager;
|
|
127
137
|
}, rebuild);
|
|
128
138
|
}
|
|
129
|
-
initProviderClient({ enableAuth = true, enableCookies = true, rebuild = false } = {}) {
|
|
139
|
+
initProviderClient({ enableAuth = true, enableCookies = true, rebuild = false, } = {}) {
|
|
130
140
|
this.initConfigManager();
|
|
141
|
+
const options = { enableAuth, enableCookies };
|
|
142
|
+
const optionsChanged = this.providerClientOptions &&
|
|
143
|
+
(this.providerClientOptions.enableAuth !== options.enableAuth ||
|
|
144
|
+
this.providerClientOptions.enableCookies !== options.enableCookies);
|
|
145
|
+
if (optionsChanged) {
|
|
146
|
+
rebuild = true;
|
|
147
|
+
this.logger.debug({ newOptions: options, oldOptions: this.providerClientOptions }, 'Provider client options changed, rebuilding');
|
|
148
|
+
}
|
|
149
|
+
const shouldSchedule = rebuild || !this.initQueue.has('providerClient');
|
|
150
|
+
const initToken = shouldSchedule
|
|
151
|
+
? ++this.providerClientInitToken
|
|
152
|
+
: this.providerClientInitToken;
|
|
131
153
|
return this.queueInit('providerClient', async () => {
|
|
132
154
|
if (this._providerClient && !rebuild) {
|
|
133
155
|
return;
|
|
134
156
|
}
|
|
135
|
-
|
|
136
|
-
|
|
157
|
+
if (rebuild && this._providerClient) {
|
|
158
|
+
this.logger.debug('Clearing existing provider client for rebuild');
|
|
159
|
+
this._providerClient = undefined;
|
|
160
|
+
}
|
|
161
|
+
await this.waitFor('configManager', { required: true });
|
|
162
|
+
const providerUrl = (await this.configManager.get('providerUrl')) || PROVIDER_URL;
|
|
137
163
|
this.logger.info('Initializing provider client');
|
|
138
164
|
const providerClient = createProviderClient({
|
|
139
165
|
baseUrl: providerUrl,
|
|
@@ -150,28 +176,28 @@ export class AppContainer {
|
|
|
150
176
|
const authMiddleware = await createAuthMiddleware(this.configManager, providerClient, this.logger);
|
|
151
177
|
providerClient.use(authMiddleware);
|
|
152
178
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
},
|
|
167
|
-
|
|
179
|
+
if (process.env.SP_CLI_DEBUG_REQUESTS === '1') {
|
|
180
|
+
providerClient.use({
|
|
181
|
+
onRequest: async ({ request }) => {
|
|
182
|
+
this.logger.debug({
|
|
183
|
+
hasAuthHeader: Boolean(request.headers.get('Authorization')),
|
|
184
|
+
hasBody: Boolean(request.body),
|
|
185
|
+
method: request.method,
|
|
186
|
+
url: request.url,
|
|
187
|
+
}, 'Requesting');
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
if (initToken !== this.providerClientInitToken) {
|
|
192
|
+
this.logger.debug({ initToken, providerClientInitToken: this.providerClientInitToken }, 'Skipping provider client assignment (superseded)');
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
168
195
|
this._providerClient = providerClient;
|
|
196
|
+
this.providerClientOptions = options;
|
|
169
197
|
}, rebuild);
|
|
170
198
|
}
|
|
171
199
|
setupRuntimeConfig(config) {
|
|
172
|
-
|
|
173
|
-
throw new Error('Cannot change runtime config after initialization has started');
|
|
174
|
-
}
|
|
200
|
+
const previousRuntimeConfigFile = this.runtimeConfigFile;
|
|
175
201
|
if (config.configFile) {
|
|
176
202
|
this.runtimeConfigFile = path.isAbsolute(config.configFile)
|
|
177
203
|
? config.configFile
|
|
@@ -180,18 +206,62 @@ export class AppContainer {
|
|
|
180
206
|
else {
|
|
181
207
|
this.runtimeConfigFile = undefined;
|
|
182
208
|
}
|
|
209
|
+
const changed = previousRuntimeConfigFile !== this.runtimeConfigFile;
|
|
210
|
+
if (changed) {
|
|
211
|
+
this.logger.debug({ previousRuntimeConfigFile, runtimeConfigFile: this.runtimeConfigFile }, 'Runtime config changed; clearing dependent services');
|
|
212
|
+
this._configManager = undefined;
|
|
213
|
+
this._accountManager = undefined;
|
|
214
|
+
this._providerClient = undefined;
|
|
215
|
+
this.providerClientOptions = undefined;
|
|
216
|
+
this.initQueue.delete('configManager');
|
|
217
|
+
this.initQueue.delete('accountManager');
|
|
218
|
+
this.initQueue.delete('providerClient');
|
|
219
|
+
this.initQueue.delete('blockchainConnector');
|
|
220
|
+
this.initQueue.delete('configFileManager');
|
|
221
|
+
}
|
|
222
|
+
if (this._configFileManager) {
|
|
223
|
+
this._configFileManager.setRuntimeConfigFile(this.runtimeConfigFile);
|
|
224
|
+
}
|
|
183
225
|
return this;
|
|
184
226
|
}
|
|
227
|
+
async getProviderClientForBootstrap() {
|
|
228
|
+
if (this._providerClient) {
|
|
229
|
+
return this._providerClient;
|
|
230
|
+
}
|
|
231
|
+
const queued = this.initQueue.get('providerClient');
|
|
232
|
+
if (queued) {
|
|
233
|
+
await queued;
|
|
234
|
+
return this.providerClient;
|
|
235
|
+
}
|
|
236
|
+
await this.waitFor('configManager', { required: true });
|
|
237
|
+
const providerUrl = (await this.configManager.get('providerUrl')) || PROVIDER_URL;
|
|
238
|
+
this.logger.debug({ providerUrl }, 'Creating bootstrap provider client');
|
|
239
|
+
return createProviderClient({
|
|
240
|
+
baseUrl: providerUrl,
|
|
241
|
+
logger: this.logger,
|
|
242
|
+
middlewares: [requestIdMiddleware, loggerMiddleware],
|
|
243
|
+
});
|
|
244
|
+
}
|
|
185
245
|
queueInit(name, task, force = false) {
|
|
186
|
-
if (
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
246
|
+
if (force) {
|
|
247
|
+
this.initQueue.delete(name);
|
|
248
|
+
}
|
|
249
|
+
if (!this.initQueue.has(name)) {
|
|
250
|
+
const wrappedPromise = task().catch((error) => {
|
|
251
|
+
if (this.initQueue.get(name) === wrappedPromise) {
|
|
252
|
+
this.initQueue.delete(name);
|
|
253
|
+
}
|
|
254
|
+
throw error;
|
|
255
|
+
});
|
|
256
|
+
this.initQueue.set(name, wrappedPromise);
|
|
190
257
|
}
|
|
191
258
|
return this;
|
|
192
259
|
}
|
|
193
|
-
async waitFor(name) {
|
|
260
|
+
async waitFor(name, options = {}) {
|
|
194
261
|
const promise = this.initQueue.get(name);
|
|
262
|
+
if (!promise && options.required) {
|
|
263
|
+
throw new Error(`Dependency "${name}" was not queued for initialization`);
|
|
264
|
+
}
|
|
195
265
|
if (promise) {
|
|
196
266
|
await promise;
|
|
197
267
|
}
|
package/dist/logger.d.ts
CHANGED
package/dist/logger.js
CHANGED
|
@@ -43,7 +43,10 @@ class PinoLogger {
|
|
|
43
43
|
this.forward('warn', formatter, args);
|
|
44
44
|
}
|
|
45
45
|
forward(level, formatter, args) {
|
|
46
|
-
this.logger[level].apply(this.logger, [
|
|
46
|
+
this.logger[level].apply(this.logger, [
|
|
47
|
+
formatter,
|
|
48
|
+
...args,
|
|
49
|
+
]);
|
|
47
50
|
}
|
|
48
51
|
}
|
|
49
52
|
const logger = (namespace) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import pino from 'pino';
|
|
2
|
-
import { Account } from '../config/config.schema.js';
|
|
3
|
-
import { IAccountManager } from '../interfaces/account-manager.interface.js';
|
|
4
|
-
import { IConfigManager } from '../interfaces/config-manager.interface.js';
|
|
1
|
+
import type pino from 'pino';
|
|
2
|
+
import { type Account } from '../config/config.schema.js';
|
|
3
|
+
import type { IAccountManager } from '../interfaces/account-manager.interface.js';
|
|
4
|
+
import type { IConfigManager } from '../interfaces/config-manager.interface.js';
|
|
5
5
|
export declare class AccountManager implements IAccountManager {
|
|
6
6
|
private readonly configManager;
|
|
7
7
|
private readonly logger;
|
|
@@ -12,9 +12,8 @@ export declare class AccountManager implements IAccountManager {
|
|
|
12
12
|
createFromKey(privateKey: string): Promise<Account>;
|
|
13
13
|
createSign(nonce: string): Promise<string>;
|
|
14
14
|
getAddress(): string;
|
|
15
|
+
hasAccount(): Promise<boolean>;
|
|
15
16
|
init(): Promise<void>;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
privateKey: string;
|
|
19
|
-
}>;
|
|
17
|
+
private loadAccount;
|
|
18
|
+
private save;
|
|
20
19
|
}
|
|
@@ -1,16 +1,7 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
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
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
import { confirm, isCancel, password } from '@clack/prompts';
|
|
8
|
-
import { ux } from '@oclif/core';
|
|
9
1
|
import { Value } from 'typebox/value';
|
|
10
|
-
import { Retryable } from 'typescript-retry-decorator';
|
|
11
2
|
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
|
|
12
3
|
import { accountSchema } from '../config/config.schema.js';
|
|
13
|
-
import { NotInitializedError } from '../errors.js';
|
|
4
|
+
import { AccountNotFoundError, NotInitializedError } from '../errors.js';
|
|
14
5
|
export class AccountManager {
|
|
15
6
|
configManager;
|
|
16
7
|
logger;
|
|
@@ -27,7 +18,7 @@ export class AccountManager {
|
|
|
27
18
|
address: account.address,
|
|
28
19
|
privateKey: this.privateKey,
|
|
29
20
|
};
|
|
30
|
-
await this.
|
|
21
|
+
await this.save();
|
|
31
22
|
this.logger.debug('Created new account');
|
|
32
23
|
return this.account;
|
|
33
24
|
}
|
|
@@ -38,7 +29,7 @@ export class AccountManager {
|
|
|
38
29
|
address: account.address,
|
|
39
30
|
privateKey: this.privateKey,
|
|
40
31
|
};
|
|
41
|
-
await this.
|
|
32
|
+
await this.save();
|
|
42
33
|
this.logger.debug('Created new account from key');
|
|
43
34
|
return this.account;
|
|
44
35
|
}
|
|
@@ -57,48 +48,32 @@ export class AccountManager {
|
|
|
57
48
|
}
|
|
58
49
|
return this.account.address;
|
|
59
50
|
}
|
|
60
|
-
async
|
|
51
|
+
async hasAccount() {
|
|
61
52
|
const account = await this.configManager.get('account');
|
|
53
|
+
return Value.Check(accountSchema, account);
|
|
54
|
+
}
|
|
55
|
+
async init() {
|
|
62
56
|
try {
|
|
63
|
-
this.
|
|
64
|
-
this.privateKey = this.account.privateKey;
|
|
57
|
+
await this.loadAccount();
|
|
65
58
|
}
|
|
66
59
|
catch (error) {
|
|
67
|
-
|
|
68
|
-
|
|
60
|
+
if (!(error instanceof AccountNotFoundError)) {
|
|
61
|
+
this.logger.warn({ err: error }, 'Unexpected error loading account');
|
|
62
|
+
}
|
|
69
63
|
}
|
|
70
64
|
}
|
|
71
|
-
async
|
|
72
|
-
|
|
73
|
-
const ask = await confirm({
|
|
74
|
-
message: 'Do you want to create a new account?',
|
|
75
|
-
});
|
|
76
|
-
if (isCancel(ask)) {
|
|
77
|
-
ux.error('Operation cancelled.', { exit: 1 });
|
|
78
|
-
}
|
|
79
|
-
if (ask) {
|
|
80
|
-
const account = await this.create();
|
|
81
|
-
ux.stdout('Generated new keyPair for new account.');
|
|
82
|
-
return account;
|
|
83
|
-
}
|
|
84
|
-
const privateKeyInput = await password({ message: 'Please input your privateKey for using in account' });
|
|
85
|
-
if (isCancel(privateKeyInput)) {
|
|
86
|
-
ux.error('Operation cancelled.', { exit: 1 });
|
|
87
|
-
}
|
|
88
|
-
const privateKey = privateKeyInput.trim();
|
|
65
|
+
async loadAccount() {
|
|
66
|
+
const account = await this.configManager.get('account');
|
|
89
67
|
try {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return account;
|
|
68
|
+
this.account = Value.Parse(accountSchema, account);
|
|
69
|
+
this.privateKey = this.account.privateKey;
|
|
93
70
|
}
|
|
94
71
|
catch (error) {
|
|
95
|
-
|
|
96
|
-
|
|
72
|
+
this.logger.warn({ err: error }, 'Incorrect config file');
|
|
73
|
+
throw new AccountNotFoundError('Account not found in config file');
|
|
97
74
|
}
|
|
98
75
|
}
|
|
76
|
+
async save() {
|
|
77
|
+
await this.configManager.set('account', this.account);
|
|
78
|
+
}
|
|
99
79
|
}
|
|
100
|
-
__decorate([
|
|
101
|
-
Retryable({
|
|
102
|
-
maxAttempts: 3,
|
|
103
|
-
})
|
|
104
|
-
], AccountManager.prototype, "interactWithUser", null);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { confirm, select } from '@clack/prompts';
|
|
2
2
|
import { ux } from '@oclif/core';
|
|
3
|
-
import pino from 'pino';
|
|
4
|
-
import { CliConfig } from '../config/config.schema.js';
|
|
5
|
-
import { IManager } from '../interfaces/manager.interface.js';
|
|
3
|
+
import type pino from 'pino';
|
|
4
|
+
import { type Account, type CliConfig } from '../config/config.schema.js';
|
|
5
|
+
import type { IManager } from '../interfaces/manager.interface.js';
|
|
6
6
|
type ConfirmPrompt = typeof confirm;
|
|
7
7
|
type SelectPrompt = typeof select;
|
|
8
8
|
type UxLike = Pick<typeof ux, 'error' | 'stdout'>;
|
|
@@ -14,7 +14,7 @@ interface ConfigFileManagerOptions {
|
|
|
14
14
|
}
|
|
15
15
|
export declare class ConfigFileManager implements IManager {
|
|
16
16
|
private readonly logger;
|
|
17
|
-
|
|
17
|
+
static readonly CONFIG_FILE = "config.json";
|
|
18
18
|
private static readonly CONFIGS_DIR;
|
|
19
19
|
private readonly configDir;
|
|
20
20
|
private readonly configFilePath;
|
|
@@ -25,8 +25,7 @@ export declare class ConfigFileManager implements IManager {
|
|
|
25
25
|
private readonly selectPrompt;
|
|
26
26
|
private readonly ux;
|
|
27
27
|
constructor(configDir: string, logger: pino.BaseLogger, options?: ConfigFileManagerOptions);
|
|
28
|
-
|
|
29
|
-
createConfig(configFileName: string, name: string, url?: string): Promise<void>;
|
|
28
|
+
createConfig(configFileName: string, name: string, url?: string, account?: Account): Promise<void>;
|
|
30
29
|
deleteConfig(configName: string): Promise<void>;
|
|
31
30
|
deleteConfigByName(name?: string, force?: boolean): Promise<void>;
|
|
32
31
|
getConfigData(configName: string): CliConfig | undefined;
|
|
@@ -40,7 +39,7 @@ export declare class ConfigFileManager implements IManager {
|
|
|
40
39
|
getCurrentConfigPath(): Promise<string>;
|
|
41
40
|
importConfig(sourcePath: string, targetName?: string): Promise<string>;
|
|
42
41
|
init(): Promise<void>;
|
|
43
|
-
removeConfig
|
|
42
|
+
private removeConfig;
|
|
44
43
|
setCurrentConfig(configName: string): Promise<void>;
|
|
45
44
|
setRuntimeConfigFile(runtimeConfigFile?: string): void;
|
|
46
45
|
private ensureDirectories;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { confirm, isCancel, select } from '@clack/prompts';
|
|
2
|
-
import { ux } from '@oclif/core';
|
|
3
1
|
import * as fs from 'node:fs';
|
|
4
2
|
import path from 'node:path';
|
|
3
|
+
import { confirm, isCancel, select } from '@clack/prompts';
|
|
4
|
+
import { ux } from '@oclif/core';
|
|
5
5
|
import { Value } from 'typebox/value';
|
|
6
6
|
import { cliConfigSchema } from '../config/config.schema.js';
|
|
7
7
|
import { DEFAULT_USER_CONFIG_FILE, DEFAULT_USER_CONFIG_NAME, DIR_ACCESS_PERMS, FILE_ACCESS_PERMS, } from '../constants.js';
|
|
@@ -9,11 +9,10 @@ import { getConfigName } from '../utils/helper.js';
|
|
|
9
9
|
export class ConfigFileManager {
|
|
10
10
|
logger;
|
|
11
11
|
static CONFIG_FILE = 'config.json';
|
|
12
|
-
static CONFIGS_DIR = '
|
|
12
|
+
static CONFIGS_DIR = 'accounts';
|
|
13
13
|
configDir;
|
|
14
14
|
configFilePath;
|
|
15
15
|
configs = {
|
|
16
|
-
configs: [],
|
|
17
16
|
currentConfig: undefined,
|
|
18
17
|
};
|
|
19
18
|
configsDir;
|
|
@@ -31,13 +30,7 @@ export class ConfigFileManager {
|
|
|
31
30
|
this.ux = options.ux ?? ux;
|
|
32
31
|
this.runtimeConfigFile = options.runtimeConfigFile;
|
|
33
32
|
}
|
|
34
|
-
async
|
|
35
|
-
if (!this.configs.configs.includes(configName)) {
|
|
36
|
-
this.configs.configs.push(configName);
|
|
37
|
-
await this.save();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
async createConfig(configFileName, name, url) {
|
|
33
|
+
async createConfig(configFileName, name, url, account) {
|
|
41
34
|
const configPath = path.join(this.configsDir, configFileName);
|
|
42
35
|
if (fs.existsSync(configPath)) {
|
|
43
36
|
throw new Error(`Configuration file already exists: ${configFileName}`);
|
|
@@ -46,12 +39,14 @@ export class ConfigFileManager {
|
|
|
46
39
|
if (url) {
|
|
47
40
|
config.providerUrl = url;
|
|
48
41
|
}
|
|
42
|
+
if (account) {
|
|
43
|
+
config.account = account;
|
|
44
|
+
}
|
|
49
45
|
fs.writeFileSync(configPath, JSON.stringify(config, undefined, 2), {
|
|
50
46
|
encoding: 'utf8',
|
|
51
47
|
flag: 'w',
|
|
52
48
|
mode: FILE_ACCESS_PERMS,
|
|
53
49
|
});
|
|
54
|
-
await this.addConfig(configFileName);
|
|
55
50
|
this.logger.info({ configFileName, name, url }, 'Created new configuration');
|
|
56
51
|
}
|
|
57
52
|
async deleteConfig(configName) {
|
|
@@ -71,7 +66,7 @@ export class ConfigFileManager {
|
|
|
71
66
|
}
|
|
72
67
|
let configToDelete;
|
|
73
68
|
if (name) {
|
|
74
|
-
const config = configs.find(c => c.name === name);
|
|
69
|
+
const config = configs.find((c) => c.name === name);
|
|
75
70
|
if (!config) {
|
|
76
71
|
this.ux.error(`Configuration not found: ${name}`);
|
|
77
72
|
}
|
|
@@ -80,7 +75,7 @@ export class ConfigFileManager {
|
|
|
80
75
|
else {
|
|
81
76
|
const selection = await this.selectPrompt({
|
|
82
77
|
message: 'Select configuration to delete:',
|
|
83
|
-
options: configs.map(config => ({
|
|
78
|
+
options: configs.map((config) => ({
|
|
84
79
|
label: config.name,
|
|
85
80
|
value: config.file,
|
|
86
81
|
})),
|
|
@@ -91,7 +86,7 @@ export class ConfigFileManager {
|
|
|
91
86
|
}
|
|
92
87
|
configToDelete = selection;
|
|
93
88
|
}
|
|
94
|
-
const configToDeleteData = configs.find(c => c.file === configToDelete);
|
|
89
|
+
const configToDeleteData = configs.find((c) => c.file === configToDelete);
|
|
95
90
|
const displayName = configToDeleteData?.name || configToDelete;
|
|
96
91
|
if (!force) {
|
|
97
92
|
const confirmed = await this.confirmPrompt({
|
|
@@ -108,12 +103,12 @@ export class ConfigFileManager {
|
|
|
108
103
|
this.ux.stdout(`Successfully deleted configuration: ${displayName}`);
|
|
109
104
|
const newCurrent = this.getCurrentConfigFile();
|
|
110
105
|
if (newCurrent) {
|
|
111
|
-
const newCurrentConfig = configs.find(c => c.file === newCurrent);
|
|
106
|
+
const newCurrentConfig = configs.find((c) => c.file === newCurrent);
|
|
112
107
|
this.ux.stdout(`Current configuration is now: ${newCurrentConfig?.name || newCurrent}`);
|
|
113
108
|
}
|
|
114
109
|
else {
|
|
115
110
|
this.ux.stdout('No configurations remaining');
|
|
116
|
-
this.ux.stdout('Create a new
|
|
111
|
+
this.ux.stdout('Create a new account with: sp account login --name "Account Name" or sp auth login');
|
|
117
112
|
}
|
|
118
113
|
}
|
|
119
114
|
catch (error) {
|
|
@@ -138,10 +133,19 @@ export class ConfigFileManager {
|
|
|
138
133
|
return this.configsDir;
|
|
139
134
|
}
|
|
140
135
|
getConfigs() {
|
|
141
|
-
|
|
136
|
+
if (!fs.existsSync(this.configsDir)) {
|
|
137
|
+
return [];
|
|
138
|
+
}
|
|
139
|
+
return fs.readdirSync(this.configsDir).filter((file) => file.endsWith('.config.json'));
|
|
142
140
|
}
|
|
143
141
|
getConfigsWithNames() {
|
|
144
|
-
|
|
142
|
+
if (!fs.existsSync(this.configsDir)) {
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
const configFiles = fs
|
|
146
|
+
.readdirSync(this.configsDir)
|
|
147
|
+
.filter((file) => file.endsWith('.config.json'));
|
|
148
|
+
return configFiles.map((configFile) => {
|
|
145
149
|
const configPath = path.join(this.configsDir, configFile);
|
|
146
150
|
let name = configFile;
|
|
147
151
|
try {
|
|
@@ -218,7 +222,6 @@ export class ConfigFileManager {
|
|
|
218
222
|
}
|
|
219
223
|
fs.copyFileSync(sourcePath, targetPath);
|
|
220
224
|
fs.chmodSync(targetPath, FILE_ACCESS_PERMS);
|
|
221
|
-
await this.addConfig(targetFileName);
|
|
222
225
|
this.logger.info({ sourcePath, targetFileName }, 'Imported configuration');
|
|
223
226
|
return targetFileName;
|
|
224
227
|
}
|
|
@@ -231,12 +234,10 @@ export class ConfigFileManager {
|
|
|
231
234
|
await this.load();
|
|
232
235
|
}
|
|
233
236
|
async removeConfig(configName) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
this.configs.currentConfig = this.configs.configs[0];
|
|
239
|
-
}
|
|
237
|
+
if (this.configs.currentConfig === configName) {
|
|
238
|
+
const configs = this.getConfigs();
|
|
239
|
+
const remainingConfigs = configs.filter((c) => c !== configName);
|
|
240
|
+
this.configs.currentConfig = remainingConfigs.length > 0 ? remainingConfigs[0] : undefined;
|
|
240
241
|
await this.save();
|
|
241
242
|
}
|
|
242
243
|
}
|
|
@@ -245,9 +246,6 @@ export class ConfigFileManager {
|
|
|
245
246
|
if (!fs.existsSync(configPath)) {
|
|
246
247
|
throw new Error(`Configuration file not found: ${configName}`);
|
|
247
248
|
}
|
|
248
|
-
if (!this.configs.configs.includes(configName)) {
|
|
249
|
-
this.configs.configs.push(configName);
|
|
250
|
-
}
|
|
251
249
|
this.configs.currentConfig = configName;
|
|
252
250
|
await this.save();
|
|
253
251
|
}
|
|
@@ -256,10 +254,16 @@ export class ConfigFileManager {
|
|
|
256
254
|
}
|
|
257
255
|
ensureDirectories() {
|
|
258
256
|
if (!fs.existsSync(this.configDir)) {
|
|
259
|
-
fs.mkdirSync(this.configDir, {
|
|
257
|
+
fs.mkdirSync(this.configDir, {
|
|
258
|
+
mode: DIR_ACCESS_PERMS,
|
|
259
|
+
recursive: true,
|
|
260
|
+
});
|
|
260
261
|
}
|
|
261
262
|
if (!fs.existsSync(this.configsDir)) {
|
|
262
|
-
fs.mkdirSync(this.configsDir, {
|
|
263
|
+
fs.mkdirSync(this.configsDir, {
|
|
264
|
+
mode: DIR_ACCESS_PERMS,
|
|
265
|
+
recursive: true,
|
|
266
|
+
});
|
|
263
267
|
}
|
|
264
268
|
}
|
|
265
269
|
async load() {
|
|
@@ -277,7 +281,6 @@ export class ConfigFileManager {
|
|
|
277
281
|
catch (error) {
|
|
278
282
|
this.logger.error({ err: error }, 'Failed to load config manager file, using defaults');
|
|
279
283
|
this.configs = {
|
|
280
|
-
configs: [],
|
|
281
284
|
currentConfig: undefined,
|
|
282
285
|
};
|
|
283
286
|
await this.save();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import pino from 'pino';
|
|
2
|
-
import { Auth, CliConfig } from '../config/config.schema.js';
|
|
3
|
-
import { IConfigManager } from '../interfaces/config-manager.interface.js';
|
|
1
|
+
import type pino from 'pino';
|
|
2
|
+
import type { Auth, CliConfig } from '../config/config.schema.js';
|
|
3
|
+
import type { IConfigManager } from '../interfaces/config-manager.interface.js';
|
|
4
4
|
export declare class ConfigManager implements IConfigManager {
|
|
5
5
|
private readonly configFile;
|
|
6
6
|
private readonly logger;
|
|
@@ -8,14 +8,14 @@ export declare class ConfigManager implements IConfigManager {
|
|
|
8
8
|
private readonly configDir;
|
|
9
9
|
constructor(configFile: string, logger: pino.BaseLogger);
|
|
10
10
|
get<K extends keyof CliConfig, V extends CliConfig[K]>(key: K): Promise<undefined | V>;
|
|
11
|
-
getConfig
|
|
11
|
+
private getConfig;
|
|
12
12
|
getCookies(): Promise<unknown>;
|
|
13
13
|
getCredentials(): Promise<{
|
|
14
14
|
accessKey: string;
|
|
15
15
|
} | undefined>;
|
|
16
16
|
init(): Promise<void>;
|
|
17
17
|
load(): Promise<CliConfig>;
|
|
18
|
-
makeBackup
|
|
18
|
+
private makeBackup;
|
|
19
19
|
save(): Promise<void>;
|
|
20
20
|
set<K extends keyof CliConfig, V extends CliConfig[K]>(key: K, value: V): Promise<void>;
|
|
21
21
|
setCookies(cookies: unknown): Promise<void>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ux } from '@oclif/core';
|
|
2
1
|
import * as fs from 'node:fs';
|
|
3
2
|
import path from 'node:path';
|
|
3
|
+
import { ux } from '@oclif/core';
|
|
4
4
|
import { DIR_ACCESS_PERMS, FILE_ACCESS_PERMS } from '../constants.js';
|
|
5
5
|
import { ConfigurationNotFoundError } from '../errors.js';
|
|
6
6
|
export class ConfigManager {
|
|
@@ -62,7 +62,10 @@ export class ConfigManager {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
async save() {
|
|
65
|
-
fs.mkdirSync(this.configDir, {
|
|
65
|
+
fs.mkdirSync(this.configDir, {
|
|
66
|
+
mode: DIR_ACCESS_PERMS,
|
|
67
|
+
recursive: true,
|
|
68
|
+
});
|
|
66
69
|
this.logger.debug({ configFile: this.getConfigPath() }, 'Saving config file');
|
|
67
70
|
fs.writeFileSync(this.getConfigPath(), JSON.stringify(this.config, undefined, ' '), {
|
|
68
71
|
encoding: 'utf8',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { MiddlewareFn, ProviderClient } from '@super-protocol/provider-client';
|
|
2
2
|
import type pino from 'pino';
|
|
3
|
-
import {
|
|
3
|
+
import type { Auth } from '../config/config.schema.js';
|
|
4
4
|
interface CredentialsStorage {
|
|
5
5
|
getCredentials(): Promise<Auth | undefined>;
|
|
6
6
|
setCredentials(auth: Auth): void;
|