@dishantlangayan/sc-cli-core 0.1.1 → 0.2.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.
@@ -0,0 +1,40 @@
1
+ import { type BrokerAuthStorage, type EncryptedData } from './auth-types.js';
2
+ /**
3
+ * Encryption utility for broker authentication storage
4
+ * Uses AES-256-GCM for authenticated encryption
5
+ */
6
+ export declare class BrokerAuthEncryption {
7
+ private static readonly ALGORITHM;
8
+ private static readonly DIGEST;
9
+ private static readonly ITERATIONS;
10
+ private static readonly IV_LENGTH;
11
+ private static readonly KEY_LENGTH;
12
+ private static readonly SALT_LENGTH;
13
+ private static readonly TAG_LENGTH;
14
+ /**
15
+ * Decrypt broker storage data
16
+ * @param encryptedData - Encrypted data to decrypt
17
+ * @param key - Decryption key
18
+ * @returns Decrypted broker storage
19
+ */
20
+ static decrypt(encryptedData: EncryptedData, key: Buffer): Promise<BrokerAuthStorage>;
21
+ /**
22
+ * Derive encryption key from password using PBKDF2
23
+ * @param password - User password
24
+ * @param salt - Salt for key derivation
25
+ * @returns Derived encryption key
26
+ */
27
+ static deriveKey(password: string, salt: Buffer): Promise<Buffer>;
28
+ /**
29
+ * Encrypt broker storage data
30
+ * @param data - Broker storage to encrypt
31
+ * @param key - Encryption key
32
+ * @returns Encrypted data with metadata
33
+ */
34
+ static encrypt(data: BrokerAuthStorage, key: Buffer): Promise<EncryptedData>;
35
+ /**
36
+ * Generate cryptographically secure random salt
37
+ * @returns Random salt buffer
38
+ */
39
+ static generateSalt(): Buffer;
40
+ }
@@ -0,0 +1,106 @@
1
+ import { createCipheriv, createDecipheriv, pbkdf2, randomBytes } from 'node:crypto';
2
+ import { promisify } from 'node:util';
3
+ import { BrokerAuthError, BrokerAuthErrorCode } from './auth-types.js';
4
+ const pbkdf2Async = promisify(pbkdf2);
5
+ /**
6
+ * Encryption utility for broker authentication storage
7
+ * Uses AES-256-GCM for authenticated encryption
8
+ */
9
+ export class BrokerAuthEncryption {
10
+ static ALGORITHM = 'aes-256-gcm';
11
+ static DIGEST = 'sha256';
12
+ static ITERATIONS = 100_000; // OWASP recommended minimum for PBKDF2
13
+ static IV_LENGTH = 16;
14
+ static KEY_LENGTH = 32; // 256 bits
15
+ static SALT_LENGTH = 32;
16
+ static TAG_LENGTH = 16;
17
+ /**
18
+ * Decrypt broker storage data
19
+ * @param encryptedData - Encrypted data to decrypt
20
+ * @param key - Decryption key
21
+ * @returns Decrypted broker storage
22
+ */
23
+ static async decrypt(encryptedData, key) {
24
+ try {
25
+ // Parse metadata and buffers
26
+ const iv = Buffer.from(encryptedData.iv, 'base64');
27
+ const authTag = Buffer.from(encryptedData.authTag, 'base64');
28
+ // Create decipher
29
+ const decipher = createDecipheriv(this.ALGORITHM, key, iv);
30
+ decipher.setAuthTag(authTag);
31
+ // Decrypt data
32
+ let decrypted = decipher.update(encryptedData.encryptedContent, 'base64', 'utf8');
33
+ decrypted += decipher.final('utf8');
34
+ // Parse JSON
35
+ const storage = JSON.parse(decrypted);
36
+ return storage;
37
+ }
38
+ catch (error) {
39
+ throw new BrokerAuthError('Failed to decrypt broker storage. The password may be incorrect or the file may be corrupted.', BrokerAuthErrorCode.DECRYPTION_FAILED, error);
40
+ }
41
+ }
42
+ /**
43
+ * Derive encryption key from password using PBKDF2
44
+ * @param password - User password
45
+ * @param salt - Salt for key derivation
46
+ * @returns Derived encryption key
47
+ */
48
+ static async deriveKey(password, salt) {
49
+ try {
50
+ if (!password || password.length === 0) {
51
+ throw new BrokerAuthError('Password cannot be empty', BrokerAuthErrorCode.INVALID_PASSWORD);
52
+ }
53
+ return await pbkdf2Async(password, salt, this.ITERATIONS, this.KEY_LENGTH, this.DIGEST);
54
+ }
55
+ catch (error) {
56
+ if (error instanceof BrokerAuthError) {
57
+ throw error;
58
+ }
59
+ throw new BrokerAuthError('Failed to derive encryption key', BrokerAuthErrorCode.ENCRYPTION_FAILED, error);
60
+ }
61
+ }
62
+ /**
63
+ * Encrypt broker storage data
64
+ * @param data - Broker storage to encrypt
65
+ * @param key - Encryption key
66
+ * @returns Encrypted data with metadata
67
+ */
68
+ static async encrypt(data, key) {
69
+ try {
70
+ // Generate random IV
71
+ const iv = randomBytes(this.IV_LENGTH);
72
+ // Create cipher
73
+ const cipher = createCipheriv(this.ALGORITHM, key, iv);
74
+ // Encrypt data
75
+ const plaintext = JSON.stringify(data);
76
+ let encrypted = cipher.update(plaintext, 'utf8', 'base64');
77
+ encrypted += cipher.final('base64');
78
+ // Get authentication tag
79
+ const authTag = cipher.getAuthTag();
80
+ // Generate new salt for next key derivation
81
+ const salt = this.generateSalt();
82
+ return {
83
+ authTag: authTag.toString('base64'),
84
+ encryptedContent: encrypted,
85
+ iv: iv.toString('base64'),
86
+ metadata: {
87
+ algorithm: this.ALGORITHM,
88
+ iterations: this.ITERATIONS,
89
+ keyDerivation: 'pbkdf2',
90
+ saltLength: this.SALT_LENGTH,
91
+ },
92
+ salt: salt.toString('base64'),
93
+ };
94
+ }
95
+ catch (error) {
96
+ throw new BrokerAuthError('Failed to encrypt broker storage', BrokerAuthErrorCode.ENCRYPTION_FAILED, error);
97
+ }
98
+ }
99
+ /**
100
+ * Generate cryptographically secure random salt
101
+ * @returns Random salt buffer
102
+ */
103
+ static generateSalt() {
104
+ return randomBytes(this.SALT_LENGTH);
105
+ }
106
+ }
@@ -0,0 +1,95 @@
1
+ import { ScConnection } from '../util/sc-connection.js';
2
+ import { type BrokerAuth } from './auth-types.js';
3
+ /**
4
+ * Manager for broker authentication storage
5
+ * Handles encrypted storage of broker credentials
6
+ */
7
+ export declare class BrokerAuthManager {
8
+ private static instance;
9
+ private readonly configDir;
10
+ private readonly configFile;
11
+ private currentPassword;
12
+ private encryptionKey;
13
+ private storage;
14
+ private constructor();
15
+ /**
16
+ * Get singleton instance
17
+ */
18
+ static getInstance(): BrokerAuthManager;
19
+ /**
20
+ * Add a new broker configuration
21
+ * @param broker - Broker authentication configuration
22
+ */
23
+ addBroker(broker: BrokerAuth): Promise<void>;
24
+ /**
25
+ * Check if broker exists
26
+ * @param name - Broker name
27
+ * @returns true if broker exists
28
+ */
29
+ brokerExists(name: string): Promise<boolean>;
30
+ /**
31
+ * Clear all broker configurations
32
+ */
33
+ clearAll(): Promise<void>;
34
+ /**
35
+ * Create ScConnection instance from stored broker config
36
+ * @param brokerName - Name of the broker to connect to
37
+ * @param timeout - Optional timeout override
38
+ * @returns Configured ScConnection instance
39
+ */
40
+ createConnection(brokerName: string, timeout?: number): Promise<ScConnection>;
41
+ /**
42
+ * Get all broker configurations
43
+ * @returns Array of all broker configurations
44
+ */
45
+ getAllBrokers(): Promise<BrokerAuth[]>;
46
+ /**
47
+ * Get broker configuration by name
48
+ * @param name - Broker name/alias
49
+ * @returns Broker configuration or null if not found
50
+ */
51
+ getBroker(name: string): Promise<BrokerAuth | null>;
52
+ /**
53
+ * Initialize the auth manager with encryption key
54
+ * @param password - Password to derive encryption key
55
+ */
56
+ initialize(password: string): Promise<void>;
57
+ /**
58
+ * List all broker names
59
+ * @returns Array of broker names
60
+ */
61
+ listBrokers(): Promise<string[]>;
62
+ /**
63
+ * Remove broker configuration
64
+ * @param name - Broker name to remove
65
+ */
66
+ removeBroker(name: string): Promise<void>;
67
+ /**
68
+ * Update existing broker configuration
69
+ * @param name - Broker name to update
70
+ * @param updates - Partial updates to apply
71
+ */
72
+ updateBroker(name: string, updates: Partial<Omit<BrokerAuth, 'name'>>): Promise<void>;
73
+ /**
74
+ * Ensure manager is initialized
75
+ */
76
+ private ensureInitialized;
77
+ /**
78
+ * Check if config file exists
79
+ */
80
+ private fileExists;
81
+ /**
82
+ * Load storage from encrypted file
83
+ * @param password - Password to decrypt
84
+ */
85
+ private loadStorage;
86
+ /**
87
+ * Save storage to encrypted file
88
+ */
89
+ private saveStorage;
90
+ /**
91
+ * Validate broker configuration
92
+ * @param broker - Broker to validate
93
+ */
94
+ private validateBroker;
95
+ }
@@ -0,0 +1,293 @@
1
+ import { mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { ScConnection } from '../util/sc-connection.js';
5
+ import { BrokerAuthEncryption } from './auth-encryption.js';
6
+ import { AuthType, BrokerAuthError, BrokerAuthErrorCode, } from './auth-types.js';
7
+ /**
8
+ * Manager for broker authentication storage
9
+ * Handles encrypted storage of broker credentials
10
+ */
11
+ export class BrokerAuthManager {
12
+ static instance = null;
13
+ configDir;
14
+ configFile;
15
+ currentPassword = null;
16
+ encryptionKey = null;
17
+ storage = null;
18
+ constructor() {
19
+ const homeDirectory = homedir();
20
+ this.configDir = join(homeDirectory, '.sc');
21
+ this.configFile = join(this.configDir, 'brokers.json');
22
+ }
23
+ /**
24
+ * Get singleton instance
25
+ */
26
+ static getInstance() {
27
+ if (!BrokerAuthManager.instance) {
28
+ BrokerAuthManager.instance = new BrokerAuthManager();
29
+ }
30
+ return BrokerAuthManager.instance;
31
+ }
32
+ /**
33
+ * Add a new broker configuration
34
+ * @param broker - Broker authentication configuration
35
+ */
36
+ async addBroker(broker) {
37
+ this.ensureInitialized();
38
+ // Validate broker
39
+ this.validateBroker(broker);
40
+ // Check if broker already exists
41
+ const existing = this.storage.brokers.find((b) => b.name === broker.name);
42
+ if (existing) {
43
+ throw new BrokerAuthError(`Broker '${broker.name}' already exists`, BrokerAuthErrorCode.BROKER_ALREADY_EXISTS);
44
+ }
45
+ // Add broker
46
+ this.storage.brokers.push(broker);
47
+ // Save to file
48
+ await this.saveStorage();
49
+ }
50
+ /**
51
+ * Check if broker exists
52
+ * @param name - Broker name
53
+ * @returns true if broker exists
54
+ */
55
+ async brokerExists(name) {
56
+ this.ensureInitialized();
57
+ return this.storage.brokers.some((b) => b.name === name);
58
+ }
59
+ /**
60
+ * Clear all broker configurations
61
+ */
62
+ async clearAll() {
63
+ this.ensureInitialized();
64
+ this.storage.brokers = [];
65
+ await this.saveStorage();
66
+ }
67
+ /**
68
+ * Create ScConnection instance from stored broker config
69
+ * @param brokerName - Name of the broker to connect to
70
+ * @param timeout - Optional timeout override
71
+ * @returns Configured ScConnection instance
72
+ */
73
+ async createConnection(brokerName, timeout = 10_000) {
74
+ this.ensureInitialized();
75
+ const broker = await this.getBroker(brokerName);
76
+ if (!broker) {
77
+ throw new BrokerAuthError(`Broker '${brokerName}' not found`, BrokerAuthErrorCode.BROKER_NOT_FOUND);
78
+ }
79
+ const baseURL = `${broker.sempEndpoint}:${broker.sempPort}`;
80
+ const accessToken = broker.authType === AuthType.OAUTH ? broker.accessToken : broker.encodedCredentials;
81
+ const isBasic = broker.authType === AuthType.BASIC;
82
+ return new ScConnection(baseURL, accessToken, timeout, isBasic);
83
+ }
84
+ /**
85
+ * Get all broker configurations
86
+ * @returns Array of all broker configurations
87
+ */
88
+ async getAllBrokers() {
89
+ this.ensureInitialized();
90
+ return [...this.storage.brokers];
91
+ }
92
+ /**
93
+ * Get broker configuration by name
94
+ * @param name - Broker name/alias
95
+ * @returns Broker configuration or null if not found
96
+ */
97
+ async getBroker(name) {
98
+ this.ensureInitialized();
99
+ const broker = this.storage.brokers.find((b) => b.name === name);
100
+ return broker ?? null;
101
+ }
102
+ /**
103
+ * Initialize the auth manager with encryption key
104
+ * @param password - Password to derive encryption key
105
+ */
106
+ async initialize(password) {
107
+ try {
108
+ // Store password for re-encryption
109
+ this.currentPassword = password;
110
+ // Try to load existing storage
111
+ const fileExists = await this.fileExists();
112
+ if (fileExists) {
113
+ // Load existing file and derive key from stored salt
114
+ await this.loadStorage(password);
115
+ }
116
+ else {
117
+ // Create new storage with new salt
118
+ const salt = BrokerAuthEncryption.generateSalt();
119
+ this.encryptionKey = await BrokerAuthEncryption.deriveKey(password, salt);
120
+ this.storage = {
121
+ brokers: [],
122
+ version: '1.0.0',
123
+ };
124
+ }
125
+ }
126
+ catch (error) {
127
+ if (error instanceof BrokerAuthError) {
128
+ throw error;
129
+ }
130
+ throw new BrokerAuthError('Failed to initialize broker auth manager', BrokerAuthErrorCode.NOT_INITIALIZED, error);
131
+ }
132
+ }
133
+ /**
134
+ * List all broker names
135
+ * @returns Array of broker names
136
+ */
137
+ async listBrokers() {
138
+ this.ensureInitialized();
139
+ return this.storage.brokers.map((b) => b.name);
140
+ }
141
+ /**
142
+ * Remove broker configuration
143
+ * @param name - Broker name to remove
144
+ */
145
+ async removeBroker(name) {
146
+ this.ensureInitialized();
147
+ const index = this.storage.brokers.findIndex((b) => b.name === name);
148
+ if (index === -1) {
149
+ throw new BrokerAuthError(`Broker '${name}' not found`, BrokerAuthErrorCode.BROKER_NOT_FOUND);
150
+ }
151
+ // Remove broker
152
+ this.storage.brokers.splice(index, 1);
153
+ // Save to file
154
+ await this.saveStorage();
155
+ }
156
+ /**
157
+ * Update existing broker configuration
158
+ * @param name - Broker name to update
159
+ * @param updates - Partial updates to apply
160
+ */
161
+ async updateBroker(name, updates) {
162
+ this.ensureInitialized();
163
+ const index = this.storage.brokers.findIndex((b) => b.name === name);
164
+ if (index === -1) {
165
+ throw new BrokerAuthError(`Broker '${name}' not found`, BrokerAuthErrorCode.BROKER_NOT_FOUND);
166
+ }
167
+ // Merge updates
168
+ const updated = {
169
+ ...this.storage.brokers[index],
170
+ ...updates,
171
+ name, // Ensure name doesn't change
172
+ };
173
+ // Validate updated broker
174
+ this.validateBroker(updated);
175
+ // Update broker
176
+ this.storage.brokers[index] = updated;
177
+ // Save to file
178
+ await this.saveStorage();
179
+ }
180
+ /**
181
+ * Ensure manager is initialized
182
+ */
183
+ ensureInitialized() {
184
+ if (!this.encryptionKey || !this.storage) {
185
+ throw new BrokerAuthError('BrokerAuthManager not initialized. Call initialize() first.', BrokerAuthErrorCode.NOT_INITIALIZED);
186
+ }
187
+ }
188
+ /**
189
+ * Check if config file exists
190
+ */
191
+ async fileExists() {
192
+ try {
193
+ await readFile(this.configFile);
194
+ return true;
195
+ }
196
+ catch {
197
+ return false;
198
+ }
199
+ }
200
+ /**
201
+ * Load storage from encrypted file
202
+ * @param password - Password to decrypt
203
+ */
204
+ async loadStorage(password) {
205
+ try {
206
+ const fileContent = await readFile(this.configFile, 'utf8');
207
+ const encryptedData = JSON.parse(fileContent);
208
+ // Derive key from password and stored salt
209
+ const salt = Buffer.from(encryptedData.salt, 'base64');
210
+ this.encryptionKey = await BrokerAuthEncryption.deriveKey(password, salt);
211
+ // Decrypt storage
212
+ this.storage = await BrokerAuthEncryption.decrypt(encryptedData, this.encryptionKey);
213
+ }
214
+ catch (error) {
215
+ if (error instanceof BrokerAuthError) {
216
+ throw error;
217
+ }
218
+ throw new BrokerAuthError('Failed to load broker storage', BrokerAuthErrorCode.FILE_READ_ERROR, error);
219
+ }
220
+ }
221
+ /**
222
+ * Save storage to encrypted file
223
+ */
224
+ async saveStorage() {
225
+ try {
226
+ if (!this.currentPassword) {
227
+ throw new BrokerAuthError('Password not set', BrokerAuthErrorCode.NOT_INITIALIZED);
228
+ }
229
+ // Ensure directory exists
230
+ await mkdir(this.configDir, { mode: 0o700, recursive: true });
231
+ // Encrypt data
232
+ const encrypted = await BrokerAuthEncryption.encrypt(this.storage, this.encryptionKey);
233
+ // Re-derive key with new salt for next save
234
+ const newSalt = Buffer.from(encrypted.salt, 'base64');
235
+ this.encryptionKey = await BrokerAuthEncryption.deriveKey(this.currentPassword, newSalt);
236
+ // Write to temp file first (atomic write)
237
+ const jsonData = JSON.stringify(encrypted, null, 2);
238
+ const tempFile = `${this.configFile}.tmp`;
239
+ await writeFile(tempFile, jsonData, { mode: 0o600 });
240
+ // Atomic rename
241
+ await rename(tempFile, this.configFile);
242
+ // Set restrictive permissions (Unix only)
243
+ if (process.platform !== 'win32') {
244
+ // Already set via writeFile mode option
245
+ }
246
+ }
247
+ catch (error) {
248
+ // Clean up temp file if it exists
249
+ try {
250
+ await unlink(`${this.configFile}.tmp`);
251
+ }
252
+ catch {
253
+ // Ignore cleanup errors
254
+ }
255
+ if (error instanceof BrokerAuthError) {
256
+ throw error;
257
+ }
258
+ throw new BrokerAuthError('Failed to save broker storage', BrokerAuthErrorCode.FILE_WRITE_ERROR, error);
259
+ }
260
+ }
261
+ /**
262
+ * Validate broker configuration
263
+ * @param broker - Broker to validate
264
+ */
265
+ validateBroker(broker) {
266
+ // Validate name
267
+ if (!broker.name || broker.name.trim() === '') {
268
+ throw new BrokerAuthError('Broker name is required', BrokerAuthErrorCode.INVALID_NAME);
269
+ }
270
+ // Validate endpoint
271
+ if (!broker.sempEndpoint || !(broker.sempEndpoint.startsWith('http://') || broker.sempEndpoint.startsWith('https://'))) {
272
+ throw new BrokerAuthError('SEMP endpoint must start with http:// or https://', BrokerAuthErrorCode.INVALID_ENDPOINT);
273
+ }
274
+ // Validate port
275
+ if (broker.sempPort < 1 || broker.sempPort > 65_535) {
276
+ throw new BrokerAuthError('SEMP port must be between 1 and 65535', BrokerAuthErrorCode.INVALID_PORT);
277
+ }
278
+ // Validate auth-specific fields
279
+ if (broker.authType === AuthType.OAUTH) {
280
+ if (!broker.accessToken || !broker.clientId) {
281
+ throw new BrokerAuthError('OAuth brokers require accessToken and clientId', BrokerAuthErrorCode.INVALID_OAUTH_CONFIG);
282
+ }
283
+ }
284
+ else if (broker.authType === AuthType.BASIC) {
285
+ if (!broker.encodedCredentials) {
286
+ throw new BrokerAuthError('Basic auth brokers require encodedCredentials', BrokerAuthErrorCode.INVALID_BASIC_CONFIG);
287
+ }
288
+ }
289
+ else {
290
+ throw new BrokerAuthError('Invalid auth type', BrokerAuthErrorCode.INVALID_AUTH_TYPE);
291
+ }
292
+ }
293
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Authentication types supported by the broker auth system
3
+ */
4
+ export declare enum AuthType {
5
+ BASIC = "basic",
6
+ OAUTH = "oauth"
7
+ }
8
+ /**
9
+ * Base broker authentication configuration
10
+ */
11
+ export interface BrokerAuthBase {
12
+ authType: AuthType;
13
+ name: string;
14
+ sempEndpoint: string;
15
+ sempPort: number;
16
+ }
17
+ /**
18
+ * OAuth broker authentication configuration
19
+ */
20
+ export interface OAuthBrokerAuth extends BrokerAuthBase {
21
+ accessToken: string;
22
+ authType: AuthType.OAUTH;
23
+ clientId: string;
24
+ refreshToken: string;
25
+ }
26
+ /**
27
+ * Basic authentication broker configuration
28
+ */
29
+ export interface BasicBrokerAuth extends BrokerAuthBase {
30
+ authType: AuthType.BASIC;
31
+ encodedCredentials: string;
32
+ }
33
+ /**
34
+ * Union type for broker authentication
35
+ */
36
+ export type BrokerAuth = BasicBrokerAuth | OAuthBrokerAuth;
37
+ /**
38
+ * Storage format for broker configurations
39
+ */
40
+ export interface BrokerAuthStorage {
41
+ brokers: BrokerAuth[];
42
+ version: string;
43
+ }
44
+ /**
45
+ * Encryption metadata stored alongside encrypted data
46
+ */
47
+ export interface EncryptionMetadata {
48
+ algorithm: string;
49
+ iterations: number;
50
+ keyDerivation: string;
51
+ saltLength: number;
52
+ }
53
+ /**
54
+ * Encrypted data structure
55
+ */
56
+ export interface EncryptedData {
57
+ authTag: string;
58
+ encryptedContent: string;
59
+ iv: string;
60
+ metadata: EncryptionMetadata;
61
+ salt: string;
62
+ }
63
+ /**
64
+ * Error codes for broker auth operations
65
+ */
66
+ export declare enum BrokerAuthErrorCode {
67
+ BROKER_ALREADY_EXISTS = "BROKER_ALREADY_EXISTS",
68
+ BROKER_NOT_FOUND = "BROKER_NOT_FOUND",
69
+ DECRYPTION_FAILED = "DECRYPTION_FAILED",
70
+ ENCRYPTION_FAILED = "ENCRYPTION_FAILED",
71
+ FILE_READ_ERROR = "FILE_READ_ERROR",
72
+ FILE_WRITE_ERROR = "FILE_WRITE_ERROR",
73
+ INVALID_AUTH_TYPE = "INVALID_AUTH_TYPE",
74
+ INVALID_BASIC_CONFIG = "INVALID_BASIC_CONFIG",
75
+ INVALID_ENDPOINT = "INVALID_ENDPOINT",
76
+ INVALID_NAME = "INVALID_NAME",
77
+ INVALID_OAUTH_CONFIG = "INVALID_OAUTH_CONFIG",
78
+ INVALID_PASSWORD = "INVALID_PASSWORD",
79
+ INVALID_PORT = "INVALID_PORT",
80
+ NOT_INITIALIZED = "NOT_INITIALIZED"
81
+ }
82
+ /**
83
+ * Custom error class for broker authentication operations
84
+ */
85
+ export declare class BrokerAuthError extends Error {
86
+ readonly code: BrokerAuthErrorCode;
87
+ readonly cause?: Error | undefined;
88
+ constructor(message: string, code: BrokerAuthErrorCode, cause?: Error | undefined);
89
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Authentication types supported by the broker auth system
3
+ */
4
+ export var AuthType;
5
+ (function (AuthType) {
6
+ AuthType["BASIC"] = "basic";
7
+ AuthType["OAUTH"] = "oauth";
8
+ })(AuthType || (AuthType = {}));
9
+ /**
10
+ * Error codes for broker auth operations
11
+ */
12
+ export var BrokerAuthErrorCode;
13
+ (function (BrokerAuthErrorCode) {
14
+ BrokerAuthErrorCode["BROKER_ALREADY_EXISTS"] = "BROKER_ALREADY_EXISTS";
15
+ BrokerAuthErrorCode["BROKER_NOT_FOUND"] = "BROKER_NOT_FOUND";
16
+ BrokerAuthErrorCode["DECRYPTION_FAILED"] = "DECRYPTION_FAILED";
17
+ BrokerAuthErrorCode["ENCRYPTION_FAILED"] = "ENCRYPTION_FAILED";
18
+ BrokerAuthErrorCode["FILE_READ_ERROR"] = "FILE_READ_ERROR";
19
+ BrokerAuthErrorCode["FILE_WRITE_ERROR"] = "FILE_WRITE_ERROR";
20
+ BrokerAuthErrorCode["INVALID_AUTH_TYPE"] = "INVALID_AUTH_TYPE";
21
+ BrokerAuthErrorCode["INVALID_BASIC_CONFIG"] = "INVALID_BASIC_CONFIG";
22
+ BrokerAuthErrorCode["INVALID_ENDPOINT"] = "INVALID_ENDPOINT";
23
+ BrokerAuthErrorCode["INVALID_NAME"] = "INVALID_NAME";
24
+ BrokerAuthErrorCode["INVALID_OAUTH_CONFIG"] = "INVALID_OAUTH_CONFIG";
25
+ BrokerAuthErrorCode["INVALID_PASSWORD"] = "INVALID_PASSWORD";
26
+ BrokerAuthErrorCode["INVALID_PORT"] = "INVALID_PORT";
27
+ BrokerAuthErrorCode["NOT_INITIALIZED"] = "NOT_INITIALIZED";
28
+ })(BrokerAuthErrorCode || (BrokerAuthErrorCode = {}));
29
+ /**
30
+ * Custom error class for broker authentication operations
31
+ */
32
+ export class BrokerAuthError extends Error {
33
+ code;
34
+ cause;
35
+ constructor(message, code, cause) {
36
+ super(message);
37
+ this.code = code;
38
+ this.cause = cause;
39
+ this.name = 'BrokerAuthError';
40
+ }
41
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Broker authentication management module
3
+ * Provides encrypted storage for SEMP broker credentials
4
+ */
5
+ export { BrokerAuthEncryption } from './auth-encryption.js';
6
+ export { BrokerAuthManager } from './auth-manager.js';
7
+ export { AuthType, type BasicBrokerAuth, type BrokerAuth, type BrokerAuthBase, BrokerAuthError, BrokerAuthErrorCode, type BrokerAuthStorage, type EncryptedData, type EncryptionMetadata, type OAuthBrokerAuth, } from './auth-types.js';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Broker authentication management module
3
+ * Provides encrypted storage for SEMP broker credentials
4
+ */
5
+ export { BrokerAuthEncryption } from './auth-encryption.js';
6
+ export { BrokerAuthManager } from './auth-manager.js';
7
+ export { AuthType, BrokerAuthError, BrokerAuthErrorCode, } from './auth-types.js';
@@ -1,7 +1,8 @@
1
1
  export declare enum EnvironmentVariable {
2
2
  'SC_ACCESS_TOKEN' = "SC_ACCESS_TOKEN",
3
3
  'SC_API_VERSION' = "SC_API_VERSION",
4
- 'SC_BASE_URL' = "SC_BASE_URL"
4
+ 'SC_BASE_URL' = "SC_BASE_URL",
5
+ 'SEMP_API_VERSION' = "SEMP_API_VERSION"
5
6
  }
6
7
  export declare const DefaultBaseUrl = "https://api.solace.cloud";
7
8
  /**
@@ -3,6 +3,7 @@ export var EnvironmentVariable;
3
3
  EnvironmentVariable["SC_ACCESS_TOKEN"] = "SC_ACCESS_TOKEN";
4
4
  EnvironmentVariable["SC_API_VERSION"] = "SC_API_VERSION";
5
5
  EnvironmentVariable["SC_BASE_URL"] = "SC_BASE_URL";
6
+ EnvironmentVariable["SEMP_API_VERSION"] = "SEMP_API_VERSION";
6
7
  })(EnvironmentVariable || (EnvironmentVariable = {}));
7
8
  export const DefaultBaseUrl = 'https://api.solace.cloud';
8
9
  /**
package/lib/exported.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export { AuthType, type BasicBrokerAuth, type BrokerAuth, BrokerAuthError, BrokerAuthErrorCode, BrokerAuthManager, type OAuthBrokerAuth, } from './auth/index.js';
1
2
  export { EnvironmentVariable, envVars } from './config/env-vars.js';
2
3
  export { ScCommand } from './sc-command.js';
3
4
  export { ScConnection } from './util/sc-connection.js';
package/lib/exported.js CHANGED
@@ -1,3 +1,4 @@
1
+ export { AuthType, BrokerAuthError, BrokerAuthErrorCode, BrokerAuthManager, } from './auth/index.js';
1
2
  export { EnvironmentVariable, envVars } from './config/env-vars.js';
2
3
  export { ScCommand } from './sc-command.js';
3
4
  export { ScConnection } from './util/sc-connection.js';
@@ -2,7 +2,7 @@ import { AxiosRequestConfig } from 'axios';
2
2
  export declare class ScConnection {
3
3
  private axiosInstance;
4
4
  private endpointUrl;
5
- constructor(baseURL?: string, accessToken?: string, timeout?: number);
5
+ constructor(baseURL?: string, accessToken?: string, timeout?: number, basic?: boolean);
6
6
  delete<T>(url: string, config?: AxiosRequestConfig): Promise<T>;
7
7
  get<T>(url: string, config?: AxiosRequestConfig): Promise<T>;
8
8
  patch<T>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>;
@@ -3,13 +3,16 @@ import { DefaultBaseUrl, EnvironmentVariable, envVars } from '../config/env-vars
3
3
  export class ScConnection {
4
4
  axiosInstance;
5
5
  endpointUrl = '';
6
- constructor(baseURL = envVars.getString(EnvironmentVariable.SC_BASE_URL, DefaultBaseUrl), accessToken = envVars.getString(EnvironmentVariable.SC_ACCESS_TOKEN, ''), timeout = 10_000) {
6
+ constructor(baseURL = envVars.getString(EnvironmentVariable.SC_BASE_URL, DefaultBaseUrl), accessToken = envVars.getString(EnvironmentVariable.SC_ACCESS_TOKEN, ''), timeout = 10_000, basic = false) {
7
7
  const apiVersion = envVars.getString(EnvironmentVariable.SC_API_VERSION, 'v2');
8
- this.endpointUrl = this.joinPaths(baseURL, `/api/${apiVersion}`);
8
+ const sempApiVersion = envVars.getString(EnvironmentVariable.SEMP_API_VERSION, 'v2');
9
+ this.endpointUrl = basic
10
+ ? this.joinPaths(baseURL, `/SEMP/${sempApiVersion}`)
11
+ : this.joinPaths(baseURL, `/api/${apiVersion}`);
9
12
  this.axiosInstance = axios.create({
10
13
  baseURL: this.endpointUrl,
11
14
  headers: {
12
- Authorization: `Bearer ${accessToken}`,
15
+ Authorization: basic ? `Basic ${accessToken}` : `Bearer ${accessToken}`,
13
16
  'Content-Type': 'application/json',
14
17
  },
15
18
  timeout,
package/package.json CHANGED
@@ -1,9 +1,15 @@
1
1
  {
2
2
  "name": "@dishantlangayan/sc-cli-core",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Base library for the Solace Cloud CLI and plugins",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Dishant Langayan",
7
+ "keywords": [
8
+ "oclif",
9
+ "solace",
10
+ "cli",
11
+ "sc"
12
+ ],
7
13
  "type": "module",
8
14
  "exports": {
9
15
  "./ScCommand.js": "./lib/ScCommand.js",
@@ -28,10 +34,12 @@
28
34
  "@oclif/prettier-config": "^0.2.1",
29
35
  "@oclif/test": "^4.1.16",
30
36
  "@types/chai": "^5.2.3",
37
+ "@types/chai-as-promised": "^8.0.2",
31
38
  "@types/mocha": "^10.0.10",
32
39
  "@types/node": "^25.0.3",
33
40
  "@types/sinon": "^21.0.0",
34
41
  "chai": "^6.2.2",
42
+ "chai-as-promised": "^8.0.2",
35
43
  "eslint": "^9",
36
44
  "eslint-config-oclif": "^6.0.137",
37
45
  "eslint-config-prettier": "^10",