codecrypto-cli 1.0.7 → 1.0.9

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 (154) hide show
  1. package/dist/commands/auth.d.ts.map +1 -1
  2. package/dist/commands/auth.js +64 -7
  3. package/dist/commands/auth.js.map +1 -1
  4. package/dist/commands/deploy-sc.d.ts.map +1 -1
  5. package/dist/commands/deploy-sc.js +162 -0
  6. package/dist/commands/deploy-sc.js.map +1 -1
  7. package/dist/commands/deploy.d.ts.map +1 -1
  8. package/dist/commands/deploy.js +556 -18
  9. package/dist/commands/deploy.js.map +1 -1
  10. package/dist/commands/doctor.d.ts +3 -0
  11. package/dist/commands/doctor.d.ts.map +1 -0
  12. package/dist/commands/doctor.js +518 -0
  13. package/dist/commands/doctor.js.map +1 -0
  14. package/dist/index.js +2 -0
  15. package/dist/index.js.map +1 -1
  16. package/docker-build/Dockerfile +18 -0
  17. package/docker-build/standalone/.next/BUILD_ID +1 -0
  18. package/docker-build/standalone/.next/app-path-routes-manifest.json +6 -0
  19. package/docker-build/standalone/.next/build-manifest.json +19 -0
  20. package/docker-build/standalone/.next/package.json +1 -0
  21. package/docker-build/standalone/.next/prerender-manifest.json +114 -0
  22. package/docker-build/standalone/.next/required-server-files.json +164 -0
  23. package/docker-build/standalone/.next/routes-manifest.json +68 -0
  24. package/docker-build/standalone/.next/server/app/_global-error/page/app-paths-manifest.json +3 -0
  25. package/docker-build/standalone/.next/server/app/_global-error/page/build-manifest.json +16 -0
  26. package/docker-build/standalone/.next/server/app/_global-error/page/next-font-manifest.json +6 -0
  27. package/docker-build/standalone/.next/server/app/_global-error/page/react-loadable-manifest.json +1 -0
  28. package/docker-build/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +4 -0
  29. package/docker-build/standalone/.next/server/app/_global-error/page.js +11 -0
  30. package/docker-build/standalone/.next/server/app/_global-error/page.js.map +5 -0
  31. package/docker-build/standalone/.next/server/app/_global-error/page.js.nft.json +1 -0
  32. package/docker-build/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +2 -0
  33. package/docker-build/standalone/.next/server/app/_global-error.html +2 -0
  34. package/docker-build/standalone/.next/server/app/_global-error.meta +15 -0
  35. package/docker-build/standalone/.next/server/app/_global-error.rsc +13 -0
  36. package/docker-build/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +5 -0
  37. package/docker-build/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +13 -0
  38. package/docker-build/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +6 -0
  39. package/docker-build/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +4 -0
  40. package/docker-build/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -0
  41. package/docker-build/standalone/.next/server/app/_not-found/page/app-paths-manifest.json +3 -0
  42. package/docker-build/standalone/.next/server/app/_not-found/page/build-manifest.json +16 -0
  43. package/docker-build/standalone/.next/server/app/_not-found/page/next-font-manifest.json +11 -0
  44. package/docker-build/standalone/.next/server/app/_not-found/page/react-loadable-manifest.json +1 -0
  45. package/docker-build/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +4 -0
  46. package/docker-build/standalone/.next/server/app/_not-found/page.js +14 -0
  47. package/docker-build/standalone/.next/server/app/_not-found/page.js.map +5 -0
  48. package/docker-build/standalone/.next/server/app/_not-found/page.js.nft.json +1 -0
  49. package/docker-build/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +2 -0
  50. package/docker-build/standalone/.next/server/app/_not-found.html +1 -0
  51. package/docker-build/standalone/.next/server/app/_not-found.meta +16 -0
  52. package/docker-build/standalone/.next/server/app/_not-found.rsc +14 -0
  53. package/docker-build/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -0
  54. package/docker-build/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +6 -0
  55. package/docker-build/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +5 -0
  56. package/docker-build/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +5 -0
  57. package/docker-build/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +4 -0
  58. package/docker-build/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -0
  59. package/docker-build/standalone/.next/server/app/favicon.ico/route/app-paths-manifest.json +3 -0
  60. package/docker-build/standalone/.next/server/app/favicon.ico/route/build-manifest.json +11 -0
  61. package/docker-build/standalone/.next/server/app/favicon.ico/route.js +6 -0
  62. package/docker-build/standalone/.next/server/app/favicon.ico/route.js.map +5 -0
  63. package/docker-build/standalone/.next/server/app/favicon.ico/route.js.nft.json +1 -0
  64. package/docker-build/standalone/.next/server/app/favicon.ico.body +0 -0
  65. package/docker-build/standalone/.next/server/app/favicon.ico.meta +1 -0
  66. package/docker-build/standalone/.next/server/app/index.html +1 -0
  67. package/docker-build/standalone/.next/server/app/index.meta +14 -0
  68. package/docker-build/standalone/.next/server/app/index.rsc +16 -0
  69. package/docker-build/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +5 -0
  70. package/docker-build/standalone/.next/server/app/index.segments/_full.segment.rsc +16 -0
  71. package/docker-build/standalone/.next/server/app/index.segments/_head.segment.rsc +6 -0
  72. package/docker-build/standalone/.next/server/app/index.segments/_index.segment.rsc +5 -0
  73. package/docker-build/standalone/.next/server/app/index.segments/_tree.segment.rsc +4 -0
  74. package/docker-build/standalone/.next/server/app/page/app-paths-manifest.json +3 -0
  75. package/docker-build/standalone/.next/server/app/page/build-manifest.json +16 -0
  76. package/docker-build/standalone/.next/server/app/page/next-font-manifest.json +11 -0
  77. package/docker-build/standalone/.next/server/app/page/react-loadable-manifest.json +1 -0
  78. package/docker-build/standalone/.next/server/app/page/server-reference-manifest.json +4 -0
  79. package/docker-build/standalone/.next/server/app/page.js +16 -0
  80. package/docker-build/standalone/.next/server/app/page.js.map +5 -0
  81. package/docker-build/standalone/.next/server/app/page.js.nft.json +1 -0
  82. package/docker-build/standalone/.next/server/app/page_client-reference-manifest.js +2 -0
  83. package/docker-build/standalone/.next/server/app-paths-manifest.json +6 -0
  84. package/docker-build/standalone/.next/server/chunks/66d90_example-navidad__next-internal_server_app_favicon_ico_route_actions_a30dceae.js +3 -0
  85. package/docker-build/standalone/.next/server/chunks/[externals]_next_dist_03fe02e0._.js +3 -0
  86. package/docker-build/standalone/.next/server/chunks/[root-of-the-server]__4b49000d._.js +21 -0
  87. package/docker-build/standalone/.next/server/chunks/[turbopack]_runtime.js +795 -0
  88. package/docker-build/standalone/.next/server/chunks/ssr/10072_infra_example-navidad__next-internal_server_app_page_actions_a387aef9.js +3 -0
  89. package/docker-build/standalone/.next/server/chunks/ssr/2025_cc_CODECRYPTO_infra_example-navidad_377109b0._.js +3 -0
  90. package/docker-build/standalone/.next/server/chunks/ssr/2025_cc_CODECRYPTO_infra_example-navidad_90799f30._.js +4 -0
  91. package/docker-build/standalone/.next/server/chunks/ssr/2025_cc_CODECRYPTO_infra_example-navidad_app_b9057478._.js +3 -0
  92. package/docker-build/standalone/.next/server/chunks/ssr/66d90_example-navidad__next-internal_server_app__global-error_page_actions_a079475f.js +3 -0
  93. package/docker-build/standalone/.next/server/chunks/ssr/66d90_example-navidad__next-internal_server_app__not-found_page_actions_ac88cec2.js +3 -0
  94. package/docker-build/standalone/.next/server/chunks/ssr/77a20_next_dist_51be1544._.js +4 -0
  95. package/docker-build/standalone/.next/server/chunks/ssr/77a20_next_dist_8dba0557._.js +6 -0
  96. package/docker-build/standalone/.next/server/chunks/ssr/77a20_next_dist_client_components_41330064._.js +3 -0
  97. package/docker-build/standalone/.next/server/chunks/ssr/77a20_next_dist_client_components_builtin_forbidden_ff3a0457.js +3 -0
  98. package/docker-build/standalone/.next/server/chunks/ssr/77a20_next_dist_client_components_builtin_global-error_e0d57e6e.js +3 -0
  99. package/docker-build/standalone/.next/server/chunks/ssr/77a20_next_dist_client_components_builtin_unauthorized_f1c47e13.js +3 -0
  100. package/docker-build/standalone/.next/server/chunks/ssr/77a20_next_dist_d332f292._.js +3 -0
  101. package/docker-build/standalone/.next/server/chunks/ssr/77a20_next_dist_esm_build_templates_app-page_cf6afba1.js +4 -0
  102. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__02f3f427._.js +3 -0
  103. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__2f460610._.js +4 -0
  104. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__4722e53c._.js +3 -0
  105. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__53b749fa._.js +3 -0
  106. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__61942f2d._.js +3 -0
  107. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__7707ad1b._.js +3 -0
  108. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__864cadbf._.js +10 -0
  109. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__9939e281._.js +3 -0
  110. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__b4b0aa8a._.js +3 -0
  111. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__d2b7072b._.js +3 -0
  112. package/docker-build/standalone/.next/server/chunks/ssr/[turbopack]_runtime.js +795 -0
  113. package/docker-build/standalone/.next/server/functions-config-manifest.json +4 -0
  114. package/docker-build/standalone/.next/server/middleware-build-manifest.js +20 -0
  115. package/docker-build/standalone/.next/server/middleware-manifest.json +6 -0
  116. package/docker-build/standalone/.next/server/next-font-manifest.js +1 -0
  117. package/docker-build/standalone/.next/server/next-font-manifest.json +15 -0
  118. package/docker-build/standalone/.next/server/pages/404.html +1 -0
  119. package/docker-build/standalone/.next/server/pages/500.html +2 -0
  120. package/docker-build/standalone/.next/server/pages-manifest.json +4 -0
  121. package/docker-build/standalone/.next/server/server-reference-manifest.js +1 -0
  122. package/docker-build/standalone/.next/server/server-reference-manifest.json +5 -0
  123. package/docker-build/standalone/.next/static/_NbfI2TKfapiyxsQgIG3h/_buildManifest.js +11 -0
  124. package/docker-build/standalone/.next/static/_NbfI2TKfapiyxsQgIG3h/_clientMiddlewareManifest.json +1 -0
  125. package/docker-build/standalone/.next/static/_NbfI2TKfapiyxsQgIG3h/_ssgManifest.js +1 -0
  126. package/docker-build/standalone/.next/static/chunks/57d1af92f5dc15fa.js +1 -0
  127. package/docker-build/standalone/.next/static/chunks/6ae71d5e8ea4d1eb.js +1 -0
  128. package/docker-build/standalone/.next/static/chunks/70977d70c9306213.js +1 -0
  129. package/docker-build/standalone/.next/static/chunks/777dac7104fe2a30.js +5 -0
  130. package/docker-build/standalone/.next/static/chunks/a6dad97d9634a72d.js +1 -0
  131. package/docker-build/standalone/.next/static/chunks/a6dad97d9634a72d.js.map +1 -0
  132. package/docker-build/standalone/.next/static/chunks/d6aec49b013224a2.css +3 -0
  133. package/docker-build/standalone/.next/static/chunks/turbopack-0ce517fb6224c1f0.js +4 -0
  134. package/docker-build/standalone/.next/static/media/4fa387ec64143e14-s.c1fdd6c2.woff2 +0 -0
  135. package/docker-build/standalone/.next/static/media/7178b3e590c64307-s.b97b3418.woff2 +0 -0
  136. package/docker-build/standalone/.next/static/media/797e433ab948586e-s.p.dbea232f.woff2 +0 -0
  137. package/docker-build/standalone/.next/static/media/8a480f0b521d4e75-s.8e0177b5.woff2 +0 -0
  138. package/docker-build/standalone/.next/static/media/bbc41e54d2fcbd21-s.799d8ef8.woff2 +0 -0
  139. package/docker-build/standalone/.next/static/media/caa3a2e1cccd8315-s.p.853070df.woff2 +0 -0
  140. package/docker-build/standalone/.next/static/media/favicon.0b3bf435.ico +0 -0
  141. package/docker-build/standalone/package.json +26 -0
  142. package/docker-build/standalone/public/file.svg +1 -0
  143. package/docker-build/standalone/public/globe.svg +1 -0
  144. package/docker-build/standalone/public/next.svg +1 -0
  145. package/docker-build/standalone/public/vercel.svg +1 -0
  146. package/docker-build/standalone/public/window.svg +1 -0
  147. package/docker-build/standalone/server.js +38 -0
  148. package/package.json +1 -1
  149. package/src/commands/auth.ts +71 -8
  150. package/src/commands/deploy-sc.ts +182 -0
  151. package/src/commands/deploy.ts +592 -21
  152. package/src/commands/doctor.ts +498 -0
  153. package/src/index.ts +2 -0
  154. package/token.json +69 -0
