@weirdfingers/baseboards 0.9.5 → 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 +561 -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(
@@ -7895,18 +7983,19 @@ async function ensureEnvFiles(ctx) {
7895
7983
  dockerEnv = dockerEnv.replace(/WEB_PORT=.*/g, `WEB_PORT=${ctx.ports.web}`);
7896
7984
  dockerEnv = dockerEnv.replace(/API_PORT=.*/g, `API_PORT=${ctx.ports.api}`);
7897
7985
  dockerEnv = dockerEnv.replace(/VERSION=.*/g, `VERSION=${ctx.version}`);
7986
+ dockerEnv = dockerEnv.replace(/BACKEND_VERSION=.*/g, `BACKEND_VERSION=${ctx.version}`);
7898
7987
  dockerEnv = dockerEnv.replace(
7899
7988
  /PROJECT_NAME=.*/g,
7900
7989
  `PROJECT_NAME=${ctx.name}`
7901
7990
  );
7902
- fs5.writeFileSync(dockerEnvPath, dockerEnv);
7991
+ fs6.writeFileSync(dockerEnvPath, dockerEnv);
7903
7992
  }
7904
7993
  spinner.succeed("Environment configured");
7905
7994
  }
7906
7995
  async function promptForApiKeys(ctx) {
7907
- console.log(chalk2.cyan("\n\u{1F511} API Key Configuration"));
7908
- console.log(chalk2.gray("Add API keys to enable image generation providers"));
7909
- 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"));
7910
7999
  const response = await prompts2([
7911
8000
  {
7912
8001
  type: "password",
@@ -7947,8 +8036,8 @@ async function promptForApiKeys(ctx) {
7947
8036
  apiKeys.OPENAI_API_KEY = response.OPENAI_API_KEY.trim();
7948
8037
  }
7949
8038
  if (Object.keys(apiKeys).length > 0) {
7950
- const apiEnvPath = path5.join(ctx.dir, "api/.env");
7951
- let apiEnv = fs5.readFileSync(apiEnvPath, "utf-8");
8039
+ const apiEnvPath = path6.join(ctx.dir, "api/.env");
8040
+ let apiEnv = fs6.readFileSync(apiEnvPath, "utf-8");
7952
8041
  const jsonKeys = JSON.stringify(apiKeys);
7953
8042
  if (apiEnv.includes("BOARDS_GENERATOR_API_KEYS=")) {
7954
8043
  apiEnv = apiEnv.replace(
@@ -7964,14 +8053,14 @@ BOARDS_GENERATOR_API_KEYS=${jsonKeys}
7964
8053
  `
7965
8054
  );
7966
8055
  }
7967
- fs5.writeFileSync(apiEnvPath, apiEnv);
7968
- 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"));
7969
8058
  console.log(
7970
- 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")
7971
8060
  );
7972
8061
  } else {
7973
- console.log(chalk2.yellow("\n\u26A0\uFE0F No API keys provided"));
7974
- 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"));
7975
8064
  }
7976
8065
  }
7977
8066
  function getComposeFiles(ctx) {
@@ -7993,8 +8082,8 @@ async function startDockerCompose(ctx) {
7993
8082
  const spinner = ora2("Starting Docker Compose...").start();
7994
8083
  const composeFiles = getComposeFiles(ctx);
7995
8084
  for (const file of composeFiles) {
7996
- const filePath = path5.join(ctx.dir, file);
7997
- if (!fs5.existsSync(filePath)) {
8085
+ const filePath = path6.join(ctx.dir, file);
8086
+ if (!fs6.existsSync(filePath)) {
7998
8087
  spinner.fail(`Compose file not found: ${file}`);
7999
8088
  throw new Error(`Compose file not found: ${file}`);
8000
8089
  }
@@ -8007,7 +8096,7 @@ async function startDockerCompose(ctx) {
8007
8096
  "--remove-orphans"
8008
8097
  ];
8009
8098
  try {
8010
- await execa2("docker", composeArgs, {
8099
+ await execa3("docker", composeArgs, {
8011
8100
  cwd: ctx.dir,
8012
8101
  stdio: "inherit"
8013
8102
  });
@@ -8019,11 +8108,11 @@ async function startDockerCompose(ctx) {
8019
8108
  }
8020
8109
  async function attachToLogs(ctx) {
8021
8110
  console.log(
8022
- 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")
8023
8112
  );
8024
- 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"));
8025
8114
  const composeArgs = [...getComposeBaseArgs(ctx), "logs", "-f"];
8026
- await execa2("docker", composeArgs, {
8115
+ await execa3("docker", composeArgs, {
8027
8116
  cwd: ctx.dir,
8028
8117
  stdio: "inherit"
8029
8118
  });
@@ -8037,7 +8126,7 @@ async function waitForHealthy(ctx) {
8037
8126
  const maxWaitMs = 12e4;
8038
8127
  const checkHealth = async () => {
8039
8128
  try {
8040
- const { stdout } = await execa2(
8129
+ const { stdout } = await execa3(
8041
8130
  "docker",
8042
8131
  [...getComposeBaseArgs(ctx), "ps", "--format", "json"],
8043
8132
  {
@@ -8067,21 +8156,21 @@ async function waitForHealthy(ctx) {
8067
8156
  } else {
8068
8157
  spinner.warn("Services taking longer than expected...");
8069
8158
  console.log(
8070
- chalk2.yellow(
8159
+ chalk3.yellow(
8071
8160
  "\n\u26A0\uFE0F Health check timeout. Services may still be starting."
8072
8161
  )
8073
8162
  );
8074
8163
  console.log(
8075
- chalk2.gray(" Run"),
8076
- chalk2.cyan("baseboards logs"),
8077
- chalk2.gray("to check progress.")
8164
+ chalk3.gray(" Run"),
8165
+ chalk3.cyan("baseboards logs"),
8166
+ chalk3.gray("to check progress.")
8078
8167
  );
8079
8168
  }
8080
8169
  }
8081
8170
  async function runMigrations(ctx) {
8082
8171
  const spinner = ora2("Running database migrations...").start();
8083
8172
  try {
8084
- const { stdout } = await execa2(
8173
+ const { stdout } = await execa3(
8085
8174
  "docker",
8086
8175
  [
8087
8176
  ...getComposeBaseArgs(ctx),
@@ -8097,12 +8186,12 @@ async function runMigrations(ctx) {
8097
8186
  }
8098
8187
  );
8099
8188
  if (stdout && (stdout.includes("Running upgrade") || process.env.DEBUG)) {
8100
- console.log(chalk2.gray("\n Migration output:"));
8101
- 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 ")));
8102
8191
  }
8103
8192
  spinner.succeed("Database migrations complete");
8104
8193
  spinner.start("Restarting API to apply migrations...");
8105
- await execa2(
8194
+ await execa3(
8106
8195
  "docker",
8107
8196
  [...getComposeBaseArgs(ctx), "restart", "api"],
8108
8197
  {
@@ -8117,42 +8206,42 @@ async function runMigrations(ctx) {
8117
8206
  const isPasswordError = errorMessage.includes("password authentication failed") || errorMessage.includes("InvalidPasswordError");
8118
8207
  if (isPasswordError) {
8119
8208
  console.log(
8120
- chalk2.red(
8209
+ chalk3.red(
8121
8210
  "\n\u274C Database password mismatch - cannot connect to existing database"
8122
8211
  )
8123
8212
  );
8124
8213
  console.log(
8125
- chalk2.yellow(
8214
+ chalk3.yellow(
8126
8215
  " Existing database volumes have a different password than the current configuration."
8127
8216
  )
8128
8217
  );
8129
- console.log(chalk2.yellow("\n To fix this, choose one of:"));
8218
+ console.log(chalk3.yellow("\n To fix this, choose one of:"));
8130
8219
  console.log(
8131
- 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")
8132
8221
  );
8133
8222
  console.log(
8134
- chalk2.cyan(" 2. Start fresh automatically:") + chalk2.gray(" baseboards up --fresh")
8223
+ chalk3.cyan(" 2. Start fresh automatically:") + chalk3.gray(" baseboards up --fresh")
8135
8224
  );
8136
8225
  console.log(
8137
- chalk2.gray(
8226
+ chalk3.gray(
8138
8227
  "\n This usually happens when project files were deleted but Docker volumes remain."
8139
8228
  )
8140
8229
  );
8141
8230
  } else {
8142
8231
  console.log(
8143
- chalk2.red(
8232
+ chalk3.red(
8144
8233
  "\n\u274C Database migrations failed"
8145
8234
  )
8146
8235
  );
8147
- console.log(chalk2.gray("\n Error details:"));
8148
- console.log(chalk2.gray(" " + errorMessage));
8236
+ console.log(chalk3.gray("\n Error details:"));
8237
+ console.log(chalk3.gray(" " + errorMessage));
8149
8238
  console.log(
8150
- chalk2.yellow(
8239
+ chalk3.yellow(
8151
8240
  "\n You can try running migrations manually:"
8152
8241
  )
8153
8242
  );
8154
8243
  console.log(
8155
- chalk2.cyan(" docker compose exec api alembic upgrade head")
8244
+ chalk3.cyan(" docker compose exec api alembic upgrade head")
8156
8245
  );
8157
8246
  }
8158
8247
  throw new Error("Database migrations failed");
@@ -8168,84 +8257,87 @@ function getDevCommand(pm) {
8168
8257
  return commands[pm];
8169
8258
  }
8170
8259
  function printDefaultSuccessMessage(ctx, hasKeyWarning) {
8171
- console.log(chalk2.green.bold("\n\u2705 Baseboards is running!\n"));
8260
+ console.log(chalk3.green.bold("\n\u2705 Baseboards is running!\n"));
8172
8261
  console.log(
8173
- chalk2.cyan(" Web: "),
8174
- chalk2.underline(`http://localhost:${ctx.ports.web}`)
8262
+ chalk3.cyan(" Web: "),
8263
+ chalk3.underline(`http://localhost:${ctx.ports.web}`)
8175
8264
  );
8176
8265
  console.log(
8177
- chalk2.cyan(" API: "),
8178
- chalk2.underline(`http://localhost:${ctx.ports.api}`)
8266
+ chalk3.cyan(" API: "),
8267
+ chalk3.underline(`http://localhost:${ctx.ports.api}`)
8179
8268
  );
8180
8269
  console.log(
8181
- chalk2.cyan(" GraphQL: "),
8182
- chalk2.underline(`http://localhost:${ctx.ports.api}/graphql`)
8270
+ chalk3.cyan(" GraphQL: "),
8271
+ chalk3.underline(`http://localhost:${ctx.ports.api}/graphql`)
8183
8272
  );
8184
8273
  if (hasKeyWarning) {
8185
- console.log(chalk2.yellow("\n\u26A0\uFE0F Remember to configure provider API keys!"));
8186
- 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"));
8187
8276
  console.log(
8188
- chalk2.gray(" Docs:"),
8189
- chalk2.cyan("https://baseboards.dev/docs/setup")
8277
+ chalk3.gray(" Docs:"),
8278
+ chalk3.cyan("https://baseboards.dev/docs/setup")
8190
8279
  );
8191
8280
  }
8192
- console.log(chalk2.gray("\nView logs:"), chalk2.cyan(`baseboards logs ${ctx.name} -f`));
8193
- 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"));
8194
8284
  console.log();
8195
8285
  }
8196
8286
  function printAppDevSuccessMessage(ctx, hasKeyWarning) {
8197
- 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"));
8198
8288
  console.log(
8199
- chalk2.cyan(" API: "),
8200
- chalk2.underline(`http://localhost:${ctx.ports.api}`)
8289
+ chalk3.cyan(" API: "),
8290
+ chalk3.underline(`http://localhost:${ctx.ports.api}`)
8201
8291
  );
8202
8292
  console.log(
8203
- chalk2.cyan(" GraphQL: "),
8204
- chalk2.underline(`http://localhost:${ctx.ports.api}/graphql`)
8293
+ chalk3.cyan(" GraphQL: "),
8294
+ chalk3.underline(`http://localhost:${ctx.ports.api}/graphql`)
8205
8295
  );
8206
- console.log(chalk2.cyan("\nTo start the frontend:\n"));
8207
- 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"));
8208
8298
  const cdCommand = relativeWebPath || "web";
8209
8299
  const packageManager = ctx.packageManager || "pnpm";
8210
8300
  const devCommand = getDevCommand(packageManager);
8211
- console.log(chalk2.cyan(` cd ${cdCommand}`));
8212
- console.log(chalk2.cyan(` ${devCommand}`));
8213
- 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"));
8214
8304
  if (hasKeyWarning) {
8215
- console.log(chalk2.yellow("\n\u26A0\uFE0F Remember to configure provider API keys!"));
8216
- 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"));
8217
8307
  }
8218
- console.log(chalk2.gray("\nView logs:"), chalk2.cyan(`baseboards logs ${ctx.name} -f`));
8219
- 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"));
8220
8311
  console.log();
8221
8312
  }
8222
8313
  function printDevPackagesSuccessMessage(ctx, hasKeyWarning) {
8223
- console.log(chalk2.green.bold("\n\u2705 Backend services are running!"));
8224
- 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"));
8225
8316
  console.log(
8226
- chalk2.cyan(" API: "),
8227
- chalk2.underline(`http://localhost:${ctx.ports.api}`)
8317
+ chalk3.cyan(" API: "),
8318
+ chalk3.underline(`http://localhost:${ctx.ports.api}`)
8228
8319
  );
8229
8320
  console.log(
8230
- chalk2.cyan(" GraphQL: "),
8231
- chalk2.underline(`http://localhost:${ctx.ports.api}/graphql`)
8321
+ chalk3.cyan(" GraphQL: "),
8322
+ chalk3.underline(`http://localhost:${ctx.ports.api}/graphql`)
8232
8323
  );
8233
- console.log(chalk2.cyan("\n\u{1F4E6} Package development workflow:\n"));
8234
- console.log(chalk2.gray(" 1. Edit package source:"));
8235
- console.log(chalk2.cyan(` ${ctx.dir}/frontend/src/`));
8236
- console.log(chalk2.gray("\n 2. Start the frontend:"));
8237
- console.log(chalk2.cyan(` cd ${ctx.dir}/web`));
8238
- console.log(chalk2.cyan(` pnpm install`));
8239
- console.log(chalk2.cyan(` pnpm dev`));
8240
- console.log(chalk2.gray("\n 3. Changes to the package will hot-reload automatically"));
8241
- 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(`
8242
8333
  Frontend will be available at http://localhost:3000`));
8243
8334
  if (hasKeyWarning) {
8244
- console.log(chalk2.yellow("\n\u26A0\uFE0F Remember to configure provider API keys!"));
8245
- 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"));
8246
8337
  }
8247
- console.log(chalk2.gray("\nView logs:"), chalk2.cyan(`baseboards logs ${ctx.name} -f`));
8248
- 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"));
8249
8341
  console.log();
8250
8342
  }
8251
8343
  function printSuccessMessage(ctx, detached, hasKeyWarning) {
@@ -8259,7 +8351,7 @@ function printSuccessMessage(ctx, detached, hasKeyWarning) {
8259
8351
  }
8260
8352
  async function checkForExistingVolumes() {
8261
8353
  try {
8262
- const { stdout } = await execa2("docker", [
8354
+ const { stdout } = await execa3("docker", [
8263
8355
  "volume",
8264
8356
  "ls",
8265
8357
  "--format",
@@ -8276,14 +8368,14 @@ async function cleanupDockerVolumes(ctx) {
8276
8368
  const spinner = ora2("Cleaning up Docker volumes...").start();
8277
8369
  try {
8278
8370
  if (ctx.isScaffolded) {
8279
- await execa2("docker", [...getComposeBaseArgs(ctx), "down", "-v"], {
8371
+ await execa3("docker", [...getComposeBaseArgs(ctx), "down", "-v"], {
8280
8372
  cwd: ctx.dir
8281
8373
  });
8282
8374
  } else {
8283
8375
  const volumesToRemove = ["baseboards_db-data", "baseboards_api-storage"];
8284
8376
  for (const volumeName of volumesToRemove) {
8285
8377
  try {
8286
- await execa2("docker", ["volume", "rm", volumeName]);
8378
+ await execa3("docker", ["volume", "rm", volumeName]);
8287
8379
  spinner.text = `Removing volume ${volumeName}...`;
8288
8380
  } catch {
8289
8381
  }
@@ -8293,25 +8385,25 @@ async function cleanupDockerVolumes(ctx) {
8293
8385
  } catch (error) {
8294
8386
  spinner.fail("Failed to clean up volumes");
8295
8387
  console.log(
8296
- chalk2.yellow(
8388
+ chalk3.yellow(
8297
8389
  "\n\u26A0\uFE0F Could not clean up volumes automatically. Try manually:"
8298
8390
  )
8299
8391
  );
8300
- console.log(chalk2.cyan(" docker volume rm baseboards_db-data"));
8392
+ console.log(chalk3.cyan(" docker volume rm baseboards_db-data"));
8301
8393
  throw error;
8302
8394
  }
8303
8395
  }
8304
8396
 
8305
8397
  // src/commands/down.ts
8306
- import { execa as execa3 } from "execa";
8307
- import path6 from "path";
8308
- import chalk3 from "chalk";
8398
+ import { execa as execa4 } from "execa";
8399
+ import path7 from "path";
8400
+ import chalk4 from "chalk";
8309
8401
  import ora3 from "ora";
8310
8402
  async function down(directory, options) {
8311
- const dir = path6.resolve(process.cwd(), directory);
8403
+ const dir = path7.resolve(process.cwd(), directory);
8312
8404
  if (!isScaffolded(dir)) {
8313
- console.error(chalk3.red("\n\u274C Error: Not a Baseboards project"));
8314
- 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."));
8315
8407
  process.exit(1);
8316
8408
  }
8317
8409
  const spinner = ora3("Stopping services...").start();
@@ -8320,12 +8412,12 @@ async function down(directory, options) {
8320
8412
  args.push("--volumes");
8321
8413
  }
8322
8414
  try {
8323
- await execa3("docker", args, {
8415
+ await execa4("docker", args, {
8324
8416
  cwd: dir
8325
8417
  });
8326
8418
  spinner.succeed("Services stopped");
8327
8419
  if (options.volumes) {
8328
- console.log(chalk3.yellow("\u26A0\uFE0F Volumes removed (database data deleted)"));
8420
+ console.log(chalk4.yellow("\u26A0\uFE0F Volumes removed (database data deleted)"));
8329
8421
  }
8330
8422
  } catch (error) {
8331
8423
  spinner.fail("Failed to stop services");
@@ -8334,14 +8426,14 @@ async function down(directory, options) {
8334
8426
  }
8335
8427
 
8336
8428
  // src/commands/logs.ts
8337
- import { execa as execa4 } from "execa";
8338
- import path7 from "path";
8339
- import chalk4 from "chalk";
8429
+ import { execa as execa5 } from "execa";
8430
+ import path8 from "path";
8431
+ import chalk5 from "chalk";
8340
8432
  async function logs(directory, services, options) {
8341
- const dir = path7.resolve(process.cwd(), directory);
8433
+ const dir = path8.resolve(process.cwd(), directory);
8342
8434
  if (!isScaffolded(dir)) {
8343
- console.error(chalk4.red("\n\u274C Error: Not a Baseboards project"));
8344
- 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."));
8345
8437
  process.exit(1);
8346
8438
  }
8347
8439
  const args = ["compose", "logs"];
@@ -8358,7 +8450,7 @@ async function logs(directory, services, options) {
8358
8450
  args.push(...services);
8359
8451
  }
8360
8452
  try {
8361
- await execa4("docker", args, {
8453
+ await execa5("docker", args, {
8362
8454
  cwd: dir,
8363
8455
  stdio: "inherit"
8364
8456
  });
@@ -8370,46 +8462,46 @@ async function logs(directory, services, options) {
8370
8462
  }
8371
8463
 
8372
8464
  // src/commands/status.ts
8373
- import { execa as execa5 } from "execa";
8374
- import path8 from "path";
8375
- import chalk5 from "chalk";
8465
+ import { execa as execa6 } from "execa";
8466
+ import path9 from "path";
8467
+ import chalk6 from "chalk";
8376
8468
  async function status(directory) {
8377
- const dir = path8.resolve(process.cwd(), directory);
8469
+ const dir = path9.resolve(process.cwd(), directory);
8378
8470
  if (!isScaffolded(dir)) {
8379
- console.error(chalk5.red("\n\u274C Error: Not a Baseboards project"));
8380
- 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."));
8381
8473
  process.exit(1);
8382
8474
  }
8383
- console.log(chalk5.blue.bold("\n\u{1F4CA} Service Status\n"));
8475
+ console.log(chalk6.blue.bold("\n\u{1F4CA} Service Status\n"));
8384
8476
  try {
8385
- await execa5("docker", ["compose", "ps"], {
8477
+ await execa6("docker", ["compose", "ps"], {
8386
8478
  cwd: dir,
8387
8479
  stdio: "inherit"
8388
8480
  });
8389
8481
  } catch (error) {
8390
- console.error(chalk5.red("\n\u274C Failed to get status"));
8482
+ console.error(chalk6.red("\n\u274C Failed to get status"));
8391
8483
  throw error;
8392
8484
  }
8393
8485
  }
8394
8486
 
8395
8487
  // src/commands/clean.ts
8396
- import { execa as execa6 } from "execa";
8397
- import path9 from "path";
8398
- import chalk6 from "chalk";
8488
+ import { execa as execa7 } from "execa";
8489
+ import path10 from "path";
8490
+ import chalk7 from "chalk";
8399
8491
  import ora4 from "ora";
8400
8492
  import prompts3 from "prompts";
8401
8493
  async function clean(directory, options) {
8402
- const dir = path9.resolve(process.cwd(), directory);
8494
+ const dir = path10.resolve(process.cwd(), directory);
8403
8495
  if (!isScaffolded(dir)) {
8404
- console.error(chalk6.red("\n\u274C Error: Not a Baseboards project"));
8405
- 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."));
8406
8498
  process.exit(1);
8407
8499
  }
8408
8500
  if (options.hard) {
8409
- console.log(chalk6.yellow("\n\u26A0\uFE0F WARNING: This will delete:"));
8410
- console.log(chalk6.yellow(" \u2022 All containers"));
8411
- console.log(chalk6.yellow(" \u2022 All volumes (database data will be lost)"));
8412
- 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"));
8413
8505
  const response = await prompts3({
8414
8506
  type: "confirm",
8415
8507
  name: "confirmed",
@@ -8417,33 +8509,33 @@ async function clean(directory, options) {
8417
8509
  initial: false
8418
8510
  });
8419
8511
  if (!response.confirmed) {
8420
- console.log(chalk6.gray("\nCancelled"));
8512
+ console.log(chalk7.gray("\nCancelled"));
8421
8513
  return;
8422
8514
  }
8423
8515
  }
8424
8516
  const spinner = ora4("Cleaning up...").start();
8425
8517
  try {
8426
- await execa6("docker", ["compose", "down", "--volumes", "--remove-orphans"], {
8518
+ await execa7("docker", ["compose", "down", "--volumes", "--remove-orphans"], {
8427
8519
  cwd: dir
8428
8520
  });
8429
8521
  if (options.hard) {
8430
8522
  try {
8431
- const { stdout } = await execa6("docker", ["compose", "images", "-q"], {
8523
+ const { stdout } = await execa7("docker", ["compose", "images", "-q"], {
8432
8524
  cwd: dir
8433
8525
  });
8434
8526
  const imageIds = stdout.split("\n").filter(Boolean);
8435
8527
  if (imageIds.length > 0) {
8436
- await execa6("docker", ["rmi", ...imageIds]);
8528
+ await execa7("docker", ["rmi", ...imageIds]);
8437
8529
  }
8438
8530
  } catch (e) {
8439
8531
  }
8440
8532
  }
8441
8533
  spinner.succeed("Cleanup complete");
8442
8534
  if (options.hard) {
8443
- console.log(chalk6.green("\n\u2728 All Docker resources removed"));
8444
- 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."));
8445
8537
  } else {
8446
- console.log(chalk6.green("\n\u2728 Containers and volumes removed"));
8538
+ console.log(chalk7.green("\n\u2728 Containers and volumes removed"));
8447
8539
  }
8448
8540
  } catch (error) {
8449
8541
  spinner.fail("Cleanup failed");
@@ -8452,34 +8544,34 @@ async function clean(directory, options) {
8452
8544
  }
8453
8545
 
8454
8546
  // src/commands/update.ts
8455
- import path10 from "path";
8456
- import chalk7 from "chalk";
8547
+ import path11 from "path";
8548
+ import chalk8 from "chalk";
8457
8549
  async function update(directory, options) {
8458
- const dir = path10.resolve(process.cwd(), directory);
8550
+ const dir = path11.resolve(process.cwd(), directory);
8459
8551
  if (!isScaffolded(dir)) {
8460
- console.error(chalk7.red("\n\u274C Error: Not a Baseboards project"));
8461
- 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."));
8462
8554
  process.exit(1);
8463
8555
  }
8464
- console.log(chalk7.blue.bold("\n\u{1F504} Update Command\n"));
8465
- console.log(chalk7.yellow("\u26A0\uFE0F This feature is coming soon!"));
8466
- console.log(chalk7.gray("\nFor now, to update:"));
8467
- console.log(chalk7.gray("1. Update the CLI:"), chalk7.cyan("npm install -g @weirdfingers/baseboards@latest"));
8468
- console.log(chalk7.gray("2. Pull new images:"), chalk7.cyan("docker compose pull"));
8469
- 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"));
8470
8562
  console.log();
8471
8563
  }
8472
8564
 
8473
8565
  // src/commands/upgrade.ts
8474
- import path15 from "path";
8475
- import chalk10 from "chalk";
8566
+ import path16 from "path";
8567
+ import chalk11 from "chalk";
8476
8568
  import prompts4 from "prompts";
8477
8569
 
8478
8570
  // src/utils/mode-detection.ts
8479
8571
  import { exec } from "child_process";
8480
8572
  import { promisify } from "util";
8481
- import path11 from "path";
8482
- import fs6 from "fs-extra";
8573
+ import path12 from "path";
8574
+ import fs7 from "fs-extra";
8483
8575
  var execAsync2 = promisify(exec);
8484
8576
  async function detectProjectMode(projectDir) {
8485
8577
  try {
@@ -8490,15 +8582,15 @@ async function detectProjectMode(projectDir) {
8490
8582
  }
8491
8583
  } catch {
8492
8584
  }
8493
- const modeFile = path11.join(projectDir, ".baseboards-mode");
8494
- if (await fs6.pathExists(modeFile)) {
8495
- 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();
8496
8588
  if (mode === "default" || mode === "app-dev") {
8497
8589
  return mode;
8498
8590
  }
8499
8591
  }
8500
- const webNodeModules = path11.join(projectDir, "web", "node_modules");
8501
- if (await fs6.pathExists(webNodeModules)) {
8592
+ const webNodeModules = path12.join(projectDir, "web", "node_modules");
8593
+ if (await fs7.pathExists(webNodeModules)) {
8502
8594
  return "app-dev";
8503
8595
  }
8504
8596
  return "default";
@@ -8509,8 +8601,8 @@ import semver from "semver";
8509
8601
 
8510
8602
  // src/utils/compatibility-fetcher.ts
8511
8603
  var import_ajv = __toESM(require_ajv(), 1);
8512
- import fs7 from "fs-extra";
8513
- import path12 from "path";
8604
+ import fs8 from "fs-extra";
8605
+ import path13 from "path";
8514
8606
  import os from "os";
8515
8607
  import addFormats from "ajv-formats";
8516
8608
 
@@ -8573,7 +8665,7 @@ var compatibility_manifest_schema_default = {
8573
8665
 
8574
8666
  // src/utils/compatibility-fetcher.ts
8575
8667
  var GITHUB_REPO = "weirdfingers/boards";
8576
- var CACHE_DIR = path12.join(os.homedir(), ".baseboards", "compatibility");
8668
+ var CACHE_DIR = path13.join(os.homedir(), ".baseboards", "compatibility");
8577
8669
  var ajv = new import_ajv.default({ strict: false });
8578
8670
  addFormats(ajv);
8579
8671
  var validateManifest = ajv.compile(compatibility_manifest_schema_default);
@@ -8621,31 +8713,31 @@ function getManifestUrl(version) {
8621
8713
  }
8622
8714
  async function loadFromCache(version) {
8623
8715
  const cachePath = getCachePath(version);
8624
- if (!await fs7.pathExists(cachePath)) {
8716
+ if (!await fs8.pathExists(cachePath)) {
8625
8717
  return null;
8626
8718
  }
8627
8719
  try {
8628
- const content = await fs7.readFile(cachePath, "utf-8");
8720
+ const content = await fs8.readFile(cachePath, "utf-8");
8629
8721
  const manifest = JSON.parse(content);
8630
8722
  if (!validateManifest(manifest)) {
8631
- await fs7.remove(cachePath);
8723
+ await fs8.remove(cachePath);
8632
8724
  return null;
8633
8725
  }
8634
8726
  return manifest;
8635
8727
  } catch (error) {
8636
- await fs7.remove(cachePath).catch(() => {
8728
+ await fs8.remove(cachePath).catch(() => {
8637
8729
  });
8638
8730
  return null;
8639
8731
  }
8640
8732
  }
8641
8733
  async function saveToCache(version, manifest) {
8642
8734
  const cachePath = getCachePath(version);
8643
- await fs7.ensureDir(CACHE_DIR);
8644
- 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");
8645
8737
  }
8646
8738
  function getCachePath(version) {
8647
8739
  const cleanVersion = version.replace(/^v/, "");
8648
- return path12.join(CACHE_DIR, `compatibility-${cleanVersion}.json`);
8740
+ return path13.join(CACHE_DIR, `compatibility-${cleanVersion}.json`);
8649
8741
  }
8650
8742
 
8651
8743
  // src/utils/compatibility-checker.ts
@@ -8697,70 +8789,70 @@ function isVersionAffected(version, affectedRange) {
8697
8789
  }
8698
8790
 
8699
8791
  // src/commands/upgrade-default.ts
8700
- import path13 from "path";
8701
- import fs8 from "fs-extra";
8702
- import chalk8 from "chalk";
8703
- 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";
8704
8796
  import ora5 from "ora";
8705
8797
  async function upgradeDefaultMode(projectDir, currentVersion, targetVersion) {
8706
- console.log(chalk8.blue(`
8798
+ console.log(chalk9.blue(`
8707
8799
  \u{1F4E6} Upgrading from v${currentVersion} to v${targetVersion}
8708
8800
  `));
8709
8801
  try {
8710
- console.log(chalk8.gray("\u23F8\uFE0F Stopping services..."));
8802
+ console.log(chalk9.gray("\u23F8\uFE0F Stopping services..."));
8711
8803
  await execAsync3("docker compose --env-file docker/.env down", { cwd: projectDir });
8712
- console.log(chalk8.gray("\u2B07\uFE0F Pulling new backend images..."));
8804
+ console.log(chalk9.gray("\u2B07\uFE0F Pulling new backend images..."));
8713
8805
  await execAsync3("docker compose --env-file docker/.env pull api worker", { cwd: projectDir });
8714
- console.log(chalk8.gray("\u{1F4DD} Updating frontend dependencies..."));
8806
+ console.log(chalk9.gray("\u{1F4DD} Updating frontend dependencies..."));
8715
8807
  await updateWebPackageJson(projectDir, targetVersion);
8716
- 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)..."));
8717
8809
  await execAsync3("docker compose --env-file docker/.env build web", { cwd: projectDir });
8718
- console.log(chalk8.gray("\u2699\uFE0F Updating configuration..."));
8810
+ console.log(chalk9.gray("\u2699\uFE0F Updating configuration..."));
8719
8811
  await updateEnvVersion(projectDir, targetVersion);
8720
- console.log(chalk8.gray("\u{1F680} Starting services..."));
8812
+ console.log(chalk9.gray("\u{1F680} Starting services..."));
8721
8813
  await execAsync3("docker compose --env-file docker/.env up -d", { cwd: projectDir });
8722
- 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..."));
8723
8815
  await waitForHealth(projectDir, ["db", "cache", "api", "worker", "web"]);
8724
- console.log(chalk8.green(`
8816
+ console.log(chalk9.green(`
8725
8817
  \u2705 Successfully upgraded to v${targetVersion}!
8726
8818
  `));
8727
8819
  printUpgradeSuccess(projectDir, targetVersion);
8728
8820
  } catch (error) {
8729
8821
  const errorMessage = error instanceof Error ? error.message : String(error);
8730
- console.error(chalk8.red(`
8822
+ console.error(chalk9.red(`
8731
8823
  \u274C Upgrade failed: ${errorMessage}
8732
8824
  `));
8733
- console.log(chalk8.yellow("To rollback:"));
8734
- console.log(chalk8.gray(` 1. Edit docker/.env and set BACKEND_VERSION=${currentVersion}`));
8735
- console.log(chalk8.gray(" 2. Run: docker compose pull"));
8736
- console.log(chalk8.gray(" 3. Run: docker compose build web"));
8737
- 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"));
8738
8830
  throw error;
8739
8831
  }
8740
8832
  }
8741
8833
  async function updateWebPackageJson(projectDir, version) {
8742
- const packageJsonPath = path13.join(projectDir, "web", "package.json");
8743
- const packageJson2 = await fs8.readJson(packageJsonPath);
8834
+ const packageJsonPath = path14.join(projectDir, "web", "package.json");
8835
+ const packageJson2 = await fs9.readJson(packageJsonPath);
8744
8836
  if (packageJson2.dependencies && packageJson2.dependencies["@weirdfingers/boards"]) {
8745
8837
  packageJson2.dependencies["@weirdfingers/boards"] = version;
8746
8838
  }
8747
- await fs8.writeJson(packageJsonPath, packageJson2, { spaces: 2 });
8839
+ await fs9.writeJson(packageJsonPath, packageJson2, { spaces: 2 });
8748
8840
  }
8749
8841
  async function updateEnvVersion(projectDir, version) {
8750
- const envPath = path13.join(projectDir, "docker", ".env");
8751
- 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");
8752
8844
  content = content.replace(
8753
8845
  /^BACKEND_VERSION=.*/m,
8754
8846
  `BACKEND_VERSION=${version}`
8755
8847
  );
8756
- await fs8.writeFile(envPath, content, "utf-8");
8848
+ await fs9.writeFile(envPath, content, "utf-8");
8757
8849
  }
8758
8850
  async function waitForHealth(projectDir, services) {
8759
8851
  const spinner = ora5("Waiting for services to be healthy...").start();
8760
8852
  const maxWaitMs = 12e4;
8761
8853
  const checkHealth = async () => {
8762
8854
  try {
8763
- const { stdout } = await execa7(
8855
+ const { stdout } = await execa8(
8764
8856
  "docker",
8765
8857
  ["compose", "--env-file", "docker/.env", "ps", "--format", "json"],
8766
8858
  {
@@ -8790,106 +8882,106 @@ async function waitForHealth(projectDir, services) {
8790
8882
  } else {
8791
8883
  spinner.warn("Services taking longer than expected...");
8792
8884
  console.log(
8793
- chalk8.yellow(
8885
+ chalk9.yellow(
8794
8886
  "\n\u26A0\uFE0F Health check timeout. Services may still be starting."
8795
8887
  )
8796
8888
  );
8797
8889
  console.log(
8798
- chalk8.gray(" Run"),
8799
- chalk8.cyan("baseboards logs"),
8800
- chalk8.gray("to check progress.")
8890
+ chalk9.gray(" Run"),
8891
+ chalk9.cyan("baseboards logs"),
8892
+ chalk9.gray("to check progress.")
8801
8893
  );
8802
8894
  }
8803
8895
  }
8804
8896
  function printUpgradeSuccess(projectDir, version) {
8805
- console.log(chalk8.gray(" Your Baseboards installation has been upgraded."));
8806
- console.log(chalk8.gray(" All services are running and healthy.\n"));
8807
- console.log(chalk8.gray("Next steps:"));
8808
- console.log(chalk8.gray(` \u2022 Check release notes: https://github.com/weirdfingers/boards/releases/tag/v${version}`));
8809
- console.log(chalk8.gray(` \u2022 View logs: baseboards logs ${path13.basename(projectDir)}`));
8810
- 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)}
8811
8903
  `));
8812
8904
  }
8813
8905
  async function execAsync3(command, options) {
8814
8906
  const [cmd, ...args] = command.split(" ");
8815
- return execa7(cmd, args, options);
8907
+ return execa8(cmd, args, options);
8816
8908
  }
8817
8909
 
8818
8910
  // src/commands/upgrade-app-dev.ts
8819
- import path14 from "path";
8820
- import fs9 from "fs-extra";
8821
- import chalk9 from "chalk";
8822
- 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";
8823
8915
  import ora6 from "ora";
8824
8916
  async function upgradeAppDevMode(projectDir, currentVersion, targetVersion) {
8825
- console.log(chalk9.blue(`
8917
+ console.log(chalk10.blue(`
8826
8918
  \u{1F4E6} Upgrading backend from v${currentVersion} to v${targetVersion}
8827
8919
  `));
8828
8920
  try {
8829
- console.log(chalk9.gray("\u23F8\uFE0F Stopping backend services..."));
8921
+ console.log(chalk10.gray("\u23F8\uFE0F Stopping backend services..."));
8830
8922
  await execAsync("docker compose --env-file docker/.env down", { cwd: projectDir });
8831
- console.log(chalk9.gray("\u2B07\uFE0F Pulling new backend images..."));
8923
+ console.log(chalk10.gray("\u2B07\uFE0F Pulling new backend images..."));
8832
8924
  await execAsync("docker compose --env-file docker/.env pull api worker", { cwd: projectDir });
8833
- console.log(chalk9.gray("\u2699\uFE0F Updating configuration..."));
8925
+ console.log(chalk10.gray("\u2699\uFE0F Updating configuration..."));
8834
8926
  await updateEnvVersion2(projectDir, targetVersion);
8835
- console.log(chalk9.gray("\u{1F680} Starting backend services..."));
8927
+ console.log(chalk10.gray("\u{1F680} Starting backend services..."));
8836
8928
  await execAsync("docker compose --env-file docker/.env up -d db cache api worker", { cwd: projectDir });
8837
- 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..."));
8838
8930
  await waitForHealth2(projectDir, ["db", "cache", "api", "worker"]);
8839
- console.log(chalk9.green(`
8931
+ console.log(chalk10.green(`
8840
8932
  \u2705 Backend upgraded to v${targetVersion}!
8841
8933
  `));
8842
8934
  await printAppDevUpgradeInstructions(projectDir, currentVersion, targetVersion);
8843
8935
  } catch (error) {
8844
8936
  const errorMessage = error instanceof Error ? error.message : String(error);
8845
- console.error(chalk9.red(`
8937
+ console.error(chalk10.red(`
8846
8938
  \u274C Upgrade failed: ${errorMessage}
8847
8939
  `));
8848
- console.log(chalk9.yellow("To rollback:"));
8849
- console.log(chalk9.gray(` 1. Edit docker/.env and set BACKEND_VERSION=${currentVersion}`));
8850
- console.log(chalk9.gray(" 2. Run: docker compose --env-file docker/.env pull"));
8851
- 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"));
8852
8944
  throw error;
8853
8945
  }
8854
8946
  }
8855
8947
  async function updateEnvVersion2(projectDir, version) {
8856
- const envPath = path14.join(projectDir, "docker", ".env");
8857
- 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");
8858
8950
  content = content.replace(
8859
8951
  /^BACKEND_VERSION=.*/m,
8860
8952
  `BACKEND_VERSION=${version}`
8861
8953
  );
8862
- await fs9.writeFile(envPath, content, "utf-8");
8954
+ await fs10.writeFile(envPath, content, "utf-8");
8863
8955
  }
8864
8956
  async function printAppDevUpgradeInstructions(projectDir, oldVersion, newVersion) {
8865
- const webDir = path14.join(projectDir, "web");
8957
+ const webDir = path15.join(projectDir, "web");
8866
8958
  const packageManager = await detectPackageManager(webDir);
8867
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}`;
8868
- console.log(chalk9.yellow("\u26A0\uFE0F Frontend requires manual upgrade:\n"));
8869
- console.log(chalk9.gray(" 1. Stop your dev server (Ctrl+C if running)\n"));
8870
- console.log(chalk9.gray(" 2. Update the frontend package:\n"));
8871
- console.log(chalk9.cyan(` cd ${path14.basename(projectDir)}/web`));
8872
- 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}
8873
8965
  `));
8874
- console.log(chalk9.gray(" 3. Check for breaking changes:\n"));
8875
- 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}
8876
8968
  `));
8877
- console.log(chalk9.gray(" 4. Restart your dev server:\n"));
8878
- console.log(chalk9.cyan(` ${packageManager} dev
8969
+ console.log(chalk10.gray(" 4. Restart your dev server:\n"));
8970
+ console.log(chalk10.cyan(` ${packageManager} dev
8879
8971
  `));
8880
8972
  try {
8881
8973
  const { stdout } = await execAsync("git status --porcelain", { cwd: webDir });
8882
8974
  if (stdout.trim()) {
8883
- console.log(chalk9.yellow("\u26A0\uFE0F You have uncommitted changes in web/"));
8884
- 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"));
8885
8977
  }
8886
8978
  } catch (error) {
8887
- const gitDir = path14.join(webDir, ".git");
8888
- if (!fs9.existsSync(gitDir)) {
8889
- 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."));
8890
8982
  } else {
8891
8983
  console.log(
8892
- chalk9.gray(
8984
+ chalk10.gray(
8893
8985
  " Skipping git status check: git is not available or an error occurred while checking repository status."
8894
8986
  )
8895
8987
  );
@@ -8901,7 +8993,7 @@ async function waitForHealth2(projectDir, services) {
8901
8993
  const maxWaitMs = 12e4;
8902
8994
  const checkHealth = async () => {
8903
8995
  try {
8904
- const { stdout } = await execa8(
8996
+ const { stdout } = await execa9(
8905
8997
  "docker",
8906
8998
  ["compose", "--env-file", "docker/.env", "ps", "--format", "json"],
8907
8999
  {
@@ -8931,61 +9023,61 @@ async function waitForHealth2(projectDir, services) {
8931
9023
  } else {
8932
9024
  spinner.warn("Services taking longer than expected...");
8933
9025
  console.log(
8934
- chalk9.yellow(
9026
+ chalk10.yellow(
8935
9027
  "\n\u26A0\uFE0F Health check timeout. Services may still be starting."
8936
9028
  )
8937
9029
  );
8938
9030
  console.log(
8939
- chalk9.gray(" Run"),
8940
- chalk9.cyan("baseboards logs"),
8941
- chalk9.gray("to check progress.")
9031
+ chalk10.gray(" Run"),
9032
+ chalk10.cyan("baseboards logs"),
9033
+ chalk10.gray("to check progress.")
8942
9034
  );
8943
9035
  }
8944
9036
  }
8945
9037
 
8946
9038
  // src/commands/upgrade.ts
8947
9039
  async function upgrade(directory, options) {
8948
- const dir = path15.resolve(process.cwd(), directory);
9040
+ const dir = path16.resolve(process.cwd(), directory);
8949
9041
  if (!isScaffolded(dir)) {
8950
- console.error(chalk10.red("\n\u274C Error: Not a Baseboards project"));
8951
- 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."));
8952
9044
  process.exit(1);
8953
9045
  }
8954
9046
  const currentVersion = await getCurrentVersion(dir);
8955
9047
  if (!currentVersion) {
8956
- console.error(chalk10.red("\n\u274C Error: Could not determine current version"));
8957
- 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"));
8958
9050
  process.exit(1);
8959
9051
  }
8960
9052
  const targetVersion = options.version || await getLatestVersion();
8961
9053
  if (currentVersion === targetVersion) {
8962
- console.log(chalk10.green(`
9054
+ console.log(chalk11.green(`
8963
9055
  \u2705 Already at v${targetVersion}`));
8964
9056
  return;
8965
9057
  }
8966
9058
  const compatCheck = await checkCompatibility(currentVersion, targetVersion);
8967
9059
  const mode = await detectProjectMode(dir);
8968
- console.log(chalk10.blue("\u{1F4CB} Upgrade Plan:\n"));
8969
- console.log(chalk10.gray(` Current version: ${currentVersion}`));
8970
- console.log(chalk10.gray(` Target version: ${targetVersion}`));
8971
- 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}`));
8972
9064
  console.log("");
8973
9065
  if (mode === "default") {
8974
- console.log(chalk10.gray(" Steps:"));
8975
- console.log(chalk10.gray(" 1. Stop all services"));
8976
- console.log(chalk10.gray(" 2. Pull new backend images"));
8977
- console.log(chalk10.gray(" 3. Update web/package.json"));
8978
- console.log(chalk10.gray(" 4. Rebuild frontend Docker image"));
8979
- console.log(chalk10.gray(" 5. Update docker/.env"));
8980
- console.log(chalk10.gray(" 6. Start services"));
8981
- 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"));
8982
9074
  } else {
8983
- console.log(chalk10.gray(" Steps:"));
8984
- console.log(chalk10.gray(" 1. Stop backend services"));
8985
- console.log(chalk10.gray(" 2. Pull new backend images"));
8986
- console.log(chalk10.gray(" 3. Update docker/.env"));
8987
- console.log(chalk10.gray(" 4. Start backend services"));
8988
- 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"));
8989
9081
  }
8990
9082
  console.log("");
8991
9083
  if (compatCheck.warnings.length > 0) {
@@ -8993,18 +9085,18 @@ async function upgrade(directory, options) {
8993
9085
  console.log("");
8994
9086
  }
8995
9087
  if (compatCheck.requiredActions.length > 0) {
8996
- console.log(chalk10.yellow("\u26A0\uFE0F Required manual actions:"));
9088
+ console.log(chalk11.yellow("\u26A0\uFE0F Required manual actions:"));
8997
9089
  compatCheck.requiredActions.forEach((action) => {
8998
- console.log(chalk10.gray(` \u2022 ${action}`));
9090
+ console.log(chalk11.gray(` \u2022 ${action}`));
8999
9091
  });
9000
9092
  console.log("");
9001
9093
  }
9002
9094
  if (options.dryRun) {
9003
- 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"));
9004
9096
  return;
9005
9097
  }
9006
9098
  if (options.force && compatCheck.breaking) {
9007
- 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"));
9008
9100
  }
9009
9101
  if (!options.force && compatCheck.breaking) {
9010
9102
  const { proceed } = await prompts4({
@@ -9014,7 +9106,7 @@ async function upgrade(directory, options) {
9014
9106
  initial: false
9015
9107
  });
9016
9108
  if (!proceed) {
9017
- console.log(chalk10.gray("\nUpgrade cancelled\n"));
9109
+ console.log(chalk11.gray("\nUpgrade cancelled\n"));
9018
9110
  return;
9019
9111
  }
9020
9112
  }
@@ -9034,104 +9126,104 @@ async function getLatestVersion() {
9034
9126
  }
9035
9127
 
9036
9128
  // src/commands/doctor.ts
9037
- import path16 from "path";
9038
- import fs10 from "fs-extra";
9039
- import chalk11 from "chalk";
9129
+ import path17 from "path";
9130
+ import fs11 from "fs-extra";
9131
+ import chalk12 from "chalk";
9040
9132
  async function doctor(directory) {
9041
- const dir = path16.resolve(process.cwd(), directory);
9042
- console.log(chalk11.blue.bold("\n\u{1FA7A} Baseboards Diagnostics\n"));
9043
- console.log(chalk11.cyan("CLI Version:"), getCliVersion());
9044
- 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:"));
9045
9137
  const prereqs = await checkPrerequisites();
9046
9138
  console.log(
9047
- chalk11.gray(" Node.js:"),
9048
- 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")
9049
9141
  );
9050
9142
  console.log(
9051
- chalk11.gray(" Docker:"),
9052
- 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")
9053
9145
  );
9054
9146
  if (prereqs.docker.composeVersion) {
9055
9147
  console.log(
9056
- chalk11.gray(" Docker Compose:"),
9057
- chalk11.green(`\u2713 v${prereqs.docker.composeVersion}`)
9148
+ chalk12.gray(" Docker Compose:"),
9149
+ chalk12.green(`\u2713 v${prereqs.docker.composeVersion}`)
9058
9150
  );
9059
9151
  } else if (prereqs.docker.installed) {
9060
- console.log(chalk11.gray(" Docker Compose:"), chalk11.red("\u2717 Not available"));
9152
+ console.log(chalk12.gray(" Docker Compose:"), chalk12.red("\u2717 Not available"));
9061
9153
  }
9062
- console.log(chalk11.gray(" Platform:"), prereqs.platform.name);
9154
+ console.log(chalk12.gray(" Platform:"), prereqs.platform.name);
9063
9155
  if (prereqs.platform.isWSL) {
9064
- console.log(chalk11.gray(" WSL:"), chalk11.blue("\u2713 Detected"));
9156
+ console.log(chalk12.gray(" WSL:"), chalk12.blue("\u2713 Detected"));
9065
9157
  }
9066
- console.log(chalk11.cyan("\n\u{1F4C2} Project:"));
9158
+ console.log(chalk12.cyan("\n\u{1F4C2} Project:"));
9067
9159
  const scaffolded = isScaffolded(dir);
9068
9160
  console.log(
9069
- chalk11.gray(" Scaffolded:"),
9070
- scaffolded ? chalk11.green("\u2713 Yes") : chalk11.yellow("\u2717 No")
9161
+ chalk12.gray(" Scaffolded:"),
9162
+ scaffolded ? chalk12.green("\u2713 Yes") : chalk12.yellow("\u2717 No")
9071
9163
  );
9072
9164
  if (scaffolded) {
9073
- console.log(chalk11.gray(" Directory:"), dir);
9074
- const webPkg = path16.join(dir, "web/package.json");
9075
- const apiPkg = path16.join(dir, "api/pyproject.toml");
9076
- 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");
9077
9169
  console.log(
9078
- chalk11.gray(" Web package:"),
9079
- fs10.existsSync(webPkg) ? chalk11.green("\u2713") : chalk11.red("\u2717")
9170
+ chalk12.gray(" Web package:"),
9171
+ fs11.existsSync(webPkg) ? chalk12.green("\u2713") : chalk12.red("\u2717")
9080
9172
  );
9081
9173
  console.log(
9082
- chalk11.gray(" API package:"),
9083
- fs10.existsSync(apiPkg) ? chalk11.green("\u2713") : chalk11.red("\u2717")
9174
+ chalk12.gray(" API package:"),
9175
+ fs11.existsSync(apiPkg) ? chalk12.green("\u2713") : chalk12.red("\u2717")
9084
9176
  );
9085
9177
  console.log(
9086
- chalk11.gray(" Compose file:"),
9087
- fs10.existsSync(composeFile) ? chalk11.green("\u2713") : chalk11.red("\u2717")
9178
+ chalk12.gray(" Compose file:"),
9179
+ fs11.existsSync(composeFile) ? chalk12.green("\u2713") : chalk12.red("\u2717")
9088
9180
  );
9089
- console.log(chalk11.cyan("\n\u{1F510} Environment:"));
9090
- const webEnv = path16.join(dir, "web/.env");
9091
- const apiEnv = path16.join(dir, "api/.env");
9092
- 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");
9093
9185
  console.log(
9094
- chalk11.gray(" Web .env:"),
9095
- 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")
9096
9188
  );
9097
9189
  console.log(
9098
- chalk11.gray(" API .env:"),
9099
- 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")
9100
9192
  );
9101
9193
  console.log(
9102
- chalk11.gray(" Docker .env:"),
9103
- 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")
9104
9196
  );
9105
- if (fs10.existsSync(apiEnv)) {
9197
+ if (fs11.existsSync(apiEnv)) {
9106
9198
  const missingKeys = detectMissingProviderKeys(apiEnv);
9107
9199
  if (missingKeys.length > 0) {
9108
9200
  console.log(
9109
- chalk11.gray(" Provider keys:"),
9110
- chalk11.yellow(`\u26A0\uFE0F ${missingKeys.length} missing`)
9201
+ chalk12.gray(" Provider keys:"),
9202
+ chalk12.yellow(`\u26A0\uFE0F ${missingKeys.length} missing`)
9111
9203
  );
9112
- 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(", "));
9113
9205
  } else {
9114
- console.log(chalk11.gray(" Provider keys:"), chalk11.green("\u2713 Configured"));
9206
+ console.log(chalk12.gray(" Provider keys:"), chalk12.green("\u2713 Configured"));
9115
9207
  }
9116
9208
  }
9117
- console.log(chalk11.cyan("\n\u2699\uFE0F Configuration:"));
9118
- const generatorsYaml = path16.join(dir, "api/config/generators.yaml");
9119
- 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");
9120
9212
  console.log(
9121
- chalk11.gray(" generators.yaml:"),
9122
- 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")
9123
9215
  );
9124
9216
  console.log(
9125
- chalk11.gray(" storage_config.yaml:"),
9126
- 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")
9127
9219
  );
9128
- const storageDir = path16.join(dir, "data/storage");
9220
+ const storageDir = path17.join(dir, "data/storage");
9129
9221
  console.log(
9130
- chalk11.gray(" Storage directory:"),
9131
- 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")
9132
9224
  );
9133
9225
  }
9134
- console.log(chalk11.cyan("\n\u{1F4A1} Recommendations:"));
9226
+ console.log(chalk12.cyan("\n\u{1F4A1} Recommendations:"));
9135
9227
  const recommendations = [];
9136
9228
  if (!prereqs.node.satisfies) {
9137
9229
  recommendations.push("Upgrade Node.js to v20 or higher");
@@ -9142,18 +9234,18 @@ async function doctor(directory) {
9142
9234
  recommendations.push("Update Docker to get Compose v2");
9143
9235
  }
9144
9236
  if (!scaffolded) {
9145
- recommendations.push("Run " + chalk11.cyan("baseboards up") + " to scaffold a project");
9237
+ recommendations.push("Run " + chalk12.cyan("baseboards up") + " to scaffold a project");
9146
9238
  }
9147
9239
  if (recommendations.length === 0) {
9148
- console.log(chalk11.green(" \u2713 Everything looks good!"));
9240
+ console.log(chalk12.green(" \u2713 Everything looks good!"));
9149
9241
  } else {
9150
- recommendations.forEach((rec) => console.log(chalk11.yellow(" \u2022"), rec));
9242
+ recommendations.forEach((rec) => console.log(chalk12.yellow(" \u2022"), rec));
9151
9243
  }
9152
9244
  console.log();
9153
9245
  }
9154
9246
 
9155
9247
  // src/commands/templates.ts
9156
- import chalk12 from "chalk";
9248
+ import chalk13 from "chalk";
9157
9249
  function formatSize(bytes) {
9158
9250
  if (bytes < 1024) {
9159
9251
  return `${bytes} B`;
@@ -9164,22 +9256,22 @@ function formatSize(bytes) {
9164
9256
  }
9165
9257
  }
9166
9258
  function displayTemplate(template, isRecommended) {
9167
- const name = chalk12.bold(template.name);
9168
- const recommended = isRecommended ? chalk12.cyan(" (recommended)") : "";
9259
+ const name = chalk13.bold(template.name);
9260
+ const recommended = isRecommended ? chalk13.cyan(" (recommended)") : "";
9169
9261
  console.log(`
9170
9262
  ${name}${recommended}`);
9171
9263
  console.log(` ${template.description}`);
9172
9264
  const frameworks = template.frameworks.join(", ");
9173
- console.log(` ${chalk12.gray("Frameworks:")} ${frameworks}`);
9265
+ console.log(` ${chalk13.gray("Frameworks:")} ${frameworks}`);
9174
9266
  const features = template.features.join(", ");
9175
- console.log(` ${chalk12.gray("Features:")} ${features}`);
9267
+ console.log(` ${chalk13.gray("Features:")} ${features}`);
9176
9268
  const size = formatSize(template.size);
9177
- console.log(` ${chalk12.gray("Size:")} ${size}`);
9269
+ console.log(` ${chalk13.gray("Size:")} ${size}`);
9178
9270
  }
9179
9271
  async function templates(options) {
9180
9272
  try {
9181
9273
  if (options.refresh) {
9182
- 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"));
9183
9275
  await clearCache();
9184
9276
  }
9185
9277
  const version = options.version || getCliVersion();
@@ -9189,24 +9281,24 @@ async function templates(options) {
9189
9281
  } catch (error) {
9190
9282
  if (error.message.includes("Failed to fetch")) {
9191
9283
  console.error(
9192
- chalk12.red("\n\u274C Network error:"),
9284
+ chalk13.red("\n\u274C Network error:"),
9193
9285
  "Unable to fetch template list"
9194
9286
  );
9195
9287
  console.log(
9196
- chalk12.yellow("\n\u{1F4A1} Tip:"),
9288
+ chalk13.yellow("\n\u{1F4A1} Tip:"),
9197
9289
  "Check your internet connection or try again later"
9198
9290
  );
9199
9291
  process.exit(1);
9200
9292
  }
9201
9293
  if (error.message.includes("not found")) {
9202
9294
  console.error(
9203
- chalk12.red("\n\u274C Version not found:"),
9295
+ chalk13.red("\n\u274C Version not found:"),
9204
9296
  `Version ${version} does not exist`
9205
9297
  );
9206
9298
  console.log(
9207
- chalk12.yellow("\n\u{1F4A1} Tip:"),
9299
+ chalk13.yellow("\n\u{1F4A1} Tip:"),
9208
9300
  "Check available versions at:",
9209
- chalk12.cyan("https://github.com/weirdfingers/boards/releases")
9301
+ chalk13.cyan("https://github.com/weirdfingers/boards/releases")
9210
9302
  );
9211
9303
  process.exit(1);
9212
9304
  }
@@ -9214,13 +9306,13 @@ async function templates(options) {
9214
9306
  }
9215
9307
  if (!manifest.templates || manifest.templates.length === 0) {
9216
9308
  console.log(
9217
- chalk12.yellow("\n\u26A0\uFE0F No templates available for version"),
9309
+ chalk13.yellow("\n\u26A0\uFE0F No templates available for version"),
9218
9310
  manifest.version
9219
9311
  );
9220
9312
  process.exit(0);
9221
9313
  }
9222
9314
  console.log(
9223
- chalk12.blue.bold(`
9315
+ chalk13.blue.bold(`
9224
9316
  \u{1F4E6} Available templates for v${manifest.version}:`)
9225
9317
  );
9226
9318
  for (const template of manifest.templates) {
@@ -9229,10 +9321,10 @@ async function templates(options) {
9229
9321
  }
9230
9322
  console.log();
9231
9323
  } catch (error) {
9232
- console.error(chalk12.red("\n\u274C Error:"), error.message || "Unknown error");
9324
+ console.error(chalk13.red("\n\u274C Error:"), error.message || "Unknown error");
9233
9325
  console.error(
9234
- chalk12.yellow("\n\u{1F4A1} Try running:"),
9235
- chalk12.cyan("baseboards doctor")
9326
+ chalk13.yellow("\n\u{1F4A1} Try running:"),
9327
+ chalk13.cyan("baseboards doctor")
9236
9328
  );
9237
9329
  process.exit(1);
9238
9330
  }
@@ -9277,18 +9369,18 @@ try {
9277
9369
  process.exit(1);
9278
9370
  }
9279
9371
  const err = error;
9280
- console.error(chalk13.red("\n\u274C Error:"), err.message || "Unknown error");
9372
+ console.error(chalk14.red("\n\u274C Error:"), err.message || "Unknown error");
9281
9373
  if (err.stderr) {
9282
- console.error(chalk13.gray("\nDetails:"));
9283
- console.error(chalk13.gray(err.stderr));
9374
+ console.error(chalk14.gray("\nDetails:"));
9375
+ console.error(chalk14.gray(err.stderr));
9284
9376
  }
9285
9377
  console.error(
9286
- chalk13.yellow("\n\u{1F4A1} Try running:"),
9287
- chalk13.cyan("baseboards doctor")
9378
+ chalk14.yellow("\n\u{1F4A1} Try running:"),
9379
+ chalk14.cyan("baseboards doctor")
9288
9380
  );
9289
9381
  console.error(
9290
- chalk13.yellow("\u{1F4D6} Documentation:"),
9291
- chalk13.cyan("https://baseboards.dev/docs")
9382
+ chalk14.yellow("\u{1F4D6} Documentation:"),
9383
+ chalk14.cyan("https://baseboards.dev/docs")
9292
9384
  );
9293
9385
  process.exit(1);
9294
9386
  }