create-better-fullstack 2.1.8 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/README.md +4 -4
  2. package/dist/{add-handler-ztNjzoMN.mjs → add-handler-z4NCxoq6.mjs} +9 -8
  3. package/dist/addons-setup-COE1e1db.mjs +7 -0
  4. package/dist/{addons-setup-LaAj43NP.mjs → addons-setup-DKtiNexf.mjs} +1 -1
  5. package/dist/{analytics-DVltG11u.mjs → analytics-BD8hZvIj.mjs} +1 -1
  6. package/dist/{bts-config-DQVWvPDs.mjs → bts-config-Bwd6GB7B.mjs} +59 -0
  7. package/dist/cli.mjs +2 -2
  8. package/dist/command-exists-DtX9ldL8.mjs +15 -0
  9. package/dist/{config-processing-D9-F2Us9.mjs → config-processing-B-RT_mVE.mjs} +32 -3
  10. package/dist/{doctor-a4ca3SMd.mjs → doctor-LmNs-hDr.mjs} +4 -3
  11. package/dist/{file-formatter-gvmrpd-g.mjs → file-formatter-DxF56-mO.mjs} +550 -24
  12. package/dist/{gen-CCClL7Ve.mjs → gen-CQfQU0uZ.mjs} +1 -1
  13. package/dist/{generated-checks-BV9jol5h.mjs → generated-checks-BUcI5VM2.mjs} +55 -22
  14. package/dist/index.d.mts +741 -211
  15. package/dist/index.mjs +30 -9
  16. package/dist/{install-dependencies-RoUyaE8o.mjs → install-dependencies-CJiUklm3.mjs} +132 -23
  17. package/dist/{mcp-492OkjcS.mjs → mcp-BBammItk.mjs} +5 -5
  18. package/dist/mcp-entry.mjs +76 -236
  19. package/dist/{registry-DSf2CEaU.mjs → registry-D0JfLCoH.mjs} +1 -1
  20. package/dist/{run-T6g1jkfy.mjs → run-BAIeghcU.mjs} +1948 -318
  21. package/dist/run-CAl4L4uU.mjs +16 -0
  22. package/dist/scaffold-manifest-CQwvyttq.mjs +4 -0
  23. package/dist/{scaffold-manifest-Dyi0voqE.mjs → scaffold-manifest-Dr3Anmlf.mjs} +34 -5
  24. package/dist/{update-DJ8CI5KW.mjs → update-CnrBdWrh.mjs} +182 -25
  25. package/package.json +24 -7
  26. package/dist/addons-setup-DnLjAzTw.mjs +0 -7
  27. package/dist/run-CD8f7PHh.mjs +0 -15
  28. package/dist/scaffold-manifest-DGRyepdb.mjs +0 -4
  29. /package/dist/{update-deps-aD-iQw4U.mjs → update-deps-G3FgqBlW.mjs} +0 -0
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
- import { b as types_exports, d as getGraphSummary, m as getLatestCLIVersion, n as previewBtsConfigUpdate, o as writeBtsConfig, r as readBtsConfig, s as getEffectiveStack, t as buildBtsConfigForPersistence, v as getDefaultConfig } from "./bts-config-DQVWvPDs.mjs";
2
+ import { b as types_exports, d as getGraphSummary, m as getLatestCLIVersion, n as previewBtsConfigUpdate, o as writeBtsConfig, r as readBtsConfig, s as getEffectiveStack, t as buildBtsConfigForPersistence, v as getDefaultConfig } from "./bts-config-Bwd6GB7B.mjs";
3
3
  import "./errors-ns_o2OKg.mjs";
4
4
  import "./prompt-environment-BR0Kkw2W.mjs";
5
- import { a as trackProjectCreation, i as trackEvent } from "./analytics-DVltG11u.mjs";
6
- import { r as validateConfigForProgrammaticUse, t as formatCode, v as CreateCommandOptionsSchema } from "./file-formatter-gvmrpd-g.mjs";
7
- import { a as getTemplateConfig, o as getTemplateDescription, s as generateReproducibleCommand, t as applyEffectBackendDefaults } from "./config-processing-D9-F2Us9.mjs";
8
- import { o as refreshScaffoldManifestFiles } from "./scaffold-manifest-Dyi0voqE.mjs";
5
+ import { a as trackProjectCreation, i as trackEvent } from "./analytics-BD8hZvIj.mjs";
6
+ import { a as asString, c as compatibilityChangesToProjectConfig, l as getCompatibilityBackend, o as asStringArray, r as validateConfigForProgrammaticUse, s as buildCompatibilityInputFromConfig, t as formatCode, w as CreateCommandOptionsSchema } from "./file-formatter-DxF56-mO.mjs";
7
+ import { a as getTemplateConfig, o as getTemplateDescription, s as generateReproducibleCommand, t as applyEffectBackendDefaults } from "./config-processing-B-RT_mVE.mjs";
8
+ import { c as refreshScaffoldManifestFiles, n as collectStructuredBaselines } from "./scaffold-manifest-Dr3Anmlf.mjs";
9
9
  import z from "zod";
10
10
  import fs from "fs-extra";
11
11
  import path from "node:path";
