@geekmidas/cli 0.10.0 → 0.13.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.
Files changed (146) hide show
  1. package/README.md +525 -0
  2. package/dist/bundler-B1qy9b-j.cjs +112 -0
  3. package/dist/bundler-B1qy9b-j.cjs.map +1 -0
  4. package/dist/bundler-DskIqW2t.mjs +111 -0
  5. package/dist/bundler-DskIqW2t.mjs.map +1 -0
  6. package/dist/{config-C9aXOHBe.cjs → config-AmInkU7k.cjs} +8 -8
  7. package/dist/config-AmInkU7k.cjs.map +1 -0
  8. package/dist/{config-BrkUalUh.mjs → config-DYULeEv8.mjs} +3 -3
  9. package/dist/config-DYULeEv8.mjs.map +1 -0
  10. package/dist/config.cjs +1 -1
  11. package/dist/config.d.cts +1 -1
  12. package/dist/config.d.mts +1 -1
  13. package/dist/config.mjs +1 -1
  14. package/dist/encryption-C8H-38Yy.mjs +42 -0
  15. package/dist/encryption-C8H-38Yy.mjs.map +1 -0
  16. package/dist/encryption-Dyf_r1h-.cjs +44 -0
  17. package/dist/encryption-Dyf_r1h-.cjs.map +1 -0
  18. package/dist/index.cjs +2123 -179
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.mjs +2141 -192
  21. package/dist/index.mjs.map +1 -1
  22. package/dist/{openapi-CZLI4QTr.mjs → openapi-BfFlOBCG.mjs} +801 -38
  23. package/dist/openapi-BfFlOBCG.mjs.map +1 -0
  24. package/dist/{openapi-BeHLKcwP.cjs → openapi-Bt_1FDpT.cjs} +794 -31
  25. package/dist/openapi-Bt_1FDpT.cjs.map +1 -0
  26. package/dist/{openapi-react-query-o5iMi8tz.cjs → openapi-react-query-B-sNWHFU.cjs} +5 -5
  27. package/dist/openapi-react-query-B-sNWHFU.cjs.map +1 -0
  28. package/dist/{openapi-react-query-CcciaVu5.mjs → openapi-react-query-B6XTeGqS.mjs} +5 -5
  29. package/dist/openapi-react-query-B6XTeGqS.mjs.map +1 -0
  30. package/dist/openapi-react-query.cjs +1 -1
  31. package/dist/openapi-react-query.d.cts.map +1 -1
  32. package/dist/openapi-react-query.d.mts.map +1 -1
  33. package/dist/openapi-react-query.mjs +1 -1
  34. package/dist/openapi.cjs +2 -2
  35. package/dist/openapi.d.cts +1 -1
  36. package/dist/openapi.d.cts.map +1 -1
  37. package/dist/openapi.d.mts +1 -1
  38. package/dist/openapi.d.mts.map +1 -1
  39. package/dist/openapi.mjs +2 -2
  40. package/dist/storage-BOOpAF8N.cjs +5 -0
  41. package/dist/storage-Bj1E26lU.cjs +187 -0
  42. package/dist/storage-Bj1E26lU.cjs.map +1 -0
  43. package/dist/storage-kSxTjkNb.mjs +133 -0
  44. package/dist/storage-kSxTjkNb.mjs.map +1 -0
  45. package/dist/storage-tgZSUnKl.mjs +3 -0
  46. package/dist/{types-b-vwGpqc.d.cts → types-BR0M2v_c.d.mts} +100 -1
  47. package/dist/types-BR0M2v_c.d.mts.map +1 -0
  48. package/dist/{types-DXgiA1sF.d.mts → types-BhkZc-vm.d.cts} +100 -1
  49. package/dist/types-BhkZc-vm.d.cts.map +1 -0
  50. package/examples/cron-example.ts +27 -27
  51. package/examples/env.ts +27 -27
  52. package/examples/function-example.ts +31 -31
  53. package/examples/gkm.config.json +20 -20
  54. package/examples/gkm.config.ts +8 -8
  55. package/examples/gkm.minimal.config.json +5 -5
  56. package/examples/gkm.production.config.json +25 -25
  57. package/examples/logger.ts +2 -2
  58. package/package.json +6 -6
  59. package/src/__tests__/EndpointGenerator.hooks.spec.ts +191 -191
  60. package/src/__tests__/config.spec.ts +55 -55
  61. package/src/__tests__/loadEnvFiles.spec.ts +93 -93
  62. package/src/__tests__/normalizeHooksConfig.spec.ts +58 -58
  63. package/src/__tests__/openapi-react-query.spec.ts +497 -497
  64. package/src/__tests__/openapi.spec.ts +428 -428
  65. package/src/__tests__/test-helpers.ts +76 -76
  66. package/src/auth/__tests__/credentials.spec.ts +204 -0
  67. package/src/auth/__tests__/index.spec.ts +168 -0
  68. package/src/auth/credentials.ts +187 -0
  69. package/src/auth/index.ts +226 -0
  70. package/src/build/__tests__/bundler.spec.ts +444 -0
  71. package/src/build/__tests__/index-new.spec.ts +474 -474
  72. package/src/build/__tests__/manifests.spec.ts +333 -333
  73. package/src/build/bundler.ts +210 -0
  74. package/src/build/endpoint-analyzer.ts +236 -0
  75. package/src/build/handler-templates.ts +1253 -0
  76. package/src/build/index.ts +260 -179
  77. package/src/build/manifests.ts +52 -52
  78. package/src/build/providerResolver.ts +145 -145
  79. package/src/build/types.ts +64 -43
  80. package/src/config.ts +39 -39
  81. package/src/deploy/__tests__/docker.spec.ts +111 -0
  82. package/src/deploy/__tests__/dokploy.spec.ts +245 -0
  83. package/src/deploy/__tests__/init.spec.ts +662 -0
  84. package/src/deploy/docker.ts +128 -0
  85. package/src/deploy/dokploy.ts +204 -0
  86. package/src/deploy/index.ts +136 -0
  87. package/src/deploy/init.ts +484 -0
  88. package/src/deploy/types.ts +48 -0
  89. package/src/dev/__tests__/index.spec.ts +266 -266
  90. package/src/dev/index.ts +647 -601
  91. package/src/docker/__tests__/compose.spec.ts +531 -0
  92. package/src/docker/__tests__/templates.spec.ts +280 -0
  93. package/src/docker/compose.ts +273 -0
  94. package/src/docker/index.ts +230 -0
  95. package/src/docker/templates.ts +446 -0
  96. package/src/generators/CronGenerator.ts +72 -72
  97. package/src/generators/EndpointGenerator.ts +699 -398
  98. package/src/generators/FunctionGenerator.ts +84 -84
  99. package/src/generators/Generator.ts +72 -72
  100. package/src/generators/OpenApiTsGenerator.ts +577 -577
  101. package/src/generators/SubscriberGenerator.ts +124 -124
  102. package/src/generators/__tests__/CronGenerator.spec.ts +433 -433
  103. package/src/generators/__tests__/EndpointGenerator.spec.ts +532 -382
  104. package/src/generators/__tests__/FunctionGenerator.spec.ts +244 -244
  105. package/src/generators/__tests__/SubscriberGenerator.spec.ts +397 -382
  106. package/src/generators/index.ts +4 -4
  107. package/src/index.ts +623 -201
  108. package/src/init/__tests__/generators.spec.ts +334 -334
  109. package/src/init/__tests__/init.spec.ts +332 -332
  110. package/src/init/__tests__/utils.spec.ts +89 -89
  111. package/src/init/generators/config.ts +175 -175
  112. package/src/init/generators/docker.ts +41 -41
  113. package/src/init/generators/env.ts +72 -72
  114. package/src/init/generators/index.ts +1 -1
  115. package/src/init/generators/models.ts +64 -64
  116. package/src/init/generators/monorepo.ts +161 -161
  117. package/src/init/generators/package.ts +71 -71
  118. package/src/init/generators/source.ts +6 -6
  119. package/src/init/index.ts +203 -208
  120. package/src/init/templates/api.ts +115 -115
  121. package/src/init/templates/index.ts +75 -75
  122. package/src/init/templates/minimal.ts +98 -98
  123. package/src/init/templates/serverless.ts +89 -89
  124. package/src/init/templates/worker.ts +98 -98
  125. package/src/init/utils.ts +54 -56
  126. package/src/openapi-react-query.ts +194 -194
  127. package/src/openapi.ts +63 -63
  128. package/src/secrets/__tests__/encryption.spec.ts +226 -0
  129. package/src/secrets/__tests__/generator.spec.ts +319 -0
  130. package/src/secrets/__tests__/index.spec.ts +91 -0
  131. package/src/secrets/__tests__/storage.spec.ts +611 -0
  132. package/src/secrets/encryption.ts +91 -0
  133. package/src/secrets/generator.ts +164 -0
  134. package/src/secrets/index.ts +383 -0
  135. package/src/secrets/storage.ts +192 -0
  136. package/src/secrets/types.ts +53 -0
  137. package/src/types.ts +295 -176
  138. package/tsdown.config.ts +11 -8
  139. package/dist/config-BrkUalUh.mjs.map +0 -1
  140. package/dist/config-C9aXOHBe.cjs.map +0 -1
  141. package/dist/openapi-BeHLKcwP.cjs.map +0 -1
  142. package/dist/openapi-CZLI4QTr.mjs.map +0 -1
  143. package/dist/openapi-react-query-CcciaVu5.mjs.map +0 -1
  144. package/dist/openapi-react-query-o5iMi8tz.cjs.map +0 -1
  145. package/dist/types-DXgiA1sF.d.mts.map +0 -1
  146. package/dist/types-b-vwGpqc.d.cts.map +0 -1
@@ -0,0 +1,128 @@
1
+ import { execSync } from 'node:child_process';
2
+ import type { GkmConfig } from '../types';
3
+ import type { DeployResult, DockerDeployConfig } from './types';
4
+
5
+ const logger = console;
6
+
7
+ export interface DockerDeployOptions {
8
+ /** Deployment stage */
9
+ stage: string;
10
+ /** Image tag */
11
+ tag: string;
12
+ /** Skip pushing to registry */
13
+ skipPush?: boolean;
14
+ /** Master key from build */
15
+ masterKey?: string;
16
+ /** Docker config from gkm.config */
17
+ config: DockerDeployConfig;
18
+ }
19
+
20
+ /**
21
+ * Get the full image reference
22
+ */
23
+ export function getImageRef(
24
+ registry: string | undefined,
25
+ imageName: string,
26
+ tag: string,
27
+ ): string {
28
+ if (registry) {
29
+ return `${registry}/${imageName}:${tag}`;
30
+ }
31
+ return `${imageName}:${tag}`;
32
+ }
33
+
34
+ /**
35
+ * Build Docker image
36
+ */
37
+ async function buildImage(imageRef: string): Promise<void> {
38
+ logger.log(`\n🔨 Building Docker image: ${imageRef}`);
39
+
40
+ try {
41
+ execSync(
42
+ `DOCKER_BUILDKIT=1 docker build -f .gkm/docker/Dockerfile -t ${imageRef} .`,
43
+ {
44
+ cwd: process.cwd(),
45
+ stdio: 'inherit',
46
+ env: { ...process.env, DOCKER_BUILDKIT: '1' },
47
+ },
48
+ );
49
+ logger.log(`✅ Image built: ${imageRef}`);
50
+ } catch (error) {
51
+ throw new Error(
52
+ `Failed to build Docker image: ${error instanceof Error ? error.message : 'Unknown error'}`,
53
+ );
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Push Docker image to registry
59
+ */
60
+ async function pushImage(imageRef: string): Promise<void> {
61
+ logger.log(`\n☁️ Pushing image: ${imageRef}`);
62
+
63
+ try {
64
+ execSync(`docker push ${imageRef}`, {
65
+ cwd: process.cwd(),
66
+ stdio: 'inherit',
67
+ });
68
+ logger.log(`✅ Image pushed: ${imageRef}`);
69
+ } catch (error) {
70
+ throw new Error(
71
+ `Failed to push Docker image: ${error instanceof Error ? error.message : 'Unknown error'}`,
72
+ );
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Deploy using Docker (build and optionally push image)
78
+ */
79
+ export async function deployDocker(
80
+ options: DockerDeployOptions,
81
+ ): Promise<DeployResult> {
82
+ const { stage, tag, skipPush, masterKey, config } = options;
83
+
84
+ const imageName = config.imageName ?? 'app';
85
+ const imageRef = getImageRef(config.registry, imageName, tag);
86
+
87
+ // Build image
88
+ await buildImage(imageRef);
89
+
90
+ // Push to registry if not skipped
91
+ if (!skipPush) {
92
+ if (!config.registry) {
93
+ logger.warn(
94
+ '\n⚠️ No registry configured. Use --skip-push or configure docker.registry in gkm.config.ts',
95
+ );
96
+ } else {
97
+ await pushImage(imageRef);
98
+ }
99
+ }
100
+
101
+ // Output deployment info
102
+ logger.log('\n✅ Docker deployment ready!');
103
+ logger.log(`\n📋 Deployment details:`);
104
+ logger.log(` Image: ${imageRef}`);
105
+ logger.log(` Stage: ${stage}`);
106
+
107
+ if (masterKey) {
108
+ logger.log(`\n🔐 Deploy with this environment variable:`);
109
+ logger.log(` GKM_MASTER_KEY=${masterKey}`);
110
+ logger.log('\n Example docker run:');
111
+ logger.log(` docker run -e GKM_MASTER_KEY=${masterKey} ${imageRef}`);
112
+ }
113
+
114
+ return {
115
+ imageRef,
116
+ masterKey,
117
+ };
118
+ }
119
+
120
+ /**
121
+ * Resolve Docker deploy config from gkm config
122
+ */
123
+ export function resolveDockerConfig(config: GkmConfig): DockerDeployConfig {
124
+ return {
125
+ registry: config.docker?.registry,
126
+ imageName: config.docker?.imageName,
127
+ };
128
+ }
@@ -0,0 +1,204 @@
1
+ import { getDokployToken } from '../auth';
2
+ import type { DeployResult, DokployDeployConfig } from './types';
3
+
4
+ const logger = console;
5
+
6
+ export interface DokployDeployOptions {
7
+ /** Deployment stage */
8
+ stage: string;
9
+ /** Image tag */
10
+ tag: string;
11
+ /** Image reference */
12
+ imageRef: string;
13
+ /** Master key from build */
14
+ masterKey?: string;
15
+ /** Dokploy config from gkm.config */
16
+ config: DokployDeployConfig;
17
+ }
18
+
19
+ interface DokployErrorResponse {
20
+ message: string;
21
+ code?: string;
22
+ issues?: Array<{ message: string }>;
23
+ }
24
+
25
+ /**
26
+ * Get the Dokploy API token from stored credentials or environment
27
+ */
28
+ async function getApiToken(): Promise<string> {
29
+ const token = await getDokployToken();
30
+ if (!token) {
31
+ throw new Error(
32
+ 'Dokploy credentials not found.\n' +
33
+ 'Run "gkm login --service dokploy" to authenticate, or set DOKPLOY_API_TOKEN.',
34
+ );
35
+ }
36
+ return token;
37
+ }
38
+
39
+ /**
40
+ * Make a request to the Dokploy API
41
+ */
42
+ async function dokployRequest<T>(
43
+ endpoint: string,
44
+ baseUrl: string,
45
+ token: string,
46
+ body: Record<string, unknown>,
47
+ ): Promise<T> {
48
+ const url = `${baseUrl}/api/${endpoint}`;
49
+
50
+ const response = await fetch(url, {
51
+ method: 'POST',
52
+ headers: {
53
+ 'Content-Type': 'application/json',
54
+ Authorization: `Bearer ${token}`,
55
+ },
56
+ body: JSON.stringify(body),
57
+ });
58
+
59
+ if (!response.ok) {
60
+ let errorMessage = `Dokploy API error: ${response.status} ${response.statusText}`;
61
+
62
+ try {
63
+ const errorBody = (await response.json()) as DokployErrorResponse;
64
+ if (errorBody.message) {
65
+ errorMessage = `Dokploy API error: ${errorBody.message}`;
66
+ }
67
+ if (errorBody.issues?.length) {
68
+ errorMessage += `\n Issues: ${errorBody.issues.map((i) => i.message).join(', ')}`;
69
+ }
70
+ } catch {
71
+ // Ignore JSON parse errors
72
+ }
73
+
74
+ throw new Error(errorMessage);
75
+ }
76
+
77
+ return response.json() as Promise<T>;
78
+ }
79
+
80
+ /**
81
+ * Update application environment variables
82
+ */
83
+ async function updateEnvironment(
84
+ baseUrl: string,
85
+ token: string,
86
+ applicationId: string,
87
+ envVars: Record<string, string>,
88
+ ): Promise<void> {
89
+ logger.log(' Updating environment variables...');
90
+
91
+ // Convert env vars to the format Dokploy expects (KEY=VALUE per line)
92
+ const envString = Object.entries(envVars)
93
+ .map(([key, value]) => `${key}=${value}`)
94
+ .join('\n');
95
+
96
+ await dokployRequest('application.update', baseUrl, token, {
97
+ applicationId,
98
+ env: envString,
99
+ });
100
+
101
+ logger.log(' ✓ Environment variables updated');
102
+ }
103
+
104
+ /**
105
+ * Trigger application deployment
106
+ */
107
+ async function triggerDeploy(
108
+ baseUrl: string,
109
+ token: string,
110
+ applicationId: string,
111
+ ): Promise<void> {
112
+ logger.log(' Triggering deployment...');
113
+
114
+ await dokployRequest('application.deploy', baseUrl, token, {
115
+ applicationId,
116
+ });
117
+
118
+ logger.log(' ✓ Deployment triggered');
119
+ }
120
+
121
+ /**
122
+ * Deploy to Dokploy
123
+ */
124
+ export async function deployDokploy(
125
+ options: DokployDeployOptions,
126
+ ): Promise<DeployResult> {
127
+ const { stage, imageRef, masterKey, config } = options;
128
+
129
+ logger.log(`\n🎯 Deploying to Dokploy...`);
130
+ logger.log(` Endpoint: ${config.endpoint}`);
131
+ logger.log(` Application: ${config.applicationId}`);
132
+
133
+ const token = await getApiToken();
134
+
135
+ // Prepare environment variables
136
+ const envVars: Record<string, string> = {};
137
+
138
+ if (masterKey) {
139
+ envVars.GKM_MASTER_KEY = masterKey;
140
+ }
141
+
142
+ // Update environment if we have variables to set
143
+ if (Object.keys(envVars).length > 0) {
144
+ await updateEnvironment(
145
+ config.endpoint,
146
+ token,
147
+ config.applicationId,
148
+ envVars,
149
+ );
150
+ }
151
+
152
+ // Trigger deployment
153
+ await triggerDeploy(config.endpoint, token, config.applicationId);
154
+
155
+ logger.log('\n✅ Dokploy deployment initiated!');
156
+ logger.log(`\n📋 Deployment details:`);
157
+ logger.log(` Image: ${imageRef}`);
158
+ logger.log(` Stage: ${stage}`);
159
+ logger.log(` Application ID: ${config.applicationId}`);
160
+
161
+ if (masterKey) {
162
+ logger.log(`\n🔐 GKM_MASTER_KEY has been set in Dokploy environment`);
163
+ }
164
+
165
+ // Construct the probable deployment URL
166
+ const deploymentUrl = `${config.endpoint}/project/${config.projectId}`;
167
+ logger.log(`\n🔗 View deployment: ${deploymentUrl}`);
168
+
169
+ return {
170
+ imageRef,
171
+ masterKey,
172
+ url: deploymentUrl,
173
+ };
174
+ }
175
+
176
+ /**
177
+ * Validate Dokploy configuration
178
+ */
179
+ export function validateDokployConfig(
180
+ config: Partial<DokployDeployConfig> | undefined,
181
+ ): config is DokployDeployConfig {
182
+ if (!config) {
183
+ return false;
184
+ }
185
+
186
+ const required = ['endpoint', 'projectId', 'applicationId'] as const;
187
+ const missing = required.filter((key) => !config[key]);
188
+
189
+ if (missing.length > 0) {
190
+ throw new Error(
191
+ `Missing Dokploy configuration: ${missing.join(', ')}\n` +
192
+ 'Configure in gkm.config.ts:\n' +
193
+ ' providers: {\n' +
194
+ ' dokploy: {\n' +
195
+ " endpoint: 'https://dokploy.example.com',\n" +
196
+ " projectId: 'proj_xxx',\n" +
197
+ " applicationId: 'app_xxx',\n" +
198
+ ' },\n' +
199
+ ' }',
200
+ );
201
+ }
202
+
203
+ return true;
204
+ }
@@ -0,0 +1,136 @@
1
+ import { buildCommand } from '../build/index';
2
+ import { loadConfig } from '../config';
3
+ import { deployDocker, resolveDockerConfig } from './docker';
4
+ import { deployDokploy, validateDokployConfig } from './dokploy';
5
+ import type { DeployOptions, DeployProvider, DeployResult } from './types';
6
+
7
+ const logger = console;
8
+
9
+ /**
10
+ * Generate image tag from stage and timestamp
11
+ */
12
+ function generateTag(stage: string): string {
13
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
14
+ return `${stage}-${timestamp}`;
15
+ }
16
+
17
+ /**
18
+ * Main deploy command
19
+ */
20
+ export async function deployCommand(
21
+ options: DeployOptions,
22
+ ): Promise<DeployResult> {
23
+ const { provider, stage, tag, skipPush, skipBuild } = options;
24
+
25
+ logger.log(`\n🚀 Deploying to ${provider}...`);
26
+ logger.log(` Stage: ${stage}`);
27
+
28
+ // Load config
29
+ const config = await loadConfig();
30
+
31
+ // Generate tag if not provided
32
+ const imageTag = tag ?? generateTag(stage);
33
+ logger.log(` Tag: ${imageTag}`);
34
+
35
+ // Build for production with secrets injection (unless skipped)
36
+ let masterKey: string | undefined;
37
+ if (!skipBuild) {
38
+ logger.log(`\n📦 Building for production...`);
39
+ const buildResult = await buildCommand({
40
+ provider: 'server',
41
+ production: true,
42
+ stage,
43
+ });
44
+ masterKey = buildResult.masterKey;
45
+ } else {
46
+ logger.log(`\n⏭️ Skipping build (--skip-build)`);
47
+ }
48
+
49
+ // Resolve docker config for image reference
50
+ const dockerConfig = resolveDockerConfig(config);
51
+ const imageName = dockerConfig.imageName ?? 'app';
52
+ const registry = dockerConfig.registry;
53
+ const imageRef = registry
54
+ ? `${registry}/${imageName}:${imageTag}`
55
+ : `${imageName}:${imageTag}`;
56
+
57
+ // Deploy based on provider
58
+ let result: DeployResult;
59
+
60
+ switch (provider) {
61
+ case 'docker': {
62
+ result = await deployDocker({
63
+ stage,
64
+ tag: imageTag,
65
+ skipPush,
66
+ masterKey,
67
+ config: dockerConfig,
68
+ });
69
+ break;
70
+ }
71
+
72
+ case 'dokploy': {
73
+ // Validate Dokploy config
74
+ const dokployConfigRaw = config.providers?.dokploy;
75
+ if (typeof dokployConfigRaw === 'boolean' || !dokployConfigRaw) {
76
+ throw new Error(
77
+ 'Dokploy provider requires configuration.\n' +
78
+ 'Configure in gkm.config.ts:\n' +
79
+ ' providers: {\n' +
80
+ ' dokploy: {\n' +
81
+ " endpoint: 'https://dokploy.example.com',\n" +
82
+ " projectId: 'proj_xxx',\n" +
83
+ " applicationId: 'app_xxx',\n" +
84
+ ' },\n' +
85
+ ' }',
86
+ );
87
+ }
88
+
89
+ // Validate required fields (throws if missing)
90
+ validateDokployConfig(dokployConfigRaw);
91
+ const dokployConfig = dokployConfigRaw;
92
+
93
+ // First build and push the Docker image
94
+ await deployDocker({
95
+ stage,
96
+ tag: imageTag,
97
+ skipPush: false, // Dokploy needs the image in registry
98
+ masterKey,
99
+ config: {
100
+ registry: dokployConfig.registry ?? dockerConfig.registry,
101
+ imageName: dockerConfig.imageName,
102
+ },
103
+ });
104
+
105
+ // Then trigger Dokploy deployment
106
+ result = await deployDokploy({
107
+ stage,
108
+ tag: imageTag,
109
+ imageRef,
110
+ masterKey,
111
+ config: dokployConfig,
112
+ });
113
+ break;
114
+ }
115
+
116
+ case 'aws-lambda': {
117
+ logger.log('\n⚠️ AWS Lambda deployment is not yet implemented.');
118
+ logger.log(' Use SST or AWS CDK for Lambda deployments.');
119
+ result = { imageRef, masterKey };
120
+ break;
121
+ }
122
+
123
+ default: {
124
+ throw new Error(
125
+ `Unknown deploy provider: ${provider}\n` +
126
+ 'Supported providers: docker, dokploy, aws-lambda',
127
+ );
128
+ }
129
+ }
130
+
131
+ logger.log('\n✅ Deployment complete!');
132
+
133
+ return result;
134
+ }
135
+
136
+ export type { DeployOptions, DeployProvider, DeployResult };