@masonator/coolify-mcp 2.10.0 → 2.12.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/README.md +27 -22
- package/dist/__tests__/coolify-client.test.js +637 -0
- package/dist/__tests__/mcp-server.test.js +71 -0
- package/dist/lib/coolify-client.d.ts +60 -1
- package/dist/lib/coolify-client.js +296 -0
- package/dist/lib/mcp-server.js +369 -20
- package/dist/types/coolify.d.ts +152 -0
- package/package.json +2 -2
|
@@ -149,6 +149,61 @@ describe('CoolifyMcpServer v2', () => {
|
|
|
149
149
|
expect(typeof client.updateCloudToken).toBe('function');
|
|
150
150
|
expect(typeof client.deleteCloudToken).toBe('function');
|
|
151
151
|
expect(typeof client.validateCloudToken).toBe('function');
|
|
152
|
+
// Application storage operations
|
|
153
|
+
expect(typeof client.listApplicationStorages).toBe('function');
|
|
154
|
+
expect(typeof client.createApplicationStorage).toBe('function');
|
|
155
|
+
expect(typeof client.updateApplicationStorage).toBe('function');
|
|
156
|
+
expect(typeof client.deleteApplicationStorage).toBe('function');
|
|
157
|
+
// Application scheduled task operations
|
|
158
|
+
expect(typeof client.listApplicationScheduledTasks).toBe('function');
|
|
159
|
+
expect(typeof client.createApplicationScheduledTask).toBe('function');
|
|
160
|
+
expect(typeof client.updateApplicationScheduledTask).toBe('function');
|
|
161
|
+
expect(typeof client.deleteApplicationScheduledTask).toBe('function');
|
|
162
|
+
expect(typeof client.listApplicationScheduledTaskExecutions).toBe('function');
|
|
163
|
+
// Application preview operations
|
|
164
|
+
expect(typeof client.deleteApplicationPreview).toBe('function');
|
|
165
|
+
// Database environment variable operations
|
|
166
|
+
expect(typeof client.listDatabaseEnvVars).toBe('function');
|
|
167
|
+
expect(typeof client.createDatabaseEnvVar).toBe('function');
|
|
168
|
+
expect(typeof client.updateDatabaseEnvVar).toBe('function');
|
|
169
|
+
expect(typeof client.bulkUpdateDatabaseEnvVars).toBe('function');
|
|
170
|
+
expect(typeof client.deleteDatabaseEnvVar).toBe('function');
|
|
171
|
+
// Database storage operations
|
|
172
|
+
expect(typeof client.listDatabaseStorages).toBe('function');
|
|
173
|
+
expect(typeof client.createDatabaseStorage).toBe('function');
|
|
174
|
+
expect(typeof client.updateDatabaseStorage).toBe('function');
|
|
175
|
+
expect(typeof client.deleteDatabaseStorage).toBe('function');
|
|
176
|
+
// Delete backup execution
|
|
177
|
+
expect(typeof client.deleteBackupExecution).toBe('function');
|
|
178
|
+
// Service env var bulk operations
|
|
179
|
+
expect(typeof client.bulkUpdateServiceEnvVars).toBe('function');
|
|
180
|
+
// Service storage operations
|
|
181
|
+
expect(typeof client.listServiceStorages).toBe('function');
|
|
182
|
+
expect(typeof client.createServiceStorage).toBe('function');
|
|
183
|
+
expect(typeof client.updateServiceStorage).toBe('function');
|
|
184
|
+
expect(typeof client.deleteServiceStorage).toBe('function');
|
|
185
|
+
// Service scheduled task operations
|
|
186
|
+
expect(typeof client.listServiceScheduledTasks).toBe('function');
|
|
187
|
+
expect(typeof client.createServiceScheduledTask).toBe('function');
|
|
188
|
+
expect(typeof client.updateServiceScheduledTask).toBe('function');
|
|
189
|
+
expect(typeof client.deleteServiceScheduledTask).toBe('function');
|
|
190
|
+
expect(typeof client.listServiceScheduledTaskExecutions).toBe('function');
|
|
191
|
+
// Hetzner cloud operations
|
|
192
|
+
expect(typeof client.listHetznerLocations).toBe('function');
|
|
193
|
+
expect(typeof client.listHetznerServerTypes).toBe('function');
|
|
194
|
+
expect(typeof client.listHetznerImages).toBe('function');
|
|
195
|
+
expect(typeof client.listHetznerSSHKeys).toBe('function');
|
|
196
|
+
expect(typeof client.createHetznerServer).toBe('function');
|
|
197
|
+
// GitHub App repository operations
|
|
198
|
+
expect(typeof client.listGitHubAppRepositories).toBe('function');
|
|
199
|
+
expect(typeof client.listGitHubAppBranches).toBe('function');
|
|
200
|
+
// Resources operations
|
|
201
|
+
expect(typeof client.listResources).toBe('function');
|
|
202
|
+
// Health operations
|
|
203
|
+
expect(typeof client.getHealth).toBe('function');
|
|
204
|
+
// API enable/disable operations
|
|
205
|
+
expect(typeof client.enableApi).toBe('function');
|
|
206
|
+
expect(typeof client.disableApi).toBe('function');
|
|
152
207
|
// Version caching
|
|
153
208
|
expect(typeof client.getCachedVersion).toBe('function');
|
|
154
209
|
});
|
|
@@ -245,6 +300,22 @@ describe('CoolifyMcpServer v2', () => {
|
|
|
245
300
|
expect(result.content[0].text).toContain('key, value required');
|
|
246
301
|
});
|
|
247
302
|
});
|
|
303
|
+
describe('system tool handler', () => {
|
|
304
|
+
const callSystem = async (srv, args) => {
|
|
305
|
+
const tool = srv._registeredTools['system'];
|
|
306
|
+
return tool.handler(args, {});
|
|
307
|
+
};
|
|
308
|
+
it('forwards include_full and reveal to listResources', async () => {
|
|
309
|
+
const spy = jest.spyOn(server['client'], 'listResources').mockResolvedValue([]);
|
|
310
|
+
await callSystem(server, { action: 'list_resources', include_full: true, reveal: true });
|
|
311
|
+
expect(spy).toHaveBeenCalledWith({ include_full: true, reveal: true });
|
|
312
|
+
});
|
|
313
|
+
it('calls listResources with undefined flags when neither is passed', async () => {
|
|
314
|
+
const spy = jest.spyOn(server['client'], 'listResources').mockResolvedValue([]);
|
|
315
|
+
await callSystem(server, { action: 'list_resources' });
|
|
316
|
+
expect(spy).toHaveBeenCalledWith({ include_full: undefined, reveal: undefined });
|
|
317
|
+
});
|
|
318
|
+
});
|
|
248
319
|
describe('bulk_env_update tool handler', () => {
|
|
249
320
|
it('forwards is_buildtime/is_runtime to bulkEnvUpdate', async () => {
|
|
250
321
|
const spy = jest.spyOn(server['client'], 'bulkEnvUpdate').mockResolvedValue({
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Coolify API Client
|
|
3
3
|
* Complete HTTP client for the Coolify API v1
|
|
4
4
|
*/
|
|
5
|
-
import type { CoolifyConfig, DeleteOptions, MessageResponse, UuidResponse, Server, ServerResource, ServerDomain, ServerValidation, CreateServerRequest, UpdateServerRequest, Project, CreateProjectRequest, UpdateProjectRequest, Environment, CreateEnvironmentRequest, Application, CreateApplicationPublicRequest, CreateApplicationPrivateGHRequest, CreateApplicationPrivateKeyRequest, CreateApplicationDockerfileRequest, CreateApplicationDockerImageRequest, CreateApplicationDockerComposeRequest, UpdateApplicationRequest, ApplicationActionResponse, EnvironmentVariable, EnvVarSummary, CreateEnvVarRequest, UpdateEnvVarRequest, BulkUpdateEnvVarsRequest, Database, UpdateDatabaseRequest, CreatePostgresqlRequest, CreateMysqlRequest, CreateMariadbRequest, CreateMongodbRequest, CreateRedisRequest, CreateKeydbRequest, CreateClickhouseRequest, CreateDragonflyRequest, CreateDatabaseResponse, DatabaseBackup, BackupExecution, CreateDatabaseBackupRequest, UpdateDatabaseBackupRequest, Service, CreateServiceRequest, UpdateServiceRequest, ServiceCreateResponse, Deployment, DeploymentEssential, Team, TeamMember, PrivateKey, CreatePrivateKeyRequest, UpdatePrivateKeyRequest, GitHubApp, CreateGitHubAppRequest, UpdateGitHubAppRequest, GitHubAppUpdateResponse, CloudToken, CreateCloudTokenRequest, UpdateCloudTokenRequest, CloudTokenValidation, Version, ApplicationDiagnostic, ServerDiagnostic, InfrastructureIssuesReport, BatchOperationResult } from '../types/coolify.js';
|
|
5
|
+
import type { CoolifyConfig, DeleteOptions, MessageResponse, UuidResponse, Server, ServerResource, ServerDomain, ServerValidation, CreateServerRequest, UpdateServerRequest, Project, CreateProjectRequest, UpdateProjectRequest, Environment, CreateEnvironmentRequest, Application, CreateApplicationPublicRequest, CreateApplicationPrivateGHRequest, CreateApplicationPrivateKeyRequest, CreateApplicationDockerfileRequest, CreateApplicationDockerImageRequest, CreateApplicationDockerComposeRequest, UpdateApplicationRequest, ApplicationActionResponse, EnvironmentVariable, EnvVarSummary, CreateEnvVarRequest, UpdateEnvVarRequest, BulkUpdateEnvVarsRequest, Database, UpdateDatabaseRequest, CreatePostgresqlRequest, CreateMysqlRequest, CreateMariadbRequest, CreateMongodbRequest, CreateRedisRequest, CreateKeydbRequest, CreateClickhouseRequest, CreateDragonflyRequest, CreateDatabaseResponse, DatabaseBackup, BackupExecution, CreateDatabaseBackupRequest, UpdateDatabaseBackupRequest, Service, CreateServiceRequest, UpdateServiceRequest, ServiceCreateResponse, Deployment, DeploymentEssential, Team, TeamMember, PrivateKey, CreatePrivateKeyRequest, UpdatePrivateKeyRequest, GitHubApp, CreateGitHubAppRequest, UpdateGitHubAppRequest, GitHubAppUpdateResponse, CloudToken, CreateCloudTokenRequest, UpdateCloudTokenRequest, CloudTokenValidation, Version, StorageListResponse, CreateStorageRequest, UpdateStorageRequest, ScheduledTask, ScheduledTaskExecution, CreateScheduledTaskRequest, UpdateScheduledTaskRequest, HetznerLocation, HetznerServerType, HetznerImage, HetznerSSHKey, CreateHetznerServerRequest, CreateHetznerServerResponse, GitHubRepository, GitHubBranch, ApplicationDiagnostic, ServerDiagnostic, InfrastructureIssuesReport, BatchOperationResult, ResourceListItem, ResourceListItemFull } from '../types/coolify.js';
|
|
6
6
|
export interface ListOptions {
|
|
7
7
|
page?: number;
|
|
8
8
|
per_page?: number;
|
|
@@ -225,6 +225,65 @@ export declare class CoolifyClient {
|
|
|
225
225
|
createDatabaseBackup(databaseUuid: string, data: CreateDatabaseBackupRequest): Promise<DatabaseBackup>;
|
|
226
226
|
updateDatabaseBackup(databaseUuid: string, backupUuid: string, data: UpdateDatabaseBackupRequest): Promise<MessageResponse>;
|
|
227
227
|
deleteDatabaseBackup(databaseUuid: string, backupUuid: string): Promise<MessageResponse>;
|
|
228
|
+
listApplicationStorages(uuid: string): Promise<StorageListResponse>;
|
|
229
|
+
createApplicationStorage(uuid: string, data: CreateStorageRequest): Promise<MessageResponse>;
|
|
230
|
+
updateApplicationStorage(uuid: string, data: UpdateStorageRequest): Promise<MessageResponse>;
|
|
231
|
+
deleteApplicationStorage(uuid: string, storageUuid: string): Promise<MessageResponse>;
|
|
232
|
+
listApplicationScheduledTasks(uuid: string): Promise<ScheduledTask[]>;
|
|
233
|
+
createApplicationScheduledTask(uuid: string, data: CreateScheduledTaskRequest): Promise<ScheduledTask>;
|
|
234
|
+
updateApplicationScheduledTask(uuid: string, taskUuid: string, data: UpdateScheduledTaskRequest): Promise<ScheduledTask>;
|
|
235
|
+
deleteApplicationScheduledTask(uuid: string, taskUuid: string): Promise<MessageResponse>;
|
|
236
|
+
listApplicationScheduledTaskExecutions(uuid: string, taskUuid: string): Promise<ScheduledTaskExecution[]>;
|
|
237
|
+
deleteApplicationPreview(uuid: string, pullRequestId: number): Promise<MessageResponse>;
|
|
238
|
+
listDatabaseEnvVars(uuid: string): Promise<EnvironmentVariable[]>;
|
|
239
|
+
createDatabaseEnvVar(uuid: string, data: CreateEnvVarRequest): Promise<UuidResponse>;
|
|
240
|
+
updateDatabaseEnvVar(uuid: string, data: UpdateEnvVarRequest): Promise<MessageResponse>;
|
|
241
|
+
bulkUpdateDatabaseEnvVars(uuid: string, data: BulkUpdateEnvVarsRequest): Promise<MessageResponse>;
|
|
242
|
+
deleteDatabaseEnvVar(uuid: string, envUuid: string): Promise<MessageResponse>;
|
|
243
|
+
listDatabaseStorages(uuid: string): Promise<StorageListResponse>;
|
|
244
|
+
createDatabaseStorage(uuid: string, data: CreateStorageRequest): Promise<MessageResponse>;
|
|
245
|
+
updateDatabaseStorage(uuid: string, data: UpdateStorageRequest): Promise<MessageResponse>;
|
|
246
|
+
deleteDatabaseStorage(uuid: string, storageUuid: string): Promise<MessageResponse>;
|
|
247
|
+
deleteBackupExecution(databaseUuid: string, backupUuid: string, executionUuid: string): Promise<MessageResponse>;
|
|
248
|
+
bulkUpdateServiceEnvVars(uuid: string, data: BulkUpdateEnvVarsRequest): Promise<MessageResponse>;
|
|
249
|
+
listServiceStorages(uuid: string): Promise<StorageListResponse>;
|
|
250
|
+
createServiceStorage(uuid: string, data: CreateStorageRequest): Promise<MessageResponse>;
|
|
251
|
+
updateServiceStorage(uuid: string, data: UpdateStorageRequest): Promise<MessageResponse>;
|
|
252
|
+
deleteServiceStorage(uuid: string, storageUuid: string): Promise<MessageResponse>;
|
|
253
|
+
listServiceScheduledTasks(uuid: string): Promise<ScheduledTask[]>;
|
|
254
|
+
createServiceScheduledTask(uuid: string, data: CreateScheduledTaskRequest): Promise<ScheduledTask>;
|
|
255
|
+
updateServiceScheduledTask(uuid: string, taskUuid: string, data: UpdateScheduledTaskRequest): Promise<ScheduledTask>;
|
|
256
|
+
deleteServiceScheduledTask(uuid: string, taskUuid: string): Promise<MessageResponse>;
|
|
257
|
+
listServiceScheduledTaskExecutions(uuid: string, taskUuid: string): Promise<ScheduledTaskExecution[]>;
|
|
258
|
+
listHetznerLocations(tokenUuid: string): Promise<HetznerLocation[]>;
|
|
259
|
+
listHetznerServerTypes(tokenUuid: string): Promise<HetznerServerType[]>;
|
|
260
|
+
listHetznerImages(tokenUuid: string): Promise<HetznerImage[]>;
|
|
261
|
+
listHetznerSSHKeys(tokenUuid: string): Promise<HetznerSSHKey[]>;
|
|
262
|
+
createHetznerServer(data: CreateHetznerServerRequest): Promise<CreateHetznerServerResponse>;
|
|
263
|
+
listGitHubAppRepositories(githubAppId: number): Promise<GitHubRepository[]>;
|
|
264
|
+
listGitHubAppBranches(githubAppId: number, owner: string, repo: string): Promise<GitHubBranch[]>;
|
|
265
|
+
/**
|
|
266
|
+
* List every resource on the Coolify instance.
|
|
267
|
+
*
|
|
268
|
+
* Defaults to an essential projection ({@link ResourceListItem}: uuid, name,
|
|
269
|
+
* type, optional status) — Coolify's `/api/v1/resources` endpoint actually
|
|
270
|
+
* returns ~95 fields per row including the full build/healthcheck/limits
|
|
271
|
+
* config, which on a moderate instance can exceed 500 KB on a single call
|
|
272
|
+
* and blow MCP/LLM context budgets. Set `include_full: true` to opt back
|
|
273
|
+
* into the raw response shape ({@link ResourceListItemFull}).
|
|
274
|
+
*
|
|
275
|
+
* When `include_full: true`, sensitive fields ({@link SENSITIVE_RESOURCE_FIELDS}:
|
|
276
|
+
* webhook HMAC secrets + basic-auth password) are replaced with `'***'`
|
|
277
|
+
* unless the caller also passes `reveal: true`. Mirrors the v2.9.0 env_vars
|
|
278
|
+
* masking posture.
|
|
279
|
+
*/
|
|
280
|
+
listResources(options?: {
|
|
281
|
+
include_full?: boolean;
|
|
282
|
+
reveal?: boolean;
|
|
283
|
+
}): Promise<ResourceListItem[] | ResourceListItemFull[]>;
|
|
284
|
+
getHealth(): Promise<MessageResponse>;
|
|
285
|
+
enableApi(): Promise<MessageResponse>;
|
|
286
|
+
disableApi(): Promise<MessageResponse>;
|
|
228
287
|
cancelDeployment(uuid: string): Promise<MessageResponse>;
|
|
229
288
|
/**
|
|
230
289
|
* Check if a string looks like a UUID (Coolify format or standard format).
|
|
@@ -180,6 +180,58 @@ function maskEnvVarSummary(envVar) {
|
|
|
180
180
|
value: MASKED_VALUE,
|
|
181
181
|
};
|
|
182
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Project a full Coolify resource row down to {@link ResourceListItem} — the
|
|
185
|
+
* four fields callers actually need for enumeration (uuid, name, type, status).
|
|
186
|
+
* Drops the ~90 extra fields Coolify returns by default to keep MCP token
|
|
187
|
+
* budgets sane.
|
|
188
|
+
*/
|
|
189
|
+
function toResourceListItemEssential(item) {
|
|
190
|
+
const essential = {
|
|
191
|
+
uuid: item.uuid,
|
|
192
|
+
name: item.name,
|
|
193
|
+
type: item.type,
|
|
194
|
+
};
|
|
195
|
+
if (typeof item.status === 'string') {
|
|
196
|
+
essential.status = item.status;
|
|
197
|
+
}
|
|
198
|
+
return essential;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Per-resource sensitive fields returned by Coolify's `/api/v1/resources`
|
|
202
|
+
* endpoint that are masked by default in {@link CoolifyClient.listResources}
|
|
203
|
+
* when `include_full: true` is passed. Mirrors the v2.9.0 env-var masking
|
|
204
|
+
* posture: the underlying API exposes these via the same access token, but
|
|
205
|
+
* the MCP layer narrows the trust boundary so an LLM client that was granted
|
|
206
|
+
* "list resources" doesn't silently exfiltrate webhook HMAC secrets or
|
|
207
|
+
* basic-auth credentials.
|
|
208
|
+
*
|
|
209
|
+
* The `manual_webhook_secret_*` fields are HMAC signing keys for inbound
|
|
210
|
+
* deploy webhooks — anyone with one can forge deploys for that repo
|
|
211
|
+
* independently of the Coolify API token. `http_basic_auth_password` is the
|
|
212
|
+
* password gating front-of-app access.
|
|
213
|
+
*/
|
|
214
|
+
const SENSITIVE_RESOURCE_FIELDS = [
|
|
215
|
+
'manual_webhook_secret_github',
|
|
216
|
+
'manual_webhook_secret_gitlab',
|
|
217
|
+
'manual_webhook_secret_gitea',
|
|
218
|
+
'manual_webhook_secret_bitbucket',
|
|
219
|
+
'http_basic_auth_password',
|
|
220
|
+
];
|
|
221
|
+
/**
|
|
222
|
+
* Replace each {@link SENSITIVE_RESOURCE_FIELDS} entry with `'***'` on a full
|
|
223
|
+
* resource row. Null/undefined values are preserved (since `null` conveys
|
|
224
|
+
* "no secret set" and matters to callers); only populated values get masked.
|
|
225
|
+
*/
|
|
226
|
+
function maskResourceItemFull(item) {
|
|
227
|
+
const masked = { ...item };
|
|
228
|
+
for (const field of SENSITIVE_RESOURCE_FIELDS) {
|
|
229
|
+
if (masked[field] != null) {
|
|
230
|
+
masked[field] = MASKED_VALUE;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return masked;
|
|
234
|
+
}
|
|
183
235
|
/**
|
|
184
236
|
* HTTP client for the Coolify API
|
|
185
237
|
*/
|
|
@@ -922,6 +974,250 @@ export class CoolifyClient {
|
|
|
922
974
|
});
|
|
923
975
|
}
|
|
924
976
|
// ===========================================================================
|
|
977
|
+
// Application Storage endpoints
|
|
978
|
+
// ===========================================================================
|
|
979
|
+
async listApplicationStorages(uuid) {
|
|
980
|
+
return this.request(`/applications/${uuid}/storages`);
|
|
981
|
+
}
|
|
982
|
+
async createApplicationStorage(uuid, data) {
|
|
983
|
+
return this.request(`/applications/${uuid}/storages`, {
|
|
984
|
+
method: 'POST',
|
|
985
|
+
body: JSON.stringify(data),
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
async updateApplicationStorage(uuid, data) {
|
|
989
|
+
return this.request(`/applications/${uuid}/storages`, {
|
|
990
|
+
method: 'PATCH',
|
|
991
|
+
body: JSON.stringify(data),
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
async deleteApplicationStorage(uuid, storageUuid) {
|
|
995
|
+
return this.request(`/applications/${uuid}/storages/${storageUuid}`, {
|
|
996
|
+
method: 'DELETE',
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
// ===========================================================================
|
|
1000
|
+
// Application Scheduled Task endpoints
|
|
1001
|
+
// ===========================================================================
|
|
1002
|
+
async listApplicationScheduledTasks(uuid) {
|
|
1003
|
+
return this.request(`/applications/${uuid}/scheduled-tasks`);
|
|
1004
|
+
}
|
|
1005
|
+
async createApplicationScheduledTask(uuid, data) {
|
|
1006
|
+
return this.request(`/applications/${uuid}/scheduled-tasks`, {
|
|
1007
|
+
method: 'POST',
|
|
1008
|
+
body: JSON.stringify(data),
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
async updateApplicationScheduledTask(uuid, taskUuid, data) {
|
|
1012
|
+
return this.request(`/applications/${uuid}/scheduled-tasks/${taskUuid}`, {
|
|
1013
|
+
method: 'PATCH',
|
|
1014
|
+
body: JSON.stringify(data),
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
async deleteApplicationScheduledTask(uuid, taskUuid) {
|
|
1018
|
+
return this.request(`/applications/${uuid}/scheduled-tasks/${taskUuid}`, {
|
|
1019
|
+
method: 'DELETE',
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
async listApplicationScheduledTaskExecutions(uuid, taskUuid) {
|
|
1023
|
+
return this.request(`/applications/${uuid}/scheduled-tasks/${taskUuid}/executions`);
|
|
1024
|
+
}
|
|
1025
|
+
// ===========================================================================
|
|
1026
|
+
// Application Preview endpoints
|
|
1027
|
+
// ===========================================================================
|
|
1028
|
+
async deleteApplicationPreview(uuid, pullRequestId) {
|
|
1029
|
+
return this.request(`/applications/${uuid}/previews/${pullRequestId}`, {
|
|
1030
|
+
method: 'DELETE',
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
// ===========================================================================
|
|
1034
|
+
// Database Environment Variable endpoints
|
|
1035
|
+
// ===========================================================================
|
|
1036
|
+
async listDatabaseEnvVars(uuid) {
|
|
1037
|
+
return this.request(`/databases/${uuid}/envs`);
|
|
1038
|
+
}
|
|
1039
|
+
async createDatabaseEnvVar(uuid, data) {
|
|
1040
|
+
return this.request(`/databases/${uuid}/envs`, {
|
|
1041
|
+
method: 'POST',
|
|
1042
|
+
body: JSON.stringify(cleanRequestData(data)),
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
async updateDatabaseEnvVar(uuid, data) {
|
|
1046
|
+
return this.request(`/databases/${uuid}/envs`, {
|
|
1047
|
+
method: 'PATCH',
|
|
1048
|
+
body: JSON.stringify(cleanRequestData(data)),
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
async bulkUpdateDatabaseEnvVars(uuid, data) {
|
|
1052
|
+
return this.request(`/databases/${uuid}/envs/bulk`, {
|
|
1053
|
+
method: 'PATCH',
|
|
1054
|
+
body: JSON.stringify(data),
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
async deleteDatabaseEnvVar(uuid, envUuid) {
|
|
1058
|
+
return this.request(`/databases/${uuid}/envs/${envUuid}`, {
|
|
1059
|
+
method: 'DELETE',
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
1062
|
+
// ===========================================================================
|
|
1063
|
+
// Database Storage endpoints
|
|
1064
|
+
// ===========================================================================
|
|
1065
|
+
async listDatabaseStorages(uuid) {
|
|
1066
|
+
return this.request(`/databases/${uuid}/storages`);
|
|
1067
|
+
}
|
|
1068
|
+
async createDatabaseStorage(uuid, data) {
|
|
1069
|
+
return this.request(`/databases/${uuid}/storages`, {
|
|
1070
|
+
method: 'POST',
|
|
1071
|
+
body: JSON.stringify(data),
|
|
1072
|
+
});
|
|
1073
|
+
}
|
|
1074
|
+
async updateDatabaseStorage(uuid, data) {
|
|
1075
|
+
return this.request(`/databases/${uuid}/storages`, {
|
|
1076
|
+
method: 'PATCH',
|
|
1077
|
+
body: JSON.stringify(data),
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
1080
|
+
async deleteDatabaseStorage(uuid, storageUuid) {
|
|
1081
|
+
return this.request(`/databases/${uuid}/storages/${storageUuid}`, {
|
|
1082
|
+
method: 'DELETE',
|
|
1083
|
+
});
|
|
1084
|
+
}
|
|
1085
|
+
// ===========================================================================
|
|
1086
|
+
// Delete Backup Execution endpoint
|
|
1087
|
+
// ===========================================================================
|
|
1088
|
+
async deleteBackupExecution(databaseUuid, backupUuid, executionUuid) {
|
|
1089
|
+
return this.request(`/databases/${databaseUuid}/backups/${backupUuid}/executions/${executionUuid}`, { method: 'DELETE' });
|
|
1090
|
+
}
|
|
1091
|
+
// ===========================================================================
|
|
1092
|
+
// Service Environment Variable (bulk) endpoint
|
|
1093
|
+
// ===========================================================================
|
|
1094
|
+
async bulkUpdateServiceEnvVars(uuid, data) {
|
|
1095
|
+
return this.request(`/services/${uuid}/envs/bulk`, {
|
|
1096
|
+
method: 'PATCH',
|
|
1097
|
+
body: JSON.stringify(data),
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
1100
|
+
// ===========================================================================
|
|
1101
|
+
// Service Storage endpoints
|
|
1102
|
+
// ===========================================================================
|
|
1103
|
+
async listServiceStorages(uuid) {
|
|
1104
|
+
return this.request(`/services/${uuid}/storages`);
|
|
1105
|
+
}
|
|
1106
|
+
async createServiceStorage(uuid, data) {
|
|
1107
|
+
return this.request(`/services/${uuid}/storages`, {
|
|
1108
|
+
method: 'POST',
|
|
1109
|
+
body: JSON.stringify(data),
|
|
1110
|
+
});
|
|
1111
|
+
}
|
|
1112
|
+
async updateServiceStorage(uuid, data) {
|
|
1113
|
+
return this.request(`/services/${uuid}/storages`, {
|
|
1114
|
+
method: 'PATCH',
|
|
1115
|
+
body: JSON.stringify(data),
|
|
1116
|
+
});
|
|
1117
|
+
}
|
|
1118
|
+
async deleteServiceStorage(uuid, storageUuid) {
|
|
1119
|
+
return this.request(`/services/${uuid}/storages/${storageUuid}`, {
|
|
1120
|
+
method: 'DELETE',
|
|
1121
|
+
});
|
|
1122
|
+
}
|
|
1123
|
+
// ===========================================================================
|
|
1124
|
+
// Service Scheduled Task endpoints
|
|
1125
|
+
// ===========================================================================
|
|
1126
|
+
async listServiceScheduledTasks(uuid) {
|
|
1127
|
+
return this.request(`/services/${uuid}/scheduled-tasks`);
|
|
1128
|
+
}
|
|
1129
|
+
async createServiceScheduledTask(uuid, data) {
|
|
1130
|
+
return this.request(`/services/${uuid}/scheduled-tasks`, {
|
|
1131
|
+
method: 'POST',
|
|
1132
|
+
body: JSON.stringify(data),
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
async updateServiceScheduledTask(uuid, taskUuid, data) {
|
|
1136
|
+
return this.request(`/services/${uuid}/scheduled-tasks/${taskUuid}`, {
|
|
1137
|
+
method: 'PATCH',
|
|
1138
|
+
body: JSON.stringify(data),
|
|
1139
|
+
});
|
|
1140
|
+
}
|
|
1141
|
+
async deleteServiceScheduledTask(uuid, taskUuid) {
|
|
1142
|
+
return this.request(`/services/${uuid}/scheduled-tasks/${taskUuid}`, {
|
|
1143
|
+
method: 'DELETE',
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
async listServiceScheduledTaskExecutions(uuid, taskUuid) {
|
|
1147
|
+
return this.request(`/services/${uuid}/scheduled-tasks/${taskUuid}/executions`);
|
|
1148
|
+
}
|
|
1149
|
+
// ===========================================================================
|
|
1150
|
+
// Hetzner Cloud endpoints
|
|
1151
|
+
// ===========================================================================
|
|
1152
|
+
async listHetznerLocations(tokenUuid) {
|
|
1153
|
+
return this.request(`/hetzner/locations?cloud_provider_token_uuid=${encodeURIComponent(tokenUuid)}`);
|
|
1154
|
+
}
|
|
1155
|
+
async listHetznerServerTypes(tokenUuid) {
|
|
1156
|
+
return this.request(`/hetzner/server-types?cloud_provider_token_uuid=${encodeURIComponent(tokenUuid)}`);
|
|
1157
|
+
}
|
|
1158
|
+
async listHetznerImages(tokenUuid) {
|
|
1159
|
+
return this.request(`/hetzner/images?cloud_provider_token_uuid=${encodeURIComponent(tokenUuid)}`);
|
|
1160
|
+
}
|
|
1161
|
+
async listHetznerSSHKeys(tokenUuid) {
|
|
1162
|
+
return this.request(`/hetzner/ssh-keys?cloud_provider_token_uuid=${encodeURIComponent(tokenUuid)}`);
|
|
1163
|
+
}
|
|
1164
|
+
async createHetznerServer(data) {
|
|
1165
|
+
return this.request('/servers/hetzner', {
|
|
1166
|
+
method: 'POST',
|
|
1167
|
+
body: JSON.stringify(data),
|
|
1168
|
+
});
|
|
1169
|
+
}
|
|
1170
|
+
// ===========================================================================
|
|
1171
|
+
// GitHub App Repository endpoints
|
|
1172
|
+
// ===========================================================================
|
|
1173
|
+
async listGitHubAppRepositories(githubAppId) {
|
|
1174
|
+
const response = await this.request(`/github-apps/${githubAppId}/repositories`);
|
|
1175
|
+
return response.repositories ?? [];
|
|
1176
|
+
}
|
|
1177
|
+
async listGitHubAppBranches(githubAppId, owner, repo) {
|
|
1178
|
+
return this.request(`/github-apps/${githubAppId}/repositories/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/branches`);
|
|
1179
|
+
}
|
|
1180
|
+
// ===========================================================================
|
|
1181
|
+
// Resources endpoint
|
|
1182
|
+
// ===========================================================================
|
|
1183
|
+
/**
|
|
1184
|
+
* List every resource on the Coolify instance.
|
|
1185
|
+
*
|
|
1186
|
+
* Defaults to an essential projection ({@link ResourceListItem}: uuid, name,
|
|
1187
|
+
* type, optional status) — Coolify's `/api/v1/resources` endpoint actually
|
|
1188
|
+
* returns ~95 fields per row including the full build/healthcheck/limits
|
|
1189
|
+
* config, which on a moderate instance can exceed 500 KB on a single call
|
|
1190
|
+
* and blow MCP/LLM context budgets. Set `include_full: true` to opt back
|
|
1191
|
+
* into the raw response shape ({@link ResourceListItemFull}).
|
|
1192
|
+
*
|
|
1193
|
+
* When `include_full: true`, sensitive fields ({@link SENSITIVE_RESOURCE_FIELDS}:
|
|
1194
|
+
* webhook HMAC secrets + basic-auth password) are replaced with `'***'`
|
|
1195
|
+
* unless the caller also passes `reveal: true`. Mirrors the v2.9.0 env_vars
|
|
1196
|
+
* masking posture.
|
|
1197
|
+
*/
|
|
1198
|
+
async listResources(options) {
|
|
1199
|
+
const full = await this.request('/resources');
|
|
1200
|
+
if (options?.include_full !== true) {
|
|
1201
|
+
return full.map(toResourceListItemEssential);
|
|
1202
|
+
}
|
|
1203
|
+
return options.reveal === true ? full : full.map(maskResourceItemFull);
|
|
1204
|
+
}
|
|
1205
|
+
// ===========================================================================
|
|
1206
|
+
// Health endpoint
|
|
1207
|
+
// ===========================================================================
|
|
1208
|
+
async getHealth() {
|
|
1209
|
+
return this.request('/health');
|
|
1210
|
+
}
|
|
1211
|
+
// ===========================================================================
|
|
1212
|
+
// API Enable/Disable endpoints
|
|
1213
|
+
// ===========================================================================
|
|
1214
|
+
async enableApi() {
|
|
1215
|
+
return this.request('/enable', { method: 'GET' });
|
|
1216
|
+
}
|
|
1217
|
+
async disableApi() {
|
|
1218
|
+
return this.request('/disable', { method: 'GET' });
|
|
1219
|
+
}
|
|
1220
|
+
// ===========================================================================
|
|
925
1221
|
// Deployment Control endpoints
|
|
926
1222
|
// ===========================================================================
|
|
927
1223
|
async cancelDeployment(uuid) {
|