@weirdfingers/baseboards 0.9.6 → 0.9.7

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 (237) hide show
  1. package/dist/index.js +560 -469
  2. package/dist/index.js.map +1 -1
  3. package/package.json +2 -5
  4. package/templates/README.md +0 -122
  5. package/templates/api/.env.example +0 -65
  6. package/templates/api/ARTIFACT_RESOLUTION_GUIDE.md +0 -148
  7. package/templates/api/Dockerfile +0 -32
  8. package/templates/api/README.md +0 -264
  9. package/templates/api/alembic/env.py +0 -114
  10. package/templates/api/alembic/script.py.mako +0 -28
  11. package/templates/api/alembic/versions/20250101_000000_initial_schema.py +0 -506
  12. package/templates/api/alembic/versions/20251022_174729_remove_provider_name_from_generations.py +0 -75
  13. package/templates/api/alembic/versions/20251023_165852_switch_to_declarative_base_and_mapping.py +0 -467
  14. package/templates/api/alembic/versions/20251202_000000_add_artifact_lineage.py +0 -134
  15. package/templates/api/alembic/versions/2025925_62735_add_seed_data_for_default_tenant.py +0 -88
  16. package/templates/api/alembic.ini +0 -36
  17. package/templates/api/config/generators.yaml +0 -237
  18. package/templates/api/config/storage_config.yaml +0 -26
  19. package/templates/api/docs/ADDING_GENERATORS.md +0 -409
  20. package/templates/api/docs/GENERATORS_API.md +0 -502
  21. package/templates/api/docs/MIGRATIONS.md +0 -472
  22. package/templates/api/docs/TESTING_LIVE_APIS.md +0 -417
  23. package/templates/api/docs/storage_providers.md +0 -337
  24. package/templates/api/pyproject.toml +0 -205
  25. package/templates/api/src/boards/__init__.py +0 -10
  26. package/templates/api/src/boards/api/app.py +0 -172
  27. package/templates/api/src/boards/api/auth.py +0 -75
  28. package/templates/api/src/boards/api/endpoints/__init__.py +0 -3
  29. package/templates/api/src/boards/api/endpoints/jobs.py +0 -76
  30. package/templates/api/src/boards/api/endpoints/setup.py +0 -505
  31. package/templates/api/src/boards/api/endpoints/sse.py +0 -129
  32. package/templates/api/src/boards/api/endpoints/storage.py +0 -155
  33. package/templates/api/src/boards/api/endpoints/tenant_registration.py +0 -296
  34. package/templates/api/src/boards/api/endpoints/uploads.py +0 -149
  35. package/templates/api/src/boards/api/endpoints/webhooks.py +0 -13
  36. package/templates/api/src/boards/auth/__init__.py +0 -15
  37. package/templates/api/src/boards/auth/adapters/__init__.py +0 -27
  38. package/templates/api/src/boards/auth/adapters/auth0.py +0 -220
  39. package/templates/api/src/boards/auth/adapters/base.py +0 -73
  40. package/templates/api/src/boards/auth/adapters/clerk.py +0 -172
  41. package/templates/api/src/boards/auth/adapters/jwt.py +0 -122
  42. package/templates/api/src/boards/auth/adapters/none.py +0 -102
  43. package/templates/api/src/boards/auth/adapters/oidc.py +0 -284
  44. package/templates/api/src/boards/auth/adapters/supabase.py +0 -110
  45. package/templates/api/src/boards/auth/context.py +0 -35
  46. package/templates/api/src/boards/auth/factory.py +0 -129
  47. package/templates/api/src/boards/auth/middleware.py +0 -221
  48. package/templates/api/src/boards/auth/provisioning.py +0 -129
  49. package/templates/api/src/boards/auth/tenant_extraction.py +0 -278
  50. package/templates/api/src/boards/cli.py +0 -354
  51. package/templates/api/src/boards/config.py +0 -131
  52. package/templates/api/src/boards/database/__init__.py +0 -7
  53. package/templates/api/src/boards/database/cli.py +0 -110
  54. package/templates/api/src/boards/database/connection.py +0 -292
  55. package/templates/api/src/boards/database/models.py +0 -19
  56. package/templates/api/src/boards/database/seed_data.py +0 -182
  57. package/templates/api/src/boards/dbmodels/__init__.py +0 -441
  58. package/templates/api/src/boards/generators/__init__.py +0 -57
  59. package/templates/api/src/boards/generators/artifact_resolution.py +0 -405
  60. package/templates/api/src/boards/generators/artifacts.py +0 -53
  61. package/templates/api/src/boards/generators/base.py +0 -144
  62. package/templates/api/src/boards/generators/implementations/__init__.py +0 -14
  63. package/templates/api/src/boards/generators/implementations/fal/__init__.py +0 -25
  64. package/templates/api/src/boards/generators/implementations/fal/audio/__init__.py +0 -23
  65. package/templates/api/src/boards/generators/implementations/fal/audio/beatoven_music_generation.py +0 -171
  66. package/templates/api/src/boards/generators/implementations/fal/audio/beatoven_sound_effect_generation.py +0 -167
  67. package/templates/api/src/boards/generators/implementations/fal/audio/chatterbox_text_to_speech.py +0 -176
  68. package/templates/api/src/boards/generators/implementations/fal/audio/chatterbox_tts_turbo.py +0 -195
  69. package/templates/api/src/boards/generators/implementations/fal/audio/elevenlabs_sound_effects_v2.py +0 -194
  70. package/templates/api/src/boards/generators/implementations/fal/audio/elevenlabs_tts_eleven_v3.py +0 -209
  71. package/templates/api/src/boards/generators/implementations/fal/audio/fal_elevenlabs_tts_turbo_v2_5.py +0 -206
  72. package/templates/api/src/boards/generators/implementations/fal/audio/fal_minimax_speech_26_hd.py +0 -237
  73. package/templates/api/src/boards/generators/implementations/fal/audio/minimax_music_v2.py +0 -173
  74. package/templates/api/src/boards/generators/implementations/fal/audio/minimax_speech_2_6_turbo.py +0 -221
  75. package/templates/api/src/boards/generators/implementations/fal/image/__init__.py +0 -63
  76. package/templates/api/src/boards/generators/implementations/fal/image/bytedance_seedream_v45_edit.py +0 -219
  77. package/templates/api/src/boards/generators/implementations/fal/image/clarity_upscaler.py +0 -220
  78. package/templates/api/src/boards/generators/implementations/fal/image/crystal_upscaler.py +0 -173
  79. package/templates/api/src/boards/generators/implementations/fal/image/fal_ideogram_character.py +0 -227
  80. package/templates/api/src/boards/generators/implementations/fal/image/flux_2.py +0 -203
  81. package/templates/api/src/boards/generators/implementations/fal/image/flux_2_edit.py +0 -230
  82. package/templates/api/src/boards/generators/implementations/fal/image/flux_2_pro.py +0 -204
  83. package/templates/api/src/boards/generators/implementations/fal/image/flux_2_pro_edit.py +0 -221
  84. package/templates/api/src/boards/generators/implementations/fal/image/flux_pro_kontext.py +0 -216
  85. package/templates/api/src/boards/generators/implementations/fal/image/flux_pro_ultra.py +0 -197
  86. package/templates/api/src/boards/generators/implementations/fal/image/gemini_25_flash_image.py +0 -177
  87. package/templates/api/src/boards/generators/implementations/fal/image/gemini_25_flash_image_edit.py +0 -208
  88. package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_15_edit.py +0 -216
  89. package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_1_5.py +0 -177
  90. package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_1_edit_image.py +0 -182
  91. package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_1_mini.py +0 -167
  92. package/templates/api/src/boards/generators/implementations/fal/image/ideogram_character_edit.py +0 -299
  93. package/templates/api/src/boards/generators/implementations/fal/image/ideogram_v2.py +0 -190
  94. package/templates/api/src/boards/generators/implementations/fal/image/imagen4_preview.py +0 -191
  95. package/templates/api/src/boards/generators/implementations/fal/image/imagen4_preview_fast.py +0 -179
  96. package/templates/api/src/boards/generators/implementations/fal/image/nano_banana.py +0 -183
  97. package/templates/api/src/boards/generators/implementations/fal/image/nano_banana_edit.py +0 -212
  98. package/templates/api/src/boards/generators/implementations/fal/image/nano_banana_pro.py +0 -179
  99. package/templates/api/src/boards/generators/implementations/fal/image/nano_banana_pro_edit.py +0 -226
  100. package/templates/api/src/boards/generators/implementations/fal/image/qwen_image.py +0 -249
  101. package/templates/api/src/boards/generators/implementations/fal/image/qwen_image_edit.py +0 -244
  102. package/templates/api/src/boards/generators/implementations/fal/image/reve_edit.py +0 -178
  103. package/templates/api/src/boards/generators/implementations/fal/image/reve_text_to_image.py +0 -155
  104. package/templates/api/src/boards/generators/implementations/fal/image/seedream_v45_text_to_image.py +0 -180
  105. package/templates/api/src/boards/generators/implementations/fal/utils.py +0 -61
  106. package/templates/api/src/boards/generators/implementations/fal/video/__init__.py +0 -77
  107. package/templates/api/src/boards/generators/implementations/fal/video/bytedance_seedance_v1_pro_text_to_video.py +0 -209
  108. package/templates/api/src/boards/generators/implementations/fal/video/creatify_lipsync.py +0 -161
  109. package/templates/api/src/boards/generators/implementations/fal/video/fal_bytedance_seedance_v1_pro_image_to_video.py +0 -222
  110. package/templates/api/src/boards/generators/implementations/fal/video/fal_minimax_hailuo_02_standard_text_to_video.py +0 -152
  111. package/templates/api/src/boards/generators/implementations/fal/video/fal_pixverse_lipsync.py +0 -197
  112. package/templates/api/src/boards/generators/implementations/fal/video/fal_sora_2_text_to_video.py +0 -173
  113. package/templates/api/src/boards/generators/implementations/fal/video/infinitalk.py +0 -221
  114. package/templates/api/src/boards/generators/implementations/fal/video/kling_video_ai_avatar_v2_pro.py +0 -168
  115. package/templates/api/src/boards/generators/implementations/fal/video/kling_video_ai_avatar_v2_standard.py +0 -159
  116. package/templates/api/src/boards/generators/implementations/fal/video/kling_video_v2_5_turbo_pro_image_to_video.py +0 -175
  117. package/templates/api/src/boards/generators/implementations/fal/video/kling_video_v2_5_turbo_pro_text_to_video.py +0 -168
  118. package/templates/api/src/boards/generators/implementations/fal/video/minimax_hailuo_2_3_pro_image_to_video.py +0 -153
  119. package/templates/api/src/boards/generators/implementations/fal/video/sora2_image_to_video.py +0 -172
  120. package/templates/api/src/boards/generators/implementations/fal/video/sora_2_image_to_video_pro.py +0 -175
  121. package/templates/api/src/boards/generators/implementations/fal/video/sora_2_text_to_video_pro.py +0 -163
  122. package/templates/api/src/boards/generators/implementations/fal/video/sync_lipsync_v2.py +0 -167
  123. package/templates/api/src/boards/generators/implementations/fal/video/sync_lipsync_v2_pro.py +0 -155
  124. package/templates/api/src/boards/generators/implementations/fal/video/veed_fabric_1_0.py +0 -180
  125. package/templates/api/src/boards/generators/implementations/fal/video/veed_lipsync.py +0 -174
  126. package/templates/api/src/boards/generators/implementations/fal/video/veo3.py +0 -194
  127. package/templates/api/src/boards/generators/implementations/fal/video/veo31.py +0 -190
  128. package/templates/api/src/boards/generators/implementations/fal/video/veo31_fast.py +0 -190
  129. package/templates/api/src/boards/generators/implementations/fal/video/veo31_fast_image_to_video.py +0 -191
  130. package/templates/api/src/boards/generators/implementations/fal/video/veo31_first_last_frame_to_video.py +0 -187
  131. package/templates/api/src/boards/generators/implementations/fal/video/veo31_image_to_video.py +0 -183
  132. package/templates/api/src/boards/generators/implementations/fal/video/veo31_reference_to_video.py +0 -172
  133. package/templates/api/src/boards/generators/implementations/fal/video/wan_25_preview_image_to_video.py +0 -212
  134. package/templates/api/src/boards/generators/implementations/fal/video/wan_25_preview_text_to_video.py +0 -208
  135. package/templates/api/src/boards/generators/implementations/fal/video/wan_pro_image_to_video.py +0 -158
  136. package/templates/api/src/boards/generators/implementations/kie/__init__.py +0 -11
  137. package/templates/api/src/boards/generators/implementations/kie/base.py +0 -316
  138. package/templates/api/src/boards/generators/implementations/kie/image/__init__.py +0 -3
  139. package/templates/api/src/boards/generators/implementations/kie/image/nano_banana_edit.py +0 -190
  140. package/templates/api/src/boards/generators/implementations/kie/utils.py +0 -98
  141. package/templates/api/src/boards/generators/implementations/kie/video/__init__.py +0 -8
  142. package/templates/api/src/boards/generators/implementations/kie/video/veo3.py +0 -161
  143. package/templates/api/src/boards/generators/implementations/openai/__init__.py +0 -1
  144. package/templates/api/src/boards/generators/implementations/openai/audio/__init__.py +0 -1
  145. package/templates/api/src/boards/generators/implementations/openai/audio/whisper.py +0 -69
  146. package/templates/api/src/boards/generators/implementations/openai/image/__init__.py +0 -1
  147. package/templates/api/src/boards/generators/implementations/openai/image/dalle3.py +0 -96
  148. package/templates/api/src/boards/generators/implementations/replicate/__init__.py +0 -1
  149. package/templates/api/src/boards/generators/implementations/replicate/image/__init__.py +0 -1
  150. package/templates/api/src/boards/generators/implementations/replicate/image/flux_pro.py +0 -88
  151. package/templates/api/src/boards/generators/implementations/replicate/video/__init__.py +0 -1
  152. package/templates/api/src/boards/generators/implementations/replicate/video/lipsync.py +0 -73
  153. package/templates/api/src/boards/generators/loader.py +0 -253
  154. package/templates/api/src/boards/generators/registry.py +0 -114
  155. package/templates/api/src/boards/generators/resolution.py +0 -632
  156. package/templates/api/src/boards/generators/testmods/class_gen.py +0 -34
  157. package/templates/api/src/boards/generators/testmods/import_side_effect.py +0 -35
  158. package/templates/api/src/boards/graphql/__init__.py +0 -7
  159. package/templates/api/src/boards/graphql/access_control.py +0 -136
  160. package/templates/api/src/boards/graphql/mutations/root.py +0 -148
  161. package/templates/api/src/boards/graphql/queries/root.py +0 -116
  162. package/templates/api/src/boards/graphql/resolvers/__init__.py +0 -8
  163. package/templates/api/src/boards/graphql/resolvers/auth.py +0 -12
  164. package/templates/api/src/boards/graphql/resolvers/board.py +0 -1053
  165. package/templates/api/src/boards/graphql/resolvers/generation.py +0 -666
  166. package/templates/api/src/boards/graphql/resolvers/generator.py +0 -50
  167. package/templates/api/src/boards/graphql/resolvers/lineage.py +0 -381
  168. package/templates/api/src/boards/graphql/resolvers/upload.py +0 -463
  169. package/templates/api/src/boards/graphql/resolvers/user.py +0 -25
  170. package/templates/api/src/boards/graphql/schema.py +0 -81
  171. package/templates/api/src/boards/graphql/types/board.py +0 -102
  172. package/templates/api/src/boards/graphql/types/generation.py +0 -166
  173. package/templates/api/src/boards/graphql/types/generator.py +0 -17
  174. package/templates/api/src/boards/graphql/types/user.py +0 -47
  175. package/templates/api/src/boards/jobs/repository.py +0 -153
  176. package/templates/api/src/boards/logging.py +0 -195
  177. package/templates/api/src/boards/middleware.py +0 -339
  178. package/templates/api/src/boards/progress/__init__.py +0 -4
  179. package/templates/api/src/boards/progress/models.py +0 -25
  180. package/templates/api/src/boards/progress/publisher.py +0 -64
  181. package/templates/api/src/boards/py.typed +0 -0
  182. package/templates/api/src/boards/redis_pool.py +0 -118
  183. package/templates/api/src/boards/storage/__init__.py +0 -52
  184. package/templates/api/src/boards/storage/base.py +0 -363
  185. package/templates/api/src/boards/storage/config.py +0 -187
  186. package/templates/api/src/boards/storage/factory.py +0 -288
  187. package/templates/api/src/boards/storage/implementations/__init__.py +0 -27
  188. package/templates/api/src/boards/storage/implementations/gcs.py +0 -340
  189. package/templates/api/src/boards/storage/implementations/local.py +0 -201
  190. package/templates/api/src/boards/storage/implementations/s3.py +0 -294
  191. package/templates/api/src/boards/storage/implementations/supabase.py +0 -218
  192. package/templates/api/src/boards/tenant_isolation.py +0 -446
  193. package/templates/api/src/boards/validation.py +0 -262
  194. package/templates/api/src/boards/workers/__init__.py +0 -1
  195. package/templates/api/src/boards/workers/actors.py +0 -274
  196. package/templates/api/src/boards/workers/cli.py +0 -125
  197. package/templates/api/src/boards/workers/context.py +0 -348
  198. package/templates/api/src/boards/workers/middleware.py +0 -58
  199. package/templates/api/src/py.typed +0 -0
  200. package/templates/compose.web.yaml +0 -35
  201. package/templates/compose.yaml +0 -116
  202. package/templates/docker/env.example +0 -23
  203. package/templates/web/.env.example +0 -28
  204. package/templates/web/Dockerfile +0 -51
  205. package/templates/web/components.json +0 -22
  206. package/templates/web/imageLoader.js +0 -18
  207. package/templates/web/next-env.d.ts +0 -5
  208. package/templates/web/next.config.js +0 -36
  209. package/templates/web/package.json +0 -41
  210. package/templates/web/postcss.config.mjs +0 -7
  211. package/templates/web/public/favicon.ico +0 -0
  212. package/templates/web/src/app/boards/[boardId]/page.tsx +0 -353
  213. package/templates/web/src/app/globals.css +0 -123
  214. package/templates/web/src/app/layout.tsx +0 -31
  215. package/templates/web/src/app/lineage/[generationId]/page.tsx +0 -235
  216. package/templates/web/src/app/page.tsx +0 -35
  217. package/templates/web/src/app/providers.tsx +0 -18
  218. package/templates/web/src/components/boards/ArtifactInputSlots.tsx +0 -206
  219. package/templates/web/src/components/boards/ArtifactPreview.tsx +0 -466
  220. package/templates/web/src/components/boards/GenerationGrid.tsx +0 -282
  221. package/templates/web/src/components/boards/GenerationInput.tsx +0 -370
  222. package/templates/web/src/components/boards/GeneratorSelector.tsx +0 -272
  223. package/templates/web/src/components/boards/UploadArtifact.tsx +0 -563
  224. package/templates/web/src/components/header.tsx +0 -32
  225. package/templates/web/src/components/theme-provider.tsx +0 -10
  226. package/templates/web/src/components/theme-toggle.tsx +0 -75
  227. package/templates/web/src/components/ui/alert-dialog.tsx +0 -157
  228. package/templates/web/src/components/ui/button.tsx +0 -58
  229. package/templates/web/src/components/ui/card.tsx +0 -92
  230. package/templates/web/src/components/ui/dropdown-menu.tsx +0 -200
  231. package/templates/web/src/components/ui/navigation-menu.tsx +0 -168
  232. package/templates/web/src/components/ui/toast.tsx +0 -128
  233. package/templates/web/src/components/ui/toaster.tsx +0 -35
  234. package/templates/web/src/components/ui/use-toast.ts +0 -187
  235. package/templates/web/src/hooks/useGeneratorMRU.ts +0 -57
  236. package/templates/web/src/lib/utils.ts +0 -6
  237. package/templates/web/tsconfig.json +0 -41