12
- import { AISchema, APISchema, AddonsSchema, AiDocsSchema, AnalyticsSchema, AnimationSchema, AstroIntegrationSchema, AuthSchema, BackendSchema, CATEGORY_ORDER, CMSSchema, CSSFrameworkSchema, CachingSchema, DatabaseSchema, DatabaseSetupSchema, DotnetApiSchema, DotnetAuthSchema, DotnetCachingSchema, DotnetDeploySchema, DotnetJobQueueSchema, DotnetObservabilitySchema, DotnetOrmSchema, DotnetRealtimeSchema, DotnetTestingSchema, DotnetValidationSchema, DotnetWebFrameworkSchema, EcosystemSchema, EffectSchema, ElixirApiSchema, ElixirAuthSchema, ElixirCachingSchema, ElixirDeploySchema, ElixirEmailSchema, ElixirHttpSchema, ElixirJobsSchema, ElixirJsonSchema, ElixirLibrariesSchema, ElixirObservabilitySchema, ElixirOrmSchema, ElixirQualitySchema, ElixirRealtimeSchema, ElixirTestingSchema, ElixirValidationSchema, ElixirWebFrameworkSchema, EmailSchema, ExamplesSchema, FeatureFlagsSchema, FileStorageSchema, FileUploadSchema, FormsSchema, FrontendSchema, GoApiSchema, GoAuthSchema, GoCachingSchema, GoCliSchema, GoConfigSchema, GoLoggingSchema, GoMessageQueueSchema, GoObservabilitySchema, GoOrmSchema, GoRealtimeSchema, GoTestingSchema, GoWebFrameworkSchema, I18nSchema, JavaApiSchema, JavaAuthSchema, JavaBuildToolSchema, JavaLanguageSchema, JavaLibrariesSchema, JavaLoggingSchema, JavaOrmSchema, JavaTestingLibrariesSchema, JavaWebFrameworkSchema, JobQueueSchema, LoggingSchema, MobileDeepLinkingSchema, MobileNavigationSchema, MobileOTASchema, MobilePushSchema, MobileStorageSchema, MobileTestingSchema, MobileUISchema, OPTION_CATEGORY_METADATA, ORMSchema, ObservabilitySchema, PackageManagerSchema, PaymentsSchema, PythonAiSchema, PythonApiSchema, PythonAuthSchema, PythonCachingSchema, PythonCliSchema, PythonGraphqlSchema, PythonObservabilitySchema, PythonOrmSchema, PythonQualitySchema, PythonRealtimeSchema, PythonTaskQueueSchema, PythonTestingSchema, PythonValidationSchema, PythonWebFrameworkSchema, RateLimitSchema, RealtimeSchema, RuntimeSchema, RustApiSchema, RustAuthSchema, RustCachingSchema, RustCliSchema, RustErrorHandlingSchema, RustFrontendSchema, RustLibrariesSchema, RustLoggingSchema, RustMessageQueueSchema, RustObservabilitySchema, RustOrmSchema, RustRealtimeSchema, RustTemplatingSchema, RustWebFrameworkSchema, SearchSchema, ServerDeploySchema, ShadcnBaseColorSchema, ShadcnBaseSchema, ShadcnColorThemeSchema, ShadcnFontSchema, ShadcnIconLibrarySchema, ShadcnRadiusSchema, ShadcnStyleSchema, StateManagementSchema, TEMPLATE_VALUES, TestingSchema, UILibrarySchema, ValidationSchema, VectorDbSchema, VersionChannelSchema, WebDeploySchema, analyzeStackCompatibility, evaluateCompatibility, formatStackPartSpec, getCategoryOrderForEcosystem, legacyProjectConfigToStackParts, parseStackPartSpecs, stackPartsToLegacyProjectConfigPartial } from "@better-fullstack/types";
12
+ import { AISchema, APISchema, AddonsSchema, AiDocsSchema, AnalyticsSchema, AnimationSchema, AstroIntegrationSchema, AuthSchema, BackendSchema, CATEGORY_ORDER, CMSSchema, CSSFrameworkSchema, CachingSchema, DatabaseSchema, DatabaseSetupSchema, DotnetApiSchema, DotnetAuthSchema, DotnetCachingSchema, DotnetDeploySchema, DotnetJobQueueSchema, DotnetLibrariesSchema, DotnetObservabilitySchema, DotnetOrmSchema, DotnetRealtimeSchema, DotnetTestingSchema, DotnetValidationSchema, DotnetWebFrameworkSchema, EcosystemSchema, EffectSchema, ElixirApiSchema, ElixirApplicationFrameworkSchema, ElixirAuthSchema, ElixirCachingSchema, ElixirClusteringSchema, ElixirDeploySchema, ElixirDocumentationSchema, ElixirEmailSchema, ElixirHttpSchema, ElixirHttpServerSchema, ElixirI18nSchema, ElixirJobsSchema, ElixirJsonSchema, ElixirLibrariesSchema, ElixirObservabilitySchema, ElixirOrmSchema, ElixirQualitySchema, ElixirRealtimeSchema, ElixirTestingSchema, ElixirValidationSchema, ElixirWebFrameworkSchema, EmailSchema, ExamplesSchema, FeatureFlagsSchema, FileStorageSchema, FileUploadSchema, FormsSchema, FrontendSchema, GoApiSchema, GoAuthSchema, GoCachingSchema, GoCliSchema, GoConfigSchema, GoDISchema, GoLoggingSchema, GoMessageQueueSchema, GoMigrationsSchema, GoObservabilitySchema, GoOrmSchema, GoProtoToolingSchema, GoQualitySchema, GoRealtimeSchema, GoTemplatingSchema, GoTestingSchema, GoValidationSchema, GoWebFrameworkSchema, I18nSchema, JavaApiSchema, JavaAuthSchema, JavaBuildToolSchema, JavaLanguageSchema, JavaLibrariesSchema, JavaLoggingSchema, JavaOrmSchema, JavaTestingLibrariesSchema, JavaWebFrameworkSchema, JobQueueSchema, LoggingSchema, MobileDeepLinkingSchema, MobileLibrariesSchema, MobileNavigationSchema, MobileOTASchema, MobilePushSchema, MobileStorageSchema, MobileTestingSchema, MobileUISchema, OPTION_CATEGORY_METADATA, ORMSchema, ObservabilitySchema, PackageManagerSchema, PaymentsSchema, PythonAiSchema, PythonApiSchema, PythonAuthSchema, PythonCachingSchema, PythonCliSchema, PythonCloudSdkSchema, PythonDataSchema, PythonGraphqlSchema, PythonHttpClientSchema, PythonMediaSchema, PythonMessageQueueSchema, PythonObservabilitySchema, PythonOrmSchema, PythonPackageManagerSchema, PythonQualitySchema, PythonRealtimeSchema, PythonServerSchema, PythonTaskQueueSchema, PythonTestingSchema, PythonValidationSchema, PythonWebFrameworkSchema, RateLimitSchema, RealtimeSchema, RuntimeSchema, RustApiSchema, RustAuthSchema, RustCachingSchema, RustCliSchema, RustErrorHandlingSchema, RustFrontendSchema, RustLibrariesSchema, RustLoggingSchema, RustMessageQueueSchema, RustObservabilitySchema, RustOrmSchema, RustRealtimeSchema, RustTemplatingSchema, RustWebFrameworkSchema, SearchSchema, ServerDeploySchema, ShadcnBaseColorSchema, ShadcnBaseSchema, ShadcnColorThemeSchema, ShadcnFontSchema, ShadcnIconLibrarySchema, ShadcnRadiusSchema, ShadcnStyleSchema, StateManagementSchema, TEMPLATE_VALUES, TestingSchema, UILibrarySchema, ValidationSchema, VectorDbSchema, VersionChannelSchema, WebDeploySchema, analyzeStackCompatibility, evaluateCompatibility, formatStackPartSpec, getCategoryOrderForEcosystem, legacyProjectConfigToStackParts, parseStackPartSpecs, stackPartsToLegacyProjectConfigPartial } from "@better-fullstack/types";
13
13
  import { tmpdir } from "node:os";
