@mks2508/coolify-mks-cli-mcp 0.6.2 → 0.8.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/dist/cli/coolify-state.d.ts +92 -4
- package/dist/cli/coolify-state.d.ts.map +1 -1
- package/dist/cli/index.js +22228 -11529
- package/dist/cli/ui/highlighter.d.ts +28 -0
- package/dist/cli/ui/highlighter.d.ts.map +1 -0
- package/dist/cli/ui/index.d.ts +9 -0
- package/dist/cli/ui/index.d.ts.map +1 -0
- package/dist/cli/ui/spinners.d.ts +100 -0
- package/dist/cli/ui/spinners.d.ts.map +1 -0
- package/dist/cli/ui/tables.d.ts +103 -0
- package/dist/cli/ui/tables.d.ts.map +1 -0
- package/dist/coolify/index.d.ts +22 -3
- package/dist/coolify/index.d.ts.map +1 -1
- package/dist/coolify/types.d.ts +99 -1
- package/dist/coolify/types.d.ts.map +1 -1
- package/dist/examples/demo-ui.d.ts +8 -0
- package/dist/examples/demo-ui.d.ts.map +1 -0
- package/dist/index.cjs +322 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +322 -12
- package/dist/index.js.map +1 -1
- package/dist/sdk.d.ts +41 -0
- package/dist/sdk.d.ts.map +1 -1
- package/dist/server/stdio.js +258 -9
- package/package.json +19 -4
- package/src/cli/actions.ts +9 -2
- package/src/cli/commands/create.ts +71 -5
- package/src/cli/commands/db.ts +37 -0
- package/src/cli/commands/delete.ts +6 -2
- package/src/cli/commands/deploy.ts +347 -49
- package/src/cli/commands/deployments.ts +6 -2
- package/src/cli/commands/diagnose.ts +3 -3
- package/src/cli/commands/env.ts +121 -22
- package/src/cli/commands/exec.ts +6 -2
- package/src/cli/commands/init.ts +937 -0
- package/src/cli/commands/logs.ts +224 -24
- package/src/cli/commands/main-menu.ts +21 -0
- package/src/cli/commands/projects.ts +312 -29
- package/src/cli/commands/restart.ts +6 -2
- package/src/cli/commands/service-logs.ts +14 -0
- package/src/cli/commands/show.ts +6 -2
- package/src/cli/commands/start.ts +6 -2
- package/src/cli/commands/status.ts +538 -0
- package/src/cli/commands/stop.ts +6 -2
- package/src/cli/commands/update.ts +27 -2
- package/src/cli/coolify-state.ts +164 -11
- package/src/cli/index.ts +91 -10
- package/src/cli/name-resolver.ts +228 -0
- package/src/cli/ui/banner.ts +276 -0
- package/src/cli/ui/highlighter.ts +176 -0
- package/src/cli/ui/index.ts +9 -0
- package/src/cli/ui/prompts.ts +155 -0
- package/src/cli/ui/screen.ts +606 -0
- package/src/cli/ui/select.ts +280 -0
- package/src/cli/ui/spinners.ts +256 -0
- package/src/cli/ui/tables.ts +407 -0
- package/src/coolify/index.ts +257 -12
- package/src/coolify/types.ts +103 -1
- package/src/examples/demo-ui.ts +78 -0
- package/src/sdk.ts +162 -0
package/src/coolify/index.ts
CHANGED
|
@@ -32,6 +32,10 @@ import {
|
|
|
32
32
|
type ICoolifyTeam,
|
|
33
33
|
type ICoolifyUpdateOptions,
|
|
34
34
|
type ICoolifyVersion,
|
|
35
|
+
type ICoolifyInfrastructureTree,
|
|
36
|
+
type ICoolifyProjectNode,
|
|
37
|
+
type ICoolifyEnvironmentNode,
|
|
38
|
+
type ICoolifyResource,
|
|
35
39
|
type IProgressCallback,
|
|
36
40
|
} from "./types.js";
|
|
37
41
|
|
|
@@ -333,18 +337,20 @@ export class CoolifyService {
|
|
|
333
337
|
server_uuid: options.serverUuid,
|
|
334
338
|
};
|
|
335
339
|
|
|
340
|
+
// Git repository — applies to all types that have a repo URL
|
|
341
|
+
if (options.githubRepoUrl) {
|
|
342
|
+
// Coolify expects 'user/repo' format, not full URL
|
|
343
|
+
body.git_repository = options.githubRepoUrl
|
|
344
|
+
.replace(/^https?:\/\/github\.com\//, "")
|
|
345
|
+
.replace(/\.git$/, "");
|
|
346
|
+
}
|
|
347
|
+
|
|
336
348
|
// Type-specific fields
|
|
337
349
|
if (
|
|
338
350
|
appType === "public" ||
|
|
339
351
|
appType === "private-github-app" ||
|
|
340
352
|
appType === "private-deploy-key"
|
|
341
353
|
) {
|
|
342
|
-
if (options.githubRepoUrl) {
|
|
343
|
-
// Coolify expects 'user/repo' format, not full URL
|
|
344
|
-
body.git_repository = options.githubRepoUrl
|
|
345
|
-
.replace(/^https?:\/\/github\.com\//, "")
|
|
346
|
-
.replace(/\.git$/, "");
|
|
347
|
-
}
|
|
348
354
|
if (options.githubAppUuid) {
|
|
349
355
|
body.github_app_uuid = options.githubAppUuid;
|
|
350
356
|
}
|
|
@@ -410,7 +416,7 @@ export class CoolifyService {
|
|
|
410
416
|
for (const [key, value] of Object.entries(envVars)) {
|
|
411
417
|
const result = await this.request(`/applications/${appUuid}/envs`, {
|
|
412
418
|
method: "POST",
|
|
413
|
-
body: JSON.stringify({ key, value, is_preview: false }),
|
|
419
|
+
body: JSON.stringify({ key, value, is_preview: false, is_buildtime: false }),
|
|
414
420
|
});
|
|
415
421
|
|
|
416
422
|
if (result.error && result.error.includes("already exists")) {
|
|
@@ -425,7 +431,7 @@ export class CoolifyService {
|
|
|
425
431
|
});
|
|
426
432
|
const repost = await this.request(`/applications/${appUuid}/envs`, {
|
|
427
433
|
method: "POST",
|
|
428
|
-
body: JSON.stringify({ key, value, is_preview: false }),
|
|
434
|
+
body: JSON.stringify({ key, value, is_preview: false, is_buildtime: false }),
|
|
429
435
|
});
|
|
430
436
|
if (repost.error) {
|
|
431
437
|
log.error(`Failed to update env var ${key}: ${repost.error}`);
|
|
@@ -484,9 +490,9 @@ export class CoolifyService {
|
|
|
484
490
|
appUuid: string,
|
|
485
491
|
key: string,
|
|
486
492
|
value: string,
|
|
487
|
-
|
|
493
|
+
isBuildTime: boolean = false,
|
|
488
494
|
): Promise<Result<void, Error>> {
|
|
489
|
-
log.info(`Setting environment variable ${key} for ${appUuid}`);
|
|
495
|
+
log.info(`Setting environment variable ${key} for ${appUuid} (buildtime: ${isBuildTime})`);
|
|
490
496
|
|
|
491
497
|
// Check if variable already exists
|
|
492
498
|
const existingVars = await this.getEnvironmentVariables(appUuid);
|
|
@@ -503,7 +509,11 @@ export class CoolifyService {
|
|
|
503
509
|
`/applications/${appUuid}/envs`,
|
|
504
510
|
{
|
|
505
511
|
method: "PATCH",
|
|
506
|
-
body: JSON.stringify({
|
|
512
|
+
body: JSON.stringify({
|
|
513
|
+
key,
|
|
514
|
+
value,
|
|
515
|
+
is_buildtime: isBuildTime,
|
|
516
|
+
}),
|
|
507
517
|
},
|
|
508
518
|
);
|
|
509
519
|
|
|
@@ -518,7 +528,11 @@ export class CoolifyService {
|
|
|
518
528
|
`/applications/${appUuid}/envs`,
|
|
519
529
|
{
|
|
520
530
|
method: "POST",
|
|
521
|
-
body: JSON.stringify({
|
|
531
|
+
body: JSON.stringify({
|
|
532
|
+
key,
|
|
533
|
+
value,
|
|
534
|
+
is_buildtime: isBuildTime,
|
|
535
|
+
}),
|
|
522
536
|
},
|
|
523
537
|
);
|
|
524
538
|
|
|
@@ -910,6 +924,24 @@ export class CoolifyService {
|
|
|
910
924
|
body.is_force_https_enabled = options.isForceHttpsEnabled;
|
|
911
925
|
if (options.isAutoDeployEnabled !== undefined)
|
|
912
926
|
body.is_auto_deploy_enabled = options.isAutoDeployEnabled;
|
|
927
|
+
if (options.healthCheckEnabled !== undefined)
|
|
928
|
+
body.health_check_enabled = options.healthCheckEnabled;
|
|
929
|
+
if (options.healthCheckPath)
|
|
930
|
+
body.health_check_path = options.healthCheckPath;
|
|
931
|
+
if (options.healthCheckPort)
|
|
932
|
+
body.health_check_port = String(options.healthCheckPort);
|
|
933
|
+
if (options.healthCheckMethod)
|
|
934
|
+
body.health_check_method = options.healthCheckMethod;
|
|
935
|
+
if (options.healthCheckInterval)
|
|
936
|
+
body.health_check_interval = options.healthCheckInterval;
|
|
937
|
+
if (options.healthCheckTimeout)
|
|
938
|
+
body.health_check_timeout = options.healthCheckTimeout;
|
|
939
|
+
if (options.healthCheckRetries)
|
|
940
|
+
body.health_check_retries = options.healthCheckRetries;
|
|
941
|
+
if (options.healthCheckStartPeriod)
|
|
942
|
+
body.health_check_start_period = options.healthCheckStartPeriod;
|
|
943
|
+
if (options.healthCheckReturnCode)
|
|
944
|
+
body.health_check_return_code = options.healthCheckReturnCode;
|
|
913
945
|
|
|
914
946
|
const result = await this.request<ICoolifyApplication>(
|
|
915
947
|
`/applications/${appUuid}`,
|
|
@@ -1620,6 +1652,186 @@ export class CoolifyService {
|
|
|
1620
1652
|
return ok({ success: true, message: "Service deleted" });
|
|
1621
1653
|
}
|
|
1622
1654
|
|
|
1655
|
+
/**
|
|
1656
|
+
* Gets the full infrastructure tree: Projects → Environments → Resources.
|
|
1657
|
+
*
|
|
1658
|
+
* Fetches all projects, apps, databases, and services in parallel,
|
|
1659
|
+
* then groups them by environment_id into a hierarchical tree.
|
|
1660
|
+
*
|
|
1661
|
+
* @returns Result with the full infrastructure tree or error
|
|
1662
|
+
*/
|
|
1663
|
+
async getInfrastructureTree(): Promise<
|
|
1664
|
+
Result<ICoolifyInfrastructureTree, Error>
|
|
1665
|
+
> {
|
|
1666
|
+
log.info("Building infrastructure tree");
|
|
1667
|
+
|
|
1668
|
+
// Fetch all data in parallel
|
|
1669
|
+
const [projectsResult, appsResult, dbsResult, svcsResult, serversResult] =
|
|
1670
|
+
await Promise.all([
|
|
1671
|
+
this.listProjects(),
|
|
1672
|
+
this.listApplications(),
|
|
1673
|
+
this.listDatabases(),
|
|
1674
|
+
this.listServices(),
|
|
1675
|
+
this.listServers(),
|
|
1676
|
+
]);
|
|
1677
|
+
|
|
1678
|
+
if (isErr(projectsResult)) return err(projectsResult.error);
|
|
1679
|
+
if (isErr(appsResult)) return err(appsResult.error);
|
|
1680
|
+
if (isErr(serversResult)) return err(serversResult.error);
|
|
1681
|
+
|
|
1682
|
+
const projects = projectsResult.value;
|
|
1683
|
+
const apps = appsResult.value;
|
|
1684
|
+
const dbs = isErr(dbsResult) ? [] : dbsResult.value;
|
|
1685
|
+
const svcs = isErr(svcsResult) ? [] : svcsResult.value;
|
|
1686
|
+
const servers = serversResult.value;
|
|
1687
|
+
|
|
1688
|
+
// Fetch environments for each project in parallel
|
|
1689
|
+
const envResults = await Promise.allSettled(
|
|
1690
|
+
projects.map((p) => this.getProjectEnvironments(p.uuid)),
|
|
1691
|
+
);
|
|
1692
|
+
|
|
1693
|
+
// Build environment_id → { projectUuid, envName, envUuid } mapping
|
|
1694
|
+
const envIdMap = new Map<
|
|
1695
|
+
number,
|
|
1696
|
+
{ projectUuid: string; envName: string; envUuid: string }
|
|
1697
|
+
>();
|
|
1698
|
+
|
|
1699
|
+
for (let i = 0; i < projects.length; i++) {
|
|
1700
|
+
const envResult = envResults[i];
|
|
1701
|
+
if (envResult.status === "fulfilled" && !isErr(envResult.value)) {
|
|
1702
|
+
for (const env of envResult.value.value) {
|
|
1703
|
+
envIdMap.set(env.id, {
|
|
1704
|
+
projectUuid: projects[i].uuid,
|
|
1705
|
+
envName: env.name,
|
|
1706
|
+
envUuid: env.uuid,
|
|
1707
|
+
});
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
// Build project nodes
|
|
1713
|
+
const projectNodes: ICoolifyProjectNode[] = projects.map((p) => ({
|
|
1714
|
+
uuid: p.uuid,
|
|
1715
|
+
name: p.name,
|
|
1716
|
+
description: p.description,
|
|
1717
|
+
environments: [],
|
|
1718
|
+
}));
|
|
1719
|
+
|
|
1720
|
+
const projectMap = new Map<string, ICoolifyProjectNode>();
|
|
1721
|
+
for (const node of projectNodes) {
|
|
1722
|
+
projectMap.set(node.uuid, node);
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
// Populate environments from envIdMap
|
|
1726
|
+
const envNodeMap = new Map<number, ICoolifyEnvironmentNode>();
|
|
1727
|
+
for (const [envId, info] of envIdMap) {
|
|
1728
|
+
const project = projectMap.get(info.projectUuid);
|
|
1729
|
+
if (!project) continue;
|
|
1730
|
+
|
|
1731
|
+
let envNode = project.environments.find((e) => e.id === envId);
|
|
1732
|
+
if (!envNode) {
|
|
1733
|
+
envNode = {
|
|
1734
|
+
id: envId,
|
|
1735
|
+
uuid: info.envUuid,
|
|
1736
|
+
name: info.envName,
|
|
1737
|
+
resources: [],
|
|
1738
|
+
};
|
|
1739
|
+
project.environments.push(envNode);
|
|
1740
|
+
}
|
|
1741
|
+
envNodeMap.set(envId, envNode);
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
// Assign apps to environments
|
|
1745
|
+
for (const app of apps) {
|
|
1746
|
+
const envNode = app.environment_id
|
|
1747
|
+
? envNodeMap.get(app.environment_id)
|
|
1748
|
+
: undefined;
|
|
1749
|
+
const resource: ICoolifyResource = {
|
|
1750
|
+
uuid: app.uuid,
|
|
1751
|
+
name: app.name,
|
|
1752
|
+
kind: "app",
|
|
1753
|
+
status: app.status,
|
|
1754
|
+
fqdn: app.fqdn,
|
|
1755
|
+
};
|
|
1756
|
+
if (envNode) {
|
|
1757
|
+
envNode.resources.push(resource);
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
// Assign databases to environments
|
|
1762
|
+
for (const db of dbs) {
|
|
1763
|
+
const envNode = (db as any).environment_id
|
|
1764
|
+
? envNodeMap.get((db as any).environment_id)
|
|
1765
|
+
: undefined;
|
|
1766
|
+
const resource: ICoolifyResource = {
|
|
1767
|
+
uuid: db.uuid,
|
|
1768
|
+
name: db.name,
|
|
1769
|
+
kind: "database",
|
|
1770
|
+
status: db.status,
|
|
1771
|
+
dbType: db.type,
|
|
1772
|
+
};
|
|
1773
|
+
if (envNode) {
|
|
1774
|
+
envNode.resources.push(resource);
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
// Assign services to environments
|
|
1779
|
+
for (const svc of svcs) {
|
|
1780
|
+
const envNode = (svc as any).environment_id
|
|
1781
|
+
? envNodeMap.get((svc as any).environment_id)
|
|
1782
|
+
: undefined;
|
|
1783
|
+
const resource: ICoolifyResource = {
|
|
1784
|
+
uuid: svc.uuid,
|
|
1785
|
+
name: svc.name,
|
|
1786
|
+
kind: "service",
|
|
1787
|
+
status: svc.status,
|
|
1788
|
+
};
|
|
1789
|
+
if (envNode) {
|
|
1790
|
+
envNode.resources.push(resource);
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
// Filter out empty projects
|
|
1795
|
+
const populatedProjects = projectNodes.filter(
|
|
1796
|
+
(p) => p.environments.some((e) => e.resources.length > 0),
|
|
1797
|
+
);
|
|
1798
|
+
|
|
1799
|
+
// Aggregate counts
|
|
1800
|
+
const allStatuses = [
|
|
1801
|
+
...apps.map((a) => a.status),
|
|
1802
|
+
...dbs.map((d) => d.status),
|
|
1803
|
+
...svcs.map((s) => s.status),
|
|
1804
|
+
];
|
|
1805
|
+
const counts = {
|
|
1806
|
+
projects: populatedProjects.length,
|
|
1807
|
+
apps: apps.length,
|
|
1808
|
+
databases: dbs.length,
|
|
1809
|
+
services: svcs.length,
|
|
1810
|
+
healthy: allStatuses.filter((s) => s.includes("healthy")).length,
|
|
1811
|
+
running: allStatuses.filter(
|
|
1812
|
+
(s) => s.startsWith("running") && !s.includes("healthy"),
|
|
1813
|
+
).length,
|
|
1814
|
+
stopped: allStatuses.filter((s) => s.includes("exited")).length,
|
|
1815
|
+
unhealthy: allStatuses.filter((s) => s.includes("unhealthy")).length,
|
|
1816
|
+
};
|
|
1817
|
+
|
|
1818
|
+
const server = servers[0] || { name: "Unknown" };
|
|
1819
|
+
|
|
1820
|
+
log.success(
|
|
1821
|
+
`Infrastructure tree built: ${counts.projects} projects, ${counts.apps} apps, ${counts.databases} dbs, ${counts.services} svcs`,
|
|
1822
|
+
);
|
|
1823
|
+
|
|
1824
|
+
return ok({
|
|
1825
|
+
server: {
|
|
1826
|
+
name: server.name,
|
|
1827
|
+
ip: server.ip,
|
|
1828
|
+
uuid: server.uuid,
|
|
1829
|
+
},
|
|
1830
|
+
projects: populatedProjects,
|
|
1831
|
+
counts,
|
|
1832
|
+
});
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1623
1835
|
/**
|
|
1624
1836
|
* Starts a service.
|
|
1625
1837
|
* Note: Coolify API uses GET for service start/stop/restart.
|
|
@@ -2295,6 +2507,35 @@ export class CoolifyService {
|
|
|
2295
2507
|
// Smart Resolution Helpers
|
|
2296
2508
|
// ===========================================================================
|
|
2297
2509
|
|
|
2510
|
+
/**
|
|
2511
|
+
* Gets full application details by UUID.
|
|
2512
|
+
*
|
|
2513
|
+
* Makes a direct GET request to /api/v1/applications/{uuid} which returns
|
|
2514
|
+
* complete application data including project_uuid and environment_uuid.
|
|
2515
|
+
*
|
|
2516
|
+
* @param appUuid - Application UUID
|
|
2517
|
+
* @returns Result with full application details or error
|
|
2518
|
+
*/
|
|
2519
|
+
async getApplication(
|
|
2520
|
+
appUuid: string,
|
|
2521
|
+
): Promise<Result<ICoolifyApplication, Error>> {
|
|
2522
|
+
log.info(`Getting application details: ${appUuid}`);
|
|
2523
|
+
|
|
2524
|
+
const result = await this.request<ICoolifyApplication>(
|
|
2525
|
+
`/applications/${appUuid}`,
|
|
2526
|
+
);
|
|
2527
|
+
|
|
2528
|
+
if (result.error) {
|
|
2529
|
+
return err(new Error(result.error));
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
if (!result.data) {
|
|
2533
|
+
return err(new Error("Application not found"));
|
|
2534
|
+
}
|
|
2535
|
+
|
|
2536
|
+
return ok(result.data);
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2298
2539
|
/**
|
|
2299
2540
|
* Resolves an application by UUID, name, or domain (FQDN).
|
|
2300
2541
|
*
|
|
@@ -2878,4 +3119,8 @@ export type {
|
|
|
2878
3119
|
ICoolifyLogsOptions,
|
|
2879
3120
|
ICoolifyLogs,
|
|
2880
3121
|
IProgressCallback,
|
|
3122
|
+
ICoolifyInfrastructureTree,
|
|
3123
|
+
ICoolifyProjectNode,
|
|
3124
|
+
ICoolifyEnvironmentNode,
|
|
3125
|
+
ICoolifyResource,
|
|
2881
3126
|
} from "./types.js";
|
package/src/coolify/types.ts
CHANGED
|
@@ -106,6 +106,24 @@ export interface ICoolifyUpdateOptions {
|
|
|
106
106
|
isForceHttpsEnabled?: boolean;
|
|
107
107
|
/** Enable auto deploy on git push */
|
|
108
108
|
isAutoDeployEnabled?: boolean;
|
|
109
|
+
/** Enable health check for the application */
|
|
110
|
+
healthCheckEnabled?: boolean;
|
|
111
|
+
/** Health check endpoint path (e.g., "/health") */
|
|
112
|
+
healthCheckPath?: string;
|
|
113
|
+
/** Health check port (defaults to application port) */
|
|
114
|
+
healthCheckPort?: string | number;
|
|
115
|
+
/** Health check HTTP method (e.g., "GET") */
|
|
116
|
+
healthCheckMethod?: string;
|
|
117
|
+
/** Health check interval in seconds */
|
|
118
|
+
healthCheckInterval?: number;
|
|
119
|
+
/** Health check timeout in seconds */
|
|
120
|
+
healthCheckTimeout?: number;
|
|
121
|
+
/** Number of retries before marking unhealthy */
|
|
122
|
+
healthCheckRetries?: number;
|
|
123
|
+
/** Grace period in seconds before health checks start */
|
|
124
|
+
healthCheckStartPeriod?: number;
|
|
125
|
+
/** Expected HTTP return code for healthy status */
|
|
126
|
+
healthCheckReturnCode?: number;
|
|
109
127
|
}
|
|
110
128
|
|
|
111
129
|
/**
|
|
@@ -224,8 +242,16 @@ export interface ICoolifyApplication {
|
|
|
224
242
|
base_directory?: string | null;
|
|
225
243
|
/** Server status (boolean) */
|
|
226
244
|
server_status?: boolean;
|
|
227
|
-
/** Environment ID */
|
|
245
|
+
/** Environment ID (numeric) */
|
|
228
246
|
environment_id?: number;
|
|
247
|
+
/** Project UUID */
|
|
248
|
+
project_uuid?: string;
|
|
249
|
+
/** Environment UUID */
|
|
250
|
+
environment_uuid?: string;
|
|
251
|
+
/** Source type (e.g., "App\\Models\\GithubApp", "App\\Models\\DeployKey") */
|
|
252
|
+
source_type?: string;
|
|
253
|
+
/** Type (legacy, may be null) */
|
|
254
|
+
type?: string;
|
|
229
255
|
/** Destination info */
|
|
230
256
|
destination?: {
|
|
231
257
|
uuid: string;
|
|
@@ -361,6 +387,8 @@ export interface ICoolifyDatabase {
|
|
|
361
387
|
status: string;
|
|
362
388
|
version?: string;
|
|
363
389
|
description?: string | null;
|
|
390
|
+
/** Environment ID (numeric, for grouping under projects) */
|
|
391
|
+
environment_id?: number;
|
|
364
392
|
destination?: {
|
|
365
393
|
uuid: string;
|
|
366
394
|
name: string;
|
|
@@ -382,6 +410,8 @@ export interface ICoolifyService {
|
|
|
382
410
|
status: string;
|
|
383
411
|
version?: string;
|
|
384
412
|
description?: string | null;
|
|
413
|
+
/** Environment ID (numeric, for grouping under projects) */
|
|
414
|
+
environment_id?: number;
|
|
385
415
|
project_uuid?: string;
|
|
386
416
|
environment_uuid?: string;
|
|
387
417
|
server_uuid?: string;
|
|
@@ -439,3 +469,75 @@ export interface ICoolifyVersion {
|
|
|
439
469
|
latest_version?: string;
|
|
440
470
|
is_latest?: boolean;
|
|
441
471
|
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* A resource (app, database, or service) within an environment.
|
|
475
|
+
*/
|
|
476
|
+
export interface ICoolifyResource {
|
|
477
|
+
/** Resource UUID */
|
|
478
|
+
uuid: string;
|
|
479
|
+
/** Resource name */
|
|
480
|
+
name: string;
|
|
481
|
+
/** Resource type: app, database, or service */
|
|
482
|
+
kind: "app" | "database" | "service";
|
|
483
|
+
/** Current status */
|
|
484
|
+
status: string;
|
|
485
|
+
/** FQDN/domain if configured */
|
|
486
|
+
fqdn?: string | null;
|
|
487
|
+
/** Database engine type (only for databases) */
|
|
488
|
+
dbType?: string;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* An environment within a project, containing resources.
|
|
493
|
+
*/
|
|
494
|
+
export interface ICoolifyEnvironmentNode {
|
|
495
|
+
/** Environment ID (numeric) */
|
|
496
|
+
id: number;
|
|
497
|
+
/** Environment UUID */
|
|
498
|
+
uuid: string;
|
|
499
|
+
/** Environment name (e.g., "production", "staging") */
|
|
500
|
+
name: string;
|
|
501
|
+
/** Resources in this environment */
|
|
502
|
+
resources: ICoolifyResource[];
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* A project node in the infrastructure tree.
|
|
507
|
+
*/
|
|
508
|
+
export interface ICoolifyProjectNode {
|
|
509
|
+
/** Project UUID */
|
|
510
|
+
uuid: string;
|
|
511
|
+
/** Project name */
|
|
512
|
+
name: string;
|
|
513
|
+
/** Project description */
|
|
514
|
+
description?: string | null;
|
|
515
|
+
/** Environments in this project */
|
|
516
|
+
environments: ICoolifyEnvironmentNode[];
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Full infrastructure tree: projects → environments → resources.
|
|
521
|
+
* Also includes global server info and aggregate counts.
|
|
522
|
+
*/
|
|
523
|
+
export interface ICoolifyInfrastructureTree {
|
|
524
|
+
/** Server info */
|
|
525
|
+
server: {
|
|
526
|
+
name: string;
|
|
527
|
+
ip?: string;
|
|
528
|
+
uuid?: string;
|
|
529
|
+
};
|
|
530
|
+
/** Projects with their environments and resources */
|
|
531
|
+
projects: ICoolifyProjectNode[];
|
|
532
|
+
/** Aggregate counts */
|
|
533
|
+
counts: {
|
|
534
|
+
projects: number;
|
|
535
|
+
apps: number;
|
|
536
|
+
databases: number;
|
|
537
|
+
services: number;
|
|
538
|
+
healthy: number;
|
|
539
|
+
running: number;
|
|
540
|
+
stopped: number;
|
|
541
|
+
unhealthy: number;
|
|
542
|
+
};
|
|
543
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Demo script showing new CLI UI features.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { highlightEnvBlock, createEnvTable, createChangeSummary } from "../cli/ui/index.js";
|
|
9
|
+
|
|
10
|
+
const sampleEnvVars = [
|
|
11
|
+
{
|
|
12
|
+
key: "DATABASE_URL",
|
|
13
|
+
value: "postgresql://user:pass@localhost:5432/mydb",
|
|
14
|
+
is_runtime: true,
|
|
15
|
+
is_buildtime: false,
|
|
16
|
+
is_required: true,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
key: "API_KEY",
|
|
20
|
+
value: "sk_test_1234567890abcdef",
|
|
21
|
+
is_runtime: true,
|
|
22
|
+
is_buildtime: false,
|
|
23
|
+
is_required: false,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
key: "NODE_ENV",
|
|
27
|
+
value: "production",
|
|
28
|
+
is_runtime: true,
|
|
29
|
+
is_buildtime: true,
|
|
30
|
+
is_required: false,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
key: "BUILD_ARG",
|
|
34
|
+
value: "some_value",
|
|
35
|
+
is_runtime: false,
|
|
36
|
+
is_buildtime: true,
|
|
37
|
+
is_required: false,
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
const sampleChanges = {
|
|
42
|
+
added: [
|
|
43
|
+
{ key: "NEW_VAR", value: "new_value" },
|
|
44
|
+
{ key: "ANOTHER_NEW", value: "another" },
|
|
45
|
+
],
|
|
46
|
+
updated: [
|
|
47
|
+
{ key: "DATABASE_URL", value: "new_db_url", oldValue: "old_db_url" },
|
|
48
|
+
{ key: "API_KEY", value: "new_key", oldValue: "old_key" },
|
|
49
|
+
],
|
|
50
|
+
removed: ["DEPRECATED_VAR", "OLD_SETTING"],
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
console.log("\n" + "=".repeat(60));
|
|
54
|
+
console.log(" CLI UI Demo - Syntax Highlighting");
|
|
55
|
+
console.log("=".repeat(60) + "\n");
|
|
56
|
+
|
|
57
|
+
// Demo 1: Syntax highlighted .env file
|
|
58
|
+
console.log("1️⃣ Syntax Highlighted .env File");
|
|
59
|
+
console.log("─".repeat(60));
|
|
60
|
+
const envContent = await Bun.file("/tmp/test.env").text();
|
|
61
|
+
console.log(highlightEnvBlock(envContent));
|
|
62
|
+
console.log();
|
|
63
|
+
|
|
64
|
+
// Demo 2: Table view
|
|
65
|
+
console.log("2️⃣ Table View with cli-table3");
|
|
66
|
+
console.log("─".repeat(60));
|
|
67
|
+
console.log(createEnvTable(sampleEnvVars, { compact: true, showType: true }));
|
|
68
|
+
console.log();
|
|
69
|
+
|
|
70
|
+
// Demo 3: Change summary
|
|
71
|
+
console.log("3️⃣ Change Summary for Sync");
|
|
72
|
+
console.log("─".repeat(60));
|
|
73
|
+
console.log(createChangeSummary(sampleChanges));
|
|
74
|
+
console.log();
|
|
75
|
+
|
|
76
|
+
console.log("=".repeat(60));
|
|
77
|
+
console.log(" ✨ Demo complete!");
|
|
78
|
+
console.log("=".repeat(60) + "\n");
|