@super-protocol/sp-cli 0.0.5 → 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.
Files changed (83) hide show
  1. package/README.md +97 -229
  2. package/dist/commands/account/base.d.ts +20 -0
  3. package/dist/commands/account/base.js +49 -0
  4. package/dist/commands/{config/delete.d.ts → account/forget.d.ts} +5 -2
  5. package/dist/commands/{config/delete.js → account/forget.js} +12 -5
  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 +254 -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 +3 -1
  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/create.js +1 -1
  22. package/dist/commands/storage/select.js +3 -5
  23. package/dist/commands/storage/show.js +2 -4
  24. package/dist/commands/storage/update.js +31 -14
  25. package/dist/commands/workflows/extend-lease.d.ts +1 -1
  26. package/dist/commands/workflows/extend-lease.js +19 -10
  27. package/dist/config/config-file.schema.d.ts +1 -2
  28. package/dist/config/config-file.schema.js +0 -1
  29. package/dist/config/config.schema.d.ts +1 -1
  30. package/dist/errors.d.ts +2 -0
  31. package/dist/errors.js +2 -0
  32. package/dist/hooks/finally/shutdown-blockchain.d.ts +1 -1
  33. package/dist/hooks/finally/shutdown-blockchain.js +1 -1
  34. package/dist/hooks/finally/unlock-config.d.ts +3 -0
  35. package/dist/hooks/finally/unlock-config.js +5 -0
  36. package/dist/hooks/init/init-container.d.ts +1 -1
  37. package/dist/hooks/init/init-container.js +2 -3
  38. package/dist/hooks/init/lock-config.d.ts +3 -0
  39. package/dist/hooks/init/lock-config.js +19 -0
  40. package/dist/hooks/prerun/auth.d.ts +3 -0
  41. package/dist/hooks/prerun/auth.js +70 -0
  42. package/dist/index.d.ts +1 -1
  43. package/dist/index.js +1 -1
  44. package/dist/interfaces/account-manager.interface.d.ts +1 -1
  45. package/dist/interfaces/config-manager.interface.d.ts +2 -2
  46. package/dist/lib/cli-instance-lock.d.ts +2 -0
  47. package/dist/lib/cli-instance-lock.js +37 -0
  48. package/dist/lib/container.d.ts +6 -4
  49. package/dist/lib/container.js +108 -38
  50. package/dist/logger.d.ts +1 -1
  51. package/dist/logger.js +4 -1
  52. package/dist/managers/account-manager.d.ts +7 -8
  53. package/dist/managers/account-manager.js +20 -45
  54. package/dist/managers/config-file-manager.d.ts +6 -7
  55. package/dist/managers/config-file-manager.js +35 -32
  56. package/dist/managers/config-manager.d.ts +5 -5
  57. package/dist/managers/config-manager.js +5 -2
  58. package/dist/middlewares/auth-middleware.d.ts +1 -1
  59. package/dist/services/auth.service.d.ts +10 -15
  60. package/dist/services/auth.service.js +71 -5
  61. package/dist/services/storage.service.d.ts +3 -3
  62. package/dist/services/storage.service.js +46 -19
  63. package/dist/utils/helper.d.ts +1 -0
  64. package/dist/utils/helper.js +15 -1
  65. package/oclif.manifest.json +258 -399
  66. package/package.json +18 -25
  67. package/dist/commands/auth/login.d.ts +0 -12
  68. package/dist/commands/auth/login.js +0 -50
  69. package/dist/commands/auth/me.d.ts +0 -5
  70. package/dist/commands/auth/me.js +0 -16
  71. package/dist/commands/config/add.d.ts +0 -13
  72. package/dist/commands/config/add.js +0 -73
  73. package/dist/commands/config/base.d.ts +0 -16
  74. package/dist/commands/config/base.js +0 -78
  75. package/dist/commands/config/create.d.ts +0 -11
  76. package/dist/commands/config/create.js +0 -41
  77. package/dist/commands/config/index.d.ts +0 -6
  78. package/dist/commands/config/index.js +0 -22
  79. package/dist/commands/config/list.d.ts +0 -6
  80. package/dist/commands/config/show.d.ts +0 -6
  81. package/dist/commands/config/show.js +0 -10
  82. package/dist/commands/config/use.d.ts +0 -6
  83. package/dist/commands/config/use.js +0 -27
@@ -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,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.';
@@ -3,15 +3,13 @@ import { StoragesUndefinedError } from '../../services/storage.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
10
  const storageId = this.ensurePromptValue(await 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
  })),
@@ -19,7 +17,7 @@ export default class StorageSelect extends BaseStorageCommand {
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,8 +1,8 @@
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 { confirm, select, text } from '@clack/prompts';
4
+ import { Flags } from '@oclif/core';
5
+ import { StorageType, } from '@super-protocol/provider-client';
6
6
  import { StoragesUndefinedError } from '../../services/storage.service.js';
7
7
  import { BaseStorageCommand } from './base.js';
8
8
  export default class StorageUpdate extends BaseStorageCommand {
@@ -25,10 +25,14 @@ 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
  }));
@@ -43,7 +47,7 @@ export default class StorageUpdate extends BaseStorageCommand {
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);
@@ -166,10 +182,11 @@ export default class StorageUpdate extends BaseStorageCommand {
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
+ this.ensurePromptValue(await 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 '@clack/prompts';
2
2
  import { BaseCommand } from '../base.js';
3
3
  export default class WorkflowsExtendLease extends BaseCommand<typeof WorkflowsExtendLease> {
4
4
  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;
@@ -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;
@@ -0,0 +1,5 @@
1
+ import { releaseCliInstanceLock } from '../../lib/cli-instance-lock.js';
2
+ const hook = async () => {
3
+ await releaseCliInstanceLock();
4
+ };
5
+ export default hook;
@@ -1,3 +1,3 @@
1
- import { Hook } from '@oclif/core';
1
+ import type { Hook } from '@oclif/core';
2
2
  declare const hook: Hook<'init'>;
3
3
  export default hook;
@@ -1,6 +1,5 @@
1
1
  import { AppContainer } from '../../lib/container.js';
2
- const hook = async function (opts) {
3
- AppContainer
4
- .initialize(process.cwd(), opts.config);
2
+ const hook = async (opts) => {
3
+ AppContainer.initialize(process.cwd(), opts.config);
5
4
  };
6
5
  export default hook;
@@ -0,0 +1,3 @@
1
+ import type { Hook } from '@oclif/core';
2
+ declare const hook: Hook<'init'>;
3
+ export default hook;
@@ -0,0 +1,19 @@
1
+ import path from 'node:path';
2
+ import { mkdirSync } from 'node:fs';
3
+ import { acquireCliInstanceLock } from '../../lib/cli-instance-lock.js';
4
+ import { ConfigFileManager } from '../../managers/config-file-manager.js';
5
+ const hook = async (opts) => {
6
+ const { context, config } = opts;
7
+ const lockFile = path.join(config.configDir, ConfigFileManager.CONFIG_FILE);
8
+ mkdirSync(config.configDir, { recursive: true });
9
+ try {
10
+ await acquireCliInstanceLock(lockFile);
11
+ }
12
+ catch (error) {
13
+ if (context) {
14
+ context.error(error, { exit: 1 });
15
+ }
16
+ throw error;
17
+ }
18
+ };
19
+ export default hook;
@@ -0,0 +1,3 @@
1
+ import type { Hook } from '@oclif/core';
2
+ declare const hook: Hook<'prerun'>;
3
+ export default hook;
@@ -0,0 +1,70 @@
1
+ import { BaseCommand } from '../../commands/base.js';
2
+ import { AppContainer } from '../../lib/container.js';
3
+ import logger from '../../logger.js';
4
+ import { AuthService } from '../../services/auth.service.js';
5
+ const isBaseCommandClass = (commandClass) => commandClass.prototype instanceof BaseCommand;
6
+ const getConfigFlag = (commandClass, argv) => {
7
+ if (!isBaseCommandClass(commandClass)) {
8
+ return undefined;
9
+ }
10
+ //Fix Parser.parse throws error Nonexistent flag we dont have the way to ignore it
11
+ for (let index = 0; index < argv.length; index += 1) {
12
+ const token = argv[index];
13
+ if (!token) {
14
+ continue;
15
+ }
16
+ if (token === '--config') {
17
+ const value = argv[index + 1];
18
+ return value && !value.startsWith('-') ? value : undefined;
19
+ }
20
+ if (token.startsWith('--config=')) {
21
+ const value = token.slice('--config='.length);
22
+ return value || undefined;
23
+ }
24
+ }
25
+ return undefined;
26
+ };
27
+ const hook = async (opts) => {
28
+ const { Command, config, context } = opts;
29
+ const commandId = Command.id;
30
+ const CommandClass = Command;
31
+ if (CommandClass.authenticate === false) {
32
+ return;
33
+ }
34
+ const pinoLogger = logger.getPino();
35
+ pinoLogger.info('Prerun hook auth called');
36
+ try {
37
+ const configFile = getConfigFlag(CommandClass, opts.argv ?? []);
38
+ const container = configFile
39
+ ? AppContainer.container.setupRuntimeConfig({ configFile })
40
+ : AppContainer.container;
41
+ await container
42
+ .initConfigFileManager()
43
+ .initConfigManager()
44
+ .initAccountManager()
45
+ .initProviderClient({ enableAuth: false, enableCookies: true })
46
+ .build();
47
+ const { configManager, accountManager, providerClient } = container;
48
+ const credentials = await configManager.get('auth');
49
+ if (!credentials?.accessKey) {
50
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
51
+ context.error('Authorization not found. Please run: sp account login', { exit: 1 });
52
+ }
53
+ const args = configFile ? ['--config', configFile] : [];
54
+ pinoLogger.info({ commandId }, 'Authorization not found, redirecting to account:login');
55
+ await config.runCommand('account:login', args);
56
+ }
57
+ const authService = new AuthService(accountManager, configManager, providerClient, pinoLogger);
58
+ await authService.auth();
59
+ pinoLogger.debug({ commandId }, 'Authentication successful');
60
+ }
61
+ catch (error) {
62
+ if (error instanceof Error && error.message.includes('not initialized')) {
63
+ pinoLogger.debug({ commandId, err: error }, 'Container not initialized, skipping auth');
64
+ return;
65
+ }
66
+ pinoLogger.error({ commandId, err: error }, 'Authentication failed in prerun hook');
67
+ throw error;
68
+ }
69
+ };
70
+ export default hook;
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { Interfaces, run as oclifRun } from '@oclif/core';
1
+ import { type Interfaces, run as oclifRun } from '@oclif/core';
2
2
  export declare const run: (argv: string[], loadOptions?: Interfaces.LoadOptions | URL) => ReturnType<typeof oclifRun>;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { run as oclifRun } from '@oclif/core';
2
1
  import { fileURLToPath } from 'node:url';
2
+ import { run as oclifRun } from '@oclif/core';
3
3
  import logger from './logger.js';
4
4
  const normalizeLoadOptions = (loadOptions) => {
5
5
  if (!loadOptions) {
@@ -1,4 +1,4 @@
1
- import { IManager } from './manager.interface.js';
1
+ import type { IManager } from './manager.interface.js';
2
2
  export interface IAccountManager extends IManager {
3
3
  createSign(nonce: string): Promise<string>;
4
4
  getAddress(): string;
@@ -1,5 +1,5 @@
1
- import { CliConfig } from '../config/config.schema.js';
2
- import { IManager } from './manager.interface.js';
1
+ import type { CliConfig } from '../config/config.schema.js';
2
+ import type { IManager } from './manager.interface.js';
3
3
  export interface IConfigManager extends IManager {
4
4
  get<K extends keyof CliConfig, V extends CliConfig[K]>(key: K): Promise<undefined | V>;
5
5
  load(): Promise<CliConfig>;
@@ -0,0 +1,2 @@
1
+ export declare const acquireCliInstanceLock: (lockTarget: string) => Promise<void>;
2
+ export declare const releaseCliInstanceLock: () => Promise<void>;
@@ -0,0 +1,37 @@
1
+ import { lock } from 'proper-lockfile';
2
+ let release;
3
+ let locked = false;
4
+ const isLockHeldError = (error) => Boolean(error &&
5
+ typeof error === 'object' &&
6
+ 'code' in error &&
7
+ error.code === 'ELOCKED');
8
+ export const acquireCliInstanceLock = async (lockTarget) => {
9
+ if (locked) {
10
+ return;
11
+ }
12
+ try {
13
+ release = await lock(lockTarget, {
14
+ realpath: false,
15
+ retries: 0,
16
+ stale: 30_000,
17
+ });
18
+ locked = true;
19
+ }
20
+ catch (error) {
21
+ if (isLockHeldError(error)) {
22
+ const lockHeldError = Object.assign(new Error('Another instance of spcli is already running.'), { code: 'ELOCKED' });
23
+ throw lockHeldError;
24
+ }
25
+ throw error;
26
+ }
27
+ };
28
+ export const releaseCliInstanceLock = async () => {
29
+ if (!release) {
30
+ locked = false;
31
+ return;
32
+ }
33
+ const currentRelease = release;
34
+ release = undefined;
35
+ locked = false;
36
+ await currentRelease();
37
+ };
@@ -1,5 +1,5 @@
1
- import { Config } from '@oclif/core';
2
- import { ProviderClient } from '@super-protocol/provider-client';
1
+ import type { Config } from '@oclif/core';
2
+ import { type ProviderClient } from '@super-protocol/provider-client';
3
3
  import { AccountManager, ConfigFileManager, ConfigManager } from '../managers/index.js';
4
4
  interface RuntimeConfig {
5
5
  configFile?: string;
@@ -12,9 +12,10 @@ export declare class AppContainer {
12
12
  private _configFileManager?;
13
13
  private _configManager?;
14
14
  private _providerClient?;
15
- private initPromises;
15
+ private providerClientOptions?;
16
16
  private readonly initQueue;
17
17
  private logger;
18
+ private providerClientInitToken;
18
19
  private runtimeConfigFile?;
19
20
  private constructor();
20
21
  static initialize(currentDir: string, config: Config): AppContainer;
@@ -28,12 +29,13 @@ export declare class AppContainer {
28
29
  initBlockchainConnector(): this;
29
30
  initConfigFileManager(rebuild?: boolean): this;
30
31
  initConfigManager(rebuild?: boolean): this;
31
- initProviderClient({ enableAuth, enableCookies, rebuild }?: {
32
+ initProviderClient({ enableAuth, enableCookies, rebuild, }?: {
32
33
  enableAuth?: boolean;
33
34
  enableCookies?: boolean;
34
35
  rebuild?: boolean;
35
36
  }): this;
36
37
  setupRuntimeConfig(config: RuntimeConfig): this;
38
+ private getProviderClientForBootstrap;
37
39
  private queueInit;
38
40
  private waitFor;
39
41
  }