14
14
  import { EMBEDDED_TEMPLATES, generateVirtualProject } from "@better-fullstack/template-generator";
15
15
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -26,11 +26,14 @@ const ARRAY_UPDATE_KEYS = new Set([
26
26
  "pythonAi",
27
27
  "pythonTesting",
28
28
  "pythonCli",
29
+ "pythonData",
29
30
  "goTesting",
30
31
  "javaLibraries",
31
32
  "javaTestingLibraries",
32
33
  "dotnetTesting",
33
34
  "dotnetObservability",
35
+ "mobileLibraries",
36
+ "dotnetLibraries",
34
37
  "elixirLibraries"
35
38
  ]);
36
39
  const NON_STACK_UPDATE_CREATE_KEYS = new Set([
@@ -249,9 +252,6 @@ function mergeDerivedStackPartsWithExistingGraph(currentConfig, proposedConfig)
249
252
  }
250
253
  return (0, types_exports.parseStackPartSpecs)(pruneScopedSpecsWithoutOwners([...new Set(nextSpecs)]), "selected");
251
254
  }
252
- function asString(value, fallback = "none") {
253
- return typeof value === "string" ? value : fallback;
254
- }
255
255
  function computeArchitectureChanges(currentConfig, proposedConfig) {
256
256
  const changes = [];
257
257
  for (const key of RISKY_ARCHITECTURE_KEYS) {
@@ -312,23 +312,6 @@ async function writeMigrationChecklist(projectDir, plan) {
312
312
  await fs.writeFile(migrationPath, `${existing}\n\n${section}\n`, "utf-8");
313
313
  } else await fs.writeFile(migrationPath, `# Migration checklist\n\n${section}\n`, "utf-8");
314
314
  }
315
- function asStringArray(value) {
316
- return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
317
- }
318
- function getCompatibilityBackend(config, webFrontend) {
319
- if (config.backend !== "self") return asString(config.backend, "hono");
320
- if (webFrontend.includes("next")) return "self-next";
321
- if (webFrontend.includes("vinext")) return "self-vinext";
322
- if (webFrontend.includes("tanstack-start")) return "self-tanstack-start";
323
- if (webFrontend.includes("astro")) return "self-astro";
324
- if (webFrontend.includes("nuxt")) return "self-nuxt";
325
- if (webFrontend.includes("svelte")) return "self-svelte";
326
- if (webFrontend.includes("solid-start")) return "self-solid-start";
327
- return "self";
328
- }
329
- function getProjectBackendFromCompatibility(backend) {
330
- return backend.startsWith("self-") ? "self" : backend;
331
- }
332
315
  function getDefaultDatabaseForDbSetup(dbSetup) {
333
316
  switch (dbSetup) {
334
317
  case "turso":
@@ -389,198 +372,7 @@ function getDefaultWebFrontendForRequestedUpdate(requestedChanges) {
389
372
  }
390
373
  function getDefaultNativeFrontendForRequestedUpdate(requestedChanges) {
391
374
  if (requestedChanges.mobileUI === "uniwind" || requestedChanges.mobileUI === "unistyles") return;
392
- return hasRequestedNonNoneValue(requestedChanges, "mobileNavigation") || hasRequestedNonNoneValue(requestedChanges, "mobileUI") || hasRequestedNonNoneValue(requestedChanges, "mobileStorage") || hasRequestedNonNoneValue(requestedChanges, "mobileTesting") || hasRequestedNonNoneValue(requestedChanges, "mobilePush") || hasRequestedNonNoneValue(requestedChanges, "mobileOTA") || hasRequestedNonNoneValue(requestedChanges, "mobileDeepLinking") ? "native-bare" : void 0;
393
- }
394
- function hasSelectedTypeScriptBackendPart(config) {
395
- return config.stackParts?.some((part) => part.source !== "provided" && !part.ownerPartId && part.role === "backend" && part.ecosystem === "typescript" && part.toolId !== "none") ?? false;
396
- }
397
- function getCompatibilityEcosystem(config) {
398
- if (config.ecosystem === "react-native" && hasSelectedTypeScriptBackendPart(config)) return "typescript";
399
- return config.ecosystem;
400
- }
401
- function buildCompatibilityInputFromConfig(config) {
402
- const frontend = asStringArray(config.frontend);
403
- const addons = asStringArray(config.addons);
404
- const webFrontend = frontend.filter((item) => !item.startsWith("native-") && item !== "none");
405
- const nativeFrontend = frontend.filter((item) => item.startsWith("native-"));
406
- const codeQuality = [];
407
- const documentation = [];
408
- const appPlatforms = [];
409
- for (const addon of addons) {
410
- const binding = (0, types_exports.getAddonStackPartBinding)(addon);
411
- if (binding?.role === "codeQuality") codeQuality.push(addon);
412
- else if (binding?.role === "documentation") documentation.push(addon);
413
- else if (addon !== "none") appPlatforms.push(addon);
414
- }
415
- return {
416
- ecosystem: getCompatibilityEcosystem(config),
417
- projectName: config.projectName ?? null,
418
- webFrontend,
419
- nativeFrontend,
420
- astroIntegration: asString(config.astroIntegration),
421
- runtime: asString(config.runtime, "bun"),
422
- backend: getCompatibilityBackend(config, webFrontend),
423
- database: asString(config.database),
424
- orm: asString(config.orm),
425
- dbSetup: asString(config.dbSetup),
426
- auth: asString(config.auth),
427
- payments: asString(config.payments),
428
- email: asString(config.email),
429
- fileUpload: asString(config.fileUpload),
430
- logging: asString(config.logging),
431
- observability: asString(config.observability),
432
- featureFlags: asString(config.featureFlags),
433
- analytics: asString(config.analytics),
434
- backendLibraries: "none",
435
- stateManagement: asString(config.stateManagement),
436
- forms: asString(config.forms),
437
- validation: asString(config.validation),
438
- testing: asString(config.testing),
439
- realtime: asString(config.realtime),
440
- jobQueue: asString(config.jobQueue),
441
- caching: asString(config.caching),
442
- rateLimit: asString(config.rateLimit),
443
- animation: asString(config.animation),
444
- cssFramework: asString(config.cssFramework),
445
- uiLibrary: asString(config.uiLibrary),
446
- shadcnBase: asString(config.shadcnBase, "radix"),
447
- shadcnStyle: asString(config.shadcnStyle, "nova"),
448
- shadcnIconLibrary: asString(config.shadcnIconLibrary, "lucide"),
449
- shadcnColorTheme: asString(config.shadcnColorTheme, "neutral"),
450
- shadcnBaseColor: asString(config.shadcnBaseColor, "neutral"),
451
- shadcnFont: asString(config.shadcnFont, "inter"),
452
- shadcnRadius: asString(config.shadcnRadius, "default"),
453
- cms: asString(config.cms),
454
- i18n: asString(config.i18n),
455
- search: asString(config.search),
456
- vectorDb: asString(config.vectorDb),
457
- fileStorage: asString(config.fileStorage),
458
- mobileNavigation: asString(config.mobileNavigation),
459
- mobileUI: asString(config.mobileUI),
460
- mobileStorage: asString(config.mobileStorage),
461
- mobileTesting: asString(config.mobileTesting),
462
- mobilePush: asString(config.mobilePush),
463
- mobileOTA: asString(config.mobileOTA),
464
- mobileDeepLinking: asString(config.mobileDeepLinking),
465
- codeQuality,
466
- documentation,
467
- appPlatforms,
468
- packageManager: asString(config.packageManager, "bun"),
469
- workspaceShape: asString(config.workspaceShape, "monorepo"),
470
- versionChannel: asString(config.versionChannel, "stable"),
471
- examples: asStringArray(config.examples),
472
- aiSdk: asString(config.ai),
473
- aiDocs: asStringArray(config.aiDocs),
474
- git: "false",
475
- install: "false",
476
- api: asString(config.api),
477
- webDeploy: asString(config.webDeploy),
478
- serverDeploy: asString(config.serverDeploy),
479
- yolo: "false",
480
- rustWebFramework: asString(config.rustWebFramework),
481
- rustFrontend: asString(config.rustFrontend),
482
- rustOrm: asString(config.rustOrm),
483
- rustApi: asString(config.rustApi),
484
- rustCli: asString(config.rustCli),
485
- rustLibraries: asStringArray(config.rustLibraries),
486
- rustLogging: asString(config.rustLogging),
487
- rustErrorHandling: asString(config.rustErrorHandling),
488
- rustCaching: asString(config.rustCaching),
489
- rustAuth: asString(config.rustAuth),
490
- rustRealtime: asString(config.rustRealtime),
491
- rustMessageQueue: asString(config.rustMessageQueue),
492
- rustObservability: asString(config.rustObservability),
493
- rustTemplating: asString(config.rustTemplating),
494
- pythonWebFramework: asString(config.pythonWebFramework),
495
- pythonOrm: asString(config.pythonOrm),
496
- pythonValidation: asString(config.pythonValidation),
497
- pythonAi: asStringArray(config.pythonAi),
498
- pythonAuth: asString(config.pythonAuth),
499
- pythonApi: asString(config.pythonApi),
500
- pythonTaskQueue: asString(config.pythonTaskQueue),
501
- pythonGraphql: asString(config.pythonGraphql),
502
- pythonQuality: asString(config.pythonQuality),
503
- pythonTesting: asStringArray(config.pythonTesting),
504
- pythonCaching: asString(config.pythonCaching),
505
- pythonRealtime: asString(config.pythonRealtime),
506
- pythonObservability: asString(config.pythonObservability),
507
- pythonCli: asStringArray(config.pythonCli),
508
- goWebFramework: asString(config.goWebFramework),
509
- goOrm: asString(config.goOrm),
510
- goApi: asString(config.goApi),
511
- goCli: asString(config.goCli),
512
- goLogging: asString(config.goLogging),
513
- goAuth: asString(config.goAuth),
514
- goTesting: asStringArray(config.goTesting),
515
- goRealtime: asString(config.goRealtime),
516
- goMessageQueue: asString(config.goMessageQueue),
517
- goCaching: asString(config.goCaching),
518
- goConfig: asString(config.goConfig),
519
- goObservability: asString(config.goObservability),
520
- javaLanguage: asString(config.javaLanguage, "java"),
521
- javaWebFramework: asString(config.javaWebFramework),
522
- javaBuildTool: asString(config.javaBuildTool),
523
- javaOrm: asString(config.javaOrm),
524
- javaAuth: asString(config.javaAuth),
525
- javaApi: asString(config.javaApi),
526
- javaLogging: asString(config.javaLogging),
527
- javaLibraries: asStringArray(config.javaLibraries),
528
- javaTestingLibraries: asStringArray(config.javaTestingLibraries),
529
- dotnetWebFramework: asString(config.dotnetWebFramework),
530
- dotnetOrm: asString(config.dotnetOrm),
531
- dotnetAuth: asString(config.dotnetAuth),
532
- dotnetApi: asString(config.dotnetApi),
533
- dotnetTesting: asStringArray(config.dotnetTesting),
534
- dotnetJobQueue: asString(config.dotnetJobQueue),
535
- dotnetRealtime: asString(config.dotnetRealtime),
536
- dotnetObservability: asStringArray(config.dotnetObservability),
537
- dotnetValidation: asString(config.dotnetValidation),
538
- dotnetCaching: asString(config.dotnetCaching),
539
- dotnetDeploy: asString(config.dotnetDeploy),
540
- elixirWebFramework: asString(config.elixirWebFramework),
541
- elixirOrm: asString(config.elixirOrm),
542
- elixirAuth: asString(config.elixirAuth),
543
- elixirApi: asString(config.elixirApi),
544
- elixirRealtime: asString(config.elixirRealtime),
545
- elixirJobs: asString(config.elixirJobs),
546
- elixirValidation: asString(config.elixirValidation),
547
- elixirHttp: asString(config.elixirHttp),
548
- elixirJson: asString(config.elixirJson),
549
- elixirEmail: asString(config.elixirEmail),
550
- elixirCaching: asString(config.elixirCaching),
551
- elixirObservability: asString(config.elixirObservability),
552
- elixirTesting: asString(config.elixirTesting),
553
- elixirQuality: asString(config.elixirQuality),
554
- elixirDeploy: asString(config.elixirDeploy),
555
- elixirLibraries: asStringArray(config.elixirLibraries)
556
- };
557
- }
558
- function compatibilityChangesToProjectConfig(adjusted, baseConfig) {
559
- const frontend = [...adjusted.webFrontend, ...adjusted.nativeFrontend];
560
- const ignoredCompatibilityKeys = new Set([
561
- "webFrontend",
562
- "nativeFrontend",
563
- "codeQuality",
564
- "documentation",
565
- "appPlatforms",
566
- "aiSdk",
567
- "backendLibraries",
568
- "projectName",
569
- "git",
570
- "install",
571
- "yolo"
572
- ]);
573
- const changes = {};
574
- for (const [key, value] of Object.entries(adjusted)) if (!ignoredCompatibilityKeys.has(key)) changes[key] = value;
575
- changes.frontend = frontend.length > 0 ? frontend : baseConfig.frontend;
576
- changes.addons = [
577
- ...adjusted.codeQuality,
578
- ...adjusted.documentation,
579
- ...adjusted.appPlatforms
580
- ];
581
- changes.ai = adjusted.aiSdk;
582
- changes.backend = getProjectBackendFromCompatibility(adjusted.backend);
583
- return changes;
375
+ return hasRequestedNonNoneValue(requestedChanges, "mobileNavigation") || hasRequestedNonNoneValue(requestedChanges, "mobileUI") || hasRequestedNonNoneValue(requestedChanges, "mobileStorage") || hasRequestedNonNoneValue(requestedChanges, "mobileTesting") || hasRequestedNonNoneValue(requestedChanges, "mobilePush") || hasRequestedNonNoneValue(requestedChanges, "mobileOTA") || hasRequestedNonNoneValue(requestedChanges, "mobileDeepLinking") || (requestedChanges.mobileLibraries?.some((value) => value !== "none") ?? false) ? "native-bare" : void 0;
584
376
  }
585
377
  function applyKnownDependencyExpansions(config, requestedChanges) {
586
378
  const next = { ...config };
@@ -795,8 +587,7 @@ function diffJsonSection(current, previous, proposed, section) {
795
587
  const blockers = [];
796
588
  for (const [name, proposedValue] of Object.entries(proposedSection)) {
797
589
  if (previousSection[name] === proposedValue) continue;
798
- const currentValue = currentSection[name];
799
- if (currentValue !== void 0 && currentValue !== previousSection[name]) {
590
+ if (currentSection[name] !== previousSection[name]) {
800
591
  blockers.push(`${section}.${name}`);
801
592
  continue;
802
593
  }
@@ -946,7 +737,10 @@ async function addMissingEnvExampleOperation(options) {
946
737
  function getInstallCommand$1(config) {
947
738
  switch (config.ecosystem) {
948
739
  case "rust": return "cargo build";
949
- case "python": return "uv sync";
740
+ case "python":
741
+ if (config.pythonPackageManager === "poetry") return "poetry install --extras dev";
742
+ if (config.pythonPackageManager === "none") return `${process.platform === "win32" ? "python" : "python3"} -m venv .venv && ${process.platform === "win32" ? ".venv\\Scripts\\pip" : ".venv/bin/pip"} install -e ".[dev]"`;
743
+ return "uv sync --extra dev";
950
744
  case "go": return "go mod tidy";
951
745
  case "java": return config.javaBuildTool === "gradle" ? "./gradlew test" : "./mvnw test";
952
746
  case "elixir": return "mix deps.get && mix compile";
@@ -990,7 +784,7 @@ async function planStackUpdate(projectDirInput, input) {
990
784
  changes: []
991
785
  };
992
786
  const compatibilityAdjustments = [...dependencyExpansion.adjustments, ...compatibilityResult.changes.map((change) => `${change.category}: ${change.message}`)];
993
- if (compatibilityResult.adjustedStack) proposedConfig = mergeProjectConfig(proposedConfig, compatibilityChangesToProjectConfig(compatibilityResult.adjustedStack, proposedConfig));
787
+ if (compatibilityResult.adjustedStack) proposedConfig = mergeProjectConfig(proposedConfig, compatibilityChangesToProjectConfig(compatibilityResult.adjustedStack));
994
788
  proposedConfig.stackParts = mergeDerivedStackPartsWithExistingGraph(currentConfig, proposedConfig);
995
789
  Object.assign(proposedConfig, mergeStackPartSpecs(proposedConfig, stackPartSpecs));
996
790
  try {
@@ -1199,14 +993,15 @@ async function applyStackUpdate(projectDirInput, input) {
1199
993
  version: plan.proposedConfig.version,
1200
994
  createdAt: plan.proposedConfig.createdAt
1201
995
  });
1202
- await refreshScaffoldManifestFiles(plan.projectDir, plan.operations.map((operation) => operation.path));
996
+ await refreshScaffoldManifestFiles(plan.projectDir, plan.operations.map((operation) => operation.path), collectStructuredBaselines(proposedTree));
1203
997
  await writeMigrationChecklist(plan.projectDir, plan);
1204
998
  return plan;
1205
999
  }
1206
1000
 
1207
1001
  //#endregion
1208
1002
  //#region src/mcp.ts
1209
- const INSTRUCTIONS = `Better-Fullstack scaffolds fullstack projects across TypeScript, React Native, Rust, Go, Python, Java, .NET, and Elixir ecosystems with ${Object.values(OPTION_CATEGORY_METADATA).reduce((sum, metadata) => sum + metadata.options.length, 0)} configurable options.
1003
+ const OPTION_ENTRY_COUNT = Object.values(OPTION_CATEGORY_METADATA).reduce((sum, metadata) => sum + metadata.options.length, 0);
1004
+ const INSTRUCTIONS = `Better-Fullstack scaffolds fullstack projects across ${EcosystemSchema.options.join(", ")} ecosystems with ${OPTION_ENTRY_COUNT} configurable options.
1210
1005
 
1211
1006
  RECOMMENDED WORKFLOW:
1212
1007
  1. Call bfs_get_guidance to understand field semantics, required fields, and workflow rules.
@@ -1222,7 +1017,7 @@ For existing projects:
1222
1017
 
1223
1018
  CRITICAL RULES:
1224
1019
  - Dependency installation is ALWAYS skipped in MCP mode (timeout risk). After scaffolding, tell the user to run install manually.
1225
- - Array fields: "frontend", "addons", "examples", "aiDocs", "rustLibraries", "pythonAi", "pythonTesting", "pythonCli", "goTesting", "javaLibraries", "javaTestingLibraries", "dotnetTesting", "dotnetObservability", and "elixirLibraries". Most other option fields are strings.
1020
+ - Array fields: "frontend", "addons", "examples", "aiDocs", "rustLibraries", "pythonAi", "pythonTesting", "pythonCli", "pythonData", "goTesting", "javaLibraries", "javaTestingLibraries", "dotnetTesting", "dotnetObservability", "elixirLibraries", "mobileLibraries", and "dotnetLibraries". Most other option fields are strings.
1226
1021
  - "none" means "skip this feature entirely", not "use the default".
1227
1022
  - Always specify "ecosystem" first — it determines which other fields are relevant.
1228
1023
  - TypeScript web-specific fields (web frontend, backend, orm, etc.) are IGNORED for react-native/rust/python/go/java/dotnet/elixir ecosystems.
@@ -1252,7 +1047,7 @@ function getGuidance() {
1252
1047
  projectName: "kebab-case directory name. Required for bfs_create_project.",
1253
1048
  ecosystem: "Must be set first. Determines which other fields are relevant.",
1254
1049
  frontend: "ARRAY of strings. TypeScript only. Supports multiple frontends in one monorepo. Use [] for API-only.",
1255
- arrayFields: "Use arrays for frontend, addons, examples, aiDocs, rustLibraries, pythonAi, pythonTesting, pythonCli, goTesting, javaLibraries, javaTestingLibraries, dotnetTesting, dotnetObservability, and elixirLibraries. Use [] for \"none\" on multi-select fields.",
1050
+ arrayFields: "Use arrays for frontend, addons, examples, aiDocs, rustLibraries, pythonAi, pythonTesting, pythonCli, pythonData, goTesting, javaLibraries, javaTestingLibraries, dotnetTesting, dotnetObservability, elixirLibraries, mobileLibraries, and dotnetLibraries. Use [] for \"none\" on multi-select fields.",
1256
1051
  backend: "String. \"self\" means fullstack mode (Next.js/Vinext/TanStack Start/Nuxt/Astro API routes). \"none\" for frontend-only.",
1257
1052
  runtime: "\"bun\" or \"node\". Must be \"none\" when backend is \"self\" or \"convex\".",
1258
1053
  addons: "ARRAY of strings. Monorepo tools, code quality, desktop (tauri), browser extensions (wxt), etc.",
@@ -1309,6 +1104,7 @@ const MCP_LEGACY_CATEGORY_KEYS = {
1309
1104
  backendLibraries: ["effect"],
1310
1105
  codeQuality: ["addons"],
1311
1106
  documentation: ["addons"],
1107
+ appShells: ["addons"],
1312
1108
  appPlatforms: ["addons"]
1313
1109
  };
1314
1110
  const MCP_SCHEMA_EXCLUDED_CATEGORIES = new Set([
@@ -1317,6 +1113,7 @@ const MCP_SCHEMA_EXCLUDED_CATEGORIES = new Set([
1317
1113
  "backendLibraries",
1318
1114
  "codeQuality",
1319
1115
  "documentation",
1116
+ "appShells",
1320
1117
  "appPlatforms",
1321
1118
  "aiDocs",
1322
1119
  "git",
@@ -1365,10 +1162,13 @@ function getSchemaOptions(category, ecosystem) {
1365
1162
  }
1366
1163
  return result;
1367
1164
  }
1368
- function getInstallCommand(ecosystem, projectName, packageManager, javaBuildTool, javaWebFramework) {
1165
+ function getInstallCommand(ecosystem, projectName, packageManager, javaBuildTool, javaWebFramework, pythonPackageManager) {
1369
1166
  switch (ecosystem) {
1370
1167
  case "rust": return `cd ${projectName} && cargo build`;
1371
- case "python": return `cd ${projectName} && uv sync`;
1168
+ case "python":
1169
+ if (pythonPackageManager === "poetry") return `cd ${projectName} && poetry install --extras dev`;
1170
+ if (pythonPackageManager === "none") return `cd ${projectName} && ${process.platform === "win32" ? "python" : "python3"} -m venv .venv && ${process.platform === "win32" ? ".venv/Scripts/pip.exe" : ".venv/bin/pip"} install -e ".[dev]"`;
1171
+ return `cd ${projectName} && uv sync --extra dev`;
1372
1172
  case "go": return `cd ${projectName} && go mod tidy`;
1373
1173
  case "elixir": return `cd ${projectName} && mix deps.get && mix compile && mix test`;
1374
1174
  case "java":
@@ -1448,6 +1248,7 @@ const MCP_COMPATIBILITY_DEFAULTS = {
1448
1248
  mobileTesting: "none",
1449
1249
  mobilePush: "none",
1450
1250
  mobileOTA: "none",
1251
+ mobileLibraries: [],
1451
1252
  packageManager: "bun",
1452
1253
  workspaceShape: "monorepo",
1453
1254
  versionChannel: "stable",
@@ -1488,6 +1289,13 @@ const MCP_COMPATIBILITY_DEFAULTS = {
1488
1289
  pythonRealtime: "none",
1489
1290
  pythonObservability: "none",
1490
1291
  pythonCli: [],
1292
+ pythonCloudSdk: "none",
1293
+ pythonHttpClient: "none",
1294
+ pythonData: [],
1295
+ pythonMedia: "none",
1296
+ pythonServer: "none",
1297
+ pythonPackageManager: "uv",
1298
+ pythonMessageQueue: "none",
1491
1299
  goWebFramework: "none",
1492
1300
  goOrm: "none",
1493
1301
  goApi: "none",
@@ -1500,6 +1308,12 @@ const MCP_COMPATIBILITY_DEFAULTS = {
1500
1308
  goCaching: "none",
1501
1309
  goConfig: "none",
1502
1310
  goObservability: "none",
1311
+ goValidation: "none",
1312
+ goQuality: "none",
1313
+ goMigrations: "none",
1314
+ goTemplating: "none",
1315
+ goProtoTooling: "none",
1316
+ goDI: "none",
1503
1317
  javaLanguage: "java",
1504
1318
  javaWebFramework: "spring-boot",
1505
1319
  javaBuildTool: "maven",
@@ -1520,6 +1334,7 @@ const MCP_COMPATIBILITY_DEFAULTS = {
1520
1334
  dotnetValidation: "none",
1521
1335
  dotnetCaching: "none",
1522
1336
  dotnetDeploy: "docker",
1337
+ dotnetLibraries: [],
1523
1338
  elixirWebFramework: "phoenix",
1524
1339
  elixirOrm: "ecto-sql",
1525
1340
  elixirAuth: "none",
@@ -1534,6 +1349,11 @@ const MCP_COMPATIBILITY_DEFAULTS = {
1534
1349
  elixirObservability: "telemetry",
1535
1350
  elixirTesting: "ex_unit",
1536
1351
  elixirQuality: "credo",
1352
+ elixirI18n: "none",
1353
+ elixirHttpServer: "cowboy",
1354
+ elixirApplicationFramework: "none",
1355
+ elixirDocumentation: "none",
1356
+ elixirClustering: "none",
1537
1357
  elixirDeploy: "none",
1538
1358
  elixirLibraries: []
1539
1359
  };
@@ -1737,7 +1557,7 @@ const GETTING_STARTED_MD = `# Getting Started with Better-Fullstack MCP
1737
1557
  - pythonOrm: "sqlalchemy"
1738
1558
  - email: "resend" (optional)
1739
1559
  - observability: "sentry" (optional)
1740
- 2. Tell the user to run: cd my-python-app && uv sync
1560
+ 2. Tell the user to run: cd my-python-app && uv sync --extra dev
1741
1561
 
1742
1562
  ## Quick Start — Go Project
1743
1563
  1. Call bfs_create_project with:
@@ -2080,7 +1900,8 @@ const mobileInputSchema = {
2080
1900
  mobileTesting: MobileTestingSchema.optional().describe("Mobile testing"),
2081
1901
  mobilePush: MobilePushSchema.optional().describe("Mobile push notifications"),
2082
1902
  mobileOTA: MobileOTASchema.optional().describe("Mobile OTA updates"),
2083
- mobileDeepLinking: MobileDeepLinkingSchema.optional().describe("Mobile deep linking")
1903
+ mobileDeepLinking: MobileDeepLinkingSchema.optional().describe("Mobile deep linking"),
1904
+ mobileLibraries: z.array(MobileLibrariesSchema).optional().describe("Mobile application libraries")
2084
1905
  };
2085
1906
  const deploymentInputSchema = {
2086
1907
  dbSetup: DatabaseSetupSchema.optional().describe("Database hosting provider"),
@@ -2116,6 +1937,13 @@ const crossEcosystemInputSchema = {
2116
1937
  pythonRealtime: PythonRealtimeSchema.optional().describe("Python realtime library"),
2117
1938
  pythonObservability: PythonObservabilitySchema.optional().describe("Python observability"),
2118
1939
  pythonCli: z.array(PythonCliSchema).optional().describe("Python CLI tooling"),
1940
+ pythonCloudSdk: PythonCloudSdkSchema.optional().describe("Python cloud SDK"),
1941
+ pythonHttpClient: PythonHttpClientSchema.optional().describe("Python HTTP client"),
1942
+ pythonData: z.array(PythonDataSchema).optional().describe("Python data/scientific libraries"),
1943
+ pythonMedia: PythonMediaSchema.optional().describe("Python media library"),
1944
+ pythonServer: PythonServerSchema.optional().describe("Python production server"),
1945
+ pythonPackageManager: PythonPackageManagerSchema.optional().describe("Python package manager"),
1946
+ pythonMessageQueue: PythonMessageQueueSchema.optional().describe("Python message queue client"),
2119
1947
  goWebFramework: GoWebFrameworkSchema.optional().describe("Go web framework"),
2120
1948
  goOrm: GoOrmSchema.optional().describe("Go ORM"),
2121
1949
  goApi: GoApiSchema.optional().describe("Go API layer"),
@@ -2128,6 +1956,12 @@ const crossEcosystemInputSchema = {
2128
1956
  goCaching: GoCachingSchema.optional().describe("Go caching library"),
2129
1957
  goConfig: GoConfigSchema.optional().describe("Go config management"),
2130
1958
  goObservability: GoObservabilitySchema.optional().describe("Go observability"),
1959
+ goValidation: GoValidationSchema.optional().describe("Go validation"),
1960
+ goQuality: GoQualitySchema.optional().describe("Go code quality"),
1961
+ goMigrations: GoMigrationsSchema.optional().describe("Go database migrations"),
1962
+ goTemplating: GoTemplatingSchema.optional().describe("Go templating"),
1963
+ goProtoTooling: GoProtoToolingSchema.optional().describe("Go protobuf tooling"),
1964
+ goDI: GoDISchema.optional().describe("Go dependency injection"),
2131
1965
  javaLanguage: JavaLanguageSchema.optional().describe("JVM language (java, kotlin)"),
2132
1966
  javaWebFramework: JavaWebFrameworkSchema.optional().describe("Java web framework"),
2133
1967
  javaBuildTool: JavaBuildToolSchema.optional().describe("Java build tool"),
@@ -2148,6 +1982,7 @@ const crossEcosystemInputSchema = {
2148
1982
  dotnetValidation: DotnetValidationSchema.optional().describe(".NET validation"),
2149
1983
  dotnetCaching: DotnetCachingSchema.optional().describe(".NET caching library"),
2150
1984
  dotnetDeploy: DotnetDeploySchema.optional().describe(".NET deployment target"),
1985
+ dotnetLibraries: z.array(DotnetLibrariesSchema).optional().describe(".NET application libraries"),
2151
1986
  elixirWebFramework: ElixirWebFrameworkSchema.optional().describe("Elixir web framework"),
2152
1987
  elixirOrm: ElixirOrmSchema.optional().describe("Elixir persistence layer"),
2153
1988
  elixirAuth: ElixirAuthSchema.optional().describe("Elixir authentication"),
@@ -2162,6 +1997,11 @@ const crossEcosystemInputSchema = {
2162
1997
  elixirObservability: ElixirObservabilitySchema.optional().describe("Elixir observability"),
2163
1998
  elixirTesting: ElixirTestingSchema.optional().describe("Elixir testing library"),
2164
1999
  elixirQuality: ElixirQualitySchema.optional().describe("Elixir code quality/security"),
2000
+ elixirI18n: ElixirI18nSchema.optional().describe("Elixir localization"),
2001
+ elixirHttpServer: ElixirHttpServerSchema.optional().describe("Elixir HTTP server"),
2002
+ elixirApplicationFramework: ElixirApplicationFrameworkSchema.optional().describe("Elixir application framework"),
2003
+ elixirDocumentation: ElixirDocumentationSchema.optional().describe("Elixir documentation tooling"),
2004
+ elixirClustering: ElixirClusteringSchema.optional().describe("Elixir clustering"),
2165
2005
  elixirDeploy: ElixirDeploySchema.optional().describe("Elixir deployment target"),
2166
2006
  elixirLibraries: z.array(ElixirLibrariesSchema).optional().describe("Elixir libraries")
2167
2007
  };
@@ -2543,12 +2383,12 @@ async function startMcpServer() {
2543
2383
  const graphPreview = getMcpGraphPreview(config);
2544
2384
  let addonWarnings = [];
2545
2385
  if (config.addons.length > 0 && config.addons[0] !== "none") {
2546
- const { setupAddons } = await import("./addons-setup-DnLjAzTw.mjs");
2386
+ const { setupAddons } = await import("./addons-setup-COE1e1db.mjs");
2547
2387
  addonWarnings = await setupAddons(config);
2548
2388
  }
2549
- const { recordScaffoldManifest } = await import("./scaffold-manifest-DGRyepdb.mjs");
2550
- await recordScaffoldManifest(projectDir);
2551
- const installCmd = getInstallCommand(input.ecosystem ?? "typescript", projectName, input.packageManager, input.javaBuildTool, input.javaWebFramework);
2389
+ const { collectStructuredBaselines: collectStructuredBaselines$1, recordScaffoldManifest } = await import("./scaffold-manifest-CQwvyttq.mjs");
2390
+ await recordScaffoldManifest(projectDir, { baselines: collectStructuredBaselines$1(result.tree) });
2391
+ const installCmd = getInstallCommand(input.ecosystem ?? "typescript", projectName, input.packageManager, input.javaBuildTool, input.javaWebFramework, input.pythonPackageManager);
2552
2392
  await trackProjectCreation(config, false, {
2553
2393
  source: "mcp",
2554
2394
  success: true,
@@ -2827,7 +2667,7 @@ async function startMcpServer() {
2827
2667
  if (result?.success) {
2828
2668
  const existingConfig = await readBtsConfig(safePath);
2829
2669
  const graphPreview = existingConfig ? getMcpGraphPreview(existingConfig) : void 0;
2830
- const installCmd = getInstallCommand(existingConfig?.ecosystem ?? "typescript", safePath.split("/").pop() ?? "project", input.packageManager, existingConfig?.javaBuildTool, existingConfig?.javaWebFramework);
2670
+ const installCmd = getInstallCommand(existingConfig?.ecosystem ?? "typescript", safePath.split("/").pop() ?? "project", input.packageManager, existingConfig?.javaBuildTool, existingConfig?.javaWebFramework, existingConfig?.pythonPackageManager);
2831
2671
  const payload = {
2832
2672
  success: true,
2833
2673
  addedAddons: result.addedAddons,
@@ -2893,4 +2733,4 @@ async function startMcpServer() {
2893
2733
  startMcpServer();
2894
2734
 
2895
2735
  //#endregion
2896
- export { startMcpServer as a, formatGeneratedTree as c, treeToFileMap as d, recommendStackFromBrief as i, generateTree as l, MCP_STACK_UPDATE_SCHEMA as n, applyStackUpdate as o, getMcpGraphPreview as r, configFromBtsConfig as s, MCP_PLAN_CREATE_SCHEMA as t, planStackUpdate as u };
2736
+ export { startMcpServer as a, configFromBtsConfig as c, mergeEnvExample as d, mergePackageJson as f, recommendStackFromBrief as i, formatGeneratedTree as l, treeToFileMap as m, MCP_STACK_UPDATE_SCHEMA as n, PACKAGE_JSON_SECTIONS as o, planStackUpdate as p, getMcpGraphPreview as r, applyStackUpdate as s, MCP_PLAN_CREATE_SCHEMA as t, generateTree as u };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { b as types_exports, r as readBtsConfig } from "./bts-config-DQVWvPDs.mjs";
2
+ import { b as types_exports, r as readBtsConfig } from "./bts-config-Bwd6GB7B.mjs";
3
3
  import { t as renderTitle } from "./render-title-zvyKC1ej.mjs";
4
4
  import { t as CLIError } from "./errors-ns_o2OKg.mjs";
5
5
  import { intro, log, outro } from "@clack/prompts";