@super-protocol/sp-cli 0.0.6 → 0.0.8

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 (92) hide show
  1. package/README.md +116 -234
  2. package/dist/commands/account/base.d.ts +19 -0
  3. package/dist/commands/account/base.js +42 -0
  4. package/dist/commands/account/forget.d.ts +14 -0
  5. package/dist/commands/account/forget.js +49 -0
  6. package/dist/commands/account/get-sppi.d.ts +2 -2
  7. package/dist/commands/account/get-sppi.js +8 -13
  8. package/dist/commands/account/info.d.ts +5 -2
  9. package/dist/commands/account/info.js +53 -3
  10. package/dist/commands/account/list.d.ts +9 -0
  11. package/dist/commands/{config → account}/list.js +16 -9
  12. package/dist/commands/account/login.d.ts +35 -0
  13. package/dist/commands/account/login.js +249 -0
  14. package/dist/commands/account/switch.d.ts +12 -0
  15. package/dist/commands/account/switch.js +40 -0
  16. package/dist/commands/base.d.ts +4 -3
  17. package/dist/commands/base.js +99 -13
  18. package/dist/commands/files/download.js +13 -5
  19. package/dist/commands/files/upload.js +11 -7
  20. package/dist/commands/storage/base.d.ts +2 -2
  21. package/dist/commands/storage/base.js +11 -11
  22. package/dist/commands/storage/create.js +1 -1
  23. package/dist/commands/storage/select.js +6 -8
  24. package/dist/commands/storage/show.js +2 -4
  25. package/dist/commands/storage/update.js +39 -22
  26. package/dist/commands/workflows/extend-lease.d.ts +1 -1
  27. package/dist/commands/workflows/extend-lease.js +21 -13
  28. package/dist/config/config-file.schema.d.ts +1 -2
  29. package/dist/config/config-file.schema.js +0 -1
  30. package/dist/config/config.schema.d.ts +1 -1
  31. package/dist/errors.d.ts +2 -0
  32. package/dist/errors.js +2 -0
  33. package/dist/hooks/finally/shutdown-blockchain.d.ts +1 -1
  34. package/dist/hooks/finally/shutdown-blockchain.js +1 -1
  35. package/dist/hooks/finally/unlock-config.d.ts +3 -0
  36. package/dist/hooks/finally/unlock-config.js +5 -0
  37. package/dist/hooks/init/init-container.d.ts +1 -1
  38. package/dist/hooks/init/init-container.js +2 -3
  39. package/dist/hooks/init/lock-config.d.ts +3 -0
  40. package/dist/hooks/init/lock-config.js +19 -0
  41. package/dist/hooks/prerun/auth.d.ts +3 -0
  42. package/dist/hooks/prerun/auth.js +70 -0
  43. package/dist/index.d.ts +1 -1
  44. package/dist/index.js +1 -1
  45. package/dist/interfaces/account-manager.interface.d.ts +1 -1
  46. package/dist/interfaces/config-manager.interface.d.ts +2 -2
  47. package/dist/lib/cli-instance-lock.d.ts +2 -0
  48. package/dist/lib/cli-instance-lock.js +37 -0
  49. package/dist/lib/container.d.ts +6 -4
  50. package/dist/lib/container.js +108 -38
  51. package/dist/logger.d.ts +1 -1
  52. package/dist/logger.js +4 -1
  53. package/dist/managers/account-manager.d.ts +7 -8
  54. package/dist/managers/account-manager.js +20 -45
  55. package/dist/managers/config-file-manager.d.ts +6 -7
  56. package/dist/managers/config-file-manager.js +35 -32
  57. package/dist/managers/config-manager.d.ts +5 -5
  58. package/dist/managers/config-manager.js +5 -2
  59. package/dist/middlewares/auth-middleware.d.ts +1 -1
  60. package/dist/services/auth.service.d.ts +10 -15
  61. package/dist/services/auth.service.js +71 -5
  62. package/dist/services/storage.service.d.ts +3 -3
  63. package/dist/services/storage.service.js +46 -19
  64. package/dist/utils/helper.d.ts +1 -0
  65. package/dist/utils/helper.js +15 -1
  66. package/dist/utils/prompt-flags.d.ts +20 -0
  67. package/dist/utils/prompt-flags.js +121 -0
  68. package/dist/utils/prompt.service.d.ts +16 -0
  69. package/dist/utils/prompt.service.js +75 -0
  70. package/dist/utils/tty.d.ts +1 -0
  71. package/dist/utils/tty.js +3 -0
  72. package/oclif.manifest.json +206 -242
  73. package/package.json +17 -24
  74. package/dist/commands/auth/login.d.ts +0 -12
  75. package/dist/commands/auth/login.js +0 -50
  76. package/dist/commands/auth/me.d.ts +0 -5
  77. package/dist/commands/auth/me.js +0 -16
  78. package/dist/commands/config/add.d.ts +0 -13
  79. package/dist/commands/config/add.js +0 -73
  80. package/dist/commands/config/base.d.ts +0 -16
  81. package/dist/commands/config/base.js +0 -78
  82. package/dist/commands/config/create.d.ts +0 -11
  83. package/dist/commands/config/create.js +0 -41
  84. package/dist/commands/config/delete.d.ts +0 -10
  85. package/dist/commands/config/delete.js +0 -25
  86. package/dist/commands/config/index.d.ts +0 -6
  87. package/dist/commands/config/index.js +0 -22
  88. package/dist/commands/config/list.d.ts +0 -6
  89. package/dist/commands/config/show.d.ts +0 -6
  90. package/dist/commands/config/show.js +0 -10
  91. package/dist/commands/config/use.d.ts +0 -6
  92. package/dist/commands/config/use.js +0 -27