package/dist/index.js CHANGED
@@ -3218,8 +3218,8 @@ var require_utils = __commonJS({
3218
3218
  }
3219
3219
  return ind;
3220
3220
  }
3221
- function removeDotSegments(path17) {
3222
- let input = path17;
3221
+ function removeDotSegments(path18) {
3222
+ let input = path18;
3223
3223
  const output = [];
3224
3224
  let nextSlash = -1;
3225
3225
  let len = 0;
@@ -3418,8 +3418,8 @@ var require_schemes = __commonJS({
3418
3418
  wsComponent.secure = void 0;
3419
3419
  }
3420
3420
  if (wsComponent.resourceName) {
3421
- const [path17, query] = wsComponent.resourceName.split("?");
3422
- wsComponent.path = path17 && path17 !== "/" ? path17 : void 0;
3421
+ const [path18, query] = wsComponent.resourceName.split("?");
3422
+ wsComponent.path = path18 && path18 !== "/" ? path18 : void 0;
3423
3423
  wsComponent.query = query;
3424
3424
  wsComponent.resourceName = void 0;
3425
3425
  }
@@ -6473,13 +6473,13 @@ import { Command } from "commander";
6473
6473
  import { readFileSync } from "fs";
6474
6474
  import { fileURLToPath as fileURLToPath3 } from "url";
6475
6475
  import { dirname, join } from "path";
6476
- import chalk13 from "chalk";
6476
+ import chalk14 from "chalk";
6477
6477
 
6478
6478
  // src/commands/up.ts
6479
- import { execa as execa2 } from "execa";
6480
- import fs5 from "fs-extra";
6481
- import path5 from "path";
6482
- import chalk2 from "chalk";
6479
+ import { execa as execa3 } from "execa";
6480
+ import fs6 from "fs-extra";
6481
+ import path6 from "path";
6482
+ import chalk3 from "chalk";
6483
6483
  import ora2 from "ora";
6484
6484
  import prompts2 from "prompts";
6485
6485
 
@@ -6709,41 +6709,120 @@ async function execAsync(command, options) {
6709
6709
  return execa(cmd, args, options);
6710
6710
  }
6711
6711
 
6712
- // src/utils/monorepo-detection.ts
6712
+ // src/utils/root-package.ts
6713
6713
  import fs2 from "fs-extra";
6714
6714
  import path2 from "path";
6715
+ import chalk2 from "chalk";
6716
+ import { execa as execa2 } from "execa";
6717
+ function createRootPackageJsonContent(projectName, cliVersion) {
6718
+ return {
6719
+ name: projectName,
6720
+ private: true,
6721
+ description: "Baseboards project - AI-powered creative toolkit",
6722
+ scripts: {
6723
+ dev: "baseboards dev",
6724
+ up: "baseboards up",
6725
+ down: "baseboards down",
6726
+ logs: "baseboards logs -f",
6727
+ status: "baseboards status",
6728
+ clean: "baseboards clean"
6729
+ },
6730
+ devDependencies: {
6731
+ "@weirdfingers/baseboards": `^${cliVersion}`
6732
+ }
6733
+ };
6734
+ }
6735
+ async function generateRootPackageJson(projectDir, projectName, cliVersion) {
6736
+ const packageJsonPath = path2.join(projectDir, "package.json");
6737
+ if (await fs2.pathExists(packageJsonPath)) {
6738
+ return;
6739
+ }
6740
+ const content = createRootPackageJsonContent(projectName, cliVersion);
6741
+ await fs2.writeJson(packageJsonPath, content, { spaces: 2 });
6742
+ }
6743
+ async function installRootDependencies(projectDir, packageManager) {
6744
+ const packageJsonPath = path2.join(projectDir, "package.json");
6745
+ if (!await fs2.pathExists(packageJsonPath)) {
6746
+ console.log(
6747
+ chalk2.yellow(
6748
+ "\n\u26A0\uFE0F No package.json found at project root, skipping dependency installation"
6749
+ )
6750
+ );
6751
+ return;
6752
+ }
6753
+ console.log(
6754
+ chalk2.cyan(
6755
+ `
6756
+ \u{1F4E6} Installing project dependencies with ${packageManager}...`
6757
+ )
6758
+ );
6759
+ try {
6760
+ await execa2(packageManager, ["install"], {
6761
+ cwd: projectDir,
6762
+ stdio: "inherit"
6763
+ });
6764
+ console.log(chalk2.green("\u2705 Project dependencies installed successfully"));
6765
+ console.log(
6766
+ chalk2.gray(" You can now use: ") + chalk2.cyan("npm run dev") + chalk2.gray(", ") + chalk2.cyan("npm run up") + chalk2.gray(", etc.")
6767
+ );
6768
+ } catch (error) {
6769
+ const errorMessage = error instanceof Error ? error.message : String(error);
6770
+ console.error(
6771
+ chalk2.red(`
6772
+ \u274C Failed to install dependencies: ${errorMessage}`)
6773
+ );
6774
+ console.log(chalk2.yellow("\nTroubleshooting:"));
6775
+ console.log(
6776
+ chalk2.gray(" \u2022 Check that package.json is valid:"),
6777
+ chalk2.cyan(`${projectDir}/package.json`)
6778
+ );
6779
+ console.log(
6780
+ chalk2.gray(` \u2022 Ensure ${packageManager} is installed:`),
6781
+ chalk2.cyan(`${packageManager} --version`)
6782
+ );
6783
+ console.log(
6784
+ chalk2.gray(" \u2022 Try running the install manually:"),
6785
+ chalk2.cyan(`cd ${projectDir} && ${packageManager} install`)
6786
+ );
6787
+ throw error;
6788
+ }
6789
+ }
6790
+
6791
+ // src/utils/monorepo-detection.ts
6792
+ import fs3 from "fs-extra";
6793
+ import path3 from "path";
6715
6794
  import { fileURLToPath as fileURLToPath2 } from "url";
6716
6795
  async function detectMonorepoRoot() {
6717
6796
  const currentFile = fileURLToPath2(import.meta.url);
6718
- const cliPackageDir = path2.resolve(path2.dirname(currentFile), "../..");
6797
+ const cliPackageDir = path3.resolve(path3.dirname(currentFile), "../..");
6719
6798
  let currentDir = cliPackageDir;
6720
6799
  const maxDepth = 5;
6721
6800
  for (let depth = 0; depth < maxDepth; depth++) {
6722
6801
  try {
6723
- const workspaceFile = path2.join(currentDir, "pnpm-workspace.yaml");
6724
- if (!await fs2.pathExists(workspaceFile)) {
6725
- const parentDir = path2.dirname(currentDir);
6802
+ const workspaceFile = path3.join(currentDir, "pnpm-workspace.yaml");
6803
+ if (!await fs3.pathExists(workspaceFile)) {
6804
+ const parentDir = path3.dirname(currentDir);
6726
6805
  if (parentDir === currentDir) {
6727
6806
  break;
6728
6807
  }
6729
6808
  currentDir = parentDir;
6730
6809
  continue;
6731
6810
  }
6732
- const frontendPackageJson = path2.join(
6811
+ const frontendPackageJson = path3.join(
6733
6812
  currentDir,
6734
6813
  "packages/frontend/package.json"
6735
6814
  );
6736
- if (!await fs2.pathExists(frontendPackageJson)) {
6737
- const parentDir = path2.dirname(currentDir);
6815
+ if (!await fs3.pathExists(frontendPackageJson)) {
6816
+ const parentDir = path3.dirname(currentDir);
6738
6817
  if (parentDir === currentDir) {
6739
6818
  break;
6740
6819
  }
6741
6820
  currentDir = parentDir;
6742
6821
  continue;
6743
6822
  }
6744
- const packageData = await fs2.readJSON(frontendPackageJson);
6823
+ const packageData = await fs3.readJSON(frontendPackageJson);
6745
6824
  if (packageData.name !== "@weirdfingers/boards") {
6746
- const parentDir = path2.dirname(currentDir);
6825
+ const parentDir = path3.dirname(currentDir);
6747
6826
  if (parentDir === currentDir) {
6748
6827
  break;
6749
6828
  }
@@ -6752,7 +6831,7 @@ async function detectMonorepoRoot() {
6752
6831
  }
6753
6832
  return currentDir;
6754
6833
  } catch (error) {
6755
- const parentDir = path2.dirname(currentDir);
6834
+ const parentDir = path3.dirname(currentDir);
6756
6835
  if (parentDir === currentDir) {
6757
6836
  break;
6758
6837
  }
@@ -6764,8 +6843,8 @@ async function detectMonorepoRoot() {
6764
6843
  }
6765
6844
 
6766
6845
  // src/utils/package-copy.ts
6767
- import fs3 from "fs-extra";
6768
- import path3 from "path";
6846
+ import fs4 from "fs-extra";
6847
+ import path4 from "path";
6769
6848
  function shouldCopyFile(filePath) {
6770
6849
  const excluded = [
6771
6850
  "node_modules",
@@ -6778,23 +6857,23 @@ function shouldCopyFile(filePath) {
6778
6857
  return !excluded.some((ex) => filePath.includes(ex));
6779
6858
  }
6780
6859
  async function copyFrontendPackage(monorepoRoot, targetDir) {
6781
- const sourceFrontendDir = path3.join(monorepoRoot, "packages/frontend");
6782
- if (!await fs3.pathExists(sourceFrontendDir)) {
6860
+ const sourceFrontendDir = path4.join(monorepoRoot, "packages/frontend");
6861
+ if (!await fs4.pathExists(sourceFrontendDir)) {
6783
6862
  throw new Error(
6784
6863
  `Frontend package not found at: ${sourceFrontendDir}
6785
6864
  The monorepo structure may be corrupted.`
6786
6865
  );
6787
6866
  }
6788
- await fs3.ensureDir(targetDir);
6867
+ await fs4.ensureDir(targetDir);
6789
6868
  try {
6790
- await fs3.copy(sourceFrontendDir, targetDir, {
6869
+ await fs4.copy(sourceFrontendDir, targetDir, {
6791
6870
  filter: (src) => shouldCopyFile(src),
6792
6871
  overwrite: true,
6793
6872
  errorOnExist: false
6794
6873
  });
6795
6874
  } catch (error) {
6796
6875
  try {
6797
- await fs3.remove(targetDir);
6876
+ await fs4.remove(targetDir);
6798
6877
  } catch {
6799
6878
  }
6800
6879
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -6814,15 +6893,15 @@ Error: ${errorMessage}`
6814
6893
  }
6815
6894
  }
6816
6895
  async function updatePackageJsonForDevPackages(webDir) {
6817
- const packageJsonPath = path3.join(webDir, "package.json");
6818
- if (!await fs3.pathExists(packageJsonPath)) {
6896
+ const packageJsonPath = path4.join(webDir, "package.json");
6897
+ if (!await fs4.pathExists(packageJsonPath)) {
6819
6898
  throw new Error(
6820
6899
  `package.json not found at: ${packageJsonPath}
6821
6900
  The web directory may not be properly scaffolded.`
6822
6901
  );
6823
6902
  }
6824
6903
  try {
6825
- const packageData = await fs3.readJSON(packageJsonPath);
6904
+ const packageData = await fs4.readJSON(packageJsonPath);
6826
6905
  if (packageData.dependencies && packageData.dependencies["@weirdfingers/boards"]) {
6827
6906
  packageData.dependencies["@weirdfingers/boards"] = "file:../frontend";
6828
6907
  } else if (packageData.devDependencies && packageData.devDependencies["@weirdfingers/boards"]) {
@@ -6833,7 +6912,7 @@ The web directory may not be properly scaffolded.`
6833
6912
  The package may not be installed or the package.json structure is unexpected.`
6834
6913
  );
6835
6914
  }
6836
- await fs3.writeJSON(packageJsonPath, packageData, { spaces: 2 });
6915
+ await fs4.writeJSON(packageJsonPath, packageData, { spaces: 2 });
6837
6916
  } catch (error) {
6838
6917
  const errorMessage = error instanceof Error ? error.message : String(error);
6839
6918
  if (errorMessage.includes("EACCES") || errorMessage.includes("EPERM")) {
@@ -6861,8 +6940,8 @@ Error: ${errorMessage}`
6861
6940
  }
6862
6941
 
6863
6942
  // src/utils/template-downloader.ts
6864
- import fs4 from "fs-extra";
6865
- import path4 from "path";
6943
+ import fs5 from "fs-extra";
6944
+ import path5 from "path";
6866
6945
  import { createHash } from "crypto";
6867
6946
  import { extract } from "tar";
6868
6947
  import { tmpdir, homedir } from "os";
@@ -7013,12 +7092,12 @@ function handleFetchError(error, context) {
7013
7092
  throw error;
7014
7093
  }
7015
7094
  function getCacheDir() {
7016
- return path4.join(homedir(), ".baseboards", "templates");
7095
+ return path5.join(homedir(), ".baseboards", "templates");
7017
7096
  }
7018
7097
  async function ensureCacheDir() {
7019
7098
  const cacheDir = getCacheDir();
7020
7099
  try {
7021
- await fs4.ensureDir(cacheDir);
7100
+ await fs5.ensureDir(cacheDir);
7022
7101
  } catch (error) {
7023
7102
  if (error.code === "EACCES" || error.code === "EPERM") {
7024
7103
  throw new PermissionError(
@@ -7087,15 +7166,15 @@ async function fetchTemplateManifest(version) {
7087
7166
  }
7088
7167
  await ensureCacheDir();
7089
7168
  const cacheDir = getCacheDir();
7090
- const cachedManifestPath = path4.join(cacheDir, `manifest-v${actualVersion}.json`);
7091
- if (await fs4.pathExists(cachedManifestPath)) {
7169
+ const cachedManifestPath = path5.join(cacheDir, `manifest-v${actualVersion}.json`);
7170
+ if (await fs5.pathExists(cachedManifestPath)) {
7092
7171
  try {
7093
- const cachedManifest = await fs4.readJson(cachedManifestPath);
7172
+ const cachedManifest = await fs5.readJson(cachedManifestPath);
7094
7173
  if (cachedManifest.version && Array.isArray(cachedManifest.templates)) {
7095
7174
  return cachedManifest;
7096
7175
  }
7097
7176
  } catch (error) {
7098
- await fs4.remove(cachedManifestPath);
7177
+ await fs5.remove(cachedManifestPath);
7099
7178
  }
7100
7179
  }
7101
7180
  const maxRetries = 3;
@@ -7142,7 +7221,7 @@ async function fetchTemplateManifest(version) {
7142
7221
  throw new Error("Invalid manifest structure");
7143
7222
  }
7144
7223
  try {
7145
- await fs4.writeJson(cachedManifestPath, manifest, { spaces: 2 });
7224
+ await fs5.writeJson(cachedManifestPath, manifest, { spaces: 2 });
7146
7225
  } catch (error) {
7147
7226
  if (error.code === "EACCES" || error.code === "EPERM") {
7148
7227
  } else if (error.code === "ENOSPC") {
@@ -7191,7 +7270,7 @@ async function verifyChecksum(filePath, expectedChecksum) {
7191
7270
  }
7192
7271
  const expectedHash = expectedChecksum.replace("sha256:", "");
7193
7272
  const hash = createHash("sha256");
7194
- const fileStream = fs4.createReadStream(filePath);
7273
+ const fileStream = fs5.createReadStream(filePath);
7195
7274
  return new Promise((resolve, reject) => {
7196
7275
  fileStream.on("data", (chunk) => {
7197
7276
  hash.update(chunk);
@@ -7235,13 +7314,13 @@ async function downloadTemplate(name, version, targetDir) {
7235
7314
  }
7236
7315
  await ensureCacheDir();
7237
7316
  const cacheDir = getCacheDir();
7238
- const cachedFilePath = path4.join(
7317
+ const cachedFilePath = path5.join(
7239
7318
  cacheDir,
7240
7319
  `template-${name}-v${manifest.version}.tar.gz`
7241
7320
  );
7242
7321
  let sourceFilePath;
7243
7322
  let cacheHit = false;
7244
- if (await fs4.pathExists(cachedFilePath)) {
7323
+ if (await fs5.pathExists(cachedFilePath)) {
7245
7324
  try {
7246
7325
  await verifyChecksum(cachedFilePath, template.checksum);
7247
7326
  sourceFilePath = cachedFilePath;
@@ -7252,7 +7331,7 @@ async function downloadTemplate(name, version, targetDir) {
7252
7331
  console.log(`Using cached template ${name}...`);
7253
7332
  }
7254
7333
  } catch (error) {
7255
- await fs4.remove(cachedFilePath);
7334
+ await fs5.remove(cachedFilePath);
7256
7335
  if (isInteractive) {
7257
7336
  console.log(`
7258
7337
  Downloading template ${name}...`);
@@ -7283,7 +7362,7 @@ Downloading template ${name}...`);
7283
7362
  );
7284
7363
  }
7285
7364
  try {
7286
- await fs4.ensureDir(targetDir);
7365
+ await fs5.ensureDir(targetDir);
7287
7366
  } catch (error) {
7288
7367
  if (error.code === "EACCES" || error.code === "EPERM") {
7289
7368
  throw new PermissionError(
@@ -7307,9 +7386,9 @@ Downloading template ${name}...`);
7307
7386
  console.log("Extracting template...");
7308
7387
  }
7309
7388
  const tempDir = tmpdir();
7310
- extractTempDir = path4.join(tempDir, `extract-${name}-${Date.now()}`);
7389
+ extractTempDir = path5.join(tempDir, `extract-${name}-${Date.now()}`);
7311
7390
  try {
7312
- await fs4.ensureDir(extractTempDir);
7391
+ await fs5.ensureDir(extractTempDir);
7313
7392
  } catch (error) {
7314
7393
  if (error.code === "ENOSPC") {
7315
7394
  throw new DiskSpaceError(
@@ -7333,11 +7412,11 @@ Downloading template ${name}...`);
7333
7412
  );
7334
7413
  }
7335
7414
  try {
7336
- const files = await fs4.readdir(extractTempDir);
7415
+ const files = await fs5.readdir(extractTempDir);
7337
7416
  for (const file of files) {
7338
- const srcPath = path4.join(extractTempDir, file);
7339
- const destPath = path4.join(targetDir, file);
7340
- await fs4.move(srcPath, destPath, { overwrite: true });
7417
+ const srcPath = path5.join(extractTempDir, file);
7418
+ const destPath = path5.join(targetDir, file);
7419
+ await fs5.move(srcPath, destPath, { overwrite: true });
7341
7420
  }
7342
7421
  } catch (error) {
7343
7422
  if (error.code === "EACCES" || error.code === "EPERM") {
@@ -7356,7 +7435,7 @@ Downloading template ${name}...`);
7356
7435
  }
7357
7436
  throw error;
7358
7437
  }
7359
- await fs4.remove(extractTempDir);
7438
+ await fs5.remove(extractTempDir);
7360
7439
  extractTempDir = null;
7361
7440
  if (spinner && isInteractive) {
7362
7441
  spinner.succeed("Template ready");
@@ -7368,11 +7447,11 @@ Downloading template ${name}...`);
7368
7447
  spinner.fail("Download failed");
7369
7448
  }
7370
7449
  try {
7371
- if (tempFilePath && await fs4.pathExists(tempFilePath)) {
7372
- await fs4.remove(tempFilePath);
7450
+ if (tempFilePath && await fs5.pathExists(tempFilePath)) {
7451
+ await fs5.remove(tempFilePath);
7373
7452
  }
7374
- if (extractTempDir && await fs4.pathExists(extractTempDir)) {
7375
- await fs4.remove(extractTempDir);
7453
+ if (extractTempDir && await fs5.pathExists(extractTempDir)) {
7454
+ await fs5.remove(extractTempDir);
7376
7455
  }
7377
7456
  } catch (cleanupError) {
7378
7457
  }
@@ -7384,7 +7463,7 @@ async function downloadAndCache(version, template, cachedFilePath, spinner = nul
7384
7463
  const maxChecksumRetries = 2;
7385
7464
  for (let checksumAttempt = 1; checksumAttempt <= maxChecksumRetries; checksumAttempt++) {
7386
7465
  const tempDir = tmpdir();
7387
- const tempFilePath = path4.join(tempDir, `${template.file}.tmp-${Date.now()}`);
7466
+ const tempFilePath = path5.join(tempDir, `${template.file}.tmp-${Date.now()}`);
7388
7467
  try {
7389
7468
  const maxDownloadRetries = 3;
7390
7469
  let downloadedBytes = 0;
@@ -7465,7 +7544,7 @@ async function downloadAndCache(version, template, cachedFilePath, spinner = nul
7465
7544
  let lastTime = Date.now();
7466
7545
  let lastLoaded = 0;
7467
7546
  const reader = response.body.getReader();
7468
- const fileStream = fs4.createWriteStream(tempFilePath);
7547
+ const fileStream = fs5.createWriteStream(tempFilePath);
7469
7548
  try {
7470
7549
  while (true) {
7471
7550
  const { done, value } = await reader.read();
@@ -7510,7 +7589,7 @@ async function downloadAndCache(version, template, cachedFilePath, spinner = nul
7510
7589
  }
7511
7590
  await verifyChecksum(tempFilePath, template.checksum);
7512
7591
  try {
7513
- await fs4.move(tempFilePath, cachedFilePath, { overwrite: true });
7592
+ await fs5.move(tempFilePath, cachedFilePath, { overwrite: true });
7514
7593
  } catch (error) {
7515
7594
  if (error.code === "ENOSPC") {
7516
7595
  throw new DiskSpaceError(
@@ -7532,8 +7611,8 @@ async function downloadAndCache(version, template, cachedFilePath, spinner = nul
7532
7611
  } catch (error) {
7533
7612
  if (error instanceof ChecksumError) {
7534
7613
  if (checksumAttempt < maxChecksumRetries) {
7535
- if (await fs4.pathExists(tempFilePath)) {
7536
- await fs4.remove(tempFilePath);
7614
+ if (await fs5.pathExists(tempFilePath)) {
7615
+ await fs5.remove(tempFilePath);
7537
7616
  }
7538
7617
  if (spinner) {
7539
7618
  spinner.text = `Checksum verification failed. Retrying download (attempt ${checksumAttempt + 1}/${maxChecksumRetries})...`;
@@ -7556,8 +7635,8 @@ async function downloadAndCache(version, template, cachedFilePath, spinner = nul
7556
7635
  }
7557
7636
  } catch (error) {
7558
7637
  try {
7559
- if (await fs4.pathExists(tempFilePath)) {
7560
- await fs4.remove(tempFilePath);
7638
+ if (await fs5.pathExists(tempFilePath)) {
7639
+ await fs5.remove(tempFilePath);
7561
7640
  }
7562
7641
  } catch (cleanupError) {
7563
7642
  }
@@ -7574,12 +7653,12 @@ async function clearCache() {
7574
7653
  const cacheDir = getCacheDir();
7575
7654
  await ensureCacheDir();
7576
7655
  try {
7577
- const files = await fs4.readdir(cacheDir);
7656
+ const files = await fs5.readdir(cacheDir);
7578
7657
  for (const file of files) {
7579
- const filePath = path4.join(cacheDir, file);
7580
- const stat = await fs4.stat(filePath);
7658
+ const filePath = path5.join(cacheDir, file);
7659
+ const stat = await fs5.stat(filePath);
7581
7660
  if (stat.isFile()) {
7582
- await fs4.remove(filePath);
7661
+ await fs5.remove(filePath);
7583
7662
  }
7584
7663
  }
7585
7664
  } catch (error) {
@@ -7601,34 +7680,34 @@ async function validateTemplate(templateName, version) {
7601
7680
  }
7602
7681
  }
7603
7682
  async function installFrontendDependencies(ctx) {
7604
- const webDir = path5.join(ctx.dir, "web");
7605
- const packageJsonPath = path5.join(webDir, "package.json");
7606
- if (!fs5.existsSync(packageJsonPath)) {
7607
- console.log(chalk2.yellow("\n\u26A0\uFE0F No package.json found in web directory, skipping dependency installation"));
7683
+ const webDir = path6.join(ctx.dir, "web");
7684
+ const packageJsonPath = path6.join(webDir, "package.json");
7685
+ if (!fs6.existsSync(packageJsonPath)) {
7686
+ console.log(chalk3.yellow("\n\u26A0\uFE0F No package.json found in web directory, skipping dependency installation"));
7608
7687
  return;
7609
7688
  }
7610
7689
  if (!ctx.packageManager) {
7611
7690
  ctx.packageManager = await promptPackageManager();
7612
7691
  }
7613
7692
  const packageManager = ctx.packageManager;
7614
- console.log(chalk2.cyan(`
7693
+ console.log(chalk3.cyan(`
7615
7694
  \u{1F4E6} Installing frontend dependencies with ${packageManager}...`));
7616
7695
  const installCmd = "install";
7617
7696
  try {
7618
- await execa2(packageManager, [installCmd], {
7697
+ await execa3(packageManager, [installCmd], {
7619
7698
  cwd: webDir,
7620
7699
  stdio: "inherit"
7621
7700
  // Show install output to user
7622
7701
  });
7623
- console.log(chalk2.green("\u2705 Dependencies installed successfully\n"));
7702
+ console.log(chalk3.green("\u2705 Dependencies installed successfully\n"));
7624
7703
  } catch (error) {
7625
7704
  const errorMessage = error instanceof Error ? error.message : String(error);
7626
- console.error(chalk2.red(`
7705
+ console.error(chalk3.red(`
7627
7706
  \u274C Failed to install dependencies: ${errorMessage}`));
7628
- console.log(chalk2.yellow("\nTroubleshooting:"));
7629
- console.log(chalk2.gray(" \u2022 Check that package.json is valid:"), chalk2.cyan(`${webDir}/package.json`));
7630
- console.log(chalk2.gray(` \u2022 Ensure ${packageManager} is installed:`), chalk2.cyan(`${packageManager} --version`));
7631
- console.log(chalk2.gray(" \u2022 Try running the install manually:"), chalk2.cyan(`cd ${webDir} && ${packageManager} install`));
7707
+ console.log(chalk3.yellow("\nTroubleshooting:"));
7708
+ console.log(chalk3.gray(" \u2022 Check that package.json is valid:"), chalk3.cyan(`${webDir}/package.json`));
7709
+ console.log(chalk3.gray(` \u2022 Ensure ${packageManager} is installed:`), chalk3.cyan(`${packageManager} --version`));
7710
+ console.log(chalk3.gray(" \u2022 Try running the install manually:"), chalk3.cyan(`cd ${webDir} && ${packageManager} install`));
7632
7711
  throw error;
7633
7712
  }
7634
7713
  }
@@ -7659,12 +7738,12 @@ async function promptTemplateSelection(version) {
7659
7738
  }
7660
7739
  }
7661
7740
  async function up(directory, options) {
7662
- console.log(chalk2.blue.bold("\n\u{1F3A8} Baseboards CLI\n"));
7741
+ console.log(chalk3.blue.bold("\n\u{1F3A8} Baseboards CLI\n"));
7663
7742
  const spinner = ora2("Checking prerequisites...").start();
7664
7743
  await assertPrerequisites();
7665
7744
  spinner.succeed("Prerequisites OK");
7666
- const dir = path5.resolve(process.cwd(), directory);
7667
- const name = path5.basename(dir);
7745
+ const dir = path6.resolve(process.cwd(), directory);
7746
+ const name = path6.basename(dir);
7668
7747
  const version = getCliVersion();
7669
7748
  let customPorts = {};
7670
7749
  if (options.ports) {
@@ -7720,17 +7799,17 @@ async function up(directory, options) {
7720
7799
  await cleanupDockerVolumes(ctx);
7721
7800
  } else if (!ctx.isScaffolded) {
7722
7801
  console.log(
7723
- chalk2.yellow(
7802
+ chalk3.yellow(
7724
7803
  "\n\u26A0\uFE0F Existing Docker volumes detected from a previous installation"
7725
7804
  )
7726
7805
  );
7727
7806
  console.log(
7728
- chalk2.gray(
7807
+ chalk3.gray(
7729
7808
  " To avoid password mismatch errors, you can start fresh or cancel."
7730
7809
  )
7731
7810
  );
7732
7811
  console.log(
7733
- chalk2.gray(
7812
+ chalk3.gray(
7734
7813
  " Starting fresh will delete ALL existing data (boards, generated images, users)."
7735
7814
  )
7736
7815
  );
@@ -7741,22 +7820,22 @@ async function up(directory, options) {
7741
7820
  initial: true
7742
7821
  });
7743
7822
  if (response.cleanVolumes === void 0) {
7744
- console.log(chalk2.yellow("\n\u26A0\uFE0F Cancelled by user"));
7823
+ console.log(chalk3.yellow("\n\u26A0\uFE0F Cancelled by user"));
7745
7824
  process.exit(0);
7746
7825
  }
7747
7826
  if (response.cleanVolumes) {
7748
7827
  await cleanupDockerVolumes(ctx);
7749
7828
  } else {
7750
7829
  console.log(
7751
- chalk2.yellow(
7830
+ chalk3.yellow(
7752
7831
  "\n\u26A0\uFE0F Proceeding without cleaning volumes. If you encounter password errors:"
7753
7832
  )
7754
7833
  );
7755
7834
  console.log(
7756
- chalk2.cyan(" baseboards up --fresh") + chalk2.gray(" (start fresh)")
7835
+ chalk3.cyan(" baseboards up --fresh") + chalk3.gray(" (start fresh)")
7757
7836
  );
7758
7837
  console.log(
7759
- chalk2.cyan(" baseboards down --volumes && baseboards up") + chalk2.gray(" (manual cleanup)")
7838
+ chalk3.cyan(" baseboards down --volumes && baseboards up") + chalk3.gray(" (manual cleanup)")
7760
7839
  );
7761
7840
  }
7762
7841
  }
@@ -7764,24 +7843,24 @@ async function up(directory, options) {
7764
7843
  }
7765
7844
  if (!ctx.isScaffolded) {
7766
7845
  console.log(
7767
- chalk2.cyan(`
7768
- \u{1F4E6} Scaffolding new project: ${chalk2.bold(name)}`)
7846
+ chalk3.cyan(`
7847
+ \u{1F4E6} Scaffolding new project: ${chalk3.bold(name)}`)
7769
7848
  );
7770
7849
  await scaffoldProject(ctx);
7771
7850
  } else {
7772
7851
  console.log(
7773
- chalk2.green(`
7774
- \u2705 Project already scaffolded: ${chalk2.bold(name)}`)
7852
+ chalk3.green(`
7853
+ \u2705 Project already scaffolded: ${chalk3.bold(name)}`)
7775
7854
  );
7776
7855
  }
7777
7856
  if (ctx.devPackages && ctx.monorepoRoot) {
7778
7857
  const spinner2 = ora2("Copying @weirdfingers/boards source from monorepo...").start();
7779
7858
  try {
7780
- const targetFrontend = path5.join(ctx.dir, "frontend");
7859
+ const targetFrontend = path6.join(ctx.dir, "frontend");
7781
7860
  await copyFrontendPackage(ctx.monorepoRoot, targetFrontend);
7782
7861
  spinner2.succeed("Package source copied");
7783
7862
  spinner2.start("Linking local package...");
7784
- const webDir = path5.join(ctx.dir, "web");
7863
+ const webDir = path6.join(ctx.dir, "web");
7785
7864
  await updatePackageJsonForDevPackages(webDir);
7786
7865
  spinner2.succeed("Local package linked successfully");
7787
7866
  } catch (error) {
@@ -7799,28 +7878,34 @@ async function up(directory, options) {
7799
7878
  if (isFreshScaffold) {
7800
7879
  await promptForApiKeys(ctx);
7801
7880
  }
7802
- const apiEnvPath = path5.join(ctx.dir, "api/.env");
7881
+ if (isFreshScaffold) {
7882
+ if (!ctx.packageManager) {
7883
+ ctx.packageManager = await promptPackageManager();
7884
+ }
7885
+ await installRootDependencies(ctx.dir, ctx.packageManager);
7886
+ }
7887
+ const apiEnvPath = path6.join(ctx.dir, "api/.env");
7803
7888
  const missingKeys = detectMissingProviderKeys(apiEnvPath);
7804
7889
  if (missingKeys.length > 0) {
7805
- console.log(chalk2.yellow("\n\u26A0\uFE0F Provider API keys not configured!"));
7806
- console.log(chalk2.gray(" Add at least one API key to api/.env:"));
7890
+ console.log(chalk3.yellow("\n\u26A0\uFE0F Provider API keys not configured!"));
7891
+ console.log(chalk3.gray(" Add at least one API key to api/.env:"));
7807
7892
  console.log(
7808
- chalk2.cyan(" \u2022 REPLICATE_API_TOKEN") + chalk2.gray(" - https://replicate.com/account/api-tokens")
7893
+ chalk3.cyan(" \u2022 REPLICATE_API_TOKEN") + chalk3.gray(" - https://replicate.com/account/api-tokens")
7809
7894
  );
7810
7895
  console.log(
7811
- chalk2.cyan(" \u2022 FAL_KEY") + chalk2.gray(" - https://fal.ai/dashboard/keys")
7896
+ chalk3.cyan(" \u2022 FAL_KEY") + chalk3.gray(" - https://fal.ai/dashboard/keys")
7812
7897
  );
7813
7898
  console.log(
7814
- chalk2.cyan(" \u2022 KIE_API_KEY") + chalk2.gray(" - https://kie.ai/dashboard")
7899
+ chalk3.cyan(" \u2022 KIE_API_KEY") + chalk3.gray(" - https://kie.ai/dashboard")
7815
7900
  );
7816
7901
  console.log(
7817
- chalk2.cyan(" \u2022 OPENAI_API_KEY") + chalk2.gray(" - https://platform.openai.com/api-keys")
7902
+ chalk3.cyan(" \u2022 OPENAI_API_KEY") + chalk3.gray(" - https://platform.openai.com/api-keys")
7818
7903
  );
7819
7904
  console.log(
7820
- chalk2.cyan(" \u2022 GOOGLE_API_KEY") + chalk2.gray(" - https://makersuite.google.com/app/apikey")
7905
+ chalk3.cyan(" \u2022 GOOGLE_API_KEY") + chalk3.gray(" - https://makersuite.google.com/app/apikey")
7821
7906
  );
7822
7907
  console.log(
7823
- chalk2.gray(
7908
+ chalk3.gray(
7824
7909
  "\n The app will start, but image generation won't work without keys.\n"
7825
7910
  )
7826
7911
  );
@@ -7838,7 +7923,7 @@ async function up(directory, options) {
7838
7923
  } catch (error) {
7839
7924
  const maybeProcError = error;
7840
7925
  if (maybeProcError.signal === "SIGINT" || maybeProcError.exitCode === 130) {
7841
- console.log(chalk2.yellow("\n\n\u26A0\uFE0F Interrupted - services stopped"));
7926
+ console.log(chalk3.yellow("\n\n\u26A0\uFE0F Interrupted - services stopped"));
7842
7927
  process.exit(0);
7843
7928
  }
7844
7929
  throw error;
@@ -7846,29 +7931,32 @@ async function up(directory, options) {
7846
7931
  }
7847
7932
  }
7848
7933
  async function scaffoldProject(ctx) {
7849
- fs5.ensureDirSync(ctx.dir);
7934
+ fs6.ensureDirSync(ctx.dir);
7850
7935
  await downloadTemplate(ctx.template, ctx.version, ctx.dir);
7851
7936
  const spinner = ora2("Creating data directories...").start();
7852
- fs5.ensureDirSync(path5.join(ctx.dir, "data/storage"));
7937
+ fs6.ensureDirSync(path6.join(ctx.dir, "data/storage"));
7853
7938
  spinner.succeed("Data directories created");
7854
- console.log(chalk2.green(" \u2728 Project scaffolded successfully!"));
7939
+ spinner.start("Generating project configuration...");
7940
+ await generateRootPackageJson(ctx.dir, ctx.name, ctx.version);
7941
+ spinner.succeed("Project configuration created");
7942
+ console.log(chalk3.green(" \u2728 Project scaffolded successfully!"));
7855
7943
  }
7856
7944
  async function ensureEnvFiles(ctx) {
7857
7945
  const spinner = ora2("Configuring environment...").start();
7858
- const webEnvPath = path5.join(ctx.dir, "web/.env");
7859
- const webEnvExamplePath = path5.join(ctx.dir, "web/.env.example");
7860
- if (!fs5.existsSync(webEnvPath) && fs5.existsSync(webEnvExamplePath)) {
7861
- let webEnv = fs5.readFileSync(webEnvExamplePath, "utf-8");
7946
+ const webEnvPath = path6.join(ctx.dir, "web/.env");
7947
+ const webEnvExamplePath = path6.join(ctx.dir, "web/.env.example");
7948
+ if (!fs6.existsSync(webEnvPath) && fs6.existsSync(webEnvExamplePath)) {
7949
+ let webEnv = fs6.readFileSync(webEnvExamplePath, "utf-8");
7862
7950
  webEnv = webEnv.replace(
7863
7951
  "http://localhost:8800",
7864
7952
  `http://localhost:${ctx.ports.api}`
7865
7953
  );
7866
- fs5.writeFileSync(webEnvPath, webEnv);
7954
+ fs6.writeFileSync(webEnvPath, webEnv);
7867
7955
  }
7868
- const apiEnvPath = path5.join(ctx.dir, "api/.env");
7869
- const apiEnvExamplePath = path5.join(ctx.dir, "api/.env.example");
7870
- if (!fs5.existsSync(apiEnvPath) && fs5.existsSync(apiEnvExamplePath)) {
7871
- let apiEnv = fs5.readFileSync(apiEnvExamplePath, "utf-8");
7956
+ const apiEnvPath = path6.join(ctx.dir, "api/.env");
7957
+ const apiEnvExamplePath = path6.join(ctx.dir, "api/.env.example");
7958
+ if (!fs6.existsSync(apiEnvPath) && fs6.existsSync(apiEnvExamplePath)) {
7959
+ let apiEnv = fs6.readFileSync(apiEnvExamplePath, "utf-8");
7872
7960
  if (apiEnv.includes("BOARDS_JWT_SECRET=\n") || apiEnv.includes("BOARDS_JWT_SECRET=\r\n")) {
7873
7961
  const jwtSecret = generateSecret(32);
7874
7962
  apiEnv = apiEnv.replace(
@@ -7876,12 +7964,12 @@ async function ensureEnvFiles(ctx) {
7876
7964
  `BOARDS_JWT_SECRET=${jwtSecret}`
7877
7965
  );
7878
7966
  }
7879
- fs5.writeFileSync(apiEnvPath, apiEnv);
7967
+ fs6.writeFileSync(apiEnvPath, apiEnv);
7880
7968
  }
7881
- const dockerEnvPath = path5.join(ctx.dir, "docker/.env");
7882
- const dockerEnvExamplePath = path5.join(ctx.dir, "docker/env.example");
7883
- if (!fs5.existsSync(dockerEnvPath) && fs5.existsSync(dockerEnvExamplePath)) {
7884
- let dockerEnv = fs5.readFileSync(dockerEnvExamplePath, "utf-8");
7969
+ const dockerEnvPath = path6.join(ctx.dir, "docker/.env");
7970
+ const dockerEnvExamplePath = path6.join(ctx.dir, "docker/env.example");
7971
+ if (!fs6.existsSync(dockerEnvPath) && fs6.existsSync(dockerEnvExamplePath)) {
7972
+ let dockerEnv = fs6.readFileSync(dockerEnvExamplePath, "utf-8");
7885
7973
  const dbPassword = generatePassword(24);
7886
7974
  const dbPasswordEncoded = encodeURIComponent(dbPassword);
7887
7975
  dockerEnv = dockerEnv.replace(
@@ -7900,14 +7988,14 @@ async function ensureEnvFiles(ctx) {
7900
7988
  /PROJECT_NAME=.*/g,
7901
7989
  `PROJECT_NAME=${ctx.name}`
7902
7990
  );
7903
- fs5.writeFileSync(dockerEnvPath, dockerEnv);
7991
+ fs6.writeFileSync(dockerEnvPath, dockerEnv);
7904
7992
  }
7905
7993
  spinner.succeed("Environment configured");
7906
7994
  }
7907
7995
  async function promptForApiKeys(ctx) {
7908
- console.log(chalk2.cyan("\n\u{1F511} API Key Configuration"));
7909
- console.log(chalk2.gray("Add API keys to enable image generation providers"));
7910
- console.log(chalk2.gray("Press Enter to skip any key\n"));
7996
+ console.log(chalk3.cyan("\n\u{1F511} API Key Configuration"));
7997
+ console.log(chalk3.gray("Add API keys to enable image generation providers"));
7998
+ console.log(chalk3.gray("Press Enter to skip any key\n"));
7911
7999
  const response = await prompts2([
7912
8000
  {
7913
8001
  type: "password",
@@ -7948,8 +8036,8 @@ async function promptForApiKeys(ctx) {
7948
8036
  apiKeys.OPENAI_API_KEY = response.OPENAI_API_KEY.trim();
7949
8037
  }
7950
8038
  if (Object.keys(apiKeys).length > 0) {
7951
- const apiEnvPath = path5.join(ctx.dir, "api/.env");
7952
- let apiEnv = fs5.readFileSync(apiEnvPath, "utf-8");
8039
+ const apiEnvPath = path6.join(ctx.dir, "api/.env");
8040
+ let apiEnv = fs6.readFileSync(apiEnvPath, "utf-8");
7953
8041
  const jsonKeys = JSON.stringify(apiKeys);
7954
8042
  if (apiEnv.includes("BOARDS_GENERATOR_API_KEYS=")) {
7955
8043
  apiEnv = apiEnv.replace(
@@ -7965,14 +8053,14 @@ BOARDS_GENERATOR_API_KEYS=${jsonKeys}
7965
8053
  `
7966
8054
  );
7967
8055
  }
7968
- fs5.writeFileSync(apiEnvPath, apiEnv);
7969
- console.log(chalk2.green("\n\u2705 API keys saved to api/.env"));
8056
+ fs6.writeFileSync(apiEnvPath, apiEnv);
8057
+ console.log(chalk3.green("\n\u2705 API keys saved to api/.env"));
7970
8058
  console.log(
7971
- chalk2.gray(" You can edit this file anytime to add/update keys\n")
8059
+ chalk3.gray(" You can edit this file anytime to add/update keys\n")
7972
8060
  );
7973
8061
  } else {
7974
- console.log(chalk2.yellow("\n\u26A0\uFE0F No API keys provided"));
7975
- console.log(chalk2.gray(" You can add them later by editing api/.env\n"));
8062
+ console.log(chalk3.yellow("\n\u26A0\uFE0F No API keys provided"));
8063
+ console.log(chalk3.gray(" You can add them later by editing api/.env\n"));
7976
8064
  }
7977
8065
  }
7978
8066
  function getComposeFiles(ctx) {
@@ -7994,8 +8082,8 @@ async function startDockerCompose(ctx) {
7994
8082
  const spinner = ora2("Starting Docker Compose...").start();
7995
8083
  const composeFiles = getComposeFiles(ctx);
7996
8084
  for (const file of composeFiles) {
7997
- const filePath = path5.join(ctx.dir, file);
7998
- if (!fs5.existsSync(filePath)) {
8085
+ const filePath = path6.join(ctx.dir, file);
8086
+ if (!fs6.existsSync(filePath)) {
7999
8087
  spinner.fail(`Compose file not found: ${file}`);
8000
8088
  throw new Error(`Compose file not found: ${file}`);
8001
8089
  }
@@ -8008,7 +8096,7 @@ async function startDockerCompose(ctx) {
8008
8096
  "--remove-orphans"
8009
8097
  ];
8010
8098
  try {
8011
- await execa2("docker", composeArgs, {
8099
+ await execa3("docker", composeArgs, {
8012
8100
  cwd: ctx.dir,
8013
8101
  stdio: "inherit"
8014
8102
  });
@@ -8020,11 +8108,11 @@ async function startDockerCompose(ctx) {
8020
8108
  }
8021
8109
  async function attachToLogs(ctx) {
8022
8110
  console.log(
8023
- chalk2.gray("\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")
8111
+ chalk3.gray("\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")
8024
8112
  );
8025
- console.log(chalk2.gray("Streaming logs... (Press Ctrl+C to stop)\n"));
8113
+ console.log(chalk3.gray("Streaming logs... (Press Ctrl+C to stop)\n"));
8026
8114
  const composeArgs = [...getComposeBaseArgs(ctx), "logs", "-f"];
8027
- await execa2("docker", composeArgs, {
8115
+ await execa3("docker", composeArgs, {
8028
8116
  cwd: ctx.dir,
8029
8117
  stdio: "inherit"
8030
8118
  });
@@ -8038,7 +8126,7 @@ async function waitForHealthy(ctx) {
8038
8126
  const maxWaitMs = 12e4;
8039
8127
  const checkHealth = async () => {
8040
8128
  try {
8041
- const { stdout } = await execa2(
8129
+ const { stdout } = await execa3(
8042
8130
  "docker",
8043
8131
  [...getComposeBaseArgs(ctx), "ps", "--format", "json"],
8044
8132
  {
@@ -8068,21 +8156,21 @@ async function waitForHealthy(ctx) {
8068
8156
  } else {
8069
8157
  spinner.warn("Services taking longer than expected...");
8070
8158
  console.log(
8071
- chalk2.yellow(
8159
+ chalk3.yellow(
8072
8160
  "\n\u26A0\uFE0F Health check timeout. Services may still be starting."
8073
8161
  )
8074
8162
  );
8075
8163
  console.log(
8076
- chalk2.gray(" Run"),
8077
- chalk2.cyan("baseboards logs"),
8078
- chalk2.gray("to check progress.")
8164
+ chalk3.gray(" Run"),
8165
+ chalk3.cyan("baseboards logs"),
8166
+ chalk3.gray("to check progress.")
8079
8167
  );
8080
8168
  }
8081
8169
  }
8082
8170
  async function runMigrations(ctx) {
8083
8171
  const spinner = ora2("Running database migrations...").start();
8084
8172
  try {
8085
- const { stdout } = await execa2(
8173
+ const { stdout } = await execa3(
8086
8174
  "docker",
8087
8175
  [
8088
8176
  ...getComposeBaseArgs(ctx),
@@ -8098,12 +8186,12 @@ async function runMigrations(ctx) {
8098
8186
  }
8099
8187
  );
8100
8188
  if (stdout && (stdout.includes("Running upgrade") || process.env.DEBUG)) {
8101
- console.log(chalk2.gray("\n Migration output:"));
8102
- console.log(chalk2.gray(" " + stdout.split("\n").join("\n ")));
8189
+ console.log(chalk3.gray("\n Migration output:"));
8190
+ console.log(chalk3.gray(" " + stdout.split("\n").join("\n ")));
8103
8191
  }
8104
8192
  spinner.succeed("Database migrations complete");
8105
8193
  spinner.start("Restarting API to apply migrations...");
8106
- await execa2(
8194
+ await execa3(
8107
8195
  "docker",
8108
8196
  [...getComposeBaseArgs(ctx), "restart", "api"],
8109
8197
  {
@@ -8118,42 +8206,42 @@ async function runMigrations(ctx) {
8118
8206
  const isPasswordError = errorMessage.includes("password authentication failed") || errorMessage.includes("InvalidPasswordError");
8119
8207
  if (isPasswordError) {
8120
8208
  console.log(
8121
- chalk2.red(
8209
+ chalk3.red(
8122
8210
  "\n\u274C Database password mismatch - cannot connect to existing database"
8123
8211
  )
8124
8212
  );
8125
8213
  console.log(
8126
- chalk2.yellow(
8214
+ chalk3.yellow(
8127
8215
  " Existing database volumes have a different password than the current configuration."
8128
8216
  )
8129
8217
  );
8130
- console.log(chalk2.yellow("\n To fix this, choose one of:"));
8218
+ console.log(chalk3.yellow("\n To fix this, choose one of:"));
8131
8219
  console.log(
8132
- chalk2.cyan(" 1. Start fresh (deletes data):") + chalk2.gray(" baseboards down --volumes && baseboards up")
8220
+ chalk3.cyan(" 1. Start fresh (deletes data):") + chalk3.gray(" baseboards down --volumes && baseboards up")
8133
8221
  );
8134
8222
  console.log(
8135
- chalk2.cyan(" 2. Start fresh automatically:") + chalk2.gray(" baseboards up --fresh")
8223
+ chalk3.cyan(" 2. Start fresh automatically:") + chalk3.gray(" baseboards up --fresh")
8136
8224
  );
8137
8225
  console.log(
8138
- chalk2.gray(
8226
+ chalk3.gray(
8139
8227
  "\n This usually happens when project files were deleted but Docker volumes remain."
8140
8228
  )
8141
8229
  );
8142
8230
  } else {
8143
8231
  console.log(
8144
- chalk2.red(
8232
+ chalk3.red(
8145
8233
  "\n\u274C Database migrations failed"
8146
8234
  )
8147
8235
  );
8148
- console.log(chalk2.gray("\n Error details:"));
8149
- console.log(chalk2.gray(" " + errorMessage));
8236
+ console.log(chalk3.gray("\n Error details:"));
8237
+ console.log(chalk3.gray(" " + errorMessage));
8150
8238
  console.log(
8151
- chalk2.yellow(
8239
+ chalk3.yellow(
8152
8240
  "\n You can try running migrations manually:"
8153
8241
  )
8154
8242
  );
8155
8243
  console.log(
8156
- chalk2.cyan(" docker compose exec api alembic upgrade head")
8244
+ chalk3.cyan(" docker compose exec api alembic upgrade head")
8157
8245
  );
8158
8246
  }
8159
8247
  throw new Error("Database migrations failed");
@@ -8169,84 +8257,87 @@ function getDevCommand(pm) {
8169
8257
  return commands[pm];
8170
8258
  }
8171
8259
  function printDefaultSuccessMessage(ctx, hasKeyWarning) {
8172
- console.log(chalk2.green.bold("\n\u2705 Baseboards is running!\n"));
8260
+ console.log(chalk3.green.bold("\n\u2705 Baseboards is running!\n"));
8173
8261
  console.log(
8174
- chalk2.cyan(" Web: "),
8175
- chalk2.underline(`http://localhost:${ctx.ports.web}`)
8262
+ chalk3.cyan(" Web: "),
8263
+ chalk3.underline(`http://localhost:${ctx.ports.web}`)
8176
8264
  );
8177
8265
  console.log(
8178
- chalk2.cyan(" API: "),
8179
- chalk2.underline(`http://localhost:${ctx.ports.api}`)
8266
+ chalk3.cyan(" API: "),
8267
+ chalk3.underline(`http://localhost:${ctx.ports.api}`)
8180
8268
  );
8181
8269
  console.log(
8182
- chalk2.cyan(" GraphQL: "),
8183
- chalk2.underline(`http://localhost:${ctx.ports.api}/graphql`)
8270
+ chalk3.cyan(" GraphQL: "),
8271
+ chalk3.underline(`http://localhost:${ctx.ports.api}/graphql`)
8184
8272
  );
8185
8273
  if (hasKeyWarning) {
8186
- console.log(chalk2.yellow("\n\u26A0\uFE0F Remember to configure provider API keys!"));
8187
- console.log(chalk2.gray(" Edit:"), chalk2.cyan("api/.env"));
8274
+ console.log(chalk3.yellow("\n\u26A0\uFE0F Remember to configure provider API keys!"));
8275
+ console.log(chalk3.gray(" Edit:"), chalk3.cyan("api/.env"));
8188
8276
  console.log(
8189
- chalk2.gray(" Docs:"),
8190
- chalk2.cyan("https://baseboards.dev/docs/setup")
8277
+ chalk3.gray(" Docs:"),
8278
+ chalk3.cyan("https://baseboards.dev/docs/setup")
8191
8279
  );
8192
8280
  }
8193
- console.log(chalk2.gray("\nView logs:"), chalk2.cyan(`baseboards logs ${ctx.name} -f`));
8194
- console.log(chalk2.gray("Stop: "), chalk2.cyan(`baseboards down ${ctx.name}`));
8281
+ console.log(chalk3.gray("\nUseful commands:"));
8282
+ console.log(chalk3.gray(" View logs: "), chalk3.cyan("npm run logs"));
8283
+ console.log(chalk3.gray(" Stop: "), chalk3.cyan("npm run down"));
8195
8284
  console.log();
8196
8285
  }
8197
8286
  function printAppDevSuccessMessage(ctx, hasKeyWarning) {
8198
- console.log(chalk2.green.bold("\n\u2705 Backend services are running!\n"));
8287
+ console.log(chalk3.green.bold("\n\u2705 Backend services are running!\n"));
8199
8288
  console.log(
8200
- chalk2.cyan(" API: "),
8201
- chalk2.underline(`http://localhost:${ctx.ports.api}`)
8289
+ chalk3.cyan(" API: "),
8290
+ chalk3.underline(`http://localhost:${ctx.ports.api}`)
8202
8291
  );
8203
8292
  console.log(
8204
- chalk2.cyan(" GraphQL: "),
8205
- chalk2.underline(`http://localhost:${ctx.ports.api}/graphql`)
8293
+ chalk3.cyan(" GraphQL: "),
8294
+ chalk3.underline(`http://localhost:${ctx.ports.api}/graphql`)
8206
8295
  );
8207
- console.log(chalk2.cyan("\nTo start the frontend:\n"));
8208
- const relativeWebPath = path5.relative(process.cwd(), path5.join(ctx.dir, "web"));
8296
+ console.log(chalk3.cyan("\nTo start the frontend:\n"));
8297
+ const relativeWebPath = path6.relative(process.cwd(), path6.join(ctx.dir, "web"));
8209
8298
  const cdCommand = relativeWebPath || "web";
8210
8299
  const packageManager = ctx.packageManager || "pnpm";
8211
8300
  const devCommand = getDevCommand(packageManager);
8212
- console.log(chalk2.cyan(` cd ${cdCommand}`));
8213
- console.log(chalk2.cyan(` ${devCommand}`));
8214
- console.log(chalk2.gray("\nThe frontend will be available at"), chalk2.underline("http://localhost:3000"));
8301
+ console.log(chalk3.cyan(` cd ${cdCommand}`));
8302
+ console.log(chalk3.cyan(` ${devCommand}`));
8303
+ console.log(chalk3.gray("\nThe frontend will be available at"), chalk3.underline("http://localhost:3000"));
8215
8304
  if (hasKeyWarning) {
8216
- console.log(chalk2.yellow("\n\u26A0\uFE0F Remember to configure provider API keys!"));
8217
- console.log(chalk2.gray(" Edit:"), chalk2.cyan("api/.env"));
8305
+ console.log(chalk3.yellow("\n\u26A0\uFE0F Remember to configure provider API keys!"));
8306
+ console.log(chalk3.gray(" Edit:"), chalk3.cyan("api/.env"));
8218
8307
  }
8219
- console.log(chalk2.gray("\nView logs:"), chalk2.cyan(`baseboards logs ${ctx.name} -f`));
8220
- console.log(chalk2.gray("Stop: "), chalk2.cyan(`baseboards down ${ctx.name}`));
8308
+ console.log(chalk3.gray("\nUseful commands:"));
8309
+ console.log(chalk3.gray(" View logs: "), chalk3.cyan("npm run logs"));
8310
+ console.log(chalk3.gray(" Stop: "), chalk3.cyan("npm run down"));
8221
8311
  console.log();
8222
8312
  }
8223
8313
  function printDevPackagesSuccessMessage(ctx, hasKeyWarning) {
8224
- console.log(chalk2.green.bold("\n\u2705 Backend services are running!"));
8225
- console.log(chalk2.green.bold("\u2705 Local @weirdfingers/boards package linked!\n"));
8314
+ console.log(chalk3.green.bold("\n\u2705 Backend services are running!"));
8315
+ console.log(chalk3.green.bold("\u2705 Local @weirdfingers/boards package linked!\n"));
8226
8316
  console.log(
8227
- chalk2.cyan(" API: "),
8228
- chalk2.underline(`http://localhost:${ctx.ports.api}`)
8317
+ chalk3.cyan(" API: "),
8318
+ chalk3.underline(`http://localhost:${ctx.ports.api}`)
8229
8319
  );
8230
8320
  console.log(
8231
- chalk2.cyan(" GraphQL: "),
8232
- chalk2.underline(`http://localhost:${ctx.ports.api}/graphql`)
8321
+ chalk3.cyan(" GraphQL: "),
8322
+ chalk3.underline(`http://localhost:${ctx.ports.api}/graphql`)
8233
8323
  );
8234
- console.log(chalk2.cyan("\n\u{1F4E6} Package development workflow:\n"));
8235
- console.log(chalk2.gray(" 1. Edit package source:"));
8236
- console.log(chalk2.cyan(` ${ctx.dir}/frontend/src/`));
8237
- console.log(chalk2.gray("\n 2. Start the frontend:"));
8238
- console.log(chalk2.cyan(` cd ${ctx.dir}/web`));
8239
- console.log(chalk2.cyan(` pnpm install`));
8240
- console.log(chalk2.cyan(` pnpm dev`));
8241
- console.log(chalk2.gray("\n 3. Changes to the package will hot-reload automatically"));
8242
- console.log(chalk2.gray(`
8324
+ console.log(chalk3.cyan("\n\u{1F4E6} Package development workflow:\n"));
8325
+ console.log(chalk3.gray(" 1. Edit package source:"));
8326
+ console.log(chalk3.cyan(` ${ctx.dir}/frontend/src/`));
8327
+ console.log(chalk3.gray("\n 2. Start the frontend:"));
8328
+ console.log(chalk3.cyan(` cd ${ctx.dir}/web`));
8329
+ console.log(chalk3.cyan(` pnpm install`));
8330
+ console.log(chalk3.cyan(` pnpm dev`));
8331
+ console.log(chalk3.gray("\n 3. Changes to the package will hot-reload automatically"));
8332
+ console.log(chalk3.gray(`
8243
8333
  Frontend will be available at http://localhost:3000`));
8244
8334
  if (hasKeyWarning) {
8245
- console.log(chalk2.yellow("\n\u26A0\uFE0F Remember to configure provider API keys!"));
8246
- console.log(chalk2.gray(" Edit:"), chalk2.cyan("api/.env"));
8335
+ console.log(chalk3.yellow("\n\u26A0\uFE0F Remember to configure provider API keys!"));
8336
+ console.log(chalk3.gray(" Edit:"), chalk3.cyan("api/.env"));
8247
8337
  }
8248
- console.log(chalk2.gray("\nView logs:"), chalk2.cyan(`baseboards logs ${ctx.name} -f`));
8249
- console.log(chalk2.gray("Stop: "), chalk2.cyan(`baseboards down ${ctx.name}`));
8338
+ console.log(chalk3.gray("\nUseful commands:"));
8339
+ console.log(chalk3.gray(" View logs: "), chalk3.cyan("npm run logs"));
8340
+ console.log(chalk3.gray(" Stop: "), chalk3.cyan("npm run down"));
8250
8341
  console.log();
8251
8342
  }
8252
8343
  function printSuccessMessage(ctx, detached, hasKeyWarning) {
@@ -8260,7 +8351,7 @@ function printSuccessMessage(ctx, detached, hasKeyWarning) {
8260
8351
  }
8261
8352
  async function checkForExistingVolumes() {
8262
8353
  try {
8263
- const { stdout } = await execa2("docker", [
8354
+ const { stdout } = await execa3("docker", [
8264
8355
  "volume",
8265
8356
  "ls",
8266
8357
  "--format",
@@ -8277,14 +8368,14 @@ async function cleanupDockerVolumes(ctx) {
8277
8368
  const spinner = ora2("Cleaning up Docker volumes...").start();
8278
8369
  try {
8279
8370
  if (ctx.isScaffolded) {
8280
- await execa2("docker", [...getComposeBaseArgs(ctx), "down", "-v"], {
8371
+ await execa3("docker", [...getComposeBaseArgs(ctx), "down", "-v"], {
8281
8372
  cwd: ctx.dir
8282
8373
  });
8283
8374
  } else {
8284
8375
  const volumesToRemove = ["baseboards_db-data", "baseboards_api-storage"];
8285
8376
  for (const volumeName of volumesToRemove) {
8286
8377
  try {
8287
- await execa2("docker", ["volume", "rm", volumeName]);
8378
+ await execa3("docker", ["volume", "rm", volumeName]);
8288
8379
  spinner.text = `Removing volume ${volumeName}...`;
8289
8380
  } catch {
8290
8381
  }
@@ -8294,25 +8385,25 @@ async function cleanupDockerVolumes(ctx) {
8294
8385
  } catch (error) {
8295
8386
  spinner.fail("Failed to clean up volumes");
8296
8387
  console.log(
8297
- chalk2.yellow(
8388
+ chalk3.yellow(
8298
8389
  "\n\u26A0\uFE0F Could not clean up volumes automatically. Try manually:"
8299
8390
  )
8300
8391
  );
8301
- console.log(chalk2.cyan(" docker volume rm baseboards_db-data"));
8392
+ console.log(chalk3.cyan(" docker volume rm baseboards_db-data"));
8302
8393
  throw error;
8303
8394
  }
8304
8395
  }
8305
8396
 
8306
8397
  // src/commands/down.ts
8307
- import { execa as execa3 } from "execa";
8308
- import path6 from "path";
8309
- import chalk3 from "chalk";
8398
+ import { execa as execa4 } from "execa";
8399
+ import path7 from "path";
8400
+ import chalk4 from "chalk";
8310
8401
  import ora3 from "ora";
8311
8402
  async function down(directory, options) {
8312
- const dir = path6.resolve(process.cwd(), directory);
8403
+ const dir = path7.resolve(process.cwd(), directory);
8313
8404
  if (!isScaffolded(dir)) {
8314
- console.error(chalk3.red("\n\u274C Error: Not a Baseboards project"));
8315
- console.log(chalk3.gray(" Run"), chalk3.cyan("baseboards up"), chalk3.gray("to scaffold a project first."));
8405
+ console.error(chalk4.red("\n\u274C Error: Not a Baseboards project"));
8406
+ console.log(chalk4.gray(" Run"), chalk4.cyan("baseboards up"), chalk4.gray("to scaffold a project first."));
8316
8407
  process.exit(1);
8317
8408
  }
8318
8409
  const spinner = ora3("Stopping services...").start();
@@ -8321,12 +8412,12 @@ async function down(directory, options) {
8321
8412
  args.push("--volumes");
8322
8413
  }
8323
8414
  try {
8324
- await execa3("docker", args, {
8415
+ await execa4("docker", args, {
8325
8416
  cwd: dir
8326
8417
  });
8327
8418
  spinner.succeed("Services stopped");
8328
8419
  if (options.volumes) {
8329
- console.log(chalk3.yellow("\u26A0\uFE0F Volumes removed (database data deleted)"));
8420
+ console.log(chalk4.yellow("\u26A0\uFE0F Volumes removed (database data deleted)"));
8330
8421
  }
8331
8422
  } catch (error) {
8332
8423
  spinner.fail("Failed to stop services");
@@ -8335,14 +8426,14 @@ async function down(directory, options) {
8335
8426
  }
8336
8427
 
8337
8428
  // src/commands/logs.ts
8338
- import { execa as execa4 } from "execa";
8339
- import path7 from "path";
8340
- import chalk4 from "chalk";
8429
+ import { execa as execa5 } from "execa";
8430
+ import path8 from "path";
8431
+ import chalk5 from "chalk";
8341
8432
  async function logs(directory, services, options) {
8342
- const dir = path7.resolve(process.cwd(), directory);
8433
+ const dir = path8.resolve(process.cwd(), directory);
8343
8434
  if (!isScaffolded(dir)) {
8344
- console.error(chalk4.red("\n\u274C Error: Not a Baseboards project"));
8345
- console.log(chalk4.gray(" Run"), chalk4.cyan("baseboards up"), chalk4.gray("to scaffold a project first."));
8435
+ console.error(chalk5.red("\n\u274C Error: Not a Baseboards project"));
8436
+ console.log(chalk5.gray(" Run"), chalk5.cyan("baseboards up"), chalk5.gray("to scaffold a project first."));
8346
8437
  process.exit(1);
8347
8438
  }
8348
8439
  const args = ["compose", "logs"];
@@ -8359,7 +8450,7 @@ async function logs(directory, services, options) {
8359
8450
  args.push(...services);
8360
8451
  }
8361
8452
  try {
8362
- await execa4("docker", args, {
8453
+ await execa5("docker", args, {
8363
8454
  cwd: dir,
8364
8455
  stdio: "inherit"
8365
8456
  });
@@ -8371,46 +8462,46 @@ async function logs(directory, services, options) {
8371
8462
  }
8372
8463
 
8373
8464
  // src/commands/status.ts
8374
- import { execa as execa5 } from "execa";
8375
- import path8 from "path";
8376
- import chalk5 from "chalk";
8465
+ import { execa as execa6 } from "execa";
8466
+ import path9 from "path";
8467
+ import chalk6 from "chalk";
8377
8468
  async function status(directory) {
8378
- const dir = path8.resolve(process.cwd(), directory);
8469
+ const dir = path9.resolve(process.cwd(), directory);
8379
8470
  if (!isScaffolded(dir)) {
8380
- console.error(chalk5.red("\n\u274C Error: Not a Baseboards project"));
8381
- console.log(chalk5.gray(" Run"), chalk5.cyan("baseboards up"), chalk5.gray("to scaffold a project first."));
8471
+ console.error(chalk6.red("\n\u274C Error: Not a Baseboards project"));
8472
+ console.log(chalk6.gray(" Run"), chalk6.cyan("baseboards up"), chalk6.gray("to scaffold a project first."));
8382
8473
  process.exit(1);
8383
8474
  }
8384
- console.log(chalk5.blue.bold("\n\u{1F4CA} Service Status\n"));
8475
+ console.log(chalk6.blue.bold("\n\u{1F4CA} Service Status\n"));
8385
8476
  try {
8386
- await execa5("docker", ["compose", "ps"], {
8477
+ await execa6("docker", ["compose", "ps"], {
8387
8478
  cwd: dir,
8388
8479
  stdio: "inherit"
8389
8480
  });
8390
8481
  } catch (error) {
8391
- console.error(chalk5.red("\n\u274C Failed to get status"));
8482
+ console.error(chalk6.red("\n\u274C Failed to get status"));
8392
8483
  throw error;
8393
8484
  }
8394
8485
  }
8395
8486
 
8396
8487
  // src/commands/clean.ts
8397
- import { execa as execa6 } from "execa";
8398
- import path9 from "path";
8399
- import chalk6 from "chalk";
8488
+ import { execa as execa7 } from "execa";
8489
+ import path10 from "path";
8490
+ import chalk7 from "chalk";
8400
8491
  import ora4 from "ora";
8401
8492
  import prompts3 from "prompts";
8402
8493
  async function clean(directory, options) {
8403
- const dir = path9.resolve(process.cwd(), directory);
8494
+ const dir = path10.resolve(process.cwd(), directory);
8404
8495
  if (!isScaffolded(dir)) {
8405
- console.error(chalk6.red("\n\u274C Error: Not a Baseboards project"));
8406
- console.log(chalk6.gray(" Run"), chalk6.cyan("baseboards up"), chalk6.gray("to scaffold a project first."));
8496
+ console.error(chalk7.red("\n\u274C Error: Not a Baseboards project"));
8497
+ console.log(chalk7.gray(" Run"), chalk7.cyan("baseboards up"), chalk7.gray("to scaffold a project first."));
8407
8498
  process.exit(1);
8408
8499
  }
8409
8500
  if (options.hard) {
8410
- console.log(chalk6.yellow("\n\u26A0\uFE0F WARNING: This will delete:"));
8411
- console.log(chalk6.yellow(" \u2022 All containers"));
8412
- console.log(chalk6.yellow(" \u2022 All volumes (database data will be lost)"));
8413
- console.log(chalk6.yellow(" \u2022 All images"));
8501
+ console.log(chalk7.yellow("\n\u26A0\uFE0F WARNING: This will delete:"));
8502
+ console.log(chalk7.yellow(" \u2022 All containers"));
8503
+ console.log(chalk7.yellow(" \u2022 All volumes (database data will be lost)"));
8504
+ console.log(chalk7.yellow(" \u2022 All images"));
8414
8505
  const response = await prompts3({
8415
8506
  type: "confirm",
8416
8507
  name: "confirmed",
@@ -8418,33 +8509,33 @@ async function clean(directory, options) {
8418
8509
  initial: false
8419
8510
  });
8420
8511
  if (!response.confirmed) {
8421
- console.log(chalk6.gray("\nCancelled"));
8512
+ console.log(chalk7.gray("\nCancelled"));
8422
8513
  return;
8423
8514
  }
8424
8515
  }
8425
8516
  const spinner = ora4("Cleaning up...").start();
8426
8517
  try {
8427
- await execa6("docker", ["compose", "down", "--volumes", "--remove-orphans"], {
8518
+ await execa7("docker", ["compose", "down", "--volumes", "--remove-orphans"], {
8428
8519
  cwd: dir
8429
8520
  });
8430
8521
  if (options.hard) {
8431
8522
  try {
8432
- const { stdout } = await execa6("docker", ["compose", "images", "-q"], {
8523
+ const { stdout } = await execa7("docker", ["compose", "images", "-q"], {
8433
8524
  cwd: dir
8434
8525
  });
8435
8526
  const imageIds = stdout.split("\n").filter(Boolean);
8436
8527
  if (imageIds.length > 0) {
8437
- await execa6("docker", ["rmi", ...imageIds]);
8528
+ await execa7("docker", ["rmi", ...imageIds]);
8438
8529
  }
8439
8530
  } catch (e) {
8440
8531
  }
8441
8532
  }
8442
8533
  spinner.succeed("Cleanup complete");
8443
8534
  if (options.hard) {
8444
- console.log(chalk6.green("\n\u2728 All Docker resources removed"));
8445
- console.log(chalk6.gray(" Run"), chalk6.cyan("baseboards up"), chalk6.gray("to start fresh."));
8535
+ console.log(chalk7.green("\n\u2728 All Docker resources removed"));
8536
+ console.log(chalk7.gray(" Run"), chalk7.cyan("baseboards up"), chalk7.gray("to start fresh."));
8446
8537
  } else {
8447
- console.log(chalk6.green("\n\u2728 Containers and volumes removed"));
8538
+ console.log(chalk7.green("\n\u2728 Containers and volumes removed"));
8448
8539
  }
8449
8540
  } catch (error) {
8450
8541
  spinner.fail("Cleanup failed");
@@ -8453,34 +8544,34 @@ async function clean(directory, options) {
8453
8544
  }
8454
8545
 
8455
8546
  // src/commands/update.ts
8456
- import path10 from "path";
8457
- import chalk7 from "chalk";
8547
+ import path11 from "path";
8548
+ import chalk8 from "chalk";
8458
8549
  async function update(directory, options) {
8459
- const dir = path10.resolve(process.cwd(), directory);
8550
+ const dir = path11.resolve(process.cwd(), directory);
8460
8551
  if (!isScaffolded(dir)) {
8461
- console.error(chalk7.red("\n\u274C Error: Not a Baseboards project"));
8462
- console.log(chalk7.gray(" Run"), chalk7.cyan("baseboards up"), chalk7.gray("to scaffold a project first."));
8552
+ console.error(chalk8.red("\n\u274C Error: Not a Baseboards project"));
8553
+ console.log(chalk8.gray(" Run"), chalk8.cyan("baseboards up"), chalk8.gray("to scaffold a project first."));
8463
8554
  process.exit(1);
8464
8555
  }
8465
- console.log(chalk7.blue.bold("\n\u{1F504} Update Command\n"));
8466
- console.log(chalk7.yellow("\u26A0\uFE0F This feature is coming soon!"));
8467
- console.log(chalk7.gray("\nFor now, to update:"));
8468
- console.log(chalk7.gray("1. Update the CLI:"), chalk7.cyan("npm install -g @weirdfingers/baseboards@latest"));
8469
- console.log(chalk7.gray("2. Pull new images:"), chalk7.cyan("docker compose pull"));
8470
- console.log(chalk7.gray("3. Restart:"), chalk7.cyan("baseboards down && baseboards up"));
8556
+ console.log(chalk8.blue.bold("\n\u{1F504} Update Command\n"));
8557
+ console.log(chalk8.yellow("\u26A0\uFE0F This feature is coming soon!"));
8558
+ console.log(chalk8.gray("\nFor now, to update:"));
8559
+ console.log(chalk8.gray("1. Update the CLI:"), chalk8.cyan("npm install -g @weirdfingers/baseboards@latest"));
8560
+ console.log(chalk8.gray("2. Pull new images:"), chalk8.cyan("docker compose pull"));
8561
+ console.log(chalk8.gray("3. Restart:"), chalk8.cyan("baseboards down && baseboards up"));
8471
8562
  console.log();
8472
8563
  }
8473
8564
 
8474
8565
  // src/commands/upgrade.ts
8475
- import path15 from "path";
8476
- import chalk10 from "chalk";
8566
+ import path16 from "path";
8567
+ import chalk11 from "chalk";
8477
8568
  import prompts4 from "prompts";
8478
8569
 
8479
8570
  // src/utils/mode-detection.ts
8480
8571
  import { exec } from "child_process";
8481
8572
  import { promisify } from "util";
8482
- import path11 from "path";
8483
- import fs6 from "fs-extra";
8573
+ import path12 from "path";
8574
+ import fs7 from "fs-extra";
8484
8575
  var execAsync2 = promisify(exec);
8485
8576
  async function detectProjectMode(projectDir) {
8486
8577
  try {
@@ -8491,15 +8582,15 @@ async function detectProjectMode(projectDir) {
8491
8582
  }
8492
8583
  } catch {
8493
8584
  }
8494
- const modeFile = path11.join(projectDir, ".baseboards-mode");
8495
- if (await fs6.pathExists(modeFile)) {
8496
- const mode = (await fs6.readFile(modeFile, "utf-8")).trim();
8585
+ const modeFile = path12.join(projectDir, ".baseboards-mode");
8586
+ if (await fs7.pathExists(modeFile)) {
8587
+ const mode = (await fs7.readFile(modeFile, "utf-8")).trim();
8497
8588
  if (mode === "default" || mode === "app-dev") {
8498
8589
  return mode;
8499
8590
  }
8500
8591
  }
8501
- const webNodeModules = path11.join(projectDir, "web", "node_modules");
8502
- if (await fs6.pathExists(webNodeModules)) {
8592
+ const webNodeModules = path12.join(projectDir, "web", "node_modules");
8593
+ if (await fs7.pathExists(webNodeModules)) {
8503
8594
  return "app-dev";
8504
8595
  }
8505
8596
  return "default";
@@ -8510,8 +8601,8 @@ import semver from "semver";
8510
8601
 
8511
8602
  // src/utils/compatibility-fetcher.ts
8512
8603
  var import_ajv = __toESM(require_ajv(), 1);
8513
- import fs7 from "fs-extra";
8514
- import path12 from "path";
8604
+ import fs8 from "fs-extra";
8605
+ import path13 from "path";
8515
8606
  import os from "os";
8516
8607
  import addFormats from "ajv-formats";
8517
8608
 
@@ -8574,7 +8665,7 @@ var compatibility_manifest_schema_default = {
8574
8665
 
8575
8666
  // src/utils/compatibility-fetcher.ts
8576
8667
  var GITHUB_REPO = "weirdfingers/boards";
8577
- var CACHE_DIR = path12.join(os.homedir(), ".baseboards", "compatibility");
8668
+ var CACHE_DIR = path13.join(os.homedir(), ".baseboards", "compatibility");
8578
8669
  var ajv = new import_ajv.default({ strict: false });
8579
8670
  addFormats(ajv);
8580
8671
  var validateManifest = ajv.compile(compatibility_manifest_schema_default);
@@ -8622,31 +8713,31 @@ function getManifestUrl(version) {
8622
8713
  }
8623
8714
  async function loadFromCache(version) {
8624
8715
  const cachePath = getCachePath(version);
8625
- if (!await fs7.pathExists(cachePath)) {
8716
+ if (!await fs8.pathExists(cachePath)) {
8626
8717
  return null;
8627
8718
  }
8628
8719
  try {
8629
- const content = await fs7.readFile(cachePath, "utf-8");
8720
+ const content = await fs8.readFile(cachePath, "utf-8");
8630
8721
  const manifest = JSON.parse(content);
8631
8722
  if (!validateManifest(manifest)) {
8632
- await fs7.remove(cachePath);
8723
+ await fs8.remove(cachePath);
8633
8724
  return null;
8634
8725
  }
8635
8726
  return manifest;
8636
8727
  } catch (error) {
8637
- await fs7.remove(cachePath).catch(() => {
8728
+ await fs8.remove(cachePath).catch(() => {
8638
8729
  });
8639
8730
  return null;
8640
8731
  }
8641
8732
  }
8642
8733
  async function saveToCache(version, manifest) {
8643
8734
  const cachePath = getCachePath(version);
8644
- await fs7.ensureDir(CACHE_DIR);
8645
- await fs7.writeFile(cachePath, JSON.stringify(manifest, null, 2), "utf-8");
8735
+ await fs8.ensureDir(CACHE_DIR);
8736
+ await fs8.writeFile(cachePath, JSON.stringify(manifest, null, 2), "utf-8");
8646
8737
  }
8647
8738
  function getCachePath(version) {
8648
8739
  const cleanVersion = version.replace(/^v/, "");
8649
- return path12.join(CACHE_DIR, `compatibility-${cleanVersion}.json`);
8740
+ return path13.join(CACHE_DIR, `compatibility-${cleanVersion}.json`);
8650
8741
  }
8651
8742
 
8652
8743
  // src/utils/compatibility-checker.ts
@@ -8698,70 +8789,70 @@ function isVersionAffected(version, affectedRange) {
8698
8789
  }
8699
8790
 
8700
8791
  // src/commands/upgrade-default.ts
8701
- import path13 from "path";
8702
- import fs8 from "fs-extra";
8703
- import chalk8 from "chalk";
8704
- import { execa as execa7 } from "execa";
8792
+ import path14 from "path";
8793
+ import fs9 from "fs-extra";
8794
+ import chalk9 from "chalk";
8795
+ import { execa as execa8 } from "execa";
8705
8796
  import ora5 from "ora";
8706
8797
  async function upgradeDefaultMode(projectDir, currentVersion, targetVersion) {
8707
- console.log(chalk8.blue(`
8798
+ console.log(chalk9.blue(`
8708
8799
  \u{1F4E6} Upgrading from v${currentVersion} to v${targetVersion}
8709
8800
  `));
8710
8801
  try {
8711
- console.log(chalk8.gray("\u23F8\uFE0F Stopping services..."));
8802
+ console.log(chalk9.gray("\u23F8\uFE0F Stopping services..."));
8712
8803
  await execAsync3("docker compose --env-file docker/.env down", { cwd: projectDir });
8713
- console.log(chalk8.gray("\u2B07\uFE0F Pulling new backend images..."));
8804
+ console.log(chalk9.gray("\u2B07\uFE0F Pulling new backend images..."));
8714
8805
  await execAsync3("docker compose --env-file docker/.env pull api worker", { cwd: projectDir });
8715
- console.log(chalk8.gray("\u{1F4DD} Updating frontend dependencies..."));
8806
+ console.log(chalk9.gray("\u{1F4DD} Updating frontend dependencies..."));
8716
8807
  await updateWebPackageJson(projectDir, targetVersion);
8717
- console.log(chalk8.gray("\u{1F528} Rebuilding frontend image (this may take a few minutes)..."));
8808
+ console.log(chalk9.gray("\u{1F528} Rebuilding frontend image (this may take a few minutes)..."));
8718
8809
  await execAsync3("docker compose --env-file docker/.env build web", { cwd: projectDir });
8719
- console.log(chalk8.gray("\u2699\uFE0F Updating configuration..."));
8810
+ console.log(chalk9.gray("\u2699\uFE0F Updating configuration..."));
8720
8811
  await updateEnvVersion(projectDir, targetVersion);
8721
- console.log(chalk8.gray("\u{1F680} Starting services..."));
8812
+ console.log(chalk9.gray("\u{1F680} Starting services..."));
8722
8813
  await execAsync3("docker compose --env-file docker/.env up -d", { cwd: projectDir });
8723
- console.log(chalk8.gray("\u{1F3E5} Waiting for services to be healthy..."));
8814
+ console.log(chalk9.gray("\u{1F3E5} Waiting for services to be healthy..."));
8724
8815
  await waitForHealth(projectDir, ["db", "cache", "api", "worker", "web"]);
8725
- console.log(chalk8.green(`
8816
+ console.log(chalk9.green(`
8726
8817
  \u2705 Successfully upgraded to v${targetVersion}!
8727
8818
  `));
8728
8819
  printUpgradeSuccess(projectDir, targetVersion);
8729
8820
  } catch (error) {
8730
8821
  const errorMessage = error instanceof Error ? error.message : String(error);
8731
- console.error(chalk8.red(`
8822
+ console.error(chalk9.red(`
8732
8823
  \u274C Upgrade failed: ${errorMessage}
8733
8824
  `));
8734
- console.log(chalk8.yellow("To rollback:"));
8735
- console.log(chalk8.gray(` 1. Edit docker/.env and set BACKEND_VERSION=${currentVersion}`));
8736
- console.log(chalk8.gray(" 2. Run: docker compose pull"));
8737
- console.log(chalk8.gray(" 3. Run: docker compose build web"));
8738
- console.log(chalk8.gray(" 4. Run: docker compose up -d\n"));
8825
+ console.log(chalk9.yellow("To rollback:"));
8826
+ console.log(chalk9.gray(` 1. Edit docker/.env and set BACKEND_VERSION=${currentVersion}`));
8827
+ console.log(chalk9.gray(" 2. Run: docker compose pull"));
8828
+ console.log(chalk9.gray(" 3. Run: docker compose build web"));
8829
+ console.log(chalk9.gray(" 4. Run: docker compose up -d\n"));
8739
8830
  throw error;
8740
8831
  }
8741
8832
  }
8742
8833
  async function updateWebPackageJson(projectDir, version) {
8743
- const packageJsonPath = path13.join(projectDir, "web", "package.json");
8744
- const packageJson2 = await fs8.readJson(packageJsonPath);
8834
+ const packageJsonPath = path14.join(projectDir, "web", "package.json");
8835
+ const packageJson2 = await fs9.readJson(packageJsonPath);
8745
8836
  if (packageJson2.dependencies && packageJson2.dependencies["@weirdfingers/boards"]) {
8746
8837
  packageJson2.dependencies["@weirdfingers/boards"] = version;
8747
8838
  }
8748
- await fs8.writeJson(packageJsonPath, packageJson2, { spaces: 2 });
8839
+ await fs9.writeJson(packageJsonPath, packageJson2, { spaces: 2 });
8749
8840
  }
8750
8841
  async function updateEnvVersion(projectDir, version) {
8751
- const envPath = path13.join(projectDir, "docker", ".env");
8752
- let content = await fs8.readFile(envPath, "utf-8");
8842
+ const envPath = path14.join(projectDir, "docker", ".env");
8843
+ let content = await fs9.readFile(envPath, "utf-8");
8753
8844
  content = content.replace(
8754
8845
  /^BACKEND_VERSION=.*/m,
8755
8846
  `BACKEND_VERSION=${version}`
8756
8847
  );
8757
- await fs8.writeFile(envPath, content, "utf-8");
8848
+ await fs9.writeFile(envPath, content, "utf-8");
8758
8849
  }
8759
8850
  async function waitForHealth(projectDir, services) {
8760
8851
  const spinner = ora5("Waiting for services to be healthy...").start();
8761
8852
  const maxWaitMs = 12e4;
8762
8853
  const checkHealth = async () => {
8763
8854
  try {
8764
- const { stdout } = await execa7(
8855
+ const { stdout } = await execa8(
8765
8856
  "docker",
8766
8857
  ["compose", "--env-file", "docker/.env", "ps", "--format", "json"],
8767
8858
  {
@@ -8791,106 +8882,106 @@ async function waitForHealth(projectDir, services) {
8791
8882
  } else {
8792
8883
  spinner.warn("Services taking longer than expected...");
8793
8884
  console.log(
8794
- chalk8.yellow(
8885
+ chalk9.yellow(
8795
8886
  "\n\u26A0\uFE0F Health check timeout. Services may still be starting."
8796
8887
  )
8797
8888
  );
8798
8889
  console.log(
8799
- chalk8.gray(" Run"),
8800
- chalk8.cyan("baseboards logs"),
8801
- chalk8.gray("to check progress.")
8890
+ chalk9.gray(" Run"),
8891
+ chalk9.cyan("baseboards logs"),
8892
+ chalk9.gray("to check progress.")
8802
8893
  );
8803
8894
  }
8804
8895
  }
8805
8896
  function printUpgradeSuccess(projectDir, version) {
8806
- console.log(chalk8.gray(" Your Baseboards installation has been upgraded."));
8807
- console.log(chalk8.gray(" All services are running and healthy.\n"));
8808
- console.log(chalk8.gray("Next steps:"));
8809
- console.log(chalk8.gray(` \u2022 Check release notes: https://github.com/weirdfingers/boards/releases/tag/v${version}`));
8810
- console.log(chalk8.gray(` \u2022 View logs: baseboards logs ${path13.basename(projectDir)}`));
8811
- console.log(chalk8.gray(` \u2022 Check status: baseboards status ${path13.basename(projectDir)}
8897
+ console.log(chalk9.gray(" Your Baseboards installation has been upgraded."));
8898
+ console.log(chalk9.gray(" All services are running and healthy.\n"));
8899
+ console.log(chalk9.gray("Next steps:"));
8900
+ console.log(chalk9.gray(` \u2022 Check release notes: https://github.com/weirdfingers/boards/releases/tag/v${version}`));
8901
+ console.log(chalk9.gray(` \u2022 View logs: baseboards logs ${path14.basename(projectDir)}`));
8902
+ console.log(chalk9.gray(` \u2022 Check status: baseboards status ${path14.basename(projectDir)}
8812
8903
  `));
8813
8904
  }
8814
8905
  async function execAsync3(command, options) {
8815
8906
  const [cmd, ...args] = command.split(" ");
8816
- return execa7(cmd, args, options);
8907
+ return execa8(cmd, args, options);
8817
8908
  }
8818
8909
 
8819
8910
  // src/commands/upgrade-app-dev.ts
8820
- import path14 from "path";
8821
- import fs9 from "fs-extra";
8822
- import chalk9 from "chalk";
8823
- import { execa as execa8 } from "execa";
8911
+ import path15 from "path";
8912
+ import fs10 from "fs-extra";
8913
+ import chalk10 from "chalk";
8914
+ import { execa as execa9 } from "execa";
8824
8915
  import ora6 from "ora";
8825
8916
  async function upgradeAppDevMode(projectDir, currentVersion, targetVersion) {
8826
- console.log(chalk9.blue(`
8917
+ console.log(chalk10.blue(`
8827
8918
  \u{1F4E6} Upgrading backend from v${currentVersion} to v${targetVersion}
8828
8919
  `));
8829
8920
  try {
8830
- console.log(chalk9.gray("\u23F8\uFE0F Stopping backend services..."));
8921
+ console.log(chalk10.gray("\u23F8\uFE0F Stopping backend services..."));
8831
8922
  await execAsync("docker compose --env-file docker/.env down", { cwd: projectDir });
8832
- console.log(chalk9.gray("\u2B07\uFE0F Pulling new backend images..."));
8923
+ console.log(chalk10.gray("\u2B07\uFE0F Pulling new backend images..."));
8833
8924
  await execAsync("docker compose --env-file docker/.env pull api worker", { cwd: projectDir });
8834
- console.log(chalk9.gray("\u2699\uFE0F Updating configuration..."));
8925
+ console.log(chalk10.gray("\u2699\uFE0F Updating configuration..."));
8835
8926
  await updateEnvVersion2(projectDir, targetVersion);
8836
- console.log(chalk9.gray("\u{1F680} Starting backend services..."));
8927
+ console.log(chalk10.gray("\u{1F680} Starting backend services..."));
8837
8928
  await execAsync("docker compose --env-file docker/.env up -d db cache api worker", { cwd: projectDir });
8838
- console.log(chalk9.gray("\u{1F3E5} Waiting for backend to be healthy..."));
8929
+ console.log(chalk10.gray("\u{1F3E5} Waiting for backend to be healthy..."));
8839
8930
  await waitForHealth2(projectDir, ["db", "cache", "api", "worker"]);
8840
- console.log(chalk9.green(`
8931
+ console.log(chalk10.green(`
8841
8932
  \u2705 Backend upgraded to v${targetVersion}!
8842
8933
  `));
8843
8934
  await printAppDevUpgradeInstructions(projectDir, currentVersion, targetVersion);
8844
8935
  } catch (error) {
8845
8936
  const errorMessage = error instanceof Error ? error.message : String(error);
8846
- console.error(chalk9.red(`
8937
+ console.error(chalk10.red(`
8847
8938
  \u274C Upgrade failed: ${errorMessage}
8848
8939
  `));
8849
- console.log(chalk9.yellow("To rollback:"));
8850
- console.log(chalk9.gray(` 1. Edit docker/.env and set BACKEND_VERSION=${currentVersion}`));
8851
- console.log(chalk9.gray(" 2. Run: docker compose --env-file docker/.env pull"));
8852
- console.log(chalk9.gray(" 3. Run: docker compose --env-file docker/.env up -d db cache api worker\n"));
8940
+ console.log(chalk10.yellow("To rollback:"));
8941
+ console.log(chalk10.gray(` 1. Edit docker/.env and set BACKEND_VERSION=${currentVersion}`));
8942
+ console.log(chalk10.gray(" 2. Run: docker compose --env-file docker/.env pull"));
8943
+ console.log(chalk10.gray(" 3. Run: docker compose --env-file docker/.env up -d db cache api worker\n"));
8853
8944
  throw error;
8854
8945
  }
8855
8946
  }
8856
8947
  async function updateEnvVersion2(projectDir, version) {
8857
- const envPath = path14.join(projectDir, "docker", ".env");
8858
- let content = await fs9.readFile(envPath, "utf-8");
8948
+ const envPath = path15.join(projectDir, "docker", ".env");
8949
+ let content = await fs10.readFile(envPath, "utf-8");
8859
8950
  content = content.replace(
8860
8951
  /^BACKEND_VERSION=.*/m,
8861
8952
  `BACKEND_VERSION=${version}`
8862
8953
  );
8863
- await fs9.writeFile(envPath, content, "utf-8");
8954
+ await fs10.writeFile(envPath, content, "utf-8");
8864
8955
  }
8865
8956
  async function printAppDevUpgradeInstructions(projectDir, oldVersion, newVersion) {
8866
- const webDir = path14.join(projectDir, "web");
8957
+ const webDir = path15.join(projectDir, "web");
8867
8958
  const packageManager = await detectPackageManager(webDir);
8868
8959
  const updateCommand = packageManager === "npm" ? `npm install @weirdfingers/boards@${newVersion}` : packageManager === "yarn" ? `yarn upgrade @weirdfingers/boards@${newVersion}` : packageManager === "bun" ? `bun update @weirdfingers/boards@${newVersion}` : `pnpm update @weirdfingers/boards@${newVersion}`;
8869
- console.log(chalk9.yellow("\u26A0\uFE0F Frontend requires manual upgrade:\n"));
8870
- console.log(chalk9.gray(" 1. Stop your dev server (Ctrl+C if running)\n"));
8871
- console.log(chalk9.gray(" 2. Update the frontend package:\n"));
8872
- console.log(chalk9.cyan(` cd ${path14.basename(projectDir)}/web`));
8873
- console.log(chalk9.cyan(` ${updateCommand}
8960
+ console.log(chalk10.yellow("\u26A0\uFE0F Frontend requires manual upgrade:\n"));
8961
+ console.log(chalk10.gray(" 1. Stop your dev server (Ctrl+C if running)\n"));
8962
+ console.log(chalk10.gray(" 2. Update the frontend package:\n"));
8963
+ console.log(chalk10.cyan(` cd ${path15.basename(projectDir)}/web`));
8964
+ console.log(chalk10.cyan(` ${updateCommand}
8874
8965
  `));
8875
- console.log(chalk9.gray(" 3. Check for breaking changes:\n"));
8876
- console.log(chalk9.gray(` https://github.com/weirdfingers/boards/releases/tag/v${newVersion}
8966
+ console.log(chalk10.gray(" 3. Check for breaking changes:\n"));
8967
+ console.log(chalk10.gray(` https://github.com/weirdfingers/boards/releases/tag/v${newVersion}
8877
8968
  `));
8878
- console.log(chalk9.gray(" 4. Restart your dev server:\n"));
8879
- console.log(chalk9.cyan(` ${packageManager} dev
8969
+ console.log(chalk10.gray(" 4. Restart your dev server:\n"));
8970
+ console.log(chalk10.cyan(` ${packageManager} dev
8880
8971
  `));
8881
8972
  try {
8882
8973
  const { stdout } = await execAsync("git status --porcelain", { cwd: webDir });
8883
8974
  if (stdout.trim()) {
8884
- console.log(chalk9.yellow("\u26A0\uFE0F You have uncommitted changes in web/"));
8885
- console.log(chalk9.gray(" Consider committing before updating dependencies.\n"));
8975
+ console.log(chalk10.yellow("\u26A0\uFE0F You have uncommitted changes in web/"));
8976
+ console.log(chalk10.gray(" Consider committing before updating dependencies.\n"));
8886
8977
  }
8887
8978
  } catch (error) {
8888
- const gitDir = path14.join(webDir, ".git");
8889
- if (!fs9.existsSync(gitDir)) {
8890
- console.log(chalk9.gray(" Skipping git status check: web/ is not a git repository."));
8979
+ const gitDir = path15.join(webDir, ".git");
8980
+ if (!fs10.existsSync(gitDir)) {
8981
+ console.log(chalk10.gray(" Skipping git status check: web/ is not a git repository."));
8891
8982
  } else {
8892
8983
  console.log(
8893
- chalk9.gray(
8984
+ chalk10.gray(
8894
8985
  " Skipping git status check: git is not available or an error occurred while checking repository status."
8895
8986
  )
8896
8987
  );
@@ -8902,7 +8993,7 @@ async function waitForHealth2(projectDir, services) {
8902
8993
  const maxWaitMs = 12e4;
8903
8994
  const checkHealth = async () => {
8904
8995
  try {
8905
- const { stdout } = await execa8(
8996
+ const { stdout } = await execa9(
8906
8997
  "docker",
8907
8998
  ["compose", "--env-file", "docker/.env", "ps", "--format", "json"],
8908
8999
  {
@@ -8932,61 +9023,61 @@ async function waitForHealth2(projectDir, services) {
8932
9023
  } else {
8933
9024
  spinner.warn("Services taking longer than expected...");
8934
9025
  console.log(
8935
- chalk9.yellow(
9026
+ chalk10.yellow(
8936
9027
  "\n\u26A0\uFE0F Health check timeout. Services may still be starting."
8937
9028
  )
8938
9029
  );
8939
9030
  console.log(
8940
- chalk9.gray(" Run"),
8941
- chalk9.cyan("baseboards logs"),
8942
- chalk9.gray("to check progress.")
9031
+ chalk10.gray(" Run"),
9032
+ chalk10.cyan("baseboards logs"),
9033
+ chalk10.gray("to check progress.")
8943
9034
  );
8944
9035
  }
8945
9036
  }
8946
9037
 
8947
9038
  // src/commands/upgrade.ts
8948
9039
  async function upgrade(directory, options) {
8949
- const dir = path15.resolve(process.cwd(), directory);
9040
+ const dir = path16.resolve(process.cwd(), directory);
8950
9041
  if (!isScaffolded(dir)) {
8951
- console.error(chalk10.red("\n\u274C Error: Not a Baseboards project"));
8952
- console.log(chalk10.gray(" Run"), chalk10.cyan("baseboards up"), chalk10.gray("to scaffold a project first."));
9042
+ console.error(chalk11.red("\n\u274C Error: Not a Baseboards project"));
9043
+ console.log(chalk11.gray(" Run"), chalk11.cyan("baseboards up"), chalk11.gray("to scaffold a project first."));
8953
9044
  process.exit(1);
8954
9045
  }
8955
9046
  const currentVersion = await getCurrentVersion(dir);
8956
9047
  if (!currentVersion) {
8957
- console.error(chalk10.red("\n\u274C Error: Could not determine current version"));
8958
- console.log(chalk10.gray(" Check docker/.env for VERSION field"));
9048
+ console.error(chalk11.red("\n\u274C Error: Could not determine current version"));
9049
+ console.log(chalk11.gray(" Check docker/.env for VERSION field"));
8959
9050
  process.exit(1);
8960
9051
  }
8961
9052
  const targetVersion = options.version || await getLatestVersion();
8962
9053
  if (currentVersion === targetVersion) {
8963
- console.log(chalk10.green(`
9054
+ console.log(chalk11.green(`
8964
9055
  \u2705 Already at v${targetVersion}`));
8965
9056
  return;
8966
9057
  }
8967
9058
  const compatCheck = await checkCompatibility(currentVersion, targetVersion);
8968
9059
  const mode = await detectProjectMode(dir);
8969
- console.log(chalk10.blue("\u{1F4CB} Upgrade Plan:\n"));
8970
- console.log(chalk10.gray(` Current version: ${currentVersion}`));
8971
- console.log(chalk10.gray(` Target version: ${targetVersion}`));
8972
- console.log(chalk10.gray(` Project mode: ${mode}`));
9060
+ console.log(chalk11.blue("\u{1F4CB} Upgrade Plan:\n"));
9061
+ console.log(chalk11.gray(` Current version: ${currentVersion}`));
9062
+ console.log(chalk11.gray(` Target version: ${targetVersion}`));
9063
+ console.log(chalk11.gray(` Project mode: ${mode}`));
8973
9064
  console.log("");
8974
9065
  if (mode === "default") {
8975
- console.log(chalk10.gray(" Steps:"));
8976
- console.log(chalk10.gray(" 1. Stop all services"));
8977
- console.log(chalk10.gray(" 2. Pull new backend images"));
8978
- console.log(chalk10.gray(" 3. Update web/package.json"));
8979
- console.log(chalk10.gray(" 4. Rebuild frontend Docker image"));
8980
- console.log(chalk10.gray(" 5. Update docker/.env"));
8981
- console.log(chalk10.gray(" 6. Start services"));
8982
- console.log(chalk10.gray(" 7. Wait for health checks"));
9066
+ console.log(chalk11.gray(" Steps:"));
9067
+ console.log(chalk11.gray(" 1. Stop all services"));
9068
+ console.log(chalk11.gray(" 2. Pull new backend images"));
9069
+ console.log(chalk11.gray(" 3. Update web/package.json"));
9070
+ console.log(chalk11.gray(" 4. Rebuild frontend Docker image"));
9071
+ console.log(chalk11.gray(" 5. Update docker/.env"));
9072
+ console.log(chalk11.gray(" 6. Start services"));
9073
+ console.log(chalk11.gray(" 7. Wait for health checks"));
8983
9074
  } else {
8984
- console.log(chalk10.gray(" Steps:"));
8985
- console.log(chalk10.gray(" 1. Stop backend services"));
8986
- console.log(chalk10.gray(" 2. Pull new backend images"));
8987
- console.log(chalk10.gray(" 3. Update docker/.env"));
8988
- console.log(chalk10.gray(" 4. Start backend services"));
8989
- console.log(chalk10.gray(" 5. Print manual frontend update instructions"));
9075
+ console.log(chalk11.gray(" Steps:"));
9076
+ console.log(chalk11.gray(" 1. Stop backend services"));
9077
+ console.log(chalk11.gray(" 2. Pull new backend images"));
9078
+ console.log(chalk11.gray(" 3. Update docker/.env"));
9079
+ console.log(chalk11.gray(" 4. Start backend services"));
9080
+ console.log(chalk11.gray(" 5. Print manual frontend update instructions"));
8990
9081
  }
8991
9082
  console.log("");
8992
9083
  if (compatCheck.warnings.length > 0) {
@@ -8994,18 +9085,18 @@ async function upgrade(directory, options) {
8994
9085
  console.log("");
8995
9086
  }
8996
9087
  if (compatCheck.requiredActions.length > 0) {
8997
- console.log(chalk10.yellow("\u26A0\uFE0F Required manual actions:"));
9088
+ console.log(chalk11.yellow("\u26A0\uFE0F Required manual actions:"));
8998
9089
  compatCheck.requiredActions.forEach((action) => {
8999
- console.log(chalk10.gray(` \u2022 ${action}`));
9090
+ console.log(chalk11.gray(` \u2022 ${action}`));
9000
9091
  });
9001
9092
  console.log("");
9002
9093
  }
9003
9094
  if (options.dryRun) {
9004
- console.log(chalk10.blue("\u{1F50D} Dry run complete - no changes made\n"));
9095
+ console.log(chalk11.blue("\u{1F50D} Dry run complete - no changes made\n"));
9005
9096
  return;
9006
9097
  }
9007
9098
  if (options.force && compatCheck.breaking) {
9008
- console.log(chalk10.yellow("\u26A0\uFE0F --force flag used: skipping confirmation despite breaking changes\n"));
9099
+ console.log(chalk11.yellow("\u26A0\uFE0F --force flag used: skipping confirmation despite breaking changes\n"));
9009
9100
  }
9010
9101
  if (!options.force && compatCheck.breaking) {
9011
9102
  const { proceed } = await prompts4({
@@ -9015,7 +9106,7 @@ async function upgrade(directory, options) {
9015
9106
  initial: false
9016
9107
  });
9017
9108
  if (!proceed) {
9018
- console.log(chalk10.gray("\nUpgrade cancelled\n"));
9109
+ console.log(chalk11.gray("\nUpgrade cancelled\n"));
9019
9110
  return;
9020
9111
  }
9021
9112
  }
@@ -9035,104 +9126,104 @@ async function getLatestVersion() {
9035
9126
  }
9036
9127
 
9037
9128
  // src/commands/doctor.ts
9038
- import path16 from "path";
9039
- import fs10 from "fs-extra";
9040
- import chalk11 from "chalk";
9129
+ import path17 from "path";
9130
+ import fs11 from "fs-extra";
9131
+ import chalk12 from "chalk";
9041
9132
  async function doctor(directory) {
9042
- const dir = path16.resolve(process.cwd(), directory);
9043
- console.log(chalk11.blue.bold("\n\u{1FA7A} Baseboards Diagnostics\n"));
9044
- console.log(chalk11.cyan("CLI Version:"), getCliVersion());
9045
- console.log(chalk11.cyan("\n\u{1F4CB} Prerequisites:"));
9133
+ const dir = path17.resolve(process.cwd(), directory);
9134
+ console.log(chalk12.blue.bold("\n\u{1FA7A} Baseboards Diagnostics\n"));
9135
+ console.log(chalk12.cyan("CLI Version:"), getCliVersion());
9136
+ console.log(chalk12.cyan("\n\u{1F4CB} Prerequisites:"));
9046
9137
  const prereqs = await checkPrerequisites();
9047
9138
  console.log(
9048
- chalk11.gray(" Node.js:"),
9049
- prereqs.node.installed ? prereqs.node.satisfies ? chalk11.green(`\u2713 v${prereqs.node.version}`) : chalk11.yellow(`\u26A0\uFE0F v${prereqs.node.version} (need v20+)`) : chalk11.red("\u2717 Not installed")
9139
+ chalk12.gray(" Node.js:"),
9140
+ prereqs.node.installed ? prereqs.node.satisfies ? chalk12.green(`\u2713 v${prereqs.node.version}`) : chalk12.yellow(`\u26A0\uFE0F v${prereqs.node.version} (need v20+)`) : chalk12.red("\u2717 Not installed")
9050
9141
  );
9051
9142
  console.log(
9052
- chalk11.gray(" Docker:"),
9053
- prereqs.docker.installed ? chalk11.green(`\u2713 v${prereqs.docker.version}`) : chalk11.red("\u2717 Not installed")
9143
+ chalk12.gray(" Docker:"),
9144
+ prereqs.docker.installed ? chalk12.green(`\u2713 v${prereqs.docker.version}`) : chalk12.red("\u2717 Not installed")
9054
9145
  );
9055
9146
  if (prereqs.docker.composeVersion) {
9056
9147
  console.log(
9057
- chalk11.gray(" Docker Compose:"),
9058
- chalk11.green(`\u2713 v${prereqs.docker.composeVersion}`)
9148
+ chalk12.gray(" Docker Compose:"),
9149
+ chalk12.green(`\u2713 v${prereqs.docker.composeVersion}`)
9059
9150
  );
9060
9151
  } else if (prereqs.docker.installed) {
9061
- console.log(chalk11.gray(" Docker Compose:"), chalk11.red("\u2717 Not available"));
9152
+ console.log(chalk12.gray(" Docker Compose:"), chalk12.red("\u2717 Not available"));
9062
9153
  }
9063
- console.log(chalk11.gray(" Platform:"), prereqs.platform.name);
9154
+ console.log(chalk12.gray(" Platform:"), prereqs.platform.name);
9064
9155
  if (prereqs.platform.isWSL) {
9065
- console.log(chalk11.gray(" WSL:"), chalk11.blue("\u2713 Detected"));
9156
+ console.log(chalk12.gray(" WSL:"), chalk12.blue("\u2713 Detected"));
9066
9157
  }
9067
- console.log(chalk11.cyan("\n\u{1F4C2} Project:"));
9158
+ console.log(chalk12.cyan("\n\u{1F4C2} Project:"));
9068
9159
  const scaffolded = isScaffolded(dir);
9069
9160
  console.log(
9070
- chalk11.gray(" Scaffolded:"),
9071
- scaffolded ? chalk11.green("\u2713 Yes") : chalk11.yellow("\u2717 No")
9161
+ chalk12.gray(" Scaffolded:"),
9162
+ scaffolded ? chalk12.green("\u2713 Yes") : chalk12.yellow("\u2717 No")
9072
9163
  );
9073
9164
  if (scaffolded) {
9074
- console.log(chalk11.gray(" Directory:"), dir);
9075
- const webPkg = path16.join(dir, "web/package.json");
9076
- const apiPkg = path16.join(dir, "api/pyproject.toml");
9077
- const composeFile = path16.join(dir, "compose.yaml");
9165
+ console.log(chalk12.gray(" Directory:"), dir);
9166
+ const webPkg = path17.join(dir, "web/package.json");
9167
+ const apiPkg = path17.join(dir, "api/pyproject.toml");
9168
+ const composeFile = path17.join(dir, "compose.yaml");
9078
9169
  console.log(
9079
- chalk11.gray(" Web package:"),
9080
- fs10.existsSync(webPkg) ? chalk11.green("\u2713") : chalk11.red("\u2717")
9170
+ chalk12.gray(" Web package:"),
9171
+ fs11.existsSync(webPkg) ? chalk12.green("\u2713") : chalk12.red("\u2717")
9081
9172
  );
9082
9173
  console.log(
9083
- chalk11.gray(" API package:"),
9084
- fs10.existsSync(apiPkg) ? chalk11.green("\u2713") : chalk11.red("\u2717")
9174
+ chalk12.gray(" API package:"),
9175
+ fs11.existsSync(apiPkg) ? chalk12.green("\u2713") : chalk12.red("\u2717")
9085
9176
  );
9086
9177
  console.log(
9087
- chalk11.gray(" Compose file:"),
9088
- fs10.existsSync(composeFile) ? chalk11.green("\u2713") : chalk11.red("\u2717")
9178
+ chalk12.gray(" Compose file:"),
9179
+ fs11.existsSync(composeFile) ? chalk12.green("\u2713") : chalk12.red("\u2717")
9089
9180
  );
9090
- console.log(chalk11.cyan("\n\u{1F510} Environment:"));
9091
- const webEnv = path16.join(dir, "web/.env");
9092
- const apiEnv = path16.join(dir, "api/.env");
9093
- const dockerEnv = path16.join(dir, "docker/.env");
9181
+ console.log(chalk12.cyan("\n\u{1F510} Environment:"));
9182
+ const webEnv = path17.join(dir, "web/.env");
9183
+ const apiEnv = path17.join(dir, "api/.env");
9184
+ const dockerEnv = path17.join(dir, "docker/.env");
9094
9185
  console.log(
9095
- chalk11.gray(" Web .env:"),
9096
- fs10.existsSync(webEnv) ? chalk11.green("\u2713") : chalk11.yellow("\u2717 Missing")
9186
+ chalk12.gray(" Web .env:"),
9187
+ fs11.existsSync(webEnv) ? chalk12.green("\u2713") : chalk12.yellow("\u2717 Missing")
9097
9188
  );
9098
9189
  console.log(
9099
- chalk11.gray(" API .env:"),
9100
- fs10.existsSync(apiEnv) ? chalk11.green("\u2713") : chalk11.yellow("\u2717 Missing")
9190
+ chalk12.gray(" API .env:"),
9191
+ fs11.existsSync(apiEnv) ? chalk12.green("\u2713") : chalk12.yellow("\u2717 Missing")
9101
9192
  );
9102
9193
  console.log(
9103
- chalk11.gray(" Docker .env:"),
9104
- fs10.existsSync(dockerEnv) ? chalk11.green("\u2713") : chalk11.yellow("\u2717 Missing")
9194
+ chalk12.gray(" Docker .env:"),
9195
+ fs11.existsSync(dockerEnv) ? chalk12.green("\u2713") : chalk12.yellow("\u2717 Missing")
9105
9196
  );
9106
- if (fs10.existsSync(apiEnv)) {
9197
+ if (fs11.existsSync(apiEnv)) {
9107
9198
  const missingKeys = detectMissingProviderKeys(apiEnv);
9108
9199
  if (missingKeys.length > 0) {
9109
9200
  console.log(
9110
- chalk11.gray(" Provider keys:"),
9111
- chalk11.yellow(`\u26A0\uFE0F ${missingKeys.length} missing`)
9201
+ chalk12.gray(" Provider keys:"),
9202
+ chalk12.yellow(`\u26A0\uFE0F ${missingKeys.length} missing`)
9112
9203
  );
9113
- console.log(chalk11.gray(" Missing:"), missingKeys.map((k) => chalk11.cyan(k)).join(", "));
9204
+ console.log(chalk12.gray(" Missing:"), missingKeys.map((k) => chalk12.cyan(k)).join(", "));
9114
9205
  } else {
9115
- console.log(chalk11.gray(" Provider keys:"), chalk11.green("\u2713 Configured"));
9206
+ console.log(chalk12.gray(" Provider keys:"), chalk12.green("\u2713 Configured"));
9116
9207
  }
9117
9208
  }
9118
- console.log(chalk11.cyan("\n\u2699\uFE0F Configuration:"));
9119
- const generatorsYaml = path16.join(dir, "api/config/generators.yaml");
9120
- const storageYaml = path16.join(dir, "api/config/storage_config.yaml");
9209
+ console.log(chalk12.cyan("\n\u2699\uFE0F Configuration:"));
9210
+ const generatorsYaml = path17.join(dir, "api/config/generators.yaml");
9211
+ const storageYaml = path17.join(dir, "api/config/storage_config.yaml");
9121
9212
  console.log(
9122
- chalk11.gray(" generators.yaml:"),
9123
- fs10.existsSync(generatorsYaml) ? chalk11.green("\u2713") : chalk11.yellow("\u2717 Missing")
9213
+ chalk12.gray(" generators.yaml:"),
9214
+ fs11.existsSync(generatorsYaml) ? chalk12.green("\u2713") : chalk12.yellow("\u2717 Missing")
9124
9215
  );
9125
9216
  console.log(
9126
- chalk11.gray(" storage_config.yaml:"),
9127
- fs10.existsSync(storageYaml) ? chalk11.green("\u2713") : chalk11.yellow("\u2717 Missing")
9217
+ chalk12.gray(" storage_config.yaml:"),
9218
+ fs11.existsSync(storageYaml) ? chalk12.green("\u2713") : chalk12.yellow("\u2717 Missing")
9128
9219
  );
9129
- const storageDir = path16.join(dir, "data/storage");
9220
+ const storageDir = path17.join(dir, "data/storage");
9130
9221
  console.log(
9131
- chalk11.gray(" Storage directory:"),
9132
- fs10.existsSync(storageDir) ? chalk11.green("\u2713") : chalk11.yellow("\u2717 Missing")
9222
+ chalk12.gray(" Storage directory:"),
9223
+ fs11.existsSync(storageDir) ? chalk12.green("\u2713") : chalk12.yellow("\u2717 Missing")
9133
9224
  );
9134
9225
  }
9135
- console.log(chalk11.cyan("\n\u{1F4A1} Recommendations:"));
9226
+ console.log(chalk12.cyan("\n\u{1F4A1} Recommendations:"));
9136
9227
  const recommendations = [];
9137
9228
  if (!prereqs.node.satisfies) {
9138
9229
  recommendations.push("Upgrade Node.js to v20 or higher");
@@ -9143,18 +9234,18 @@ async function doctor(directory) {
9143
9234
  recommendations.push("Update Docker to get Compose v2");
9144
9235
  }
9145
9236
  if (!scaffolded) {
9146
- recommendations.push("Run " + chalk11.cyan("baseboards up") + " to scaffold a project");
9237
+ recommendations.push("Run " + chalk12.cyan("baseboards up") + " to scaffold a project");
9147
9238
  }
9148
9239
  if (recommendations.length === 0) {
9149
- console.log(chalk11.green(" \u2713 Everything looks good!"));
9240
+ console.log(chalk12.green(" \u2713 Everything looks good!"));
9150
9241
  } else {
9151
- recommendations.forEach((rec) => console.log(chalk11.yellow(" \u2022"), rec));
9242
+ recommendations.forEach((rec) => console.log(chalk12.yellow(" \u2022"), rec));
9152
9243
  }
9153
9244
  console.log();
9154
9245
  }
9155
9246
 
9156
9247
  // src/commands/templates.ts
9157
- import chalk12 from "chalk";
9248
+ import chalk13 from "chalk";
9158
9249
  function formatSize(bytes) {
9159
9250
  if (bytes < 1024) {
9160
9251
  return `${bytes} B`;
@@ -9165,22 +9256,22 @@ function formatSize(bytes) {
9165
9256
  }
9166
9257
  }
9167
9258
  function displayTemplate(template, isRecommended) {
9168
- const name = chalk12.bold(template.name);
9169
- const recommended = isRecommended ? chalk12.cyan(" (recommended)") : "";
9259
+ const name = chalk13.bold(template.name);
9260
+ const recommended = isRecommended ? chalk13.cyan(" (recommended)") : "";
9170
9261
  console.log(`
9171
9262
  ${name}${recommended}`);
9172
9263
  console.log(` ${template.description}`);
9173
9264
  const frameworks = template.frameworks.join(", ");
9174
- console.log(` ${chalk12.gray("Frameworks:")} ${frameworks}`);
9265
+ console.log(` ${chalk13.gray("Frameworks:")} ${frameworks}`);
9175
9266
  const features = template.features.join(", ");
9176
- console.log(` ${chalk12.gray("Features:")} ${features}`);
9267
+ console.log(` ${chalk13.gray("Features:")} ${features}`);
9177
9268
  const size = formatSize(template.size);
9178
- console.log(` ${chalk12.gray("Size:")} ${size}`);
9269
+ console.log(` ${chalk13.gray("Size:")} ${size}`);
9179
9270
  }
9180
9271
  async function templates(options) {
9181
9272
  try {
9182
9273
  if (options.refresh) {
9183
- console.log(chalk12.blue("\u{1F504} Clearing cache and refreshing templates...\n"));
9274
+ console.log(chalk13.blue("\u{1F504} Clearing cache and refreshing templates...\n"));
9184
9275
  await clearCache();
9185
9276
  }
9186
9277
  const version = options.version || getCliVersion();
@@ -9190,24 +9281,24 @@ async function templates(options) {
9190
9281
  } catch (error) {
9191
9282
  if (error.message.includes("Failed to fetch")) {
9192
9283
  console.error(
9193
- chalk12.red("\n\u274C Network error:"),
9284
+ chalk13.red("\n\u274C Network error:"),
9194
9285
  "Unable to fetch template list"
9195
9286
  );
9196
9287
  console.log(
9197
- chalk12.yellow("\n\u{1F4A1} Tip:"),
9288
+ chalk13.yellow("\n\u{1F4A1} Tip:"),
9198
9289
  "Check your internet connection or try again later"
9199
9290
  );
9200
9291
  process.exit(1);
9201
9292
  }
9202
9293
  if (error.message.includes("not found")) {
9203
9294
  console.error(
9204
- chalk12.red("\n\u274C Version not found:"),
9295
+ chalk13.red("\n\u274C Version not found:"),
9205
9296
  `Version ${version} does not exist`
9206
9297
  );
9207
9298
  console.log(
9208
- chalk12.yellow("\n\u{1F4A1} Tip:"),
9299
+ chalk13.yellow("\n\u{1F4A1} Tip:"),
9209
9300
  "Check available versions at:",
9210
- chalk12.cyan("https://github.com/weirdfingers/boards/releases")
9301
+ chalk13.cyan("https://github.com/weirdfingers/boards/releases")
9211
9302
  );
9212
9303
  process.exit(1);
9213
9304
  }
@@ -9215,13 +9306,13 @@ async function templates(options) {
9215
9306
  }
9216
9307
  if (!manifest.templates || manifest.templates.length === 0) {
9217
9308
  console.log(
9218
- chalk12.yellow("\n\u26A0\uFE0F No templates available for version"),
9309
+ chalk13.yellow("\n\u26A0\uFE0F No templates available for version"),
9219
9310
  manifest.version
9220
9311
  );
9221
9312
  process.exit(0);
9222
9313
  }
9223
9314
  console.log(
9224
- chalk12.blue.bold(`
9315
+ chalk13.blue.bold(`
9225
9316
  \u{1F4E6} Available templates for v${manifest.version}:`)
9226
9317
  );
9227
9318
  for (const template of manifest.templates) {
@@ -9230,10 +9321,10 @@ async function templates(options) {
9230
9321
  }
9231
9322
  console.log();
9232
9323
  } catch (error) {
9233
- console.error(chalk12.red("\n\u274C Error:"), error.message || "Unknown error");
9324
+ console.error(chalk13.red("\n\u274C Error:"), error.message || "Unknown error");
9234
9325
  console.error(
9235
- chalk12.yellow("\n\u{1F4A1} Try running:"),
9236
- chalk12.cyan("baseboards doctor")
9326
+ chalk13.yellow("\n\u{1F4A1} Try running:"),
9327
+ chalk13.cyan("baseboards doctor")
9237
9328
  );
9238
9329
  process.exit(1);
9239
9330
  }
@@ -9278,18 +9369,18 @@ try {
9278
9369
  process.exit(1);
9279
9370
  }
9280
9371
  const err = error;
9281
- console.error(chalk13.red("\n\u274C Error:"), err.message || "Unknown error");
9372
+ console.error(chalk14.red("\n\u274C Error:"), err.message || "Unknown error");
9282
9373
  if (err.stderr) {
9283
- console.error(chalk13.gray("\nDetails:"));
9284
- console.error(chalk13.gray(err.stderr));
9374
+ console.error(chalk14.gray("\nDetails:"));
9375
+ console.error(chalk14.gray(err.stderr));
9285
9376
  }
9286
9377
  console.error(
9287
- chalk13.yellow("\n\u{1F4A1} Try running:"),
9288
- chalk13.cyan("baseboards doctor")
9378
+ chalk14.yellow("\n\u{1F4A1} Try running:"),
9379
+ chalk14.cyan("baseboards doctor")
9289
9380
  );
9290
9381
  console.error(
9291
- chalk13.yellow("\u{1F4D6} Documentation:"),
9292
- chalk13.cyan("https://baseboards.dev/docs")
9382
+ chalk14.yellow("\u{1F4D6} Documentation:"),
9383
+ chalk14.cyan("https://baseboards.dev/docs")
9293
9384
  );
9294
9385
  process.exit(1);
9295
9386
  }