@@ -0,0 +1,498 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import ora from 'ora';
4
+ import { execSync } from 'child_process';
5
+ import * as fs from 'fs';
6
+ import * as path from 'path';
7
+ import * as os from 'os';
8
+
9
+ interface CheckResult {
10
+ name: string;
11
+ status: 'success' | 'warning' | 'error';
12
+ message: string;
13
+ details?: string;
14
+ }
15
+
16
+ export const doctorCommand = new Command('doctor')
17
+ .description('Validate all requirements for Next.js/Docker and Foundry deployments')
18
+ .option('--verbose', 'Show detailed information', false)
19
+ .action(async (options) => {
20
+ console.log(chalk.blue('\n🏥 CodeCrypto Doctor - System Health Check\n'));
21
+
22
+ const checks: CheckResult[] = [];
23
+ const verbose = options.verbose;
24
+
25
+ // ============================================
26
+ // NEXT.JS / DOCKER CHECKS
27
+ // ============================================
28
+ console.log(chalk.cyan('📦 Next.js / Docker Deployment Checks\n'));
29
+
30
+ // 1. Check Node.js
31
+ const nodeCheck = ora('Checking Node.js...').start();
32
+ try {
33
+ const nodeVersion = execSync('node --version', { encoding: 'utf-8', stdio: 'pipe' }).trim();
34
+ nodeCheck.succeed(`Node.js: ${nodeVersion}`);
35
+ checks.push({
36
+ name: 'Node.js',
37
+ status: 'success',
38
+ message: `Node.js installed: ${nodeVersion}`
39
+ });
40
+ } catch (error) {
41
+ nodeCheck.fail('Node.js not found');
42
+ checks.push({
43
+ name: 'Node.js',
44
+ status: 'error',
45
+ message: 'Node.js is not installed or not in PATH',
46
+ details: 'Install Node.js from https://nodejs.org/'
47
+ });
48
+ }
49
+
50
+ // 2. Check npm
51
+ const npmCheck = ora('Checking npm...').start();
52
+ try {
53
+ const npmVersion = execSync('npm --version', { encoding: 'utf-8', stdio: 'pipe' }).trim();
54
+ npmCheck.succeed(`npm: ${npmVersion}`);
55
+ checks.push({
56
+ name: 'npm',
57
+ status: 'success',
58
+ message: `npm installed: ${npmVersion}`
59
+ });
60
+ } catch (error) {
61
+ npmCheck.fail('npm not found');
62
+ checks.push({
63
+ name: 'npm',
64
+ status: 'error',
65
+ message: 'npm is not installed or not in PATH',
66
+ details: 'npm comes with Node.js, reinstall Node.js if needed'
67
+ });
68
+ }
69
+
70
+ // 3. Check Docker
71
+ const dockerCheck = ora('Checking Docker...').start();
72
+ try {
73
+ const dockerVersion = execSync('docker --version', { encoding: 'utf-8', stdio: 'pipe' }).trim();
74
+ dockerCheck.succeed(`Docker: ${dockerVersion}`);
75
+ checks.push({
76
+ name: 'Docker',
77
+ status: 'success',
78
+ message: `Docker installed: ${dockerVersion}`
79
+ });
80
+ } catch (error) {
81
+ dockerCheck.fail('Docker not found');
82
+ checks.push({
83
+ name: 'Docker',
84
+ status: 'error',
85
+ message: 'Docker is not installed or not in PATH',
86
+ details: 'Install Docker from https://www.docker.com/get-started'
87
+ });
88
+ }
89
+
90
+ // 4. Check Docker daemon
91
+ const dockerDaemonCheck = ora('Checking Docker daemon...').start();
92
+ try {
93
+ execSync('docker info', { encoding: 'utf-8', stdio: 'pipe' });
94
+ dockerDaemonCheck.succeed('Docker daemon is running');
95
+ checks.push({
96
+ name: 'Docker Daemon',
97
+ status: 'success',
98
+ message: 'Docker daemon is running'
99
+ });
100
+ } catch (error) {
101
+ dockerDaemonCheck.fail('Docker daemon is not running');
102
+ checks.push({
103
+ name: 'Docker Daemon',
104
+ status: 'error',
105
+ message: 'Docker daemon is not running',
106
+ details: 'Start Docker Desktop or Docker daemon'
107
+ });
108
+ }
109
+
110
+ // 5. Check Docker buildx
111
+ const buildxCheck = ora('Checking Docker buildx...').start();
112
+ try {
113
+ const buildxVersion = execSync('docker buildx version', { encoding: 'utf-8', stdio: 'pipe' }).trim();
114
+ buildxCheck.succeed(`Docker buildx: ${buildxVersion}`);
115
+ checks.push({
116
+ name: 'Docker buildx',
117
+ status: 'success',
118
+ message: `Docker buildx available: ${buildxVersion}`
119
+ });
120
+ } catch (error) {
121
+ buildxCheck.fail('Docker buildx not found');
122
+ checks.push({
123
+ name: 'Docker buildx',
124
+ status: 'error',
125
+ message: 'Docker buildx is not available',
126
+ details: 'Docker buildx should come with Docker. Update Docker if needed.'
127
+ });
128
+ }
129
+
130
+ // 6. Check Docker Hub authentication (optional)
131
+ const dockerAuthCheck = ora('Checking Docker Hub authentication...').start();
132
+ try {
133
+ execSync('docker pull hello-world:latest', { encoding: 'utf-8', stdio: 'pipe' });
134
+ dockerAuthCheck.succeed('Docker Hub authentication OK');
135
+ checks.push({
136
+ name: 'Docker Hub Auth',
137
+ status: 'success',
138
+ message: 'Docker Hub authentication verified'
139
+ });
140
+ } catch (error) {
141
+ dockerAuthCheck.warn('Docker Hub authentication may be required');
142
+ checks.push({
143
+ name: 'Docker Hub Auth',
144
+ status: 'warning',
145
+ message: 'Docker Hub authentication not verified',
146
+ details: 'Run "docker login" if you need to push images'
147
+ });
148
+ }
149
+
150
+ // 7. Check CodeCrypto token
151
+ const tokenCheck = ora('Checking CodeCrypto authentication token...').start();
152
+ const tokenFilePath = path.join(os.homedir(), '.codecrypto', 'token.json');
153
+ if (fs.existsSync(tokenFilePath)) {
154
+ try {
155
+ const tokenData = JSON.parse(fs.readFileSync(tokenFilePath, 'utf-8'));
156
+ if (tokenData.token && tokenData.email) {
157
+ tokenCheck.succeed(`Token found for: ${tokenData.email}`);
158
+ checks.push({
159
+ name: 'CodeCrypto Token',
160
+ status: 'success',
161
+ message: `Token found for: ${tokenData.email}`
162
+ });
163
+ } else {
164
+ tokenCheck.fail('Token file exists but is invalid');
165
+ checks.push({
166
+ name: 'CodeCrypto Token',
167
+ status: 'error',
168
+ message: 'Token file exists but is invalid',
169
+ details: 'Run "codecrypto auth --force" to refresh your token'
170
+ });
171
+ }
172
+ } catch (error: any) {
173
+ tokenCheck.fail('Token file is corrupted');
174
+ checks.push({
175
+ name: 'CodeCrypto Token',
176
+ status: 'error',
177
+ message: 'Token file is corrupted',
178
+ details: 'Run "codecrypto auth --force" to refresh your token'
179
+ });
180
+ }
181
+ } else {
182
+ tokenCheck.fail('Token file not found');
183
+ checks.push({
184
+ name: 'CodeCrypto Token',
185
+ status: 'error',
186
+ message: 'Token file not found',
187
+ details: 'Run "codecrypto auth" to authenticate'
188
+ });
189
+ }
190
+
191
+ // 8. Check Docker certificates in token.json
192
+ const certCheck = ora('Checking Docker certificates in token.json...').start();
193
+ try {
194
+ if (fs.existsSync(tokenFilePath)) {
195
+ const tokenData = JSON.parse(fs.readFileSync(tokenFilePath, 'utf-8'));
196
+ if (tokenData.adminGlobals && Array.isArray(tokenData.adminGlobals)) {
197
+ const certKeys = {
198
+ ca: 'docker-client/ca-pem',
199
+ cert: 'docker-client/cert.pem',
200
+ key: 'docker-client/key.pem'
201
+ };
202
+
203
+ const foundCerts: string[] = [];
204
+ for (const global of tokenData.adminGlobals) {
205
+ if (global && global.key) {
206
+ if (global.key === certKeys.ca || global.key === certKeys.cert || global.key === certKeys.key) {
207
+ foundCerts.push(global.key);
208
+ }
209
+ }
210
+ }
211
+
212
+ if (foundCerts.length === 3) {
213
+ certCheck.succeed('All Docker certificates found in token.json');
214
+ checks.push({
215
+ name: 'Docker Certificates',
216
+ status: 'success',
217
+ message: 'All Docker certificates found in token.json'
218
+ });
219
+ } else {
220
+ certCheck.fail(`Missing certificates: ${3 - foundCerts.length} of 3`);
221
+ const missing = Object.values(certKeys).filter(k => !foundCerts.includes(k));
222
+ checks.push({
223
+ name: 'Docker Certificates',
224
+ status: 'error',
225
+ message: `Missing certificates: ${missing.join(', ')}`,
226
+ details: 'Run "codecrypto auth --force" to refresh your token with certificates'
227
+ });
228
+ }
229
+ } else {
230
+ certCheck.fail('adminGlobals not found in token.json');
231
+ checks.push({
232
+ name: 'Docker Certificates',
233
+ status: 'error',
234
+ message: 'adminGlobals not found in token.json',
235
+ details: 'Run "codecrypto auth --force" to refresh your token'
236
+ });
237
+ }
238
+ } else {
239
+ certCheck.fail('Token file not found');
240
+ checks.push({
241
+ name: 'Docker Certificates',
242
+ status: 'error',
243
+ message: 'Token file not found',
244
+ details: 'Run "codecrypto auth" to authenticate'
245
+ });
246
+ }
247
+ } catch (error: any) {
248
+ certCheck.fail('Error checking certificates');
249
+ checks.push({
250
+ name: 'Docker Certificates',
251
+ status: 'error',
252
+ message: `Error checking certificates: ${error.message}`,
253
+ details: 'Run "codecrypto auth --force" to refresh your token'
254
+ });
255
+ }
256
+
257
+ // 9. Check Git (optional but recommended)
258
+ const gitCheck = ora('Checking Git...').start();
259
+ try {
260
+ const gitVersion = execSync('git --version', { encoding: 'utf-8', stdio: 'pipe' }).trim();
261
+ gitCheck.succeed(`Git: ${gitVersion}`);
262
+ checks.push({
263
+ name: 'Git',
264
+ status: 'success',
265
+ message: `Git installed: ${gitVersion}`
266
+ });
267
+ } catch (error) {
268
+ gitCheck.warn('Git not found');
269
+ checks.push({
270
+ name: 'Git',
271
+ status: 'warning',
272
+ message: 'Git is not installed or not in PATH',
273
+ details: 'Git is recommended for version control. Install from https://git-scm.com/'
274
+ });
275
+ }
276
+
277
+ // ============================================
278
+ // FOUNDRY / SMART CONTRACTS CHECKS
279
+ // ============================================
280
+ console.log(chalk.cyan('\n🔷 Foundry / Smart Contracts Deployment Checks\n'));
281
+
282
+ // 10. Check Foundry (forge)
283
+ const forgeCheck = ora('Checking Foundry (forge)...').start();
284
+ try {
285
+ const forgeVersion = execSync('forge --version', { encoding: 'utf-8', stdio: 'pipe' }).trim();
286
+ forgeCheck.succeed(`Foundry: ${forgeVersion}`);
287
+ checks.push({
288
+ name: 'Foundry (forge)',
289
+ status: 'success',
290
+ message: `Foundry installed: ${forgeVersion}`
291
+ });
292
+ } catch (error) {
293
+ forgeCheck.fail('Foundry (forge) not found');
294
+ checks.push({
295
+ name: 'Foundry (forge)',
296
+ status: 'error',
297
+ message: 'Foundry (forge) is not installed or not in PATH',
298
+ details: 'Install Foundry: curl -L https://foundry.paradigm.xyz | bash && foundryup'
299
+ });
300
+ }
301
+
302
+ // 11. Check cast
303
+ const castCheck = ora('Checking cast...').start();
304
+ try {
305
+ const castVersion = execSync('cast --version', { encoding: 'utf-8', stdio: 'pipe' }).trim();
306
+ castCheck.succeed(`cast: ${castVersion}`);
307
+ checks.push({
308
+ name: 'cast',
309
+ status: 'success',
310
+ message: `cast installed: ${castVersion}`
311
+ });
312
+ } catch (error) {
313
+ castCheck.fail('cast not found');
314
+ checks.push({
315
+ name: 'cast',
316
+ status: 'error',
317
+ message: 'cast is not installed or not in PATH',
318
+ details: 'cast comes with Foundry. Run "foundryup" to update.'
319
+ });
320
+ }
321
+
322
+ // 12. Check anvil
323
+ const anvilCheck = ora('Checking anvil...').start();
324
+ try {
325
+ const anvilVersion = execSync('anvil --version', { encoding: 'utf-8', stdio: 'pipe' }).trim();
326
+ anvilCheck.succeed(`anvil: ${anvilVersion}`);
327
+ checks.push({
328
+ name: 'anvil',
329
+ status: 'success',
330
+ message: `anvil installed: ${anvilVersion}`
331
+ });
332
+ } catch (error) {
333
+ anvilCheck.fail('anvil not found');
334
+ checks.push({
335
+ name: 'anvil',
336
+ status: 'error',
337
+ message: 'anvil is not installed or not in PATH',
338
+ details: 'anvil comes with Foundry. Run "foundryup" to update.'
339
+ });
340
+ }
341
+
342
+ // 13. Check if Anvil is running on correct port and chain-id
343
+ const anvilRunningCheck = ora('Checking if Anvil is running (port 55556, chain-id 3133731337)...').start();
344
+ try {
345
+ // Try to get chain id from the RPC
346
+ const rpcUrl = 'http://localhost:55556';
347
+ const chainIdResponse = execSync(
348
+ `cast chain-id --rpc-url ${rpcUrl}`,
349
+ { encoding: 'utf-8', stdio: 'pipe', timeout: 5000 }
350
+ ).trim();
351
+
352
+ // cast chain-id returns decimal number, but handle hex if needed
353
+ let chainId: number;
354
+ if (chainIdResponse.startsWith('0x') || chainIdResponse.startsWith('0X')) {
355
+ chainId = parseInt(chainIdResponse, 16);
356
+ } else {
357
+ chainId = parseInt(chainIdResponse, 10);
358
+ }
359
+
360
+ if (chainId === 3133731337) {
361
+ anvilRunningCheck.succeed(`Anvil running on port 55556 with chain-id ${chainId}`);
362
+ checks.push({
363
+ name: 'Anvil Running',
364
+ status: 'success',
365
+ message: `Anvil running on port 55556 with chain-id ${chainId}`
366
+ });
367
+ } else {
368
+ anvilRunningCheck.fail(`Anvil running but wrong chain-id: ${chainId} (expected 3133731337)`);
369
+ checks.push({
370
+ name: 'Anvil Running',
371
+ status: 'error',
372
+ message: `Anvil running but wrong chain-id: ${chainId}`,
373
+ details: 'Start Anvil with: anvil --chain-id 3133731337 --port 55556'
374
+ });
375
+ }
376
+ } catch (error: any) {
377
+ const errorMsg = error.message || String(error);
378
+ if (errorMsg.includes('ECONNREFUSED') || errorMsg.includes('Connection refused')) {
379
+ anvilRunningCheck.fail('Anvil is not running');
380
+ checks.push({
381
+ name: 'Anvil Running',
382
+ status: 'error',
383
+ message: 'Anvil is not running on port 55556',
384
+ details: 'Start Anvil with: anvil --chain-id 3133731337 --port 55556'
385
+ });
386
+ } else if (errorMsg.includes('timeout') || errorMsg.includes('ETIMEDOUT')) {
387
+ anvilRunningCheck.fail('Anvil connection timeout');
388
+ checks.push({
389
+ name: 'Anvil Running',
390
+ status: 'error',
391
+ message: 'Anvil connection timeout',
392
+ details: 'Check if Anvil is running: anvil --chain-id 3133731337 --port 55556'
393
+ });
394
+ } else {
395
+ anvilRunningCheck.fail('Cannot connect to Anvil');
396
+ checks.push({
397
+ name: 'Anvil Running',
398
+ status: 'error',
399
+ message: 'Cannot connect to Anvil',
400
+ details: `Error: ${errorMsg}. Start Anvil with: anvil --chain-id 3133731337 --port 55556`
401
+ });
402
+ }
403
+ }
404
+
405
+ // 14. Check Anvil account 0
406
+ const anvilAccountCheck = ora('Checking Anvil account 0...').start();
407
+ try {
408
+ const rpcUrl = 'http://localhost:55556';
409
+ const balance = execSync(
410
+ `cast balance 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --rpc-url ${rpcUrl}`,
411
+ { encoding: 'utf-8', stdio: 'pipe', timeout: 5000 }
412
+ ).trim();
413
+
414
+ anvilAccountCheck.succeed(`Account 0 balance: ${balance} wei`);
415
+ checks.push({
416
+ name: 'Anvil Account 0',
417
+ status: 'success',
418
+ message: `Account 0 available with balance: ${balance} wei`
419
+ });
420
+ } catch (error: any) {
421
+ anvilAccountCheck.fail('Cannot access Anvil account 0');
422
+ checks.push({
423
+ name: 'Anvil Account 0',
424
+ status: 'error',
425
+ message: 'Cannot access Anvil account 0',
426
+ details: 'Make sure Anvil is running and account 0 is unlocked'
427
+ });
428
+ }
429
+
430
+ // ============================================
431
+ // SUMMARY
432
+ // ============================================
433
+ console.log(chalk.cyan('\n📊 Summary\n'));
434
+ console.log(chalk.gray('─'.repeat(60)));
435
+
436
+ const successCount = checks.filter(c => c.status === 'success').length;
437
+ const warningCount = checks.filter(c => c.status === 'warning').length;
438
+ const errorCount = checks.filter(c => c.status === 'error').length;
439
+
440
+ console.log(chalk.white(` Total checks: ${chalk.cyan(checks.length)}`));
441
+ console.log(chalk.white(` ${chalk.green('✓')} Success: ${chalk.green(successCount)}`));
442
+ console.log(chalk.white(` ${chalk.yellow('⚠')} Warnings: ${chalk.yellow(warningCount)}`));
443
+ console.log(chalk.white(` ${chalk.red('✗')} Errors: ${chalk.red(errorCount)}`));
444
+ console.log(chalk.gray('─'.repeat(60)));
445
+
446
+ if (verbose) {
447
+ console.log(chalk.cyan('\n📋 Detailed Results\n'));
448
+ checks.forEach(check => {
449
+ const icon = check.status === 'success' ? chalk.green('✓') :
450
+ check.status === 'warning' ? chalk.yellow('⚠') :
451
+ chalk.red('✗');
452
+ console.log(chalk.gray(` ${icon} ${chalk.white(check.name)}: ${check.message}`));
453
+ if (check.details) {
454
+ console.log(chalk.gray(` ${chalk.dim(check.details)}`));
455
+ }
456
+ });
457
+ }
458
+
459
+ // Show errors and warnings
460
+ const errors = checks.filter(c => c.status === 'error');
461
+ const warnings = checks.filter(c => c.status === 'warning');
462
+
463
+ if (errors.length > 0) {
464
+ console.log(chalk.red('\n❌ Errors that need to be fixed:\n'));
465
+ errors.forEach(error => {
466
+ console.log(chalk.red(` ✗ ${error.name}`));
467
+ console.log(chalk.white(` ${error.message}`));
468
+ if (error.details) {
469
+ console.log(chalk.gray(` 💡 ${error.details}`));
470
+ }
471
+ });
472
+ }
473
+
474
+ if (warnings.length > 0) {
475
+ console.log(chalk.yellow('\n⚠️ Warnings (optional but recommended):\n'));
476
+ warnings.forEach(warning => {
477
+ console.log(chalk.yellow(` ⚠ ${warning.name}`));
478
+ console.log(chalk.white(` ${warning.message}`));
479
+ if (warning.details) {
480
+ console.log(chalk.gray(` 💡 ${warning.details}`));
481
+ }
482
+ });
483
+ }
484
+
485
+ // Final status
486
+ console.log('');
487
+ if (errorCount === 0 && warningCount === 0) {
488
+ console.log(chalk.green('✅ All checks passed! You are ready to deploy.\n'));
489
+ process.exit(0);
490
+ } else if (errorCount === 0) {
491
+ console.log(chalk.yellow('⚠️ Some warnings found, but you can proceed with deployments.\n'));
492
+ process.exit(0);
493
+ } else {
494
+ console.log(chalk.red('❌ Some errors found. Please fix them before deploying.\n'));
495
+ process.exit(1);
496
+ }
497
+ });
498
+
package/src/index.ts CHANGED
@@ -4,6 +4,7 @@ import { Command } from 'commander';
4
4
  import { deployCommand } from './commands/deploy';