@@ -1,14 +1,36 @@
1
- import { isCancel } from '@clack/prompts';
2
- import { Command, Flags, } from '@oclif/core';
1
+ import { Command, Flags } from '@oclif/core';
3
2
  import { AppContainer } from '../lib/container.js';
4
3
  import logger from '../logger.js';
4
+ import { findMissingRequiredArgs, findMissingRequiredFlags, formatMissingArgsError, formatMissingFlagsError, promptForArg, promptForFlag, } from '../utils/prompt-flags.js';
5
+ import { promptService } from '../utils/prompt.service.js';
6
+ import { isInteractiveMode } from '../utils/tty.js';
7
+ const relaxRequired = (definitions) => {
8
+ if (!definitions) {
9
+ return definitions;
10
+ }
11
+ return Object.fromEntries(Object.entries(definitions).map(([name, definition]) => [
12
+ name,
13
+ {
14
+ ...definition,
15
+ required: false,
16
+ },
17
+ ]));
18
+ };
5
19
  export class BaseCommand extends Command {
20
+ static authenticate = true;
6
21
  static baseFlags = {
7
22
  config: Flags.string({
8
23
  helpGroup: 'GLOBAL',
24
+ hidden: true,
9
25
  required: false,
10
26
  summary: 'Specify config file.',
11
27
  }),
28
+ tty: Flags.boolean({
29
+ allowNo: true,
30
+ helpGroup: 'GLOBAL',
31
+ required: false,
32
+ summary: 'Force or disable interactive mode (use --no-tty to disable).',
33
+ }),
12
34
  };
13
35
  static enableJsonFlag = true;
14
36
  args;
@@ -20,24 +42,88 @@ export class BaseCommand extends Command {
20
42
  this.logger = logger.getPino();
21
43
  }
22
44
  ensurePromptValue(value, errorMessage = 'Operation cancelled.') {
23
- if (isCancel(value)) {
24
- this.error(errorMessage);
45
+ try {
46
+ return promptService.ensureValue(value, errorMessage);
47
+ }
48
+ catch (error) {
49
+ this.error(error instanceof Error ? error.message : String(error));
25
50
  }
26
- return value;
27
51
  }
28
52
  async init() {
29
53
  await super.init();
30
- const { args, flags } = await this.parse({
31
- args: this.ctor.args,
32
- baseFlags: super.ctor.baseFlags,
54
+ const allFlags = { ...this.ctor.flags, ...super.ctor.baseFlags };
55
+ const relaxedArgs = relaxRequired(this.ctor.args);
56
+ const relaxedFlags = relaxRequired(this.ctor.flags);
57
+ const relaxedBaseFlags = relaxRequired(super.ctor.baseFlags);
58
+ let parsedResult = await this.parse({
59
+ args: relaxedArgs,
60
+ baseFlags: relaxedBaseFlags,
33
61
  enableJsonFlag: this.ctor.enableJsonFlag,
34
- flags: this.ctor.flags,
35
- strict: this.ctor.strict,
62
+ flags: relaxedFlags,
63
+ strict: false,
36
64
  });
37
- this.flags = flags;
38
- this.args = args;
65
+ const isInteractive = isInteractiveMode(parsedResult.flags.tty);
66
+ const missingFlags = await findMissingRequiredFlags(parsedResult.flags, allFlags);
67
+ const missingArgs = await findMissingRequiredArgs(parsedResult.args, this.ctor.args);
68
+ if (missingFlags.length > 0 || missingArgs.length > 0) {
69
+ if (!isInteractive) {
70
+ const errors = [];
71
+ if (missingFlags.length > 0) {
72
+ errors.push(formatMissingFlagsError(missingFlags));
73
+ }
74
+ if (missingArgs.length > 0) {
75
+ errors.push(formatMissingArgsError(missingArgs));
76
+ }
77
+ this.error(errors.join(' '), { exit: 1 });
78
+ }
79
+ const argValues = [];
80
+ for (const missingArg of missingArgs) {
81
+ const value = await promptForArg(missingArg);
82
+ argValues.push(String(value));
83
+ }
84
+ const flagPairs = [];
85
+ for (const missingFlag of missingFlags) {
86
+ const value = await promptForFlag(missingFlag);
87
+ if (missingFlag.type === 'boolean') {
88
+ const boolValue = Boolean(value);
89
+ if (boolValue) {
90
+ flagPairs.push(`--${missingFlag.name}`);
91
+ }
92
+ else if ('allowNo' in missingFlag.definition &&
93
+ Boolean(missingFlag.definition.allowNo)) {
94
+ flagPairs.push(`--no-${missingFlag.name}`);
95
+ }
96
+ else {
97
+ this.error(`Flag --${missingFlag.name} is required and only supports "true".`);
98
+ }
99
+ }
100
+ else {
101
+ flagPairs.push(`--${missingFlag.name}`, String(value));
102
+ }
103
+ }
104
+ const updatedArgv = [...this.argv, ...argValues, ...flagPairs];
105
+ this.argv = updatedArgv;
106
+ parsedResult = await this.parse({
107
+ args: this.ctor.args,
108
+ baseFlags: super.ctor.baseFlags,
109
+ enableJsonFlag: this.ctor.enableJsonFlag,
110
+ flags: this.ctor.flags,
111
+ strict: this.ctor.strict,
112
+ });
113
+ }
114
+ else if (this.ctor.strict) {
115
+ parsedResult = await this.parse({
116
+ args: this.ctor.args,
117
+ baseFlags: super.ctor.baseFlags,
118
+ enableJsonFlag: this.ctor.enableJsonFlag,
119
+ flags: this.ctor.flags,
120
+ strict: true,
121
+ });
122
+ }
123
+ this.flags = parsedResult.flags;
124
+ this.args = parsedResult.args;
39
125
  this.container = AppContainer.container.setupRuntimeConfig({
40
- configFile: flags.config,
126
+ configFile: parsedResult.flags.config,
41
127
  });
42
128
  }
43
129
  }
@@ -4,9 +4,14 @@ import { createProgressPrinter } from '../../utils/progress.js';
4
4
  import { BaseCommand } from '../base.js';
5
5
  export default class FilesDownload extends BaseCommand {
6
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 }),
7
+ resourceFile: Args.string({
8
+ description: 'Path to a resource file',
9
+ required: true,
10
+ }),
11
+ localDirectory: Args.string({
12
+ description: 'Path to save downloaded file',
13
+ required: true,
14
+ }),
10
15
  };
11
16
  static description = 'Download file or directory described in resource file';
12
17
  static examples = [
@@ -14,7 +19,10 @@ export default class FilesDownload extends BaseCommand {
14
19
  ];
15
20
  static flags = {
16
21
  'maximum-concurrent': Flags.integer({
17
- default: 1, description: 'Maximum concurrent pieces to download at once per transfer', max: 1000, min: 1,
22
+ default: 1,
23
+ description: 'Maximum concurrent pieces to download at once per transfer',
24
+ max: 1000,
25
+ min: 1,
18
26
  }),
19
27
  };
20
28
  static help = 'Download and decrypt a file from the remote storage to <localPath> using resource file <resourcePath>';
@@ -36,7 +44,7 @@ export default class FilesDownload extends BaseCommand {
36
44
  maximumConcurrent: flags['maximum-concurrent'],
37
45
  resourcePath: args.resourceFile,
38
46
  }, ({ current, key, total }) => {
39
- progress.advance(key, current / total * 100, `Downloading: ${key} [${current}/${total}]`);
47
+ progress.advance(key, (current / total) * 100, `Downloading: ${key} [${current}/${total}]`);
40
48
  });
41
49
  }
