@geekmidas/cli 0.13.0 → 0.15.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/{bundler-DskIqW2t.mjs → bundler-D7cM_FWw.mjs} +34 -10
- package/dist/bundler-D7cM_FWw.mjs.map +1 -0
- package/dist/{bundler-B1qy9b-j.cjs → bundler-Nuew7Xcn.cjs} +33 -9
- package/dist/bundler-Nuew7Xcn.cjs.map +1 -0
- package/dist/config.d.cts +1 -1
- package/dist/config.d.mts +1 -1
- package/dist/dokploy-api-B7KxOQr3.cjs +3 -0
- package/dist/dokploy-api-C7F9VykY.cjs +317 -0
- package/dist/dokploy-api-C7F9VykY.cjs.map +1 -0
- package/dist/dokploy-api-CaETb2L6.mjs +305 -0
- package/dist/dokploy-api-CaETb2L6.mjs.map +1 -0
- package/dist/dokploy-api-DHvfmWbi.mjs +3 -0
- package/dist/{encryption-Dyf_r1h-.cjs → encryption-D7Efcdi9.cjs} +1 -1
- package/dist/{encryption-Dyf_r1h-.cjs.map → encryption-D7Efcdi9.cjs.map} +1 -1
- package/dist/{encryption-C8H-38Yy.mjs → encryption-h4Nb6W-M.mjs} +1 -1
- package/dist/{encryption-C8H-38Yy.mjs.map → encryption-h4Nb6W-M.mjs.map} +1 -1
- package/dist/index.cjs +1508 -1073
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1508 -1073
- package/dist/index.mjs.map +1 -1
- package/dist/{openapi-Bt_1FDpT.cjs → openapi-C89hhkZC.cjs} +3 -3
- package/dist/{openapi-Bt_1FDpT.cjs.map → openapi-C89hhkZC.cjs.map} +1 -1
- package/dist/{openapi-BfFlOBCG.mjs → openapi-CZVcfxk-.mjs} +3 -3
- package/dist/{openapi-BfFlOBCG.mjs.map → openapi-CZVcfxk-.mjs.map} +1 -1
- package/dist/{openapi-react-query-B6XTeGqS.mjs → openapi-react-query-CM2_qlW9.mjs} +1 -1
- package/dist/{openapi-react-query-B6XTeGqS.mjs.map → openapi-react-query-CM2_qlW9.mjs.map} +1 -1
- package/dist/{openapi-react-query-B-sNWHFU.cjs → openapi-react-query-iKjfLzff.cjs} +1 -1
- package/dist/{openapi-react-query-B-sNWHFU.cjs.map → openapi-react-query-iKjfLzff.cjs.map} +1 -1
- package/dist/openapi-react-query.cjs +1 -1
- package/dist/openapi-react-query.mjs +1 -1
- package/dist/openapi.cjs +1 -1
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/openapi.mjs +1 -1
- package/dist/{storage-kSxTjkNb.mjs → storage-BaOP55oq.mjs} +16 -2
- package/dist/storage-BaOP55oq.mjs.map +1 -0
- package/dist/{storage-Bj1E26lU.cjs → storage-Bn3K9Ccu.cjs} +21 -1
- package/dist/storage-Bn3K9Ccu.cjs.map +1 -0
- package/dist/storage-UfyTn7Zm.cjs +7 -0
- package/dist/storage-nkGIjeXt.mjs +3 -0
- package/dist/{types-BhkZc-vm.d.cts → types-BgaMXsUa.d.cts} +3 -1
- package/dist/{types-BR0M2v_c.d.mts.map → types-BgaMXsUa.d.cts.map} +1 -1
- package/dist/{types-BR0M2v_c.d.mts → types-iFk5ms7y.d.mts} +3 -1
- package/dist/{types-BhkZc-vm.d.cts.map → types-iFk5ms7y.d.mts.map} +1 -1
- package/package.json +4 -4
- package/src/auth/__tests__/credentials.spec.ts +127 -0
- package/src/auth/__tests__/index.spec.ts +69 -0
- package/src/auth/credentials.ts +33 -0
- package/src/auth/index.ts +57 -50
- package/src/build/__tests__/bundler.spec.ts +5 -4
- package/src/build/__tests__/endpoint-analyzer.spec.ts +623 -0
- package/src/build/__tests__/handler-templates.spec.ts +272 -0
- package/src/build/bundler.ts +61 -8
- package/src/build/index.ts +21 -0
- package/src/build/types.ts +6 -0
- package/src/deploy/__tests__/docker.spec.ts +44 -6
- package/src/deploy/__tests__/dokploy-api.spec.ts +698 -0
- package/src/deploy/__tests__/dokploy.spec.ts +196 -6
- package/src/deploy/__tests__/index.spec.ts +401 -0
- package/src/deploy/__tests__/init.spec.ts +147 -16
- package/src/deploy/docker.ts +109 -5
- package/src/deploy/dokploy-api.ts +581 -0
- package/src/deploy/dokploy.ts +66 -93
- package/src/deploy/index.ts +630 -32
- package/src/deploy/init.ts +192 -249
- package/src/deploy/types.ts +24 -2
- package/src/dev/__tests__/index.spec.ts +95 -0
- package/src/docker/__tests__/templates.spec.ts +144 -0
- package/src/docker/index.ts +96 -6
- package/src/docker/templates.ts +114 -27
- package/src/generators/EndpointGenerator.ts +2 -2
- package/src/index.ts +34 -13
- package/src/secrets/storage.ts +15 -0
- package/src/types.ts +2 -0
- package/dist/bundler-B1qy9b-j.cjs.map +0 -1
- package/dist/bundler-DskIqW2t.mjs.map +0 -1
- package/dist/storage-BOOpAF8N.cjs +0 -5
- package/dist/storage-Bj1E26lU.cjs.map +0 -1
- package/dist/storage-kSxTjkNb.mjs.map +0 -1
- package/dist/storage-tgZSUnKl.mjs +0 -3
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized Dokploy API client
|
|
3
|
+
*
|
|
4
|
+
* Handles authentication, error handling, and provides typed methods for all Dokploy API endpoints.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface DokployApiOptions {
|
|
8
|
+
/** Dokploy server URL (e.g., https://dokploy.example.com) */
|
|
9
|
+
baseUrl: string;
|
|
10
|
+
/** API token for authentication */
|
|
11
|
+
token: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface DokployErrorResponse {
|
|
15
|
+
message?: string;
|
|
16
|
+
issues?: Array<{ message: string }>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class DokployApiError extends Error {
|
|
20
|
+
constructor(
|
|
21
|
+
message: string,
|
|
22
|
+
public status: number,
|
|
23
|
+
public statusText: string,
|
|
24
|
+
public issues?: Array<{ message: string }>,
|
|
25
|
+
) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = 'DokployApiError';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Dokploy API client
|
|
33
|
+
*/
|
|
34
|
+
export class DokployApi {
|
|
35
|
+
private baseUrl: string;
|
|
36
|
+
private token: string;
|
|
37
|
+
|
|
38
|
+
constructor(options: DokployApiOptions) {
|
|
39
|
+
this.baseUrl = options.baseUrl.replace(/\/$/, ''); // Remove trailing slash
|
|
40
|
+
this.token = options.token;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Make a GET request to the Dokploy API
|
|
45
|
+
*/
|
|
46
|
+
async get<T>(endpoint: string): Promise<T> {
|
|
47
|
+
return this.request<T>('GET', endpoint);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Make a POST request to the Dokploy API
|
|
52
|
+
*/
|
|
53
|
+
async post<T>(endpoint: string, body?: Record<string, unknown>): Promise<T> {
|
|
54
|
+
return this.request<T>('POST', endpoint, body);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Make a request to the Dokploy API
|
|
59
|
+
*/
|
|
60
|
+
private async request<T>(
|
|
61
|
+
method: 'GET' | 'POST' | 'PUT' | 'DELETE',
|
|
62
|
+
endpoint: string,
|
|
63
|
+
body?: Record<string, unknown>,
|
|
64
|
+
): Promise<T> {
|
|
65
|
+
const url = `${this.baseUrl}/api/${endpoint}`;
|
|
66
|
+
|
|
67
|
+
const response = await fetch(url, {
|
|
68
|
+
method,
|
|
69
|
+
headers: {
|
|
70
|
+
'Content-Type': 'application/json',
|
|
71
|
+
'x-api-key': this.token,
|
|
72
|
+
},
|
|
73
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
if (!response.ok) {
|
|
77
|
+
let errorMessage = `Dokploy API error: ${response.status} ${response.statusText}`;
|
|
78
|
+
let issues: Array<{ message: string }> | undefined;
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
const errorBody = (await response.json()) as DokployErrorResponse;
|
|
82
|
+
if (errorBody.message) {
|
|
83
|
+
errorMessage = `Dokploy API error: ${errorBody.message}`;
|
|
84
|
+
}
|
|
85
|
+
if (errorBody.issues?.length) {
|
|
86
|
+
issues = errorBody.issues;
|
|
87
|
+
errorMessage += `\n Issues: ${errorBody.issues.map((i) => i.message).join(', ')}`;
|
|
88
|
+
}
|
|
89
|
+
} catch {
|
|
90
|
+
// Ignore JSON parse errors
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
throw new DokployApiError(
|
|
94
|
+
errorMessage,
|
|
95
|
+
response.status,
|
|
96
|
+
response.statusText,
|
|
97
|
+
issues,
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Handle empty responses (204 No Content or empty body)
|
|
102
|
+
const text = await response.text();
|
|
103
|
+
if (!text || text.trim() === '') {
|
|
104
|
+
return undefined as T;
|
|
105
|
+
}
|
|
106
|
+
return JSON.parse(text) as T;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Validate the API token by making a test request
|
|
111
|
+
*/
|
|
112
|
+
async validateToken(): Promise<boolean> {
|
|
113
|
+
try {
|
|
114
|
+
await this.get('project.all');
|
|
115
|
+
return true;
|
|
116
|
+
} catch {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ============================================
|
|
122
|
+
// Project endpoints
|
|
123
|
+
// ============================================
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* List all projects
|
|
127
|
+
*/
|
|
128
|
+
async listProjects(): Promise<DokployProject[]> {
|
|
129
|
+
return this.get<DokployProject[]>('project.all');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Get a single project by ID
|
|
134
|
+
*/
|
|
135
|
+
async getProject(projectId: string): Promise<DokployProjectDetails> {
|
|
136
|
+
return this.get<DokployProjectDetails>(
|
|
137
|
+
`project.one?projectId=${projectId}`,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Create a new project
|
|
143
|
+
*/
|
|
144
|
+
async createProject(
|
|
145
|
+
name: string,
|
|
146
|
+
description?: string,
|
|
147
|
+
): Promise<{ project: DokployProject; environment: DokployEnvironment }> {
|
|
148
|
+
return this.post<{
|
|
149
|
+
project: DokployProject;
|
|
150
|
+
environment: DokployEnvironment;
|
|
151
|
+
}>('project.create', {
|
|
152
|
+
name,
|
|
153
|
+
description: description ?? `Created by gkm CLI`,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ============================================
|
|
158
|
+
// Environment endpoints
|
|
159
|
+
// ============================================
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Create an environment in a project
|
|
163
|
+
*/
|
|
164
|
+
async createEnvironment(
|
|
165
|
+
projectId: string,
|
|
166
|
+
name: string,
|
|
167
|
+
description?: string,
|
|
168
|
+
): Promise<DokployEnvironment> {
|
|
169
|
+
return this.post<DokployEnvironment>('environment.create', {
|
|
170
|
+
projectId,
|
|
171
|
+
name,
|
|
172
|
+
description: description ?? `${name} environment`,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ============================================
|
|
177
|
+
// Application endpoints
|
|
178
|
+
// ============================================
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Create a new application
|
|
182
|
+
*/
|
|
183
|
+
async createApplication(
|
|
184
|
+
name: string,
|
|
185
|
+
projectId: string,
|
|
186
|
+
environmentId: string,
|
|
187
|
+
): Promise<DokployApplication> {
|
|
188
|
+
return this.post<DokployApplication>('application.create', {
|
|
189
|
+
name,
|
|
190
|
+
projectId,
|
|
191
|
+
environmentId,
|
|
192
|
+
appName: name.toLowerCase().replace(/[^a-z0-9-]/g, '-'),
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Update an application
|
|
198
|
+
*/
|
|
199
|
+
async updateApplication(
|
|
200
|
+
applicationId: string,
|
|
201
|
+
updates: Partial<DokployApplicationUpdate>,
|
|
202
|
+
): Promise<void> {
|
|
203
|
+
await this.post('application.update', {
|
|
204
|
+
applicationId,
|
|
205
|
+
...updates,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Save environment variables for an application
|
|
211
|
+
*/
|
|
212
|
+
async saveApplicationEnv(applicationId: string, env: string): Promise<void> {
|
|
213
|
+
await this.post('application.saveEnvironment', {
|
|
214
|
+
applicationId,
|
|
215
|
+
env,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Configure application to use Docker provider (pull from registry)
|
|
221
|
+
*
|
|
222
|
+
* For private registries, either:
|
|
223
|
+
* - Use `registryId` if the registry is configured in Dokploy
|
|
224
|
+
* - Or provide `username`, `password`, and `registryUrl` directly
|
|
225
|
+
*/
|
|
226
|
+
async saveDockerProvider(
|
|
227
|
+
applicationId: string,
|
|
228
|
+
dockerImage: string,
|
|
229
|
+
options?: {
|
|
230
|
+
/** Registry ID in Dokploy (for pre-configured registries) */
|
|
231
|
+
registryId?: string;
|
|
232
|
+
/** Registry username (for direct auth) */
|
|
233
|
+
username?: string;
|
|
234
|
+
/** Registry password (for direct auth) */
|
|
235
|
+
password?: string;
|
|
236
|
+
/** Registry URL (for direct auth, e.g., ghcr.io) */
|
|
237
|
+
registryUrl?: string;
|
|
238
|
+
},
|
|
239
|
+
): Promise<void> {
|
|
240
|
+
await this.post('application.saveDockerProvider', {
|
|
241
|
+
applicationId,
|
|
242
|
+
dockerImage,
|
|
243
|
+
...options,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Deploy an application
|
|
249
|
+
*/
|
|
250
|
+
async deployApplication(applicationId: string): Promise<void> {
|
|
251
|
+
await this.post('application.deploy', { applicationId });
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// ============================================
|
|
255
|
+
// Registry endpoints
|
|
256
|
+
// ============================================
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* List all registries
|
|
260
|
+
*/
|
|
261
|
+
async listRegistries(): Promise<DokployRegistry[]> {
|
|
262
|
+
return this.get<DokployRegistry[]>('registry.all');
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Create a new registry
|
|
267
|
+
*/
|
|
268
|
+
async createRegistry(
|
|
269
|
+
registryName: string,
|
|
270
|
+
registryUrl: string,
|
|
271
|
+
username: string,
|
|
272
|
+
password: string,
|
|
273
|
+
options?: {
|
|
274
|
+
imagePrefix?: string;
|
|
275
|
+
},
|
|
276
|
+
): Promise<DokployRegistry> {
|
|
277
|
+
return this.post<DokployRegistry>('registry.create', {
|
|
278
|
+
registryName,
|
|
279
|
+
registryUrl,
|
|
280
|
+
username,
|
|
281
|
+
password,
|
|
282
|
+
imagePrefix: options?.imagePrefix,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Get a registry by ID
|
|
288
|
+
*/
|
|
289
|
+
async getRegistry(registryId: string): Promise<DokployRegistry> {
|
|
290
|
+
return this.get<DokployRegistry>(`registry.one?registryId=${registryId}`);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Update a registry
|
|
295
|
+
*/
|
|
296
|
+
async updateRegistry(
|
|
297
|
+
registryId: string,
|
|
298
|
+
updates: Partial<{
|
|
299
|
+
registryName: string;
|
|
300
|
+
registryUrl: string;
|
|
301
|
+
username: string;
|
|
302
|
+
password: string;
|
|
303
|
+
imagePrefix: string;
|
|
304
|
+
}>,
|
|
305
|
+
): Promise<void> {
|
|
306
|
+
await this.post('registry.update', { registryId, ...updates });
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Delete a registry
|
|
311
|
+
*/
|
|
312
|
+
async deleteRegistry(registryId: string): Promise<void> {
|
|
313
|
+
await this.post('registry.remove', { registryId });
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// ============================================
|
|
317
|
+
// Postgres endpoints
|
|
318
|
+
// ============================================
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Create a new Postgres database
|
|
322
|
+
*/
|
|
323
|
+
async createPostgres(
|
|
324
|
+
name: string,
|
|
325
|
+
projectId: string,
|
|
326
|
+
environmentId: string,
|
|
327
|
+
options?: {
|
|
328
|
+
appName?: string;
|
|
329
|
+
databaseName?: string;
|
|
330
|
+
databaseUser?: string;
|
|
331
|
+
databasePassword?: string;
|
|
332
|
+
dockerImage?: string;
|
|
333
|
+
description?: string;
|
|
334
|
+
},
|
|
335
|
+
): Promise<DokployPostgres> {
|
|
336
|
+
return this.post<DokployPostgres>('postgres.create', {
|
|
337
|
+
name,
|
|
338
|
+
projectId,
|
|
339
|
+
environmentId,
|
|
340
|
+
appName:
|
|
341
|
+
options?.appName ?? name.toLowerCase().replace(/[^a-z0-9-]/g, '-'),
|
|
342
|
+
databaseName: options?.databaseName ?? 'app',
|
|
343
|
+
databaseUser: options?.databaseUser ?? 'postgres',
|
|
344
|
+
databasePassword: options?.databasePassword,
|
|
345
|
+
dockerImage: options?.dockerImage ?? 'postgres:16-alpine',
|
|
346
|
+
description: options?.description ?? `Postgres database for ${name}`,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Get a Postgres database by ID
|
|
352
|
+
*/
|
|
353
|
+
async getPostgres(postgresId: string): Promise<DokployPostgres> {
|
|
354
|
+
return this.get<DokployPostgres>(`postgres.one?postgresId=${postgresId}`);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Deploy a Postgres database
|
|
359
|
+
*/
|
|
360
|
+
async deployPostgres(postgresId: string): Promise<void> {
|
|
361
|
+
await this.post('postgres.deploy', { postgresId });
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Save environment variables for Postgres
|
|
366
|
+
*/
|
|
367
|
+
async savePostgresEnv(postgresId: string, env: string): Promise<void> {
|
|
368
|
+
await this.post('postgres.saveEnvironment', { postgresId, env });
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Set external port for Postgres (for external access)
|
|
373
|
+
*/
|
|
374
|
+
async savePostgresExternalPort(
|
|
375
|
+
postgresId: string,
|
|
376
|
+
externalPort: number | null,
|
|
377
|
+
): Promise<void> {
|
|
378
|
+
await this.post('postgres.saveExternalPort', { postgresId, externalPort });
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Update Postgres configuration
|
|
383
|
+
*/
|
|
384
|
+
async updatePostgres(
|
|
385
|
+
postgresId: string,
|
|
386
|
+
updates: Partial<DokployPostgresUpdate>,
|
|
387
|
+
): Promise<void> {
|
|
388
|
+
await this.post('postgres.update', { postgresId, ...updates });
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// ============================================
|
|
392
|
+
// Redis endpoints
|
|
393
|
+
// ============================================
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Create a new Redis instance
|
|
397
|
+
*/
|
|
398
|
+
async createRedis(
|
|
399
|
+
name: string,
|
|
400
|
+
projectId: string,
|
|
401
|
+
environmentId: string,
|
|
402
|
+
options?: {
|
|
403
|
+
appName?: string;
|
|
404
|
+
databasePassword?: string;
|
|
405
|
+
dockerImage?: string;
|
|
406
|
+
description?: string;
|
|
407
|
+
},
|
|
408
|
+
): Promise<DokployRedis> {
|
|
409
|
+
return this.post<DokployRedis>('redis.create', {
|
|
410
|
+
name,
|
|
411
|
+
projectId,
|
|
412
|
+
environmentId,
|
|
413
|
+
appName:
|
|
414
|
+
options?.appName ?? name.toLowerCase().replace(/[^a-z0-9-]/g, '-'),
|
|
415
|
+
databasePassword: options?.databasePassword,
|
|
416
|
+
dockerImage: options?.dockerImage ?? 'redis:7-alpine',
|
|
417
|
+
description: options?.description ?? `Redis instance for ${name}`,
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Get a Redis instance by ID
|
|
423
|
+
*/
|
|
424
|
+
async getRedis(redisId: string): Promise<DokployRedis> {
|
|
425
|
+
return this.get<DokployRedis>(`redis.one?redisId=${redisId}`);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Deploy a Redis instance
|
|
430
|
+
*/
|
|
431
|
+
async deployRedis(redisId: string): Promise<void> {
|
|
432
|
+
await this.post('redis.deploy', { redisId });
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Save environment variables for Redis
|
|
437
|
+
*/
|
|
438
|
+
async saveRedisEnv(redisId: string, env: string): Promise<void> {
|
|
439
|
+
await this.post('redis.saveEnvironment', { redisId, env });
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Set external port for Redis (for external access)
|
|
444
|
+
*/
|
|
445
|
+
async saveRedisExternalPort(
|
|
446
|
+
redisId: string,
|
|
447
|
+
externalPort: number | null,
|
|
448
|
+
): Promise<void> {
|
|
449
|
+
await this.post('redis.saveExternalPort', { redisId, externalPort });
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Update Redis configuration
|
|
454
|
+
*/
|
|
455
|
+
async updateRedis(
|
|
456
|
+
redisId: string,
|
|
457
|
+
updates: Partial<DokployRedisUpdate>,
|
|
458
|
+
): Promise<void> {
|
|
459
|
+
await this.post('redis.update', { redisId, ...updates });
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// ============================================
|
|
464
|
+
// Type definitions for Dokploy API responses
|
|
465
|
+
// ============================================
|
|
466
|
+
|
|
467
|
+
export interface DokployProject {
|
|
468
|
+
projectId: string;
|
|
469
|
+
name: string;
|
|
470
|
+
description: string | null;
|
|
471
|
+
createdAt?: string;
|
|
472
|
+
adminId?: string;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
export interface DokployEnvironment {
|
|
476
|
+
environmentId: string;
|
|
477
|
+
name: string;
|
|
478
|
+
description: string | null;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
export interface DokployProjectDetails extends DokployProject {
|
|
482
|
+
environments: DokployEnvironment[];
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
export interface DokployApplication {
|
|
486
|
+
applicationId: string;
|
|
487
|
+
name: string;
|
|
488
|
+
appName: string;
|
|
489
|
+
projectId: string;
|
|
490
|
+
environmentId?: string;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
export interface DokployApplicationUpdate {
|
|
494
|
+
registryId: string;
|
|
495
|
+
dockerImage: string;
|
|
496
|
+
sourceType: 'docker';
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
export interface DokployRegistry {
|
|
500
|
+
registryId: string;
|
|
501
|
+
registryName: string;
|
|
502
|
+
registryUrl: string;
|
|
503
|
+
username: string;
|
|
504
|
+
imagePrefix: string | null;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
export interface DokployPostgres {
|
|
508
|
+
postgresId: string;
|
|
509
|
+
name: string;
|
|
510
|
+
appName: string;
|
|
511
|
+
databaseName: string;
|
|
512
|
+
databaseUser: string;
|
|
513
|
+
databasePassword: string;
|
|
514
|
+
dockerImage: string;
|
|
515
|
+
description: string | null;
|
|
516
|
+
projectId: string;
|
|
517
|
+
environmentId: string;
|
|
518
|
+
applicationStatus: 'idle' | 'running' | 'done' | 'error';
|
|
519
|
+
externalPort: number | null;
|
|
520
|
+
createdAt?: string;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
export interface DokployPostgresUpdate {
|
|
524
|
+
name: string;
|
|
525
|
+
appName: string;
|
|
526
|
+
databaseName: string;
|
|
527
|
+
databaseUser: string;
|
|
528
|
+
databasePassword: string;
|
|
529
|
+
dockerImage: string;
|
|
530
|
+
description: string;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
export interface DokployRedis {
|
|
534
|
+
redisId: string;
|
|
535
|
+
name: string;
|
|
536
|
+
appName: string;
|
|
537
|
+
databasePassword: string;
|
|
538
|
+
dockerImage: string;
|
|
539
|
+
description: string | null;
|
|
540
|
+
projectId: string;
|
|
541
|
+
environmentId: string;
|
|
542
|
+
applicationStatus: 'idle' | 'running' | 'done' | 'error';
|
|
543
|
+
externalPort: number | null;
|
|
544
|
+
createdAt?: string;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
export interface DokployRedisUpdate {
|
|
548
|
+
name: string;
|
|
549
|
+
appName: string;
|
|
550
|
+
databasePassword: string;
|
|
551
|
+
dockerImage: string;
|
|
552
|
+
description: string;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Create a Dokploy API client from stored credentials or environment
|
|
557
|
+
*/
|
|
558
|
+
export async function createDokployApi(
|
|
559
|
+
endpoint?: string,
|
|
560
|
+
): Promise<DokployApi | null> {
|
|
561
|
+
const { getDokployCredentials } = await import('../auth/credentials');
|
|
562
|
+
|
|
563
|
+
// Try environment variable first
|
|
564
|
+
const envToken = process.env.DOKPLOY_API_TOKEN;
|
|
565
|
+
const envEndpoint = endpoint || process.env.DOKPLOY_ENDPOINT;
|
|
566
|
+
|
|
567
|
+
if (envToken && envEndpoint) {
|
|
568
|
+
return new DokployApi({ baseUrl: envEndpoint, token: envToken });
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// Fall back to stored credentials
|
|
572
|
+
const creds = await getDokployCredentials();
|
|
573
|
+
if (creds) {
|
|
574
|
+
return new DokployApi({
|
|
575
|
+
baseUrl: endpoint || creds.endpoint,
|
|
576
|
+
token: creds.token,
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
return null;
|
|
581
|
+
}
|