@super-protocol/sp-cli 0.0.2 → 0.0.4-beta.0

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 (59) hide show
  1. package/README.md +217 -263
  2. package/bin/dev.js +1 -1
  3. package/dist/commands/account/get-sppi.d.ts +8 -0
  4. package/dist/commands/account/get-sppi.js +23 -0
  5. package/dist/commands/account/info.d.ts +22 -0
  6. package/dist/commands/account/info.js +46 -0
  7. package/dist/commands/auth/login.d.ts +6 -11
  8. package/dist/commands/auth/login.js +28 -76
  9. package/dist/commands/base.d.ts +2 -4
  10. package/dist/commands/base.js +8 -10
  11. package/dist/commands/config/add.js +1 -12
  12. package/dist/commands/config/base.d.ts +5 -3
  13. package/dist/commands/config/base.js +30 -14
  14. package/dist/commands/config/create.js +1 -11
  15. package/dist/commands/config/list.js +20 -19
  16. package/dist/commands/config/use.js +5 -3
  17. package/dist/commands/files/download.d.ts +15 -0
  18. package/dist/commands/files/download.js +55 -0
  19. package/dist/commands/files/upload.d.ts +18 -0
  20. package/dist/commands/files/upload.js +79 -0
  21. package/dist/commands/storage/base.d.ts +13 -0
  22. package/dist/commands/storage/base.js +125 -0
  23. package/dist/commands/storage/create.d.ts +11 -0
  24. package/dist/commands/storage/create.js +53 -0
  25. package/dist/commands/storage/select.d.ts +9 -0
  26. package/dist/commands/storage/select.js +40 -0
  27. package/dist/commands/storage/show.d.ts +17 -0
  28. package/dist/commands/storage/show.js +36 -0
  29. package/dist/commands/storage/update.d.ts +14 -0
  30. package/dist/commands/storage/update.js +187 -0
  31. package/dist/commands/workflows/extend-lease.d.ts +17 -0
  32. package/dist/commands/workflows/extend-lease.js +94 -0
  33. package/dist/config/config-file.schema.d.ts +4 -4
  34. package/dist/config/config-file.schema.js +1 -1
  35. package/dist/config/config.schema.d.ts +25 -15
  36. package/dist/config/config.schema.js +7 -10
  37. package/dist/constants.d.ts +5 -0
  38. package/dist/constants.js +5 -0
  39. package/dist/errors.d.ts +2 -0
  40. package/dist/errors.js +2 -0
  41. package/dist/hooks/finally/shutdown-blockchain.d.ts +3 -0
  42. package/dist/hooks/finally/shutdown-blockchain.js +8 -0
  43. package/dist/lib/container.d.ts +7 -7
  44. package/dist/lib/container.js +48 -26
  45. package/dist/managers/account-manager.d.ts +4 -1
  46. package/dist/managers/account-manager.js +29 -30
  47. package/dist/managers/config-file-manager.d.ts +2 -2
  48. package/dist/managers/config-file-manager.js +29 -12
  49. package/dist/middlewares/auth-middleware.js +5 -1
  50. package/dist/services/auth.service.d.ts +24 -0
  51. package/dist/services/auth.service.js +93 -0
  52. package/dist/services/storage.service.d.ts +73 -0
  53. package/dist/services/storage.service.js +351 -0
  54. package/dist/utils/helper.d.ts +6 -0
  55. package/dist/utils/helper.js +23 -0
  56. package/dist/utils/progress.d.ts +8 -0
  57. package/dist/utils/progress.js +35 -0
  58. package/oclif.manifest.json +432 -156
  59. package/package.json +19 -9
@@ -0,0 +1,94 @@
1
+ import { select } from '@clack/prompts';
2
+ import { Args, Flags } from '@oclif/core';
3
+ import { Orders } from '@super-protocol/sdk-js';
4
+ import { formatEther, parseEther } from 'viem/utils';
5
+ import { BaseCommand } from '../base.js';
6
+ export default class WorkflowsExtendLease extends BaseCommand {
7
+ static args = {
8
+ orderId: Args.string({ description: 'Order ID', required: true }),
9
+ };
10
+ static description = 'Replenish deposit for a workflow to extend its lease time';
11
+ static examples = [
12
+ '<%= config.bin %> <%= command.id %> <orderId> --sppi 1.5',
13
+ '<%= config.bin %> <%= command.id %> <orderId> --minutes 120',
14
+ '<%= config.bin %> <%= command.id %> <orderId> --sppi 2 --yes',
15
+ ];
16
+ static flags = {
17
+ minutes: Flags.integer({ description: 'Time to extend order in minutes (automatically calculates tokens)' }),
18
+ sppi: Flags.string({ description: 'SPPI token amount to add to the order' }),
19
+ yes: Flags.boolean({ char: 'y', default: false, description: 'Skip confirmation prompt' }),
20
+ };
21
+ async init() {
22
+ await super.init();
23
+ await this.container
24
+ .initConfigManager()
25
+ .initAccountManager()
26
+ .initBlockchainConnector()
27
+ .initProviderClient({ enableAuth: true })
28
+ .build();
29
+ }
30
+ async run() {
31
+ const { args, flags } = await this.parse(WorkflowsExtendLease);
32
+ const { providerClient } = this.container;
33
+ try {
34
+ this.logger.info(`Checking order ${args.orderId}`);
35
+ // Get actual per-hour price from blockchain
36
+ const amountPerHour = await Orders.calculateWorkflowPerHourPrice(args.orderId);
37
+ let tokenAmount;
38
+ let minutes;
39
+ if (flags.minutes) {
40
+ // Calculate token amount from minutes
41
+ tokenAmount = (BigInt(amountPerHour) * BigInt(flags.minutes)) / 60n;
42
+ minutes = flags.minutes;
43
+ }
44
+ else if (flags.sppi) {
45
+ // Use provided SPPI amount
46
+ tokenAmount = parseEther(flags.sppi);
47
+ minutes = Number((tokenAmount * 60n) / BigInt(amountPerHour));
48
+ }
49
+ else {
50
+ this.error('Please provide either --sppi or --minutes flag to specify the replenishment amount');
51
+ return;
52
+ }
53
+ // Confirmation prompt
54
+ const confirmed = this.flags.yes || await this.selectPrompt({
55
+ message: `Deposit will be replenished by ${formatEther(tokenAmount)} SPPI. Order time is extended by ${minutes} minutes. Confirm?`,
56
+ options: [
57
+ { label: 'Yes', value: true },
58
+ { label: 'No', value: false },
59
+ ],
60
+ });
61
+ if (!confirmed) {
62
+ this.logger.info('Operation cancelled by user');
63
+ return;
64
+ }
65
+ // Call API to replenish deposit
66
+ const { data, error } = await providerClient.POST('/api/workflows/{orderId}/replenish', {
67
+ body: {
68
+ amount: tokenAmount.toString(),
69
+ },
70
+ params: {
71
+ path: {
72
+ orderId: args.orderId,
73
+ },
74
+ },
75
+ });
76
+ if (error) {
77
+ this.logger.error({ error }, `Order ${args.orderId} was not replenished`);
78
+ this.error(`Failed to replenish deposit: ${error.message || 'Unknown error'}`);
79
+ return;
80
+ }
81
+ this.logger.info({ data }, 'Deposit replenished successfully');
82
+ this.log('Deposit replenished successfully');
83
+ }
84
+ catch (error) {
85
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
86
+ this.logger.error({ error }, `Order ${args.orderId} was not replenished`);
87
+ this.error(`Order ${args.orderId} was not replenished: ${errorMessage}`);
88
+ }
89
+ }
90
+ async selectPrompt(options) {
91
+ const result = await select(options);
92
+ return this.ensurePromptValue(result);
93
+ }
94
+ }
@@ -1,6 +1,6 @@
1
- import { Static } from '@sinclair/typebox';
2
- export declare const configFileManagerSchema: import("@sinclair/typebox").TObject<{
3
- configs: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
4
- currentConfig: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
1
+ import { Static, Type } from 'typebox';
2
+ export declare const configFileManagerSchema: Type.TObject<{
3
+ configs: Type.TArray<Type.TString>;
4
+ currentConfig: Type.TOptional<Type.TString>;
5
5
  }>;
6
6
  export type ConfigFileManagerData = Static<typeof configFileManagerSchema>;
@@ -1,4 +1,4 @@
1
- import { Type } from '@sinclair/typebox';
1
+ import { Type } from 'typebox';
2
2
  export const configFileManagerSchema = Type.Object({
3
3
  configs: Type.Array(Type.String()),
4
4
  currentConfig: Type.Optional(Type.String()),
@@ -1,23 +1,33 @@
1
- import { Static } from '@sinclair/typebox';
2
- export declare const accountSchema: import("@sinclair/typebox").TObject<{
3
- address: import("@sinclair/typebox").TString;
4
- privateKey: import("@sinclair/typebox").TString;
1
+ import { Static, Type } from 'typebox';
2
+ export declare const accountSchema: Type.TObject<{
3
+ address: Type.TString;
4
+ privateKey: Type.TString;
5
5
  }>;
6
- export declare const authSchema: import("@sinclair/typebox").TObject<{
7
- accessKey: import("@sinclair/typebox").TString;
6
+ export declare const authSchema: Type.TObject<{
7
+ accessKey: Type.TString;
8
8
  }>;
9
- export declare const cliConfigSchema: import("@sinclair/typebox").TObject<{
10
- account: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
11
- address: import("@sinclair/typebox").TString;
12
- privateKey: import("@sinclair/typebox").TString;
9
+ export declare const blockchainSchema: Type.TObject<{
10
+ blockchainUrl: Type.TOptional<Type.TString>;
11
+ contractAddress: Type.TString;
12
+ }>;
13
+ export declare const cliConfigSchema: Type.TObject<{
14
+ account: Type.TOptional<Type.TObject<{
15
+ address: Type.TString;
16
+ privateKey: Type.TString;
17
+ }>>;
18
+ auth: Type.TOptional<Type.TObject<{
19
+ accessKey: Type.TString;
13
20
  }>>;
14
- auth: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
15
- accessKey: import("@sinclair/typebox").TString;
21
+ blockchain: Type.TOptional<Type.TObject<{
22
+ blockchainUrl: Type.TOptional<Type.TString>;
23
+ contractAddress: Type.TString;
16
24
  }>>;
17
- cookies: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnknown>;
18
- name: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
19
- providerUrl: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
25
+ cookies: Type.TOptional<Type.TUnknown>;
26
+ name: Type.TOptional<Type.TString>;
27
+ providerUrl: Type.TOptional<Type.TString>;
28
+ selectedStorage: Type.TOptional<Type.TString>;
20
29
  }>;
21
30
  export type CliConfig = Static<typeof cliConfigSchema>;
22
31
  export type Account = Static<typeof accountSchema>;
23
32
  export type Auth = Static<typeof authSchema>;
33
+ export type Blockchain = Static<typeof blockchainSchema>;
@@ -1,13 +1,4 @@
1
- import { FormatRegistry, Type } from '@sinclair/typebox';
2
- FormatRegistry.Set('url', (value) => {
3
- try {
4
- const u = new URL(value);
5
- return u.protocol === 'http:' || u.protocol === 'https:';
6
- }
7
- catch {
8
- return false;
9
- }
10
- });
1
+ import { Type } from 'typebox';
11
2
  export const accountSchema = Type.Object({
12
3
  address: Type.String({ pattern: '^0x[a-fA-F0-9]{40}$' }),
13
4
  privateKey: Type.String({ pattern: '^0x[a-fA-F0-9]{64}$' }),
@@ -15,10 +6,16 @@ export const accountSchema = Type.Object({
15
6
  export const authSchema = Type.Object({
16
7
  accessKey: Type.String(),
17
8
  });
9
+ export const blockchainSchema = Type.Object({
10
+ blockchainUrl: Type.Optional(Type.String({ format: 'url' })),
11
+ contractAddress: Type.String({ pattern: '^0x[a-fA-F0-9]{40}$' }),
12
+ });
18
13
  export const cliConfigSchema = Type.Object({
19
14
  account: Type.Optional(accountSchema),
20
15
  auth: Type.Optional(authSchema),
16
+ blockchain: Type.Optional(blockchainSchema),
21
17
  cookies: Type.Optional(Type.Unknown()),
22
18
  name: Type.Optional(Type.String()),
23
19
  providerUrl: Type.Optional(Type.String({ format: 'url' })),
20
+ selectedStorage: Type.Optional(Type.String({ maxLength: 36, minLength: 36 })),
24
21
  });
@@ -1,3 +1,8 @@
1
1
  export declare const FILE_ACCESS_PERMS = 384;
2
2
  export declare const DIR_ACCESS_PERMS = 448;
3
3
  export declare const PROVIDER_URL = "https://api.dp.superprotocol.com";
4
+ export declare const REFRESH_TOKEN_URI = "/api/auth/refresh-access";
5
+ export declare const S3_ENDPOINT = "https://gateway.storjshare.io";
6
+ export declare const S3_REGION = "us-east-1";
7
+ export declare const DEFAULT_USER_CONFIG_FILE = "default.config.json";
8
+ export declare const DEFAULT_USER_CONFIG_NAME = "Default";
package/dist/constants.js CHANGED
@@ -3,3 +3,8 @@ export const FILE_ACCESS_PERMS = 0o600;
3
3
  // Directory permissions. 'drwx------'
4
4
  export const DIR_ACCESS_PERMS = 0o700;
5
5
  export const PROVIDER_URL = 'https://api.dp.superprotocol.com';
6
+ export const REFRESH_TOKEN_URI = '/api/auth/refresh-access';
7
+ export const S3_ENDPOINT = 'https://gateway.storjshare.io';
8
+ export const S3_REGION = 'us-east-1';
9
+ export const DEFAULT_USER_CONFIG_FILE = 'default.config.json';
10
+ export const DEFAULT_USER_CONFIG_NAME = 'Default';
package/dist/errors.d.ts CHANGED
@@ -6,3 +6,5 @@ export declare class InvalidPrivateKeyError extends Error {
6
6
  }
7
7
  export declare class AuthorizationRequiredError extends Error {
8
8
  }
9
+ export declare class ProviderClientError extends Error {
10
+ }
package/dist/errors.js CHANGED
@@ -6,3 +6,5 @@ export class InvalidPrivateKeyError extends Error {
6
6
  }
7
7
  export class AuthorizationRequiredError extends Error {
8
8
  }
9
+ export class ProviderClientError extends Error {
10
+ }
@@ -0,0 +1,3 @@
1
+ import { Hook } from '@oclif/core';
2
+ declare const hook: Hook<'finally'>;
3
+ export default hook;
@@ -0,0 +1,8 @@
1
+ import { BlockchainConnector } from '@super-protocol/sdk-js';
2
+ const hook = async function () {
3
+ const connector = BlockchainConnector.getInstance();
4
+ if (connector.isInitialized()) {
5
+ connector.shutdown();
6
+ }
7
+ };
8
+ export default hook;
@@ -3,7 +3,6 @@ import { ProviderClient } from '@super-protocol/provider-client';
3
3
  import { AccountManager, ConfigFileManager, ConfigManager } from '../managers/index.js';
4
4
  interface RuntimeConfig {
5
5
  configFile?: string;
6
- url?: string;
7
6
  }
8
7
  export declare class AppContainer {
9
8
  readonly cwdDir: string;
@@ -17,7 +16,6 @@ export declare class AppContainer {
17
16
  private readonly initQueue;
18
17
  private logger;
19
18
  private runtimeConfigFile?;
20
- private runtimeProviderUrl?;
21
19
  private constructor();
22
20
  static initialize(currentDir: string, config: Config): AppContainer;
23
21
  get accountManager(): AccountManager;
@@ -25,13 +23,15 @@ export declare class AppContainer {
25
23
  get configManager(): ConfigManager;
26
24
  static get container(): AppContainer;
27
25
  get providerClient(): ProviderClient;
28
- build(): Promise<void>;
29
- initAccountManager(): this;
30
- initConfigFileManager(): this;
31
- initConfigManager(): this;
32
- initProviderClient({ enableAuth, enableCookies }?: {
26
+ build(): Promise<this>;
27
+ initAccountManager(rebuild?: boolean): this;
28
+ initBlockchainConnector(): this;
29
+ initConfigFileManager(rebuild?: boolean): this;
30
+ initConfigManager(rebuild?: boolean): this;
31
+ initProviderClient({ enableAuth, enableCookies, rebuild }?: {
33
32
  enableAuth?: boolean;
34
33
  enableCookies?: boolean;
34
+ rebuild?: boolean;
35
35
  }): this;
36
36
  setupRuntimeConfig(config: RuntimeConfig): this;
37
37
  private queueInit;
@@ -1,4 +1,5 @@
1
1
  import { createProviderClient, loggerMiddleware, requestIdMiddleware, } from '@super-protocol/provider-client';
2
+ import { BlockchainConnector } from '@super-protocol/sdk-js';
2
3
  import path from 'node:path';
3
4
  import { PROVIDER_URL } from '../constants.js';
4
5
  import logger from '../logger.js';
@@ -17,7 +18,6 @@ export class AppContainer {
17
18
  initQueue = new Map();
18
19
  logger;
19
20
  runtimeConfigFile;
20
- runtimeProviderUrl;
21
21
  constructor(cwdDir, oclifConfig) {
22
22
  this.cwdDir = cwdDir;
23
23
  this.oclifConfig = oclifConfig;
@@ -61,9 +61,10 @@ export class AppContainer {
61
61
  }
62
62
  async build() {
63
63
  await Promise.all(this.initPromises);
64
+ return this;
64
65
  }
65
- initAccountManager() {
66
- this.initConfigManager();
66
+ initAccountManager(rebuild = true) {
67
+ this.initConfigManager(rebuild);
67
68
  return this.queueInit('accountManager', async () => {
68
69
  await this.waitFor('configManager');
69
70
  if (this._accountManager) {
@@ -73,9 +74,30 @@ export class AppContainer {
73
74
  const accountManager = new AccountManager(this.configManager, this.logger);
74
75
  await accountManager.init();
75
76
  this._accountManager = accountManager;
77
+ }, rebuild);
78
+ }
79
+ initBlockchainConnector() {
80
+ this.initConfigManager();
81
+ return this.queueInit('blockchainConnector', async () => {
82
+ await this.waitFor('configManager');
83
+ let blockchainConfig = await this.configManager.get('blockchain');
84
+ if (!blockchainConfig) {
85
+ await this.waitFor('providerClient');
86
+ const { data, error } = await this.providerClient.GET('/api/config');
87
+ if (error || !data) {
88
+ throw new Error('Could not get configuration from provider');
89
+ }
90
+ blockchainConfig = {
91
+ blockchainUrl: data.blockchainUrl,
92
+ contractAddress: data.contractAddress,
93
+ };
94
+ await this.configManager.set('blockchain', blockchainConfig);
95
+ }
96
+ this.logger.info('Initializing blockchain connector');
97
+ await BlockchainConnector.getInstance().initialize(blockchainConfig);
76
98
  });
77
99
  }
78
- initConfigFileManager() {
100
+ initConfigFileManager(rebuild = false) {
79
101
  return this.queueInit('configFileManager', async () => {
80
102
  if (this._configFileManager) {
81
103
  return;
@@ -85,16 +107,16 @@ export class AppContainer {
85
107
  });
86
108
  await configFileManager.init();
87
109
  this._configFileManager = configFileManager;
88
- });
110
+ }, rebuild);
89
111
  }
90
- initConfigManager() {
91
- this.initConfigFileManager();
112
+ initConfigManager(rebuild = false) {
113
+ this.initConfigFileManager(rebuild);
92
114
  return this.queueInit('configManager', async () => {
93
115
  await this.waitFor('configFileManager');
94
116
  if (this._configManager) {
95
117
  return;
96
118
  }
97
- const configFilePath = this.configFileManager.getCurrentConfigPath();
119
+ const configFilePath = await this.configFileManager.getCurrentConfigPath();
98
120
  if (!configFilePath) {
99
121
  throw new Error('Config file not found');
100
122
  }
@@ -102,22 +124,32 @@ export class AppContainer {
102
124
  const configManager = new ConfigManager(configFilePath, this.logger);
103
125
  await configManager.init();
104
126
  this._configManager = configManager;
105
- });
127
+ }, rebuild);
106
128
  }
107
- initProviderClient({ enableAuth = true, enableCookies = true } = {}) {
129
+ initProviderClient({ enableAuth = true, enableCookies = true, rebuild = false } = {}) {
108
130
  this.initConfigManager();
109
131
  return this.queueInit('providerClient', async () => {
110
- if (this._providerClient) {
132
+ if (this._providerClient && !rebuild) {
111
133
  return;
112
134
  }
113
135
  await this.waitFor('configManager');
114
- const providerUrl = this.runtimeProviderUrl || await this.configManager.get('providerUrl') || PROVIDER_URL;
136
+ const providerUrl = await this.configManager.get('providerUrl') || PROVIDER_URL;
115
137
  this.logger.info('Initializing provider client');
116
138
  const providerClient = createProviderClient({
117
139
  baseUrl: providerUrl,
118
140
  logger: this.logger,
119
141
  middlewares: [requestIdMiddleware, loggerMiddleware],
120
142
  });
143
+ if (enableCookies) {
144
+ this.logger.info('Initializing cookie middleware');
145
+ const cookiesMiddleware = await createCookieMiddleware(this.configManager, this.logger, providerUrl);
146
+ providerClient.use(cookiesMiddleware);
147
+ }
148
+ if (enableAuth) {
149
+ this.logger.info('Initializing auth middleware');
150
+ const authMiddleware = await createAuthMiddleware(this.configManager, providerClient, this.logger);
151
+ providerClient.use(authMiddleware);
152
+ }
121
153
  providerClient.use({
122
154
  onRequest: async ({ request }) => {
123
155
  const req = request.clone();
@@ -128,28 +160,18 @@ export class AppContainer {
128
160
  }
129
161
  this.logger.debug({
130
162
  body,
163
+ token: req.headers.get('Authorization'),
131
164
  url: req.url,
132
165
  }, 'Requesting');
133
166
  },
134
167
  });
135
- if (enableCookies) {
136
- this.logger.info('Initializing cookie middleware');
137
- const cookiesMiddleware = await createCookieMiddleware(this.configManager, this.logger, providerUrl);
138
- providerClient.use(cookiesMiddleware);
139
- }
140
- if (enableAuth) {
141
- this.logger.info('Initializing auth middleware');
142
- const authMiddleware = await createAuthMiddleware(this.configManager, providerClient, this.logger);
143
- providerClient.use(authMiddleware);
144
- }
145
168
  this._providerClient = providerClient;
146
- });
169
+ }, rebuild);
147
170
  }
148
171
  setupRuntimeConfig(config) {
149
172
  if (this.initQueue.size > 0) {
150
173
  throw new Error('Cannot change runtime config after initialization has started');
151
174
  }
152
- this.runtimeProviderUrl = config.url;
153
175
  if (config.configFile) {
154
176
  this.runtimeConfigFile = path.isAbsolute(config.configFile)
155
177
  ? config.configFile
@@ -160,8 +182,8 @@ export class AppContainer {
160
182
  }
161
183
  return this;
162
184
  }
163
- queueInit(name, task) {
164
- if (!this.initQueue.has(name)) {
185
+ queueInit(name, task, force = false) {
186
+ if (!this.initQueue.has(name) || force) {
165
187
  const promise = task();
166
188
  this.initQueue.set(name, promise);
167
189
  this.initPromises.push(promise);
@@ -13,5 +13,8 @@ export declare class AccountManager implements IAccountManager {
13
13
  createSign(nonce: string): Promise<string>;
14
14
  getAddress(): string;
15
15
  init(): Promise<void>;
16
- promptAccount(): Promise<Account>;
16
+ interactWithUser(): Promise<{
17
+ address: string;
18
+ privateKey: string;
19
+ }>;
17
20
  }
@@ -4,9 +4,9 @@ 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 '@inquirer/prompts';
7
+ import { confirm, isCancel, password } from '@clack/prompts';
8
8
  import { ux } from '@oclif/core';
9
- import { Value } from '@sinclair/typebox/value';
9
+ import { Value } from 'typebox/value';
10
10
  import { Retryable } from 'typescript-retry-decorator';
11
11
  import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
12
12
  import { accountSchema } from '../config/config.schema.js';
@@ -65,41 +65,40 @@ export class AccountManager {
65
65
  }
66
66
  catch (error) {
67
67
  this.logger.warn({ err: error }, 'Incorrect config file');
68
- ux.warn('Config not found or have errors');
69
- const ask = await confirm({
70
- message: 'Do you want to create new one?',
71
- });
72
- if (ask) {
73
- await this.promptAccount();
74
- }
75
- else {
76
- ux.error('Credentials not generated please check config file and rerun command again', { exit: 1 });
77
- }
68
+ await this.interactWithUser();
78
69
  }
79
70
  }
80
- async promptAccount() {
81
- const askPrivateKey = await confirm({
82
- message: 'Do you want to input privateKey?',
71
+ async interactWithUser() {
72
+ ux.warn("Account doesn't exist in current configuration");
73
+ const ask = await confirm({
74
+ message: 'Do you want to create a new account?',
83
75
  });
84
- if (askPrivateKey) {
85
- const privateKey = await password({ message: 'Please input your privateKey for using in account' });
86
- try {
87
- const account = await this.createFromKey(privateKey);
88
- ux.stdout('Your privateKey will be used in config. Keypair created');
89
- return account;
90
- }
91
- catch (error) {
92
- ux.warn(error);
93
- ux.error('Invalid private key format. Please try again.');
94
- }
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();
89
+ try {
90
+ const account = await this.createFromKey(privateKey);
91
+ ux.stdout('Your privateKey will be used in config. Keypair created');
92
+ return account;
93
+ }
94
+ catch (error) {
95
+ ux.warn(error);
96
+ ux.error('Invalid private key format. Please try again.');
95
97
  }
96
- const account = await this.create();
97
- ux.stdout('Generated new keyPair for new account.');
98
- return account;
99
98
  }
100
99
  }
101
100
  __decorate([
102
101
  Retryable({
103
102
  maxAttempts: 3,
104
103
  })
105
- ], AccountManager.prototype, "promptAccount", null);
104
+ ], AccountManager.prototype, "interactWithUser", null);
@@ -1,4 +1,4 @@
1
- import { confirm, select } from '@inquirer/prompts';
1
+ import { confirm, select } from '@clack/prompts';
2
2
  import { ux } from '@oclif/core';
3
3
  import pino from 'pino';
4
4
  import { CliConfig } from '../config/config.schema.js';
@@ -37,7 +37,7 @@ export declare class ConfigFileManager implements IManager {
37
37
  name: string;
38
38
  }>;
39
39
  getCurrentConfigFile(): string | undefined;
40
- getCurrentConfigPath(): string | undefined;
40
+ getCurrentConfigPath(): Promise<string>;
41
41
  importConfig(sourcePath: string, targetName?: string): Promise<string>;
42
42
  init(): Promise<void>;
43
43
  removeConfig(configName: string): Promise<void>;
@@ -1,10 +1,10 @@
1
- import { confirm, select } from '@inquirer/prompts';
1
+ import { confirm, isCancel, select } from '@clack/prompts';
2
2
  import { ux } from '@oclif/core';
3
- import { Value } from '@sinclair/typebox/value';
4
3
  import * as fs from 'node:fs';
5
4
  import path from 'node:path';
5
+ import { Value } from 'typebox/value';
6
6
  import { cliConfigSchema } from '../config/config.schema.js';
7
- import { DIR_ACCESS_PERMS, FILE_ACCESS_PERMS } from '../constants.js';
7
+ import { DEFAULT_USER_CONFIG_FILE, DEFAULT_USER_CONFIG_NAME, DIR_ACCESS_PERMS, FILE_ACCESS_PERMS, } from '../constants.js';
8
8
  import { getConfigName } from '../utils/helper.js';
9
9
  export class ConfigFileManager {
10
10
  logger;
@@ -78,22 +78,27 @@ export class ConfigFileManager {
78
78
  configToDelete = config.file;
79
79
  }
80
80
  else {
81
- configToDelete = await this.selectPrompt({
82
- choices: configs.map(config => ({
83
- name: config.name,
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
- default: false,
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
  }
@@ -160,14 +165,26 @@ export class ConfigFileManager {
160
165
  }
161
166
  return this.configs.currentConfig;
162
167
  }
163
- getCurrentConfigPath() {
168
+ async getCurrentConfigPath() {
164
169
  if (this.runtimeConfigFile) {
165
170
  return this.runtimeConfigFile;
166
171
  }
167
172
  if (!this.configs.currentConfig) {
168
- return undefined;
173
+ try {
174
+ await this.createConfig(DEFAULT_USER_CONFIG_FILE, DEFAULT_USER_CONFIG_NAME);
175
+ }
176
+ catch {
177
+ //
178
+ }
179
+ try {
180
+ await this.setCurrentConfig(DEFAULT_USER_CONFIG_FILE);
181
+ }
182
+ catch (error) {
183
+ this.logger.error({ err: error }, 'Failed to set default config');
184
+ throw error;
185
+ }
169
186
  }
170
- return path.join(this.configsDir, this.configs.currentConfig);
187
+ return path.join(this.configsDir, this.configs.currentConfig || DEFAULT_USER_CONFIG_FILE);
171
188
  }
172
189
  async importConfig(sourcePath, targetName) {
173
190
  if (!fs.existsSync(sourcePath)) {
@@ -1,4 +1,5 @@
1
1
  import { decode } from 'jsonwebtoken';
2
+ import { REFRESH_TOKEN_URI } from '../constants.js';
2
3
  import { AuthorizationRequiredError } from '../errors.js';
3
4
  function isAccessKeyExpired(accessKey) {
4
5
  try {
@@ -23,7 +24,7 @@ export async function createAuthMiddleware(configManager, providerClient, logger
23
24
  logger.info('Performed refresh token');
24
25
  let refreshResult;
25
26
  try {
26
- refreshResult = await providerClient.POST('/api/auth/refresh-access');
27
+ refreshResult = await providerClient.POST(REFRESH_TOKEN_URI);
27
28
  }
28
29
  catch (error) {
29
30
  logger.error({ err: error }, 'failure refresh token');
@@ -76,6 +77,9 @@ export async function createAuthMiddleware(configManager, providerClient, logger
76
77
  }
77
78
  const middleware = {
78
79
  async onRequest({ request }) {
80
+ if (request.url.endsWith(REFRESH_TOKEN_URI)) {
81
+ return request;
82
+ }
79
83
  const accessToken = await ensureAccessKey();
80
84
  if (accessToken) {
81
85
  request.headers.set('Authorization', `Bearer ${accessToken}`);