42
50
  catch (error) {
@@ -4,19 +4,23 @@ import { createProgressPrinter } from '../../utils/progress.js';
4
4
  import { BaseCommand } from '../base.js';
5
5
  export default class FilesUpload extends BaseCommand {
6
6
  static args = {
7
- path: Args.string({ description: 'file or directory to upload', required: true }),
7
+ path: Args.string({
8
+ description: 'file or directory to upload',
9
+ required: true,
10
+ }),
8
11
  };
9
12
  static description = 'Upload file or directory to remote storage';
10
- static examples = [
11
- '<%= config.bin %> <%= command.id %> ./file.txt',
12
- ];
13
+ static examples = ['<%= config.bin %> <%= command.id %> ./file.txt'];
13
14
  static flags = {
14
15
  filename: Flags.string({
15
16
  description: 'The name of the resulting file/directory in the storage',
16
17
  required: false,
17
18
  }),
18
19
  'maximum-concurrent': Flags.integer({
19
- default: 1, description: 'Maximum concurrent pieces to upload at once per transfer', max: 1000, min: 1,
20
+ default: 1,
21
+ description: 'Maximum concurrent pieces to upload at once per transfer',
22
+ max: 1000,
23
+ min: 1,
20
24
  }),
21
25
  metadata: Flags.string({
22
26
  description: 'Path to a metadata file for adding fields to the resource file',
@@ -34,7 +38,7 @@ export default class FilesUpload extends BaseCommand {
34
38
  }),
35
39
  sync: Flags.boolean({
36
40
  default: false,
37
- description: 'Sync mode: delete files in target that don\'t exist in source',
41
+ description: "Sync mode: delete files in target that don't exist in source",
38
42
  required: false,
39
43
  }),
40
44
  };
@@ -60,7 +64,7 @@ export default class FilesUpload extends BaseCommand {
60
64
  sync: flags.sync,
61
65
  withEncryption: !flags['skip-encryption'],
62
66
  }, ({ current, key, total }) => {
63
- progress.advance(key, current / total * 100, `Uploading: ${key} [${current}/${total}]`);
67
+ progress.advance(key, (current / total) * 100, `Uploading: ${key} [${current}/${total}]`);
64
68
  });
65
69
  }
66
70
  catch (error) {
@@ -1,5 +1,5 @@
1
- import { Command } from '@oclif/core';
2
- import { AddStorageDto } from '@super-protocol/provider-client';
1
+ import type { Command } from '@oclif/core';
2
+ import { type AddStorageDto } from '@super-protocol/provider-client';
3
3
  import { BaseCommand } from '../../commands/base.js';
4
4
  import { StorageService } from '../../services/storage.service.js';
5
5
  export declare abstract class BaseStorageCommand<T extends typeof Command> extends BaseCommand<T> {
@@ -1,8 +1,8 @@
1
- import { password, select, text } from '@clack/prompts';
2
1
  import { StorageType } from '@super-protocol/provider-client';
3
2
  import { BaseCommand } from '../../commands/base.js';
4
3
  import { S3_REGION } from '../../constants.js';
5
4
  import { StorageService } from '../../services/storage.service.js';
5
+ import { promptService } from '../../utils/prompt.service.js';
6
6
  export class BaseStorageCommand extends BaseCommand {
7
7
  currentDir = process.cwd();
8
8
  storageService;
@@ -14,25 +14,25 @@ export class BaseStorageCommand extends BaseCommand {
14
14
  }
15
15
  async promptS3Credentials() {
16
16
  const region = S3_REGION;
17
- const readAccessKeyId = this.ensurePromptValue(await text({
17
+ const readAccessKeyId = (await promptService.text({
18
18
  message: 'Read access key ID',
19
19
  validate(value) {
20
20
  return value ? undefined : 'Read access key ID is required';
21
21
  },
22
22
  })).trim();
23
- const readSecretAccessKey = this.ensurePromptValue(await password({
23
+ const readSecretAccessKey = (await promptService.password({
24
24
  message: 'Read secret access key',
25
25
  validate(value) {
26
26
  return value ? undefined : 'Read secret access key is required';
27
27
  },
28
28
  })).trim();
29
- const writeAccessKeyId = this.ensurePromptValue(await text({
29
+ const writeAccessKeyId = (await promptService.text({
30
30
  message: 'Write access key ID',
31
31
  validate(value) {
32
32
  return value ? undefined : 'Write access key ID is required';
33
33
  },
34
34
  })).trim();
35
- const writeSecretAccessKey = this.ensurePromptValue(await password({
35
+ const writeSecretAccessKey = (await promptService.password({
36
36
  message: 'Write secret access key',
37
37
  validate(value) {
38
38
  return value ? undefined : 'Write secret access key is required';
@@ -47,20 +47,20 @@ export class BaseStorageCommand extends BaseCommand {
47
47
  };
48
48
  }
49
49
  async promptStoragePayload() {
50
- const storageType = this.ensurePromptValue(await select({
50
+ const storageType = await promptService.select({
51
51
  message: 'Select storage type',
52
52
  options: [
53
53
  { label: 'S3', value: StorageType.S3 },
54
54
  { label: 'StorJ', value: StorageType.StorJ },
55
55
  ],
56
- }));
57
- const bucket = this.ensurePromptValue(await text({
56
+ });
57
+ const bucket = (await promptService.text({
58
58
  message: 'Bucket name',
59
59
  validate(value) {
60
60
  return value ? undefined : 'Bucket is required';
61
61
  },
62
62
  })).trim();
63
- const prefix = this.ensurePromptValue(await text({
63
+ const prefix = (await promptService.text({
64
64
  defaultValue: '/',
65
65
  initialValue: '/',
66
66
  message: 'Prefix',
@@ -82,13 +82,13 @@ export class BaseStorageCommand extends BaseCommand {
82
82
  return storage;
83
83
  }
84
84
  async promptStorJCredentials() {
85
- const readAccessToken = this.ensurePromptValue(await password({
85
+ const readAccessToken = (await promptService.password({
86
86
  message: 'Read access token',
87
87
  validate(value) {
88
88
  return value ? undefined : 'Read access token is required';
89
89
  },
90
90
  })).trim();
91
- const writeAccessToken = this.ensurePromptValue(await password({
91
+ const writeAccessToken = (await promptService.password({
92
92
  message: 'Write access token',
93
93
  validate(value) {
94
94
  return value ? undefined : 'Write access token is required';
@@ -1,6 +1,6 @@
1
- import { Flags } from '@oclif/core';
2
1
  import fs from 'node:fs/promises';
3
2
  import path from 'node:path';
3
+ import { Flags } from '@oclif/core';
4
4
  import { BaseStorageCommand } from './base.js';
5
5
  export default class StorageCreate extends BaseStorageCommand {
6
6
  static description = 'Create a new storage entry from file or interactive prompts.';
@@ -1,25 +1,23 @@
1
- import { select } from '@clack/prompts';
2
1
  import { StoragesUndefinedError } from '../../services/storage.service.js';
2
+ import { promptService } from '../../utils/prompt.service.js';
3
3
  import { BaseStorageCommand } from './base.js';
4
4
  export default class StorageSelect extends BaseStorageCommand {
5
5
  static description = 'Select a storage that will be used by subsequent commands.';
6
- static examples = [
7
- '<%= config.bin %> storage select',
8
- ];
6
+ static examples = ['<%= config.bin %> storage select'];
9
7
  async run() {
10
8
  try {
11
9
  const storages = await this.storageService.requestStorages();
12
- const storageId = this.ensurePromptValue(await select({
10
+ const storageId = await promptService.select({
13
11
  message: 'Select storage',
14
- options: storages.map(storage => ({
12
+ options: storages.map((storage) => ({
15
13
  label: this.storageService.getLabel(storage),
16
14
  value: storage.id,
17
15
  })),
18
- }));
16
+ });
19
17
  if (!storageId) {
20
18
  this.error('Storage ID is required');
21
19
  }
22
- const storage = storages.find(storage => storage.id === storageId);
20
+ const storage = storages.find((storage) => storage.id === storageId);
23
21
  if (!storage) {
24
22
  this.error(`Storage with ID: ${storageId} not found `);
25
23
  }
@@ -8,9 +8,7 @@ const stripString = (str, chars) => {
8
8
  };
9
9
  export default class StorageShow extends BaseStorageCommand {
10
10
  static description = 'Show current selected storage';
11
- static examples = [
12
- '<%= config.bin %> <%= command.id %>',
13
- ];
11
+ static examples = ['<%= config.bin %> <%= command.id %>'];
14
12
  async run() {
15
13
  const storage = await this.storageService.getCurrentStorage();
16
14
  this.log(`Current storage: ${storage.isCentralized ? 'Super Cloud' : 'Custom storage'}`);
@@ -20,7 +18,7 @@ export default class StorageShow extends BaseStorageCommand {
20
18
  this.log(`- Prefix: ${storage.prefix}`);
21
19
  this.log(' -- Credentials --');
22
20
  if (storage.storageType === StorageType.S3) {
23
- const { readAccessKeyId, readSecretAccessKey = '', writeAccessKeyId, writeSecretAccessKey = '' } = storage.s3Credentials || {};
21
+ const { readAccessKeyId, readSecretAccessKey = '', writeAccessKeyId, writeSecretAccessKey = '', } = storage.s3Credentials || {};
24
22
  this.log(` readAccessKeyId: ${readAccessKeyId}`);
25
23
  this.log(` readSecretAccessKey: ${stripString(readSecretAccessKey, 5)}`);
26
24
  this.log(` writeAccessKeyId: ${writeAccessKeyId}`);
@@ -1,9 +1,9 @@
1
- import { confirm, select, text, } from '@clack/prompts';
2
- import { Flags } from '@oclif/core';
3
- import { StorageType } from '@super-protocol/provider-client';
4
1
  import fs from 'node:fs/promises';
5
2
  import path from 'node:path';
3
+ import { Flags } from '@oclif/core';
4
+ import { StorageType, } from '@super-protocol/provider-client';
6
5
  import { StoragesUndefinedError } from '../../services/storage.service.js';
6
+ import { promptService } from '../../utils/prompt.service.js';
7
7
  import { BaseStorageCommand } from './base.js';
8
8
  export default class StorageUpdate extends BaseStorageCommand {
9
9
  static description = 'Update the configuration of an existing storage.';
@@ -25,25 +25,29 @@ export default class StorageUpdate extends BaseStorageCommand {
25
25
  const { flags } = await this.parse(StorageUpdate);
26
26
  try {
27
27
  const shouldRequestStorages = !flags.fromFile || !flags.id;
28
- const storages = shouldRequestStorages ? await this.storageService.requestStorages() : undefined;
28
+ const storages = shouldRequestStorages
29
+ ? await this.storageService.requestStorages()
30
+ : undefined;
29
31
  let storageId = flags.id;
30
32
  if (!storageId) {
31
- const options = (storages || []).filter(cp => !cp.isCentralized).map(storage => ({
33
+ const options = (storages || [])
34
+ .filter((cp) => !cp.isCentralized)
35
+ .map((storage) => ({
32
36
  label: `${storage.id} (${storage.storageType}) ${storage.bucket}/${storage.prefix} `,
33
37
  value: storage.id,
34
38
  }));
35
39
  if (!options || options.length === 0) {
36
40
  throw new StoragesUndefinedError('No storages available to update');
37
41
  }
38
- storageId = this.ensurePromptValue(await select({
42
+ storageId = await promptService.select({
39
43
  message: 'Select storage to update',
40
44
  options,
41
- }));
45
+ });
42
46
  }
43
47
  if (!storageId) {
44
48
  this.error('Storage ID is required');
45
49
  }
46
- const storageToUpdate = storages?.find(storage => storage.id === storageId);
50
+ const storageToUpdate = storages?.find((storage) => storage.id === storageId);
47
51
  if (flags.id && storages && !storageToUpdate) {
48
52
  this.error(`Storage with ID ${storageId} not found`);
49
53
  }
@@ -72,8 +76,14 @@ export default class StorageUpdate extends BaseStorageCommand {
72
76
  if (!payload || typeof payload !== 'object') {
73
77
  this.error('Storage update definition must be an object');
74
78
  }
75
- const updateFields = ['bucket', 'prefix', 'storageType', 's3Credentials', 'storjCredentials'];
76
- const hasUpdates = updateFields.some(key => payload[key] !== undefined);
79
+ const updateFields = [
80
+ 'bucket',
81
+ 'prefix',
82
+ 'storageType',
83
+ 's3Credentials',
84
+ 'storjCredentials',
85
+ ];
86
+ const hasUpdates = updateFields.some((key) => payload[key] !== undefined);
77
87
  if (!hasUpdates) {
78
88
  this.error('Update payload must include at least one property');
79
89
  }
@@ -82,7 +92,11 @@ export default class StorageUpdate extends BaseStorageCommand {
82
92
  }
83
93
  if (payload.s3Credentials) {
84
94
  const { readAccessKeyId, readSecretAccessKey, region, writeAccessKeyId, writeSecretAccessKey, } = payload.s3Credentials;
85
- if (!readAccessKeyId || !readSecretAccessKey || !region || !writeAccessKeyId || !writeSecretAccessKey) {
95
+ if (!readAccessKeyId ||
96
+ !readSecretAccessKey ||
97
+ !region ||
98
+ !writeAccessKeyId ||
99
+ !writeSecretAccessKey) {
86
100
  this.error('S3 credentials must include readAccessKeyId, readSecretAccessKey, region, writeAccessKeyId and writeSecretAccessKey');
87
101
  }
88
102
  }
@@ -120,7 +134,9 @@ export default class StorageUpdate extends BaseStorageCommand {
120
134
  return sanitized;
121
135
  }
122
136
  async loadStorageFromFile(filePath) {
123
- const absolutePath = path.isAbsolute(filePath) ? filePath : path.join(this.currentDir, filePath);
137
+ const absolutePath = path.isAbsolute(filePath)
138
+ ? filePath
139
+ : path.join(this.currentDir, filePath);
124
140
  try {
125
141
  const fileContent = await fs.readFile(absolutePath, 'utf8');
126
142
  const parsed = JSON.parse(fileContent);
@@ -132,14 +148,14 @@ export default class StorageUpdate extends BaseStorageCommand {
132
148
  }
133
149
  async promptStorageUpdate(existingStorage) {
134
150
  const payload = {};
135
- const bucket = this.ensurePromptValue(await text({
151
+ const bucket = (await promptService.text({
136
152
  defaultValue: existingStorage?.bucket ?? '',
137
153
  message: 'Bucket name (leave empty to keep current)',
138
154
  })).trim();
139
155
  if (bucket) {
140
156
  payload.bucket = bucket;
141
157
  }
142
- const prefix = this.ensurePromptValue(await text({
158
+ const prefix = (await promptService.text({
143
159
  defaultValue: existingStorage?.prefix ?? '',
144
160
  message: 'Prefix (leave empty to keep current)',
145
161
  })).trim();
@@ -147,29 +163,30 @@ export default class StorageUpdate extends BaseStorageCommand {
147
163
  payload.prefix = prefix;
148
164
  }
149
165
  let newStorageType;
150
- const shouldChangeType = this.ensurePromptValue(await confirm({
166
+ const shouldChangeType = await promptService.confirm({
151
167
  initialValue: false,
152
168
  message: existingStorage
153
169
  ? `Change storage type? (current: ${existingStorage.storageType})`
154
170
  : 'Change storage type?',
155
- }));
171
+ });
156
172
  if (shouldChangeType) {
157
- newStorageType = this.ensurePromptValue(await select({
173
+ newStorageType = await promptService.select({
158
174
  message: 'Select new storage type',
159
175
  options: [
160
176
  { label: 'Amazon S3', value: StorageType.S3 },
161
177
  { label: 'StorJ', value: StorageType.StorJ },
162
178
  ],
163
- }));
179
+ });
164
180
  payload.storageType = newStorageType;
165
181
  }
166
182
  const effectiveType = newStorageType ?? existingStorage?.storageType;
167
183
  const credentialsRequired = Boolean(newStorageType);
168
184
  if (effectiveType) {
169
- const updateCredentials = credentialsRequired || this.ensurePromptValue(await confirm({
170
- initialValue: false,
171
- message: `Update ${effectiveType} credentials?`,
172
- }));
185
+ const updateCredentials = credentialsRequired ||
186
+ (await promptService.confirm({
187
+ initialValue: false,
188
+ message: `Update ${effectiveType} credentials?`,
189
+ }));
173
190
  if (updateCredentials) {
174
191
  if (effectiveType === StorageType.S3) {
175
192
  payload.s3Credentials = await this.promptS3Credentials();
@@ -1,4 +1,4 @@
1
- import { SelectOptions } from '@clack/prompts';
1
+ import { type SelectOptions } from '../../utils/prompt.service.js';
2
2
  import { BaseCommand } from '../base.js';
3
3
  export default class WorkflowsExtendLease extends BaseCommand<typeof WorkflowsExtendLease> {
4
4
  static args: {
@@ -1,7 +1,7 @@
1
- import { select } from '@clack/prompts';
2
1
  import { Args, Flags } from '@oclif/core';
3
2
  import { Orders } from '@super-protocol/sdk-js';
4
3
  import { formatEther, parseEther } from 'viem/utils';
4
+ import { promptService } from '../../utils/prompt.service.js';
5
5
  import { BaseCommand } from '../base.js';
6
6
  export default class WorkflowsExtendLease extends BaseCommand {
7
7
  static args = {
@@ -14,9 +14,17 @@ export default class WorkflowsExtendLease extends BaseCommand {
14
14
  '<%= config.bin %> <%= command.id %> <orderId> --sppi 2 --yes',
15
15
  ];
16
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' }),
17
+ minutes: Flags.integer({
18
+ description: 'Time to extend order in minutes (automatically calculates tokens)',
19
+ }),
20
+ sppi: Flags.string({
21
+ description: 'SPPI token amount to add to the order',
22
+ }),
23
+ yes: Flags.boolean({
24
+ char: 'y',
25
+ default: false,
26
+ description: 'Skip confirmation prompt',
27
+ }),
20
28
  };
21
29
  async init() {
22
30
  await super.init();
@@ -51,13 +59,14 @@ export default class WorkflowsExtendLease extends BaseCommand {
51
59
  return;
52
60
  }
53
61
  // 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
- });
62
+ const confirmed = this.flags.yes ||
63
+ (await this.selectPrompt({
64
+ message: `Deposit will be replenished by ${formatEther(tokenAmount)} SPPI. Order time is extended by ${minutes} minutes. Confirm?`,
65
+ options: [
66
+ { label: 'Yes', value: true },
67
+ { label: 'No', value: false },
68
+ ],
69
+ }));
61
70
  if (!confirmed) {
62
71
  this.logger.info('Operation cancelled by user');
63
72
  return;
@@ -88,7 +97,6 @@ export default class WorkflowsExtendLease extends BaseCommand {
88
97
  }
89
98
  }
90
99
  async selectPrompt(options) {
91
- const result = await select(options);
92
- return this.ensurePromptValue(result);
100
+ return promptService.select(options);
93
101
  }
94
102
  }
@@ -1,6 +1,5 @@
1
- import { Static, Type } from 'typebox';
1
+ import { type Static, Type } from 'typebox';
2
2
  export declare const configFileManagerSchema: Type.TObject<{
3
- configs: Type.TArray<Type.TString>;
4
3
  currentConfig: Type.TOptional<Type.TString>;
5
4
  }>;
6
5
  export type ConfigFileManagerData = Static<typeof configFileManagerSchema>;
@@ -1,5 +1,4 @@
1
1
  import { Type } from 'typebox';
2
2
  export const configFileManagerSchema = Type.Object({
3
- configs: Type.Array(Type.String()),
4
3
  currentConfig: Type.Optional(Type.String()),
5
4
  });
@@ -1,4 +1,4 @@
1
- import { Static, Type } from 'typebox';
1
+ import { type Static, Type } from 'typebox';
2
2
  export declare const accountSchema: Type.TObject<{
3
3
  address: Type.TString;
4
4
  privateKey: Type.TString;
package/dist/errors.d.ts CHANGED
@@ -2,6 +2,8 @@ export declare class ConfigurationNotFoundError extends Error {
2
2
  }
3
3
  export declare class NotInitializedError extends Error {
4
4
  }
5
+ export declare class AccountNotFoundError extends Error {
6
+ }
5
7
  export declare class InvalidPrivateKeyError extends Error {
6
8
  }
7
9
  export declare class AuthorizationRequiredError extends Error {
package/dist/errors.js CHANGED
@@ -2,6 +2,8 @@ export class ConfigurationNotFoundError extends Error {
2
2
  }
3
3
  export class NotInitializedError extends Error {
4
4
  }
5
+ export class AccountNotFoundError extends Error {
6
+ }
5
7
  export class InvalidPrivateKeyError extends Error {
6
8
  }
7
9
  export class AuthorizationRequiredError extends Error {
@@ -1,3 +1,3 @@
1
- import { Hook } from '@oclif/core';
1
+ import type { Hook } from '@oclif/core';
2
2
  declare const hook: Hook<'finally'>;
3
3
  export default hook;
@@ -1,5 +1,5 @@
1
1
  import { BlockchainConnector } from '@super-protocol/sdk-js';
2
- const hook = async function () {
2
+ const hook = async () => {
3
3
  const connector = BlockchainConnector.getInstance();
4
4
  if (connector.isInitialized()) {
5
5
  connector.shutdown();
@@ -0,0 +1,3 @@
1
+ import type { Hook } from '@oclif/core';
2
+ declare const hook: Hook<'finally'>;
3
+ export default hook;