@geekmidas/cli 0.13.0 → 0.14.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 (79) hide show
  1. package/dist/{bundler-B1qy9b-j.cjs → bundler-BjholBlA.cjs} +26 -7
  2. package/dist/bundler-BjholBlA.cjs.map +1 -0
  3. package/dist/{bundler-DskIqW2t.mjs → bundler-DWctKN1z.mjs} +27 -8
  4. package/dist/bundler-DWctKN1z.mjs.map +1 -0
  5. package/dist/config.d.cts +1 -1
  6. package/dist/config.d.mts +1 -1
  7. package/dist/dokploy-api-B7KxOQr3.cjs +3 -0
  8. package/dist/dokploy-api-C7F9VykY.cjs +317 -0
  9. package/dist/dokploy-api-C7F9VykY.cjs.map +1 -0
  10. package/dist/dokploy-api-CaETb2L6.mjs +305 -0
  11. package/dist/dokploy-api-CaETb2L6.mjs.map +1 -0
  12. package/dist/dokploy-api-DHvfmWbi.mjs +3 -0
  13. package/dist/{encryption-Dyf_r1h-.cjs → encryption-D7Efcdi9.cjs} +1 -1
  14. package/dist/{encryption-Dyf_r1h-.cjs.map → encryption-D7Efcdi9.cjs.map} +1 -1
  15. package/dist/{encryption-C8H-38Yy.mjs → encryption-h4Nb6W-M.mjs} +1 -1
  16. package/dist/{encryption-C8H-38Yy.mjs.map → encryption-h4Nb6W-M.mjs.map} +1 -1
  17. package/dist/index.cjs +1513 -1136
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.mjs +1513 -1136
  20. package/dist/index.mjs.map +1 -1
  21. package/dist/{openapi-Bt_1FDpT.cjs → openapi-C89hhkZC.cjs} +3 -3
  22. package/dist/{openapi-Bt_1FDpT.cjs.map → openapi-C89hhkZC.cjs.map} +1 -1
  23. package/dist/{openapi-BfFlOBCG.mjs → openapi-CZVcfxk-.mjs} +3 -3
  24. package/dist/{openapi-BfFlOBCG.mjs.map → openapi-CZVcfxk-.mjs.map} +1 -1
  25. package/dist/{openapi-react-query-B6XTeGqS.mjs → openapi-react-query-CM2_qlW9.mjs} +1 -1
  26. package/dist/{openapi-react-query-B6XTeGqS.mjs.map → openapi-react-query-CM2_qlW9.mjs.map} +1 -1
  27. package/dist/{openapi-react-query-B-sNWHFU.cjs → openapi-react-query-iKjfLzff.cjs} +1 -1
  28. package/dist/{openapi-react-query-B-sNWHFU.cjs.map → openapi-react-query-iKjfLzff.cjs.map} +1 -1
  29. package/dist/openapi-react-query.cjs +1 -1
  30. package/dist/openapi-react-query.mjs +1 -1
  31. package/dist/openapi.cjs +1 -1
  32. package/dist/openapi.d.cts +1 -1
  33. package/dist/openapi.d.mts +1 -1
  34. package/dist/openapi.mjs +1 -1
  35. package/dist/{storage-kSxTjkNb.mjs → storage-BaOP55oq.mjs} +16 -2
  36. package/dist/storage-BaOP55oq.mjs.map +1 -0
  37. package/dist/{storage-Bj1E26lU.cjs → storage-Bn3K9Ccu.cjs} +21 -1
  38. package/dist/storage-Bn3K9Ccu.cjs.map +1 -0
  39. package/dist/storage-UfyTn7Zm.cjs +7 -0
  40. package/dist/storage-nkGIjeXt.mjs +3 -0
  41. package/dist/{types-BhkZc-vm.d.cts → types-BgaMXsUa.d.cts} +3 -1
  42. package/dist/{types-BR0M2v_c.d.mts.map → types-BgaMXsUa.d.cts.map} +1 -1
  43. package/dist/{types-BR0M2v_c.d.mts → types-iFk5ms7y.d.mts} +3 -1
  44. package/dist/{types-BhkZc-vm.d.cts.map → types-iFk5ms7y.d.mts.map} +1 -1
  45. package/package.json +3 -3
  46. package/src/auth/__tests__/credentials.spec.ts +127 -0
  47. package/src/auth/__tests__/index.spec.ts +69 -0
  48. package/src/auth/credentials.ts +33 -0
  49. package/src/auth/index.ts +57 -50
  50. package/src/build/__tests__/bundler.spec.ts +1 -1
  51. package/src/build/__tests__/endpoint-analyzer.spec.ts +623 -0
  52. package/src/build/__tests__/handler-templates.spec.ts +272 -0
  53. package/src/build/bundler.ts +53 -4
  54. package/src/build/index.ts +21 -0
  55. package/src/build/types.ts +6 -0
  56. package/src/deploy/__tests__/dokploy-api.spec.ts +698 -0
  57. package/src/deploy/__tests__/dokploy.spec.ts +196 -6
  58. package/src/deploy/__tests__/index.spec.ts +339 -0
  59. package/src/deploy/__tests__/init.spec.ts +147 -16
  60. package/src/deploy/docker.ts +32 -3
  61. package/src/deploy/dokploy-api.ts +581 -0
  62. package/src/deploy/dokploy.ts +66 -93
  63. package/src/deploy/index.ts +587 -32
  64. package/src/deploy/init.ts +192 -249
  65. package/src/deploy/types.ts +19 -1
  66. package/src/dev/__tests__/index.spec.ts +95 -0
  67. package/src/docker/__tests__/templates.spec.ts +144 -0
  68. package/src/docker/index.ts +96 -6
  69. package/src/docker/templates.ts +114 -27
  70. package/src/generators/EndpointGenerator.ts +2 -2
  71. package/src/index.ts +34 -13
  72. package/src/secrets/storage.ts +15 -0
  73. package/src/types.ts +2 -0
  74. package/dist/bundler-B1qy9b-j.cjs.map +0 -1
  75. package/dist/bundler-DskIqW2t.mjs.map +0 -1
  76. package/dist/storage-BOOpAF8N.cjs +0 -5
  77. package/dist/storage-Bj1E26lU.cjs.map +0 -1
  78. package/dist/storage-kSxTjkNb.mjs.map +0 -1
  79. package/dist/storage-tgZSUnKl.mjs +0 -3