5
5
  import { deployScCommand } from './commands/deploy-sc';
6
6
  import { authCommand } from './commands/auth';
7
+ import { doctorCommand } from './commands/doctor';
7
8
 
8
9
  const program = new Command();
9
10
 
@@ -16,5 +17,6 @@ program
16
17
  program.addCommand(deployCommand);
17
18
  program.addCommand(deployScCommand);
18
19
  program.addCommand(authCommand);
20
+ program.addCommand(doctorCommand);
19
21
 
20
22
  program.parse(process.argv);
package/token.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "token": "eyJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6Imp2aWVqb0BnbWFpbC5jb20iLCJpYXQiOjE3NjY5NDI5NDMsImV4cCI6MTc5ODQ3ODk0M30.ZILFm5cFxIbcpeHOXP3Ya2mLHCIXtJWGBJBk5GiE1M4",
3
+ "email": "jviejo@gmail.com",
4
+ "tokenId": "695168be3a6c2001aa651404",
5
+ "code": "615267",
6
+ "serverUrl": "http://localhost:3000",
7
+ "verifiedAt": "2025-12-28T17:29:05.128Z",
8
+ "studentGlobalsAll": [
9
+ {
10
+ "_id": "694c2b5c4b5b842a33ec9c59",
11
+ "projectId": "global",
12
+ "studentEmail": "jviejo@gmail.com",
13
+ "environment": "dev",
14
+ "key": "A",
15
+ "value": "1",
16
+ "createdAt": "2025-12-24T18:05:16.826Z",
17
+ "updatedAt": "2025-12-24T18:05:16.826Z"
18
+ },
19
+ {
20
+ "_id": "694c2b5c4b5b842a33ec9c5a",
21
+ "projectId": "global",
22
+ "studentEmail": "jviejo@gmail.com",
23
+ "environment": "dev",
24
+ "key": "B",
25
+ "value": "2",
26
+ "createdAt": "2025-12-24T18:05:16.888Z",
27
+ "updatedAt": "2025-12-24T18:05:16.888Z"
28
+ }
29
+ ],
30
+ "adminGlobals": [
31
+ {
32
+ "_id": "6950fd3a8d438028a4492cd9",
33
+ "projectId": "global",
34
+ "environment": "all",
35
+ "key": "docker-client/ca-pem",
36
+ "value": "-----BEGIN CERTIFICATE-----\nMIIFiTCCA3GgAwIBAgIUCA9aZbNMRyz1oTh01G6mMpzZoUgwDQYJKoZIhvcNAQEL\nBQAwVDELMAkGA1UEBhMCRVMxDzANBgNVBAgMBk1hZHJpZDEPMA0GA1UEBwwGTWFk\ncmlkMQ8wDQYDVQQKDAZEb2NrZXIxEjAQBgNVBAMMCURvY2tlci1DQTAeFw0yNTEy\nMjUxOTE3NTVaFw0yNjEyMjUxOTE3NTVaMFQxCzAJBgNVBAYTAkVTMQ8wDQYDVQQI\nDAZNYWRyaWQxDzANBgNVBAcMBk1hZHJpZDEPMA0GA1UECgwGRG9ja2VyMRIwEAYD\nVQQDDAlEb2NrZXItQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM\nhPVDHtJCKoD6mfPvXK1qyQA7cqTPf3pooCR6y1W0E9lRMP9DetdZS45HFy+vJgMR\nTpxqFod1eBnmTw/tGCeuzndpA1ntFTScTbE+nCozHF/6SmH0++7SH3qqZ3Df4myj\nKUJUYgylAL++tcZsJkkAZ3KPC55y+7hdDsR3aLt2AuqBN2x1nYmFx776N7j6hArP\nmM+PJEKVd+1bVB/f3Yz0tNzup4cgESIee+a7dXKFXDPibhmiRn+pA1l3Opmo7f09\nKLiGAxj72ILI61wsWg774xg4Ncv2IDo6NpHtW9q345frpjRPJMmaqJWKZ7cQU8m4\nbwx2w4YH2riNbD0jWoUx+dDkBX2esI5gmrugZKnSj81cZwyQFr+9Dgxa4N9yn5V/\nXXht2EID7S8oYXI8Fz7u54iShf8wtk6YQumQYUc4b3GL6Y8Jg7SXzsvuY2oo+cId\n05b1r8ESV8SxLZ75+irhC8g0IH2KjMluk0ceUsoCfEh3WaJs4fEcfqywEfkU+3VA\nFdYxaeMBydVBa/BsxXMVQudzixXJr1qAZ6WA/zGnMbCI0idxxStEgHt3+d42bfMv\n99iT5/rgQRxHl1GW7G78hTz6AEJf4ULLG+VJsiBqUahlSKVpquZjLRPAtZjzZ0qv\n4BgQi8SuPqDZ7KNiYJuBdlTyIR8hXC70j5NxqdcZOwIDAQABo1MwUTAdBgNVHQ4E\nFgQUZvAcG1qqcADfqXTCjCoNbqzhy9cwHwYDVR0jBBgwFoAUZvAcG1qqcADfqXTC\njCoNbqzhy9cwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAxRqx\nTNyAtoc3bOkp45a93AY8OY/OnVAiCBt6KQ+nS7iv4NZ/I3VI/ZD+OyG8+Rk1A2HB\nY9AdRt9vfSHNpEH+MDdomx3Bvq5ErFDgDDbCGVkdtlcFTHs7UNL/161Z9oh1RCvF\nYVygIJZKxJ6v0dCSZvUvjKmCdR5XN+FAsDZvWNePkaTY7usInUuDM9ONwEXTuoo8\n9h9pLU/R9o4GNwXR5H8l6EqGcevKJhMnaaIdg8AyYIiL2vC0Qnt4BPFFV0S2Aeim\nAOPT2ERuypEA9xlG0NiWsY5B84oX5wiR7D8gsws4EzIvMm8LSlkBHM7joppMKNPq\nXsD/SAlLpGO2w9mZe2lEYQ7S1PX8RJlCMaPx6PYn1QRGGG9tstyaHlA3RCqfQXgk\n96wmGfKu7wmohD8lJIlDXayYOJE45ogZ6R9gOJNUF8pj0YN5ElvdCCoRan/vbyOH\nj7e9cEr6+if7o/fTG8x7FoxBOWQbPfOqVf7tM4LUA91O1xdqk5fqWmjNIqa075Oi\nlkDhAo2hr8yDbzJRxW7KrtvEh0GzlG0pwVrlU14EwuwdZadgkzyiv4goNSDg+hfA\n59Sx7bmfGX9Te+5ELg8WcH+XcLI+143Dh0QPm8dpRdgK452y05QRl0YTASXnxEXf\n//7MY0ONUH55rumpj03vAy+RMhANd4Jv7q8sKT8=\n-----END CERTIFICATE-----",
37
+ "createdAt": "2025-12-28T09:49:46.110Z",
38
+ "updatedAt": "2025-12-28T10:04:15.387Z"
39
+ },
40
+ {
41
+ "_id": "6950fd6b8d438028a4492cda",
42
+ "projectId": "global",
43
+ "environment": "all",
44
+ "key": "docker-client/cert.pem",
45
+ "value": "-----BEGIN CERTIFICATE-----\nMIIFZjCCA06gAwIBAgIULnKTk/HTmOsi2yZETw4PHCwLGvcwDQYJKoZIhvcNAQEL\nBQAwVDELMAkGA1UEBhMCRVMxDzANBgNVBAgMBk1hZHJpZDEPMA0GA1UEBwwGTWFk\ncmlkMQ8wDQYDVQQKDAZEb2NrZXIxEjAQBgNVBAMMCURvY2tlci1DQTAeFw0yNTEy\nMjUxOTE4MzBaFw0yNjEyMjUxOTE4MzBaMBUxEzARBgNVBAMMCmNvZGVjcnlwdG8w\nggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCaUBQkyZYS9RgeSK3t7oed\niOrOpwvBvLHLvPeh1EHGRt7ZIbfMTDBTCeMUqgbiQ0aoEk6Y0bsY/KBrqtpZFhiC\n/zZk5lnHOjJpX+jWMDrLQbHUCmIhPYRE8ZyxPuKl1wYpiRRjVY37cFW6oicn0e4T\njAG59k+1/fltn5OYq4LOJDrScOwuCHeuoryqimXKqhqVHO8537Ye+8r6HcP84+BO\n9gtuXKXBnVHi/xSIfgZ/ErcpeO+jQ3D3l0Zmj/BIAY3qSNw1HcDULSKKtwrqdMNW\nuKGHl58mBiGvTG9SYiD8H207S0vvnyGThzwtbNRhM96cK3OyhVRVx+ilE+Mr4oOX\nfH/OTWp2dGXysPAQbmpWL6cWeea5+Ts/SoryAgFNmtqxLLa9riVhBmF+sR8wyDZw\nYuSE/CWs1J5bds9Mip/fndRvBuLEV3B91GcxZXX/dHOof74awlAMLdL2QVdhD+1U\nMIQynJ8a38VBuexKzg8jqx8EBFKQQSirfFnJX1NTpANIjUWwCCds0rmxXMJEuBfP\nOEc1wYr52b7nLylpwaAkTQJaQRpvoKm+xTIxWoBtWIVaOuQpvgRtRVfXFUooD8KN\nPRGNqUtzjZBaJPMs6O1NPHP2pef+vTuR/x45Hx5bX6xg+sEZO4YmNP5GQMVZXDWP\nRUKk8N8SPXaV0mj1V1DyrwIDAQABo28wbTAfBgNVHSMEGDAWgBRm8BwbWqpwAN+p\ndMKMKg1urOHL1zAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDATBgNVHSUEDDAKBggr\nBgEFBQcDAjAdBgNVHQ4EFgQUB1Z0Z9m6Wkqm1+gzAGURQIFBOtgwDQYJKoZIhvcN\nAQELBQADggIBAIPlwhzIA43IJx3Wd4u5zKgEXbBrD7rJRzhuLs0qFi3pIUoBzTka\nUwABshAn6ZZzXi0YZfygskIsNX4TIxgkDtu2IcKttHHYAXetYRalZD/CDt/QNUgY\nnQwNiAT0rNPUcPiiizkifXbQu0Qr1/vWAtSrJbElJqMBpjwUiBjrfxt2BSnCwl4/\n9wYYL7j/164MdA+gwOVYCyAzGzaRW9mlORTP4bbTho+dsHYTyZbt5pxybDLnYBxs\nHDknLdaa24Uso8SUW7wNnalg+Bqy3oWFr/hl78EjNxyCNQ1CBrTnQVi7L9NkFh/N\nzbG86aH8sBPjqpU2WOl8nUQbfTGCwScb1BJUPKu0nYpHC3C4ghuQfSD3tDfgGPcj\nPxXjY+A/K0CU+0l5CyRAu+pMYJo9HMALmcidcghX0sRZt/ZEvKe4k/cGZ0yIxRlV\nXAso6RaJ+Auok+JOSmao+3WZCqrXEG0st0PBG9PyiClxjGxSYmB5Caa91UAmlaFG\nVFlEQfkhm0VwOqr/ANGOdHOn+QzLOn7y3ZWB+xL5JFRBY/ZC1JpAtB2t+e+iYN8u\n/D4IzSW62gdsg+yU/1NAyT6ygmnya2p4VHaIxy/pzPOr/c0hPHciBG1/5st9vKy/\n0CAQH9PFBR4jX0zkVJQdn35V0opNs6PWWRfJtPPvt/HCn/6tBsCkvQEY\n-----END CERTIFICATE-----",
46
+ "createdAt": "2025-12-28T09:50:35.462Z",
47
+ "updatedAt": "2025-12-28T17:21:40.620Z"
48
+ },
49
+ {
50
+ "_id": "6950fda68d438028a4492cdb",
51
+ "projectId": "global",
52
+ "environment": "all",
53
+ "key": "docker-client/key.pem",
54
+ "value": "-----BEGIN PRIVATE KEY-----\n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\no99r+Qeei3PQTkI4bhvZ7y9Rz7gE\n-----END PRIVATE KEY-----",
55
+ "createdAt": "2025-12-28T09:51:34.588Z",
56
+ "updatedAt": "2025-12-28T10:02:41.563Z"
57
+ },
58
+ {
59
+ "_id": "6951068b3a6c2001aa6513d7",
60
+ "projectId": "global",
61
+ "environment": "dev",
62
+ "scope": "client",
63
+ "key": "clave ",
64
+ "value": "valor",
65
+ "createdAt": "2025-12-28T10:29:31.244Z",
66
+ "updatedAt": "2025-12-28T10:29:31.244Z"
67
+ }
68
+ ]
69
+ }