@aifabrix/builder 2.11.0 → 2.21.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.
- package/.cursor/rules/project-rules.mdc +194 -0
- package/README.md +12 -0
- package/lib/api/applications.api.js +164 -0
- package/lib/api/auth.api.js +303 -0
- package/lib/api/datasources-core.api.js +87 -0
- package/lib/api/datasources-extended.api.js +117 -0
- package/lib/api/datasources.api.js +13 -0
- package/lib/api/deployments.api.js +126 -0
- package/lib/api/environments.api.js +245 -0
- package/lib/api/external-systems.api.js +251 -0
- package/lib/api/index.js +236 -0
- package/lib/api/pipeline.api.js +234 -0
- package/lib/api/types/applications.types.js +136 -0
- package/lib/api/types/auth.types.js +218 -0
- package/lib/api/types/datasources.types.js +272 -0
- package/lib/api/types/deployments.types.js +184 -0
- package/lib/api/types/environments.types.js +197 -0
- package/lib/api/types/external-systems.types.js +244 -0
- package/lib/api/types/pipeline.types.js +125 -0
- package/lib/app-list.js +5 -7
- package/lib/app-rotate-secret.js +4 -10
- package/lib/cli.js +30 -0
- package/lib/commands/login.js +41 -12
- package/lib/datasource-deploy.js +7 -30
- package/lib/datasource-list.js +9 -6
- package/lib/deployer.js +103 -135
- package/lib/environment-deploy.js +15 -26
- package/lib/external-system-deploy.js +12 -39
- package/lib/external-system-download.js +5 -13
- package/lib/external-system-test.js +9 -12
- package/lib/generator-split.js +342 -0
- package/lib/generator.js +94 -5
- package/lib/utils/app-register-api.js +5 -10
- package/lib/utils/deployment-errors.js +88 -6
- package/package.json +1 -1
- package/tatus +0 -181
|
@@ -47,6 +47,23 @@ lib/
|
|
|
47
47
|
├── templates.js # Template rendering
|
|
48
48
|
├── secrets.js # Secret resolution (kv://)
|
|
49
49
|
├── config.js # Configuration management
|
|
50
|
+
├── api/ # Centralized API client structure
|
|
51
|
+
│ ├── index.js # Main API client class
|
|
52
|
+
│ ├── types/ # JSDoc type definitions
|
|
53
|
+
│ │ ├── auth.types.js
|
|
54
|
+
│ │ ├── applications.types.js
|
|
55
|
+
│ │ ├── deployments.types.js
|
|
56
|
+
│ │ ├── environments.types.js
|
|
57
|
+
│ │ ├── datasources.types.js
|
|
58
|
+
│ │ ├── external-systems.types.js
|
|
59
|
+
│ │ └── pipeline.types.js
|
|
60
|
+
│ ├── auth.api.js # Authentication API functions
|
|
61
|
+
│ ├── applications.api.js
|
|
62
|
+
│ ├── deployments.api.js
|
|
63
|
+
│ ├── environments.api.js
|
|
64
|
+
│ ├── datasources.api.js
|
|
65
|
+
│ ├── external-systems.api.js
|
|
66
|
+
│ └── pipeline.api.js
|
|
50
67
|
├── utils/ # Utility functions
|
|
51
68
|
└── schema/ # JSON schemas
|
|
52
69
|
```
|
|
@@ -140,6 +157,92 @@ if (!valid) {
|
|
|
140
157
|
}
|
|
141
158
|
```
|
|
142
159
|
|
|
160
|
+
### API Client Structure Pattern
|
|
161
|
+
Use the centralized API client structure in `lib/api/` for all API calls. This provides typed interfaces, domain separation, and consistent error handling.
|
|
162
|
+
|
|
163
|
+
**Structure**:
|
|
164
|
+
- Base client (`lib/api/index.js`) - Main HTTP client with authentication and error handling
|
|
165
|
+
- Type definitions (`lib/api/types/`) - JSDoc type definitions for request/response types
|
|
166
|
+
- Domain modules (`lib/api/*.api.js`) - Domain-specific API functions
|
|
167
|
+
|
|
168
|
+
**Type Definitions Pattern**:
|
|
169
|
+
Use JSDoc `@typedef` for all request/response types in `lib/api/types/`:
|
|
170
|
+
```javascript
|
|
171
|
+
/**
|
|
172
|
+
* @fileoverview Authentication API type definitions
|
|
173
|
+
* @author AI Fabrix Team
|
|
174
|
+
* @version 2.0.0
|
|
175
|
+
*/
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Token request payload
|
|
179
|
+
* @typedef {Object} TokenRequest
|
|
180
|
+
* @property {string} clientId - Client ID
|
|
181
|
+
* @property {string} clientSecret - Client secret
|
|
182
|
+
*/
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Token response payload
|
|
186
|
+
* @typedef {Object} TokenResponse
|
|
187
|
+
* @property {boolean} success - Request success flag
|
|
188
|
+
* @property {string} token - Authentication token
|
|
189
|
+
* @property {number} expiresIn - Token expiration time in seconds
|
|
190
|
+
* @property {string} expiresAt - Token expiration timestamp
|
|
191
|
+
*/
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**API Module Pattern**:
|
|
195
|
+
Each domain module exports typed API functions:
|
|
196
|
+
```javascript
|
|
197
|
+
/**
|
|
198
|
+
* @fileoverview Authentication API functions
|
|
199
|
+
* @author AI Fabrix Team
|
|
200
|
+
* @version 2.0.0
|
|
201
|
+
*/
|
|
202
|
+
|
|
203
|
+
const { ApiClient } = require('./index');
|
|
204
|
+
const { TokenRequest, TokenResponse } = require('./types/auth.types');
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Get authentication token using client credentials
|
|
208
|
+
* @async
|
|
209
|
+
* @function getToken
|
|
210
|
+
* @param {string} clientId - Client ID
|
|
211
|
+
* @param {string} clientSecret - Client secret
|
|
212
|
+
* @param {string} controllerUrl - Controller base URL
|
|
213
|
+
* @returns {Promise<TokenResponse>} Token response with access token
|
|
214
|
+
* @throws {Error} If authentication fails
|
|
215
|
+
*/
|
|
216
|
+
async function getToken(clientId, clientSecret, controllerUrl) {
|
|
217
|
+
const client = new ApiClient(controllerUrl);
|
|
218
|
+
return await client.post('/api/v1/auth/token', {
|
|
219
|
+
headers: {
|
|
220
|
+
'x-client-id': clientId,
|
|
221
|
+
'x-client-secret': clientSecret
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
module.exports = { getToken };
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**Usage Pattern**:
|
|
230
|
+
Import and use domain-specific API modules:
|
|
231
|
+
```javascript
|
|
232
|
+
const { getToken } = require('../api/auth.api');
|
|
233
|
+
const { registerApplication } = require('../api/applications.api');
|
|
234
|
+
|
|
235
|
+
// Use typed API functions
|
|
236
|
+
const tokenResponse = await getToken(clientId, clientSecret, controllerUrl);
|
|
237
|
+
const appResponse = await registerApplication(controllerUrl, environment, data, token);
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Migration Strategy**:
|
|
241
|
+
- New code should use `lib/api/` modules
|
|
242
|
+
- Existing code can continue using `lib/utils/api.js` (backward compatible)
|
|
243
|
+
- Gradually migrate modules to use centralized API client
|
|
244
|
+
- Eventually deprecate direct usage of `lib/utils/api.js`
|
|
245
|
+
|
|
143
246
|
## Code Style
|
|
144
247
|
|
|
145
248
|
### JavaScript Conventions
|
|
@@ -255,15 +358,18 @@ tests/
|
|
|
255
358
|
### Mock Patterns
|
|
256
359
|
- Mock fs operations: `jest.mock('fs')` or `jest.mock('fs').promises`
|
|
257
360
|
- Mock axios: `jest.mock('axios')` or use `makeApiCall` mock
|
|
361
|
+
- Mock API client: `jest.mock('../lib/api')` or mock individual API modules
|
|
258
362
|
- Mock child_process: `jest.mock('child_process')`
|
|
259
363
|
- Mock templates: provide test templates in `tests/fixtures/`
|
|
260
364
|
- Pattern:
|
|
261
365
|
```javascript
|
|
262
366
|
jest.mock('fs');
|
|
263
367
|
jest.mock('fs').promises;
|
|
368
|
+
jest.mock('../lib/api/auth.api');
|
|
264
369
|
|
|
265
370
|
const fs = require('fs');
|
|
266
371
|
const fsp = require('fs').promises;
|
|
372
|
+
const { getToken } = require('../lib/api/auth.api');
|
|
267
373
|
|
|
268
374
|
describe('ModuleName', () => {
|
|
269
375
|
beforeEach(() => {
|
|
@@ -272,16 +378,50 @@ describe('ModuleName', () => {
|
|
|
272
378
|
|
|
273
379
|
it('should handle success case', async () => {
|
|
274
380
|
fsp.readFile = jest.fn().resolves('content');
|
|
381
|
+
getToken = jest.fn().resolves({ success: true, token: 'test-token' });
|
|
275
382
|
// Test implementation
|
|
276
383
|
});
|
|
277
384
|
|
|
278
385
|
it('should handle error case', async () => {
|
|
279
386
|
fsp.readFile = jest.fn().rejects(new Error('File not found'));
|
|
387
|
+
getToken = jest.fn().resolves({ success: false, error: 'Auth failed' });
|
|
280
388
|
// Test error handling
|
|
281
389
|
});
|
|
282
390
|
});
|
|
283
391
|
```
|
|
284
392
|
|
|
393
|
+
### API Client Testing Pattern
|
|
394
|
+
Test API modules by mocking the base client:
|
|
395
|
+
```javascript
|
|
396
|
+
jest.mock('../lib/api/index');
|
|
397
|
+
|
|
398
|
+
const { ApiClient } = require('../lib/api/index');
|
|
399
|
+
const { getToken } = require('../lib/api/auth.api');
|
|
400
|
+
|
|
401
|
+
describe('auth.api', () => {
|
|
402
|
+
beforeEach(() => {
|
|
403
|
+
jest.clearAllMocks();
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
it('should get token successfully', async () => {
|
|
407
|
+
const mockResponse = { success: true, token: 'test-token' };
|
|
408
|
+
ApiClient.prototype.post = jest.fn().resolves(mockResponse);
|
|
409
|
+
|
|
410
|
+
const result = await getToken('client-id', 'secret', 'https://controller');
|
|
411
|
+
expect(result).toEqual(mockResponse);
|
|
412
|
+
expect(ApiClient.prototype.post).toHaveBeenCalledWith(
|
|
413
|
+
'/api/v1/auth/token',
|
|
414
|
+
expect.objectContaining({
|
|
415
|
+
headers: expect.objectContaining({
|
|
416
|
+
'x-client-id': 'client-id',
|
|
417
|
+
'x-client-secret': 'secret'
|
|
418
|
+
})
|
|
419
|
+
})
|
|
420
|
+
);
|
|
421
|
+
});
|
|
422
|
+
});
|
|
423
|
+
```
|
|
424
|
+
|
|
285
425
|
### Test Coverage
|
|
286
426
|
- Aim for 80%+ branch coverage
|
|
287
427
|
- Test edge cases (null tokens, empty arrays, file errors)
|
|
@@ -585,6 +725,54 @@ const rendered = template(context);
|
|
|
585
725
|
await fs.writeFile(outputPath, rendered, 'utf8');
|
|
586
726
|
```
|
|
587
727
|
|
|
728
|
+
### API Client Usage
|
|
729
|
+
Use the centralized API client for all API calls:
|
|
730
|
+
```javascript
|
|
731
|
+
const { getToken } = require('../api/auth.api');
|
|
732
|
+
const { registerApplication } = require('../api/applications.api');
|
|
733
|
+
|
|
734
|
+
// Typed API calls with automatic error handling
|
|
735
|
+
try {
|
|
736
|
+
const tokenResponse = await getToken(clientId, clientSecret, controllerUrl);
|
|
737
|
+
if (!tokenResponse.success) {
|
|
738
|
+
throw new Error(tokenResponse.formattedError || 'Authentication failed');
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
const appResponse = await registerApplication(
|
|
742
|
+
controllerUrl,
|
|
743
|
+
environment,
|
|
744
|
+
registrationData,
|
|
745
|
+
tokenResponse.token
|
|
746
|
+
);
|
|
747
|
+
} catch (error) {
|
|
748
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
749
|
+
throw error;
|
|
750
|
+
}
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
### Type Definition Pattern
|
|
754
|
+
Define request/response types using JSDoc `@typedef`:
|
|
755
|
+
```javascript
|
|
756
|
+
/**
|
|
757
|
+
* Application registration request
|
|
758
|
+
* @typedef {Object} RegisterApplicationRequest
|
|
759
|
+
* @property {string} appKey - Application key
|
|
760
|
+
* @property {string} name - Application name
|
|
761
|
+
* @property {string} [description] - Application description (optional)
|
|
762
|
+
* @property {string[]} [tags] - Application tags (optional)
|
|
763
|
+
*/
|
|
764
|
+
|
|
765
|
+
/**
|
|
766
|
+
* Application registration response
|
|
767
|
+
* @typedef {Object} RegisterApplicationResponse
|
|
768
|
+
* @property {boolean} success - Request success flag
|
|
769
|
+
* @property {Object} data - Response data
|
|
770
|
+
* @property {string} data.appKey - Registered application key
|
|
771
|
+
* @property {string} data.clientId - Generated client ID
|
|
772
|
+
* @property {string} data.clientSecret - Generated client secret
|
|
773
|
+
*/
|
|
774
|
+
```
|
|
775
|
+
|
|
588
776
|
## Quality Gates
|
|
589
777
|
|
|
590
778
|
### Mandatory Checks Before Commit
|
|
@@ -663,6 +851,9 @@ await fs.writeFile(outputPath, rendered, 'utf8');
|
|
|
663
851
|
- ✅ Use path.join() for cross-platform paths
|
|
664
852
|
- ✅ Validate YAML syntax before parsing
|
|
665
853
|
- ✅ Never log secrets or sensitive data
|
|
854
|
+
- ✅ Use centralized API client (`lib/api/`) for new API calls
|
|
855
|
+
- ✅ Define request/response types using JSDoc `@typedef` in `lib/api/types/`
|
|
856
|
+
- ✅ Use domain-specific API modules (`lib/api/*.api.js`) instead of direct `makeApiCall`
|
|
666
857
|
|
|
667
858
|
### Must Not Do (❌)
|
|
668
859
|
- ❌ Never hardcode secrets, passwords, or tokens
|
|
@@ -674,6 +865,9 @@ await fs.writeFile(outputPath, rendered, 'utf8');
|
|
|
674
865
|
- ❌ Never skip tests for new functionality
|
|
675
866
|
- ❌ Never use `eval()` or `Function()` constructor
|
|
676
867
|
- ❌ Never use raw paths (always use path.join)
|
|
868
|
+
- ❌ Never make direct API calls using `makeApiCall` in new code (use `lib/api/` modules)
|
|
869
|
+
- ❌ Never skip type definitions for API request/response types
|
|
870
|
+
- ❌ Never log authentication tokens or secrets in API calls
|
|
677
871
|
|
|
678
872
|
---
|
|
679
873
|
|
package/README.md
CHANGED
|
@@ -68,6 +68,18 @@ aifabrix run miso-controller
|
|
|
68
68
|
4. **Run** - Start locally, connected to infrastructure
|
|
69
69
|
5. **Deploy** - Push to ACR and deploy via controller
|
|
70
70
|
|
|
71
|
+
```mermaid
|
|
72
|
+
flowchart TD
|
|
73
|
+
Install[Install CLI] --> Up[Start Infrastructure]
|
|
74
|
+
Up --> Create[Create App]
|
|
75
|
+
Create --> Build[Build Image]
|
|
76
|
+
Build --> Run[Run Locally]
|
|
77
|
+
Run --> Deploy[Deploy to Azure]
|
|
78
|
+
|
|
79
|
+
style Install fill:#0062FF,color:#FFFFFF
|
|
80
|
+
style Deploy fill:#10B981,color:#FFFFFF
|
|
81
|
+
```
|
|
82
|
+
|
|
71
83
|
## Requirements
|
|
72
84
|
|
|
73
85
|
- **Docker Desktop** - For running containers
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Applications API functions
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 2.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { ApiClient } = require('./index');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* List all template applications
|
|
11
|
+
* GET /api/v1/applications
|
|
12
|
+
* @async
|
|
13
|
+
* @function listApplications
|
|
14
|
+
* @param {string} controllerUrl - Controller base URL
|
|
15
|
+
* @param {Object} authConfig - Authentication configuration
|
|
16
|
+
* @param {Object} [options] - List options
|
|
17
|
+
* @param {number} [options.page] - Page number
|
|
18
|
+
* @param {number} [options.pageSize] - Items per page
|
|
19
|
+
* @param {string} [options.sort] - Sort parameter
|
|
20
|
+
* @param {string} [options.filter] - Filter parameter
|
|
21
|
+
* @param {string} [options.search] - Search term
|
|
22
|
+
* @returns {Promise<Object>} Paginated list of template applications
|
|
23
|
+
* @throws {Error} If request fails
|
|
24
|
+
*/
|
|
25
|
+
async function listApplications(controllerUrl, authConfig, options = {}) {
|
|
26
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
27
|
+
return await client.get('/api/v1/applications', {
|
|
28
|
+
params: options
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Create new template application
|
|
34
|
+
* POST /api/v1/applications
|
|
35
|
+
* @async
|
|
36
|
+
* @function createApplication
|
|
37
|
+
* @param {string} controllerUrl - Controller base URL
|
|
38
|
+
* @param {Object} authConfig - Authentication configuration
|
|
39
|
+
* @param {Object} applicationData - Application data
|
|
40
|
+
* @param {string} applicationData.key - Application key
|
|
41
|
+
* @param {string} applicationData.displayName - Display name
|
|
42
|
+
* @param {Object} applicationData.configuration - Application configuration
|
|
43
|
+
* @param {string} [applicationData.description] - Application description
|
|
44
|
+
* @param {string} [applicationData.url] - Application URL
|
|
45
|
+
* @returns {Promise<Object>} Created application response
|
|
46
|
+
* @throws {Error} If creation fails
|
|
47
|
+
*/
|
|
48
|
+
async function createApplication(controllerUrl, authConfig, applicationData) {
|
|
49
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
50
|
+
return await client.post('/api/v1/applications', {
|
|
51
|
+
body: applicationData
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Get template application details
|
|
57
|
+
* GET /api/v1/applications/{appKey}
|
|
58
|
+
* @async
|
|
59
|
+
* @function getApplication
|
|
60
|
+
* @param {string} controllerUrl - Controller base URL
|
|
61
|
+
* @param {string} appKey - Application key
|
|
62
|
+
* @param {Object} authConfig - Authentication configuration
|
|
63
|
+
* @returns {Promise<Object>} Application details response
|
|
64
|
+
* @throws {Error} If request fails
|
|
65
|
+
*/
|
|
66
|
+
async function getApplication(controllerUrl, appKey, authConfig) {
|
|
67
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
68
|
+
return await client.get(`/api/v1/applications/${appKey}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Update template application
|
|
73
|
+
* PATCH /api/v1/applications/{appKey}
|
|
74
|
+
* @async
|
|
75
|
+
* @function updateApplication
|
|
76
|
+
* @param {string} controllerUrl - Controller base URL
|
|
77
|
+
* @param {string} appKey - Application key
|
|
78
|
+
* @param {Object} authConfig - Authentication configuration
|
|
79
|
+
* @param {Object} updateData - Update data
|
|
80
|
+
* @param {string} [updateData.displayName] - Display name
|
|
81
|
+
* @param {string} [updateData.description] - Description
|
|
82
|
+
* @param {string} [updateData.url] - URL
|
|
83
|
+
* @param {Object} [updateData.configuration] - Configuration
|
|
84
|
+
* @param {string} [updateData.status] - Status
|
|
85
|
+
* @returns {Promise<Object>} Updated application response
|
|
86
|
+
* @throws {Error} If update fails
|
|
87
|
+
*/
|
|
88
|
+
async function updateApplication(controllerUrl, appKey, authConfig, updateData) {
|
|
89
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
90
|
+
return await client.patch(`/api/v1/applications/${appKey}`, {
|
|
91
|
+
body: updateData
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Delete template application
|
|
97
|
+
* DELETE /api/v1/applications/{appKey}
|
|
98
|
+
* @async
|
|
99
|
+
* @function deleteApplication
|
|
100
|
+
* @param {string} controllerUrl - Controller base URL
|
|
101
|
+
* @param {string} appKey - Application key
|
|
102
|
+
* @param {Object} authConfig - Authentication configuration
|
|
103
|
+
* @returns {Promise<Object>} Delete response
|
|
104
|
+
* @throws {Error} If deletion fails
|
|
105
|
+
*/
|
|
106
|
+
async function deleteApplication(controllerUrl, appKey, authConfig) {
|
|
107
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
108
|
+
return await client.delete(`/api/v1/applications/${appKey}`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Register application in an environment
|
|
113
|
+
* POST /api/v1/environments/{envKey}/applications/register
|
|
114
|
+
* @async
|
|
115
|
+
* @function registerApplication
|
|
116
|
+
* @param {string} controllerUrl - Controller base URL
|
|
117
|
+
* @param {string} envKey - Environment key
|
|
118
|
+
* @param {Object} authConfig - Authentication configuration
|
|
119
|
+
* @param {Object} registrationData - Registration data
|
|
120
|
+
* @param {string} registrationData.key - Application key
|
|
121
|
+
* @param {string} registrationData.displayName - Display name
|
|
122
|
+
* @param {string} registrationData.type - Application type
|
|
123
|
+
* @param {string} [registrationData.description] - Application description
|
|
124
|
+
* @param {string} [registrationData.registryMode] - Registry mode
|
|
125
|
+
* @param {number} [registrationData.port] - Application port
|
|
126
|
+
* @param {string} [registrationData.image] - Container image
|
|
127
|
+
* @param {Object} [registrationData.externalIntegration] - External integration config
|
|
128
|
+
* @returns {Promise<Object>} Registration response with application and credentials
|
|
129
|
+
* @throws {Error} If registration fails
|
|
130
|
+
*/
|
|
131
|
+
async function registerApplication(controllerUrl, envKey, authConfig, registrationData) {
|
|
132
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
133
|
+
return await client.post(`/api/v1/environments/${envKey}/applications/register`, {
|
|
134
|
+
body: registrationData
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Rotate application secret
|
|
140
|
+
* POST /api/v1/environments/{envKey}/applications/{appKey}/rotate-secret
|
|
141
|
+
* @async
|
|
142
|
+
* @function rotateApplicationSecret
|
|
143
|
+
* @param {string} controllerUrl - Controller base URL
|
|
144
|
+
* @param {string} envKey - Environment key
|
|
145
|
+
* @param {string} appKey - Application key
|
|
146
|
+
* @param {Object} authConfig - Authentication configuration
|
|
147
|
+
* @returns {Promise<Object>} Response with new credentials
|
|
148
|
+
* @throws {Error} If rotation fails
|
|
149
|
+
*/
|
|
150
|
+
async function rotateApplicationSecret(controllerUrl, envKey, appKey, authConfig) {
|
|
151
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
152
|
+
return await client.post(`/api/v1/environments/${envKey}/applications/${appKey}/rotate-secret`);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
module.exports = {
|
|
156
|
+
listApplications,
|
|
157
|
+
createApplication,
|
|
158
|
+
getApplication,
|
|
159
|
+
updateApplication,
|
|
160
|
+
deleteApplication,
|
|
161
|
+
registerApplication,
|
|
162
|
+
rotateApplicationSecret
|
|
163
|
+
};
|
|
164
|
+
|