@@ -41,7 +41,7 @@ describe('Dokploy API interactions', () => {
41
41
  method: 'GET',
42
42
  headers: {
43
43
  'Content-Type': 'application/json',
44
- Authorization: 'Bearer test-token',
44
+ 'x-api-key': 'test-token',
45
45
  },
46
46
  },
47
47
  );
@@ -62,11 +62,18 @@ describe('Dokploy API interactions', () => {
62
62
  description?: string;
63
63
  };
64
64
  return HttpResponse.json({
65
- projectId: 'proj_new',
66
- name: body.name,
67
- description: body.description || null,
68
- createdAt: new Date().toISOString(),
69
- adminId: 'admin_1',
65
+ project: {
66
+ projectId: 'proj_new',
67
+ name: body.name,
68
+ description: body.description || null,
69
+ createdAt: new Date().toISOString(),
70
+ adminId: 'admin_1',
71
+ },
72
+ environment: {
73
+ environmentId: 'env_default',
74
+ name: 'production',
75
+ description: 'Production environment',
76
+ },
70
77
  });
71
78
  },
72
79
  ),
@@ -78,7 +85,7 @@ describe('Dokploy API interactions', () => {
78
85
  method: 'POST',
79
86
  headers: {
80
87
  'Content-Type': 'application/json',
81
- Authorization: 'Bearer test-token',
88
+ 'x-api-key': 'test-token',
82
89
  },
83
90
  body: JSON.stringify({
84
91
  name: 'New Project',
@@ -88,9 +95,10 @@ describe('Dokploy API interactions', () => {
88
95
  );
89
96
 
90
97
  expect(response.ok).toBe(true);
91
- const project = await response.json();
92
- expect(project.projectId).toBe('proj_new');
93
- expect(project.name).toBe('New Project');
98
+ const result = await response.json();
99
+ expect(result.project.projectId).toBe('proj_new');
100
+ expect(result.project.name).toBe('New Project');
101
+ expect(result.environment.environmentId).toBe('env_default');
94
102
  });
95
103
 
96
104
  it('should get a single project', async () => {
@@ -120,7 +128,7 @@ describe('Dokploy API interactions', () => {
120
128
  method: 'POST',
121
129
  headers: {
122
130
  'Content-Type': 'application/json',
123
- Authorization: 'Bearer test-token',
131
+ 'x-api-key': 'test-token',
124
132
  },
125
133
  body: JSON.stringify({ projectId: 'proj_1' }),
126
134
  },
@@ -159,7 +167,7 @@ describe('Dokploy API interactions', () => {
159
167
  method: 'POST',
160
168
  headers: {
161
169
  'Content-Type': 'application/json',
162
- Authorization: 'Bearer test-token',
170
+ 'x-api-key': 'test-token',
163
171
  },
164
172
  body: JSON.stringify({
165
173
  name: 'api',
@@ -194,7 +202,7 @@ describe('Dokploy API interactions', () => {
194
202
  method: 'POST',
195
203
  headers: {
196
204
  'Content-Type': 'application/json',
197
- Authorization: 'Bearer test-token',
205
+ 'x-api-key': 'test-token',
198
206
  },
199
207
  body: JSON.stringify({
200
208
  applicationId: 'app_1',
@@ -229,7 +237,7 @@ describe('Dokploy API interactions', () => {
229
237
  method: 'GET',
230
238
  headers: {
231
239
  'Content-Type': 'application/json',
232
- Authorization: 'Bearer test-token',
240
+ 'x-api-key': 'test-token',
233
241
  },
234
242
  },
235
243
  );
@@ -265,7 +273,7 @@ describe('Dokploy API interactions', () => {
265
273
  method: 'POST',
266
274
  headers: {
267
275
  'Content-Type': 'application/json',
268
- Authorization: 'Bearer test-token',
276
+ 'x-api-key': 'test-token',
269
277
  },
270
278
  body: JSON.stringify({
271
279
  projectId: 'proj_1',
@@ -298,7 +306,7 @@ describe('Dokploy API interactions', () => {
298
306
  method: 'GET',
299
307
  headers: {
300
308
  'Content-Type': 'application/json',
301
- Authorization: 'Bearer invalid-token',
309
+ 'x-api-key': 'invalid-token',
302
310
  },
303
311
  },
304
312
  );
@@ -659,4 +667,127 @@ export default defineConfig({
659
667
  ),
660
668
  ).resolves.toBeUndefined();
661
669
  });
670
+
671
+ it('should include registryId when provided', async () => {
672
+ const configPath = join(tempDir, 'gkm.config.ts');
673
+ await writeFile(
674
+ configPath,
675
+ `import { defineConfig } from '@geekmidas/cli';
676
+
677
+ export default defineConfig({
678
+ routes: 'src/endpoints/**/*.ts',
679
+ envParser: './src/env.ts',
680
+ });`,
681
+ );
682
+
683
+ await updateConfig(
684
+ {
685
+ endpoint: 'https://dokploy.example.com',
686
+ projectId: 'proj_123',
687
+ applicationId: 'app_456',
688
+ registryId: 'reg_789',
689
+ },
690
+ tempDir,
691
+ );
692
+
693
+ const content = await readFile(configPath, 'utf-8');
694
+ expect(content).toContain("registryId: 'reg_789'");
695
+ expect(content).toContain("endpoint: 'https://dokploy.example.com'");
696
+ expect(content).toContain("projectId: 'proj_123'");
697
+ expect(content).toContain("applicationId: 'app_456'");
698
+ });
699
+
700
+ it('should omit registryId when not provided', async () => {
701
+ const configPath = join(tempDir, 'gkm.config.ts');
702
+ await writeFile(
703
+ configPath,
704
+ `import { defineConfig } from '@geekmidas/cli';
705
+
706
+ export default defineConfig({
707
+ routes: 'src/endpoints/**/*.ts',
708
+ });`,
709
+ );
710
+
711
+ await updateConfig(
712
+ {
713
+ endpoint: 'https://dokploy.example.com',
714
+ projectId: 'proj_123',
715
+ applicationId: 'app_456',
716
+ },
717
+ tempDir,
718
+ );
719
+
720
+ const content = await readFile(configPath, 'utf-8');
721
+ expect(content).not.toContain('registryId:');
722
+ });
723
+
724
+ it('should update existing dokploy config with registryId', async () => {
725
+ const configPath = join(tempDir, 'gkm.config.ts');
726
+ await writeFile(
727
+ configPath,
728
+ `import { defineConfig } from '@geekmidas/cli';
729
+
730
+ export default defineConfig({
731
+ routes: 'src/endpoints/**/*.ts',
732
+ providers: {
733
+ dokploy: {
734
+ endpoint: 'https://old.dokploy.com',
735
+ projectId: 'old_proj',
736
+ applicationId: 'old_app',
737
+ },
738
+ },
739
+ });`,
740
+ );
741
+
742
+ await updateConfig(
743
+ {
744
+ endpoint: 'https://new.dokploy.com',
745
+ projectId: 'new_proj',
746
+ applicationId: 'new_app',
747
+ registryId: 'new_reg',
748
+ },
749
+ tempDir,
750
+ );
751
+
752
+ const content = await readFile(configPath, 'utf-8');
753
+ expect(content).toContain("registryId: 'new_reg'");
754
+ expect(content).toContain("endpoint: 'https://new.dokploy.com'");
755
+ expect(content).not.toContain('old.dokploy.com');
756
+ });
757
+
758
+ it('should preserve existing config with multi-line dokploy that has registryId', async () => {
759
+ const configPath = join(tempDir, 'gkm.config.ts');
760
+ await writeFile(
761
+ configPath,
762
+ `import { defineConfig } from '@geekmidas/cli';
763
+
764
+ export default defineConfig({
765
+ routes: 'src/endpoints/**/*.ts',
766
+ providers: {
767
+ dokploy: {
768
+ endpoint: 'https://old.dokploy.com',
769
+ projectId: 'old_proj',
770
+ applicationId: 'old_app',
771
+ registryId: 'old_reg',
772
+ },
773
+ },
774
+ });`,
775
+ );
776
+
777
+ await updateConfig(
778
+ {
779
+ endpoint: 'https://new.dokploy.com',
780
+ projectId: 'new_proj',
781
+ applicationId: 'new_app',
782
+ registryId: 'new_reg',
783
+ },
784
+ tempDir,
785
+ );
786
+
787
+ const content = await readFile(configPath, 'utf-8');
788
+ expect(content).toContain("registryId: 'new_reg'");
789
+ expect(content).toContain("endpoint: 'https://new.dokploy.com'");
790
+ expect(content).not.toContain('old.dokploy.com');
791
+ expect(content).not.toContain('old_reg');
792
+ });
662
793
  });
@@ -1,5 +1,6 @@
1
1
  import { execSync } from 'node:child_process';
2
- import type { GkmConfig } from '../types';
2
+ import { dirname, join, relative } from 'node:path';
3
+ import { dockerCommand, findLockfilePath, isMonorepo } from '../docker';
3
4
  import type { DeployResult, DockerDeployConfig } from './types';
4
5
 
5
6
  const logger = console;
@@ -37,11 +38,39 @@ export function getImageRef(
37
38
  async function buildImage(imageRef: string): Promise<void> {
38
39
  logger.log(`\n🔨 Building Docker image: ${imageRef}`);
39
40
 
41
+ const cwd = process.cwd();
42
+ const inMonorepo = isMonorepo(cwd);
43
+
44
+ // Generate appropriate Dockerfile
45
+ if (inMonorepo) {
46
+ logger.log(' Generating Dockerfile for monorepo (turbo prune)...');
47
+ } else {
48
+ logger.log(' Generating Dockerfile...');
49
+ }
50
+ await dockerCommand({});
51
+
52
+ // Determine build context and Dockerfile path
53
+ let buildCwd = cwd;
54
+ let dockerfilePath = '.gkm/docker/Dockerfile';
55
+
56
+ if (inMonorepo) {
57
+ // For monorepos, build from root so turbo prune can access all packages
58
+ const lockfilePath = findLockfilePath(cwd);
59
+ if (lockfilePath) {
60
+ const monorepoRoot = dirname(lockfilePath);
61
+ const appRelPath = relative(monorepoRoot, cwd);
62
+ dockerfilePath = join(appRelPath, '.gkm/docker/Dockerfile');
63
+ buildCwd = monorepoRoot;
64
+ logger.log(` Building from monorepo root: ${monorepoRoot}`);
65
+ }
66
+ }
67
+
40
68
  try {
69
+ // Build for linux/amd64 to ensure compatibility with most cloud servers
41
70
  execSync(
42
- `DOCKER_BUILDKIT=1 docker build -f .gkm/docker/Dockerfile -t ${imageRef} .`,
71
+ `DOCKER_BUILDKIT=1 docker build --platform linux/amd64 -f ${dockerfilePath} -t ${imageRef} .`,
43
72
  {
44
- cwd: process.cwd(),
73
+ cwd: buildCwd,
45
74
  stdio: 'inherit',
46
75
  env: { ...process.env, DOCKER_BUILDKIT: '1' },
47
76
  },