@companyhelm/cli 0.4.1 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/dist/cli_io_interface.d.ts +12 -0
  2. package/dist/cli_io_interface.js +2 -0
  3. package/dist/cli_io_interface.js.map +1 -0
  4. package/dist/companyhelm_cli.d.ts +21 -0
  5. package/dist/companyhelm_cli.js +90 -0
  6. package/dist/companyhelm_cli.js.map +1 -0
  7. package/dist/console_io.d.ts +10 -0
  8. package/dist/console_io.js +24 -0
  9. package/dist/console_io.js.map +1 -0
  10. package/dist/index.d.ts +2 -0
  11. package/dist/index.js +4 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/provider/login_client.d.ts +34 -0
  14. package/dist/provider/login_client.js +41 -0
  15. package/dist/provider/login_client.js.map +1 -0
  16. package/dist/provider/login_command.d.ts +19 -0
  17. package/dist/provider/login_command.js +35 -0
  18. package/dist/provider/login_command.js.map +1 -0
  19. package/dist/provider/oauth_login_runner.d.ts +12 -0
  20. package/dist/provider/oauth_login_runner.js +37 -0
  21. package/dist/provider/oauth_login_runner.js.map +1 -0
  22. package/package.json +21 -29
  23. package/LICENSE +0 -21
  24. package/README.md +0 -66
  25. package/dist/cli.d.ts +0 -2
  26. package/dist/cli.js +0 -39
  27. package/dist/commands/dependencies.d.ts +0 -28
  28. package/dist/commands/dependencies.js +0 -292
  29. package/dist/commands/down.d.ts +0 -3
  30. package/dist/commands/down.js +0 -5
  31. package/dist/commands/interactive.d.ts +0 -7
  32. package/dist/commands/interactive.js +0 -25
  33. package/dist/commands/logs.d.ts +0 -3
  34. package/dist/commands/logs.js +0 -14
  35. package/dist/commands/register-commands.d.ts +0 -3
  36. package/dist/commands/register-commands.js +0 -23
  37. package/dist/commands/reset.d.ts +0 -7
  38. package/dist/commands/reset.js +0 -51
  39. package/dist/commands/set-image-version.d.ts +0 -31
  40. package/dist/commands/set-image-version.js +0 -87
  41. package/dist/commands/setup-github-app.d.ts +0 -13
  42. package/dist/commands/setup-github-app.js +0 -233
  43. package/dist/commands/startup-preferences.d.ts +0 -3
  44. package/dist/commands/startup-preferences.js +0 -39
  45. package/dist/commands/status.d.ts +0 -3
  46. package/dist/commands/status.js +0 -7
  47. package/dist/commands/up.d.ts +0 -3
  48. package/dist/commands/up.js +0 -39
  49. package/dist/config/image_config.d.ts +0 -4
  50. package/dist/config/image_config.js +0 -4
  51. package/dist/core/bootstrap/DeploymentBootstrapper.d.ts +0 -15
  52. package/dist/core/bootstrap/DeploymentBootstrapper.js +0 -118
  53. package/dist/core/bootstrap/SeedSqlRenderer.d.ts +0 -12
  54. package/dist/core/bootstrap/SeedSqlRenderer.js +0 -44
  55. package/dist/core/config/ApiEnvFileWriter.d.ts +0 -8
  56. package/dist/core/config/ApiEnvFileWriter.js +0 -33
  57. package/dist/core/config/GithubAppConfig.d.ts +0 -6
  58. package/dist/core/config/GithubAppConfig.js +0 -26
  59. package/dist/core/config/GithubAppConfigStore.d.ts +0 -11
  60. package/dist/core/config/GithubAppConfigStore.js +0 -57
  61. package/dist/core/docker/ComposeTemplateRenderer.d.ts +0 -22
  62. package/dist/core/docker/ComposeTemplateRenderer.js +0 -66
  63. package/dist/core/docker/DockerStackManager.d.ts +0 -29
  64. package/dist/core/docker/DockerStackManager.js +0 -163
  65. package/dist/core/local/ApiLocalService.d.ts +0 -22
  66. package/dist/core/local/ApiLocalService.js +0 -65
  67. package/dist/core/local/LocalRepoSourceResolver.d.ts +0 -24
  68. package/dist/core/local/LocalRepoSourceResolver.js +0 -33
  69. package/dist/core/local/LocalServiceProcessManager.d.ts +0 -18
  70. package/dist/core/local/LocalServiceProcessManager.js +0 -83
  71. package/dist/core/local/WebLocalService.d.ts +0 -23
  72. package/dist/core/local/WebLocalService.js +0 -101
  73. package/dist/core/logs/LogsService.d.ts +0 -6
  74. package/dist/core/logs/LogsService.js +0 -14
  75. package/dist/core/process/CommandRunner.d.ts +0 -4
  76. package/dist/core/process/CommandRunner.js +0 -51
  77. package/dist/core/runner/RunnerSupervisor.d.ts +0 -29
  78. package/dist/core/runner/RunnerSupervisor.js +0 -90
  79. package/dist/core/runner/runner-bootstrap.d.ts +0 -2
  80. package/dist/core/runner/runner-bootstrap.js +0 -48
  81. package/dist/core/runtime/CliPackageMetadata.d.ts +0 -3
  82. package/dist/core/runtime/CliPackageMetadata.js +0 -8
  83. package/dist/core/runtime/CliRoot.d.ts +0 -2
  84. package/dist/core/runtime/CliRoot.js +0 -23
  85. package/dist/core/runtime/ImageCatalog.d.ts +0 -11
  86. package/dist/core/runtime/ImageCatalog.js +0 -16
  87. package/dist/core/runtime/ImageConfigStore.d.ts +0 -15
  88. package/dist/core/runtime/ImageConfigStore.js +0 -51
  89. package/dist/core/runtime/LocalConfigStore.d.ts +0 -16
  90. package/dist/core/runtime/LocalConfigStore.js +0 -50
  91. package/dist/core/runtime/ManagedImages.d.ts +0 -10
  92. package/dist/core/runtime/ManagedImages.js +0 -27
  93. package/dist/core/runtime/PortAllocator.d.ts +0 -9
  94. package/dist/core/runtime/PortAllocator.js +0 -20
  95. package/dist/core/runtime/PublicImageTagRegistry.d.ts +0 -17
  96. package/dist/core/runtime/PublicImageTagRegistry.js +0 -168
  97. package/dist/core/runtime/RuntimePaths.d.ts +0 -16
  98. package/dist/core/runtime/RuntimePaths.js +0 -43
  99. package/dist/core/runtime/RuntimeState.d.ts +0 -38
  100. package/dist/core/runtime/RuntimeState.js +0 -1
  101. package/dist/core/runtime/RuntimeStateStore.d.ts +0 -11
  102. package/dist/core/runtime/RuntimeStateStore.js +0 -81
  103. package/dist/core/runtime/Secrets.d.ts +0 -10
  104. package/dist/core/runtime/Secrets.js +0 -26
  105. package/dist/core/runtime/VersionCatalog.d.ts +0 -10
  106. package/dist/core/runtime/VersionCatalog.js +0 -21
  107. package/dist/core/services/ManagedServiceNames.d.ts +0 -5
  108. package/dist/core/services/ManagedServiceNames.js +0 -12
  109. package/dist/core/status/StatusService.d.ts +0 -19
  110. package/dist/core/status/StatusService.js +0 -30
  111. package/dist/core/ui/TerminalRenderer.d.ts +0 -17
  112. package/dist/core/ui/TerminalRenderer.js +0 -71
  113. package/dist/preflight/ApiPortPreflightCheck.d.ts +0 -6
  114. package/dist/preflight/ApiPortPreflightCheck.js +0 -10
  115. package/dist/preflight/DockerInstalledPreflightCheck.d.ts +0 -7
  116. package/dist/preflight/DockerInstalledPreflightCheck.js +0 -15
  117. package/dist/preflight/PortAvailabilityPreflightCheck.d.ts +0 -7
  118. package/dist/preflight/PortAvailabilityPreflightCheck.js +0 -31
  119. package/dist/preflight/PostgresPortPreflightCheck.d.ts +0 -6
  120. package/dist/preflight/PostgresPortPreflightCheck.js +0 -10
  121. package/dist/preflight/PreflightCheck.d.ts +0 -3
  122. package/dist/preflight/PreflightCheck.js +0 -1
  123. package/dist/preflight/WebPortPreflightCheck.d.ts +0 -6
  124. package/dist/preflight/WebPortPreflightCheck.js +0 -10
  125. package/dist/preflight/runStartupPreflightChecks.d.ts +0 -18
  126. package/dist/preflight/runStartupPreflightChecks.js +0 -42
  127. package/dist/templates/api.env.tpl +0 -3
  128. package/dist/templates/docker-compose.yaml.tpl +0 -24
  129. package/dist/templates/seed.sql.tpl +0 -76
  130. package/src/config/image_config.ts +0 -4
  131. package/src/templates/api.env.tpl +0 -3
  132. package/src/templates/docker-compose.yaml.tpl +0 -24
  133. package/src/templates/seed.sql.tpl +0 -76
@@ -1,168 +0,0 @@
1
- import { buildManagedImageReference, getManagedImageDefinition } from "./ManagedImages.js";
2
- const RETRYABLE_STATUS_CODES = new Set([429, 500, 502, 503, 504]);
3
- const MAX_FETCH_ATTEMPTS = 3;
4
- const DEFAULT_RETRY_DELAY_MS = 250;
5
- const METADATA_FETCH_CONCURRENCY = 6;
6
- class PublicRegistryRequestError extends Error {
7
- status;
8
- retryAfterMs;
9
- constructor(url, status, retryAfterMs) {
10
- super(`Public registry returned ${status} for ${url}.`);
11
- this.status = status;
12
- this.retryAfterMs = retryAfterMs;
13
- }
14
- }
15
- export class PublicImageTagRegistry {
16
- async listAvailableTags(service, limit = 20) {
17
- if (!Number.isInteger(limit) || limit < 1) {
18
- throw new Error("Image tag limit must be a positive integer.");
19
- }
20
- const { repositoryPath } = getManagedImageDefinition(service);
21
- const token = await this.fetchToken(repositoryPath);
22
- const response = await fetch(`https://public.ecr.aws/v2/${repositoryPath}/tags/list`, {
23
- headers: {
24
- Authorization: `Bearer ${token}`
25
- }
26
- });
27
- if (!response.ok) {
28
- throw new Error(`Public registry returned ${response.status} for ${service} tags.`);
29
- }
30
- const payload = (await response.json());
31
- if (payload.errors?.length) {
32
- throw new Error(payload.errors[0]?.message || `Unable to load ${service} image tags.`);
33
- }
34
- const uniqueTags = [...new Set(payload.tags ?? [])].map((tag, position) => ({ tag, position }));
35
- const candidateTags = uniqueTags.slice(0, limit);
36
- const createdAtByDigest = new Map();
37
- const tagsWithMetadata = await this.mapWithConcurrency(candidateTags, METADATA_FETCH_CONCURRENCY, async ({ tag, position }) => ({
38
- tag,
39
- position,
40
- createdAt: await this.fetchCreatedAt(repositoryPath, token, tag, createdAtByDigest)
41
- }));
42
- return tagsWithMetadata
43
- .sort((left, right) => {
44
- const leftTimestamp = left.createdAt ? Date.parse(left.createdAt) : Number.NEGATIVE_INFINITY;
45
- const rightTimestamp = right.createdAt ? Date.parse(right.createdAt) : Number.NEGATIVE_INFINITY;
46
- if (rightTimestamp !== leftTimestamp) {
47
- return rightTimestamp - leftTimestamp;
48
- }
49
- return left.position - right.position;
50
- })
51
- .map(({ tag, createdAt }) => ({ tag, createdAt }));
52
- }
53
- buildImageReference(service, tag) {
54
- return buildManagedImageReference(service, tag);
55
- }
56
- async fetchToken(repositoryPath) {
57
- const scope = `repository:${repositoryPath}:pull`;
58
- const response = await fetch(`https://public.ecr.aws/token/?service=public.ecr.aws&scope=${encodeURIComponent(scope)}`);
59
- if (!response.ok) {
60
- throw new Error(`Public registry token request returned ${response.status}.`);
61
- }
62
- const payload = (await response.json());
63
- if (!payload.token) {
64
- throw new Error("Public registry token response did not include a token.");
65
- }
66
- return payload.token;
67
- }
68
- async fetchCreatedAt(repositoryPath, token, tag, createdAtByDigest) {
69
- try {
70
- const manifestReference = await this.fetchJson(`https://public.ecr.aws/v2/${repositoryPath}/manifests/${encodeURIComponent(tag)}`, {
71
- Authorization: `Bearer ${token}`,
72
- Accept: [
73
- "application/vnd.oci.image.index.v1+json",
74
- "application/vnd.docker.distribution.manifest.list.v2+json",
75
- "application/vnd.oci.image.manifest.v1+json",
76
- "application/vnd.docker.distribution.manifest.v2+json"
77
- ].join(", ")
78
- });
79
- const digest = this.selectManifestDigest(manifestReference);
80
- const manifest = digest
81
- ? await this.fetchJson(`https://public.ecr.aws/v2/${repositoryPath}/manifests/${encodeURIComponent(digest)}`, {
82
- Authorization: `Bearer ${token}`,
83
- Accept: ["application/vnd.oci.image.manifest.v1+json", "application/vnd.docker.distribution.manifest.v2+json"].join(", ")
84
- })
85
- : manifestReference;
86
- const configDigest = "config" in manifest ? manifest.config?.digest : undefined;
87
- if (!configDigest) {
88
- return undefined;
89
- }
90
- const existingCreatedAt = createdAtByDigest.get(configDigest);
91
- if (existingCreatedAt) {
92
- return await existingCreatedAt;
93
- }
94
- const createdAtPromise = this.fetchJson(`https://public.ecr.aws/v2/${repositoryPath}/blobs/${configDigest}`, {
95
- Authorization: `Bearer ${token}`
96
- })
97
- .then((config) => config.created)
98
- .catch((error) => {
99
- createdAtByDigest.delete(configDigest);
100
- throw error;
101
- });
102
- createdAtByDigest.set(configDigest, createdAtPromise);
103
- return await createdAtPromise;
104
- }
105
- catch (error) {
106
- if (error instanceof PublicRegistryRequestError) {
107
- return undefined;
108
- }
109
- throw error;
110
- }
111
- }
112
- selectManifestDigest(manifest) {
113
- if (!("manifests" in manifest) || !manifest.manifests?.length) {
114
- return undefined;
115
- }
116
- return (manifest.manifests.find((entry) => entry.platform?.os === "linux" && entry.platform?.architecture === "amd64")
117
- ?.digest ?? manifest.manifests[0]?.digest);
118
- }
119
- async fetchJson(url, headers) {
120
- for (let attempt = 1; attempt <= MAX_FETCH_ATTEMPTS; attempt += 1) {
121
- const response = await fetch(url, { headers });
122
- if (response.ok) {
123
- return (await response.json());
124
- }
125
- const retryAfterMs = this.parseRetryAfterMs(response);
126
- if (attempt < MAX_FETCH_ATTEMPTS && RETRYABLE_STATUS_CODES.has(response.status)) {
127
- await this.sleep(retryAfterMs ?? DEFAULT_RETRY_DELAY_MS * attempt);
128
- continue;
129
- }
130
- throw new PublicRegistryRequestError(url, response.status, retryAfterMs);
131
- }
132
- throw new PublicRegistryRequestError(url, 500);
133
- }
134
- parseRetryAfterMs(response) {
135
- const retryAfter = response.headers.get("retry-after");
136
- if (!retryAfter) {
137
- return undefined;
138
- }
139
- const retryAfterSeconds = Number.parseInt(retryAfter, 10);
140
- if (Number.isFinite(retryAfterSeconds)) {
141
- return Math.max(retryAfterSeconds, 0) * 1000;
142
- }
143
- const retryAt = Date.parse(retryAfter);
144
- if (Number.isNaN(retryAt)) {
145
- return undefined;
146
- }
147
- return Math.max(retryAt - Date.now(), 0);
148
- }
149
- async sleep(delayMs) {
150
- await new Promise((resolve) => setTimeout(resolve, delayMs));
151
- }
152
- async mapWithConcurrency(items, concurrency, mapper) {
153
- if (items.length === 0) {
154
- return [];
155
- }
156
- const results = new Array(items.length);
157
- let nextIndex = 0;
158
- const workerCount = Math.min(concurrency, items.length);
159
- await Promise.all(Array.from({ length: workerCount }, async () => {
160
- while (nextIndex < items.length) {
161
- const currentIndex = nextIndex;
162
- nextIndex += 1;
163
- results[currentIndex] = await mapper(items[currentIndex], currentIndex);
164
- }
165
- }));
166
- return results;
167
- }
168
- }
@@ -1,16 +0,0 @@
1
- export declare class RuntimePaths {
2
- private readonly root;
3
- constructor(root: string);
4
- stateFilePath(): string;
5
- composeFilePath(): string;
6
- apiDirectoryPath(): string;
7
- apiEnvPath(): string;
8
- apiConfigPath(): string;
9
- frontendConfigPath(): string;
10
- seedFilePath(): string;
11
- runnerConfigPath(): string;
12
- runnerStateDbPath(): string;
13
- runnerLogPath(): string;
14
- serviceRuntimePath(): string;
15
- serviceLogPath(service: "api" | "frontend"): string;
16
- }
@@ -1,43 +0,0 @@
1
- import path from "node:path";
2
- export class RuntimePaths {
3
- root;
4
- constructor(root) {
5
- this.root = root;
6
- }
7
- stateFilePath() {
8
- return path.join(this.root, "state.yaml");
9
- }
10
- composeFilePath() {
11
- return path.join(this.root, "docker-compose.yaml");
12
- }
13
- apiDirectoryPath() {
14
- return path.join(this.root, "api");
15
- }
16
- apiEnvPath() {
17
- return path.join(this.apiDirectoryPath(), ".env");
18
- }
19
- apiConfigPath() {
20
- return path.join(this.root, "api-config.yaml");
21
- }
22
- frontendConfigPath() {
23
- return path.join(this.root, "frontend-config.yaml");
24
- }
25
- seedFilePath() {
26
- return path.join(this.root, "seed.sql");
27
- }
28
- runnerConfigPath() {
29
- return path.join(this.root, "runner");
30
- }
31
- runnerStateDbPath() {
32
- return path.join(this.runnerConfigPath(), "state.db");
33
- }
34
- runnerLogPath() {
35
- return path.join(this.runnerConfigPath(), "daemon.log");
36
- }
37
- serviceRuntimePath() {
38
- return path.join(this.root, "services");
39
- }
40
- serviceLogPath(service) {
41
- return path.join(this.serviceRuntimePath(), `${service}.log`);
42
- }
43
- }
@@ -1,38 +0,0 @@
1
- export interface RuntimePorts {
2
- apiHttp: number;
3
- ui: number;
4
- runnerGrpc: number;
5
- agentCliGrpc: number;
6
- }
7
- export interface DockerManagedServiceRuntime {
8
- source: "docker";
9
- }
10
- export interface LocalManagedServiceRuntime {
11
- source: "local";
12
- repoPath: string;
13
- logPath: string;
14
- pid: number;
15
- }
16
- export type ManagedServiceRuntime = DockerManagedServiceRuntime | LocalManagedServiceRuntime;
17
- export interface RuntimeState {
18
- version: 1;
19
- company: {
20
- id: string;
21
- name: string;
22
- };
23
- auth: {
24
- username: string;
25
- password: string;
26
- jwtPrivateKeyPem: string;
27
- jwtPublicKeyPem: string;
28
- };
29
- runner: {
30
- name: string;
31
- secret: string;
32
- };
33
- ports: RuntimePorts;
34
- services: {
35
- api: ManagedServiceRuntime;
36
- frontend: ManagedServiceRuntime;
37
- };
38
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,11 +0,0 @@
1
- import type { RuntimeState } from "./RuntimeState.js";
2
- export declare class RuntimeStateStore {
3
- private readonly root;
4
- private readonly runtimePaths;
5
- private static readonly DEFAULT_USERNAME;
6
- constructor(root: string);
7
- initialize(): RuntimeState;
8
- load(): RuntimeState | null;
9
- persist(state: RuntimeState): void;
10
- private save;
11
- }
@@ -1,81 +0,0 @@
1
- import fs from "node:fs";
2
- import YAML from "yaml";
3
- import { PortAllocator } from "./PortAllocator.js";
4
- import { RuntimePaths } from "./RuntimePaths.js";
5
- import { createPemKeyPair, randomCompanyId, randomSecret } from "./Secrets.js";
6
- export class RuntimeStateStore {
7
- root;
8
- runtimePaths;
9
- static DEFAULT_USERNAME = "admin@local";
10
- constructor(root) {
11
- this.root = root;
12
- this.runtimePaths = new RuntimePaths(root);
13
- }
14
- initialize() {
15
- const existingState = this.load();
16
- if (existingState) {
17
- return existingState;
18
- }
19
- fs.mkdirSync(this.root, { recursive: true });
20
- const authKeys = createPemKeyPair();
21
- const state = {
22
- version: 1,
23
- company: {
24
- id: randomCompanyId(),
25
- name: "Local CompanyHelm"
26
- },
27
- auth: {
28
- username: RuntimeStateStore.DEFAULT_USERNAME,
29
- password: randomSecret(),
30
- jwtPrivateKeyPem: authKeys.privateKeyPem,
31
- jwtPublicKeyPem: authKeys.publicKeyPem
32
- },
33
- runner: {
34
- name: "local-runner",
35
- secret: randomSecret()
36
- },
37
- ports: new PortAllocator().allocate(),
38
- services: {
39
- api: {
40
- source: "docker"
41
- },
42
- frontend: {
43
- source: "docker"
44
- }
45
- }
46
- };
47
- this.save(state);
48
- return state;
49
- }
50
- load() {
51
- if (!fs.existsSync(this.runtimePaths.stateFilePath())) {
52
- return null;
53
- }
54
- const state = YAML.parse(fs.readFileSync(this.runtimePaths.stateFilePath(), "utf8"));
55
- if (state.auth.username !== RuntimeStateStore.DEFAULT_USERNAME && state.auth.username === "admin") {
56
- state.auth.username = RuntimeStateStore.DEFAULT_USERNAME;
57
- this.save(state);
58
- }
59
- if (!state.services) {
60
- state.services = {
61
- api: {
62
- source: "docker"
63
- },
64
- frontend: {
65
- source: "docker"
66
- }
67
- };
68
- this.save(state);
69
- }
70
- return state;
71
- }
72
- persist(state) {
73
- this.save(state);
74
- }
75
- save(state) {
76
- fs.writeFileSync(this.runtimePaths.stateFilePath(), YAML.stringify(state), {
77
- encoding: "utf8",
78
- mode: 0o600
79
- });
80
- }
81
- }
@@ -1,10 +0,0 @@
1
- export declare function randomSecret(length?: number): string;
2
- export declare function randomCompanyId(): string;
3
- export declare function createPasswordHash(password: string): {
4
- passwordSalt: string;
5
- passwordHash: string;
6
- };
7
- export declare function createPemKeyPair(): {
8
- privateKeyPem: string;
9
- publicKeyPem: string;
10
- };
@@ -1,26 +0,0 @@
1
- import { generateKeyPairSync, randomBytes, randomUUID, scryptSync } from "node:crypto";
2
- export function randomSecret(length = 24) {
3
- return randomBytes(length).toString("base64url");
4
- }
5
- export function randomCompanyId() {
6
- return randomUUID();
7
- }
8
- export function createPasswordHash(password) {
9
- const passwordSalt = randomBytes(16).toString("hex");
10
- const passwordHash = scryptSync(password, passwordSalt, 64).toString("hex");
11
- return {
12
- passwordSalt,
13
- passwordHash
14
- };
15
- }
16
- export function createPemKeyPair() {
17
- const { privateKey, publicKey } = generateKeyPairSync("rsa", {
18
- modulusLength: 2048,
19
- privateKeyEncoding: { format: "pem", type: "pkcs1" },
20
- publicKeyEncoding: { format: "pem", type: "pkcs1" }
21
- });
22
- return {
23
- privateKeyPem: privateKey,
24
- publicKeyPem: publicKey
25
- };
26
- }
@@ -1,10 +0,0 @@
1
- import { type RuntimeImages } from "./ImageCatalog.js";
2
- export interface RuntimeVersions {
3
- cliPackage: string;
4
- runnerPackage: string;
5
- images: RuntimeImages;
6
- }
7
- export declare class VersionCatalog {
8
- resolve(): RuntimeVersions;
9
- private readPackageVersion;
10
- }
@@ -1,21 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { createRequire } from "node:module";
4
- import { fileURLToPath } from "node:url";
5
- import { ImageCatalog } from "./ImageCatalog.js";
6
- const require = createRequire(import.meta.url);
7
- const __filename = fileURLToPath(import.meta.url);
8
- const __dirname = path.dirname(__filename);
9
- export class VersionCatalog {
10
- resolve() {
11
- return {
12
- cliPackage: this.readPackageVersion(path.resolve(__dirname, "../../../package.json")),
13
- runnerPackage: this.readPackageVersion(require.resolve("@companyhelm/runner/package.json")),
14
- images: new ImageCatalog().resolve()
15
- };
16
- }
17
- readPackageVersion(packageJsonPath) {
18
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
19
- return `${packageJson.name}@${packageJson.version}`;
20
- }
21
- }
@@ -1,5 +0,0 @@
1
- export declare const MANAGED_SERVICE_KEYS: readonly ["postgres", "api", "frontend", "runner"];
2
- export type ManagedServiceKey = (typeof MANAGED_SERVICE_KEYS)[number];
3
- export declare const MANAGED_SERVICE_NAMES: Record<ManagedServiceKey, string>;
4
- export declare const AVAILABLE_MANAGED_SERVICE_NAMES: string[];
5
- export declare function resolveManagedServiceKey(serviceName: string): ManagedServiceKey | null;
@@ -1,12 +0,0 @@
1
- export const MANAGED_SERVICE_KEYS = ["postgres", "api", "frontend", "runner"];
2
- export const MANAGED_SERVICE_NAMES = {
3
- postgres: "postgres",
4
- api: "companyhelm-api",
5
- frontend: "companyhelm-web",
6
- runner: "companyhelm-runner"
7
- };
8
- const SERVICE_NAME_TO_KEY = new Map(Object.entries(MANAGED_SERVICE_NAMES).map(([key, value]) => [value, key]));
9
- export const AVAILABLE_MANAGED_SERVICE_NAMES = MANAGED_SERVICE_KEYS.map((key) => MANAGED_SERVICE_NAMES[key]);
10
- export function resolveManagedServiceKey(serviceName) {
11
- return SERVICE_NAME_TO_KEY.get(serviceName.trim()) ?? null;
12
- }
@@ -1,19 +0,0 @@
1
- export type ManagedServiceStatus = "running" | "stopped";
2
- export interface StatusSnapshot {
3
- postgres: ManagedServiceStatus;
4
- api: ManagedServiceStatus;
5
- frontend: ManagedServiceStatus;
6
- runner: ManagedServiceStatus;
7
- }
8
- export interface StatusOverrides {
9
- api?: () => Promise<boolean | undefined> | boolean | undefined;
10
- frontend?: () => Promise<boolean | undefined> | boolean | undefined;
11
- runner?: () => Promise<boolean | undefined> | boolean | undefined;
12
- }
13
- export declare class StatusService {
14
- private readonly listRunningServices;
15
- private readonly overrides;
16
- constructor(listRunningServices: () => Promise<string>, overrides?: StatusOverrides);
17
- read(): Promise<StatusSnapshot>;
18
- private resolveServiceRunning;
19
- }
@@ -1,30 +0,0 @@
1
- export class StatusService {
2
- listRunningServices;
3
- overrides;
4
- constructor(listRunningServices, overrides = {}) {
5
- this.listRunningServices = listRunningServices;
6
- this.overrides = overrides;
7
- }
8
- async read() {
9
- const running = new Set((await this.listRunningServices())
10
- .split("\n")
11
- .map((service) => service.trim())
12
- .filter(Boolean));
13
- const apiRunning = await this.resolveServiceRunning("api", this.overrides.api, running);
14
- const frontendRunning = await this.resolveServiceRunning("frontend", this.overrides.frontend, running);
15
- const runnerRunning = await this.resolveServiceRunning("runner", this.overrides.runner, running);
16
- return {
17
- postgres: running.has("postgres") ? "running" : "stopped",
18
- api: apiRunning ? "running" : "stopped",
19
- frontend: frontendRunning ? "running" : "stopped",
20
- runner: runnerRunning ? "running" : "stopped"
21
- };
22
- }
23
- async resolveServiceRunning(service, override, running) {
24
- if (!override) {
25
- return running.has(service);
26
- }
27
- const result = await override();
28
- return typeof result === "boolean" ? result : running.has(service);
29
- }
30
- }
@@ -1,17 +0,0 @@
1
- import type { StatusReport } from "../../commands/dependencies.js";
2
- export declare class TerminalRenderer {
3
- private readonly useColor;
4
- private static readonly OSC;
5
- private static readonly BEL;
6
- constructor(useColor?: boolean);
7
- renderBanner(): string;
8
- success(message: string): string;
9
- progress(message: string): string;
10
- successHighlight(message: string): string;
11
- clickableUrl(url: string): string;
12
- renderStatus(report: StatusReport): string;
13
- private renderServiceLine;
14
- private warn;
15
- private formatDetail;
16
- private colorize;
17
- }
@@ -1,71 +0,0 @@
1
- import chalk from "chalk";
2
- import figlet from "figlet";
3
- export class TerminalRenderer {
4
- useColor;
5
- static OSC = "\u001B]";
6
- static BEL = "\u0007";
7
- constructor(useColor = true) {
8
- this.useColor = useColor;
9
- }
10
- renderBanner() {
11
- const banner = figlet.textSync("COMPANYHELM", {
12
- horizontalLayout: "fitted"
13
- });
14
- return this.colorize(`COMPANYHELM\n${banner}`, "cyan");
15
- }
16
- success(message) {
17
- return `${this.colorize("[ok]", "green")} ${message}`;
18
- }
19
- progress(message) {
20
- return this.colorize(`... ${message}`, "cyan");
21
- }
22
- successHighlight(message) {
23
- if (!this.useColor) {
24
- return message;
25
- }
26
- return chalk.green.bold(message);
27
- }
28
- clickableUrl(url) {
29
- if (!this.useColor) {
30
- return url;
31
- }
32
- const display = this.successHighlight(url);
33
- return `${TerminalRenderer.OSC}8;;${url}${TerminalRenderer.BEL}${display}${TerminalRenderer.OSC}8;;${TerminalRenderer.BEL}`;
34
- }
35
- renderStatus(report) {
36
- const lines = ["Status"];
37
- lines.push(this.renderServiceLine("Postgres", report.services.postgres));
38
- lines.push(this.renderServiceLine("API", report.services.api, report.apiUrl));
39
- lines.push(this.renderServiceLine("companyhelm-web", report.services.frontend, report.uiUrl));
40
- lines.push(this.renderServiceLine("Runner", report.services.runner));
41
- if (report.versions) {
42
- lines.push(`CompanyHelm CLI: ${report.versions.cliPackage}`);
43
- lines.push(`Runner package: ${report.versions.runnerPackage}`);
44
- lines.push(`API image: ${report.versions.images.api}`);
45
- lines.push(`companyhelm-web image: ${report.versions.images.frontend}`);
46
- lines.push(`Postgres image: ${report.versions.images.postgres}`);
47
- }
48
- if (report.username) {
49
- lines.push(`username: ${report.username}`);
50
- }
51
- return lines.join("\n");
52
- }
53
- renderServiceLine(label, status, detail) {
54
- const statusLabel = status === "running" ? this.success("running") : this.warn("stopped");
55
- return detail && status === "running"
56
- ? `${label}: ${statusLabel} (${this.formatDetail(detail)})`
57
- : `${label}: ${statusLabel}`;
58
- }
59
- warn(message) {
60
- return `${this.colorize("[!]", "yellow")} ${message}`;
61
- }
62
- formatDetail(detail) {
63
- return detail.startsWith("http://") || detail.startsWith("https://") ? this.clickableUrl(detail) : detail;
64
- }
65
- colorize(text, color) {
66
- if (!this.useColor) {
67
- return text;
68
- }
69
- return chalk[color](text);
70
- }
71
- }
@@ -1,6 +0,0 @@
1
- import type { PreflightCheck } from "./PreflightCheck.js";
2
- export declare class ApiPortPreflightCheck implements PreflightCheck {
3
- private readonly delegate;
4
- constructor(port: number);
5
- run(): Promise<void>;
6
- }
@@ -1,10 +0,0 @@
1
- import { PortAvailabilityPreflightCheck } from "./PortAvailabilityPreflightCheck.js";
2
- export class ApiPortPreflightCheck {
3
- delegate;
4
- constructor(port) {
5
- this.delegate = new PortAvailabilityPreflightCheck("companyhelm-api", port);
6
- }
7
- run() {
8
- return this.delegate.run();
9
- }
10
- }
@@ -1,7 +0,0 @@
1
- import { CommandRunner } from "../core/process/CommandRunner.js";
2
- import type { PreflightCheck } from "./PreflightCheck.js";
3
- export declare class DockerInstalledPreflightCheck implements PreflightCheck {
4
- private readonly commandRunner;
5
- constructor(commandRunner?: CommandRunner);
6
- run(): Promise<void>;
7
- }
@@ -1,15 +0,0 @@
1
- import { CommandRunner } from "../core/process/CommandRunner.js";
2
- export class DockerInstalledPreflightCheck {
3
- commandRunner;
4
- constructor(commandRunner = new CommandRunner()) {
5
- this.commandRunner = commandRunner;
6
- }
7
- async run() {
8
- try {
9
- await this.commandRunner.capture("docker", ["--version"]);
10
- }
11
- catch {
12
- throw new Error("Docker is required for `companyhelm up`, but the `docker` command is unavailable. Install Docker and make sure it is on your PATH.");
13
- }
14
- }
15
- }
@@ -1,7 +0,0 @@
1
- import type { PreflightCheck } from "./PreflightCheck.js";
2
- export declare class PortAvailabilityPreflightCheck implements PreflightCheck {
3
- private readonly serviceName;
4
- private readonly port;
5
- constructor(serviceName: string, port: number);
6
- run(): Promise<void>;
7
- }