@better-fullstack/types 1.8.0 → 2.0.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 (40) hide show
  1. package/dist/{defaults-CFAJhN--.d.mts → defaults-BSM_JIBn.d.mts} +2 -2
  2. package/dist/defaults-BSM_JIBn.d.mts.map +1 -0
  3. package/dist/{defaults-D23vxGYl.mjs → defaults-DNmNiuxG.mjs} +1 -1
  4. package/dist/{defaults-D23vxGYl.mjs.map → defaults-DNmNiuxG.mjs.map} +1 -1
  5. package/dist/defaults.d.mts +3 -3
  6. package/dist/defaults.mjs +1 -1
  7. package/dist/index.d.mts +6 -5
  8. package/dist/index.d.mts.map +1 -1
  9. package/dist/index.mjs +5 -4
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/json-schema.d.mts +570 -42
  12. package/dist/json-schema.d.mts.map +1 -1
  13. package/dist/json-schema.mjs +1 -1
  14. package/dist/{schemas-Bs_n2xLj.d.mts → schemas-B5EgRfVL.d.mts} +556 -46
  15. package/dist/schemas-B5EgRfVL.d.mts.map +1 -0
  16. package/dist/{schemas-BHCZL3uR.mjs → schemas-DnEGgQzA.mjs} +74 -7
  17. package/dist/schemas-DnEGgQzA.mjs.map +1 -0
  18. package/dist/schemas.d.mts +2 -2
  19. package/dist/schemas.mjs +2 -2
  20. package/dist/stack-graph-C2tzuzRe.mjs +585 -0
  21. package/dist/stack-graph-C2tzuzRe.mjs.map +1 -0
  22. package/dist/stack-graph-_551XvrL.d.mts +68 -0
  23. package/dist/stack-graph-_551XvrL.d.mts.map +1 -0
  24. package/dist/stack-graph.d.mts +4 -0
  25. package/dist/stack-graph.mjs +4 -0
  26. package/dist/{stack-translation-_uOX-Io0.mjs → stack-translation-BcsaMRuV.mjs} +260 -22
  27. package/dist/stack-translation-BcsaMRuV.mjs.map +1 -0
  28. package/dist/{stack-translation-xj8JvbAI.d.mts → stack-translation-CqslePvp.d.mts} +14 -7
  29. package/dist/stack-translation-CqslePvp.d.mts.map +1 -0
  30. package/dist/stack-translation.d.mts +5 -5
  31. package/dist/stack-translation.mjs +4 -3
  32. package/dist/{types-DwFVhx5c.d.mts → types-DorAmN4i.d.mts} +7 -3
  33. package/dist/{types-DwFVhx5c.d.mts.map → types-DorAmN4i.d.mts.map} +1 -1
  34. package/dist/types.d.mts +3 -3
  35. package/package.json +5 -1
  36. package/dist/defaults-CFAJhN--.d.mts.map +0 -1
  37. package/dist/schemas-BHCZL3uR.mjs.map +0 -1
  38. package/dist/schemas-Bs_n2xLj.d.mts.map +0 -1
  39. package/dist/stack-translation-_uOX-Io0.mjs.map +0 -1
  40. package/dist/stack-translation-xj8JvbAI.d.mts.map +0 -1
@@ -1,5 +1,6 @@
1
- import { $ as ELIXIR_VALIDATION_VALUES, $n as RUST_API_VALUES, $t as JOB_QUEUE_VALUES, An as PYTHON_API_VALUES, Ar as STATE_MANAGEMENT_VALUES, B as ELIXIR_API_VALUES, Cn as OBSERVABILITY_VALUES, Cr as SHADCN_BASE_COLOR_VALUES, Ct as FILE_STORAGE_VALUES, D as CMS_VALUES, Dn as PACKAGE_MANAGER_VALUES, Dr as SHADCN_ICON_LIBRARY_VALUES, Er as SHADCN_FONT_VALUES, Fn as PYTHON_TASK_QUEUE_VALUES, Ft as GO_LOGGING_VALUES, G as ELIXIR_HTTP_VALUES, H as ELIXIR_CACHING_VALUES, Hr as TESTING_VALUES, In as PYTHON_VALIDATION_VALUES, It as GO_ORM_VALUES, J as ELIXIR_OBSERVABILITY_VALUES, Jr as VERSION_CHANNEL_VALUES, Jt as JAVA_BUILD_TOOL_VALUES, K as ELIXIR_JOBS_VALUES, Kr as UI_LIBRARY_VALUES, Ln as PYTHON_WEB_FRAMEWORK_VALUES, Lt as GO_WEB_FRAMEWORK_VALUES, M as DATABASE_SETUP_VALUES, Mn as PYTHON_GRAPHQL_VALUES, Mt as GO_API_VALUES, N as DATABASE_VALUES, Nn as PYTHON_ORM_VALUES, Nt as GO_AUTH_VALUES, On as PAYMENTS_VALUES, Or as SHADCN_RADIUS_VALUES, Pn as PYTHON_QUALITY_VALUES, Pt as GO_CLI_VALUES, Q as ELIXIR_TESTING_VALUES, Qn as RUNTIME_VALUES, Qt as JAVA_WEB_FRAMEWORK_VALUES, Sr as SERVER_DEPLOY_VALUES, St as FEATURE_FLAGS_VALUES, Tn as ORM_VALUES, Tr as SHADCN_COLOR_THEME_VALUES, Tt as FORMS_VALUES, U as ELIXIR_DEPLOY_VALUES, V as ELIXIR_AUTH_VALUES, W as ELIXIR_EMAIL_VALUES, Wt as I18N_VALUES, X as ELIXIR_QUALITY_VALUES, Xt as JAVA_ORM_VALUES, Y as ELIXIR_ORM_VALUES, Yt as JAVA_LIBRARIES_VALUES, Z as ELIXIR_REALTIME_VALUES, Zn as REALTIME_VALUES, Zr as WEB_DEPLOY_VALUES, Zt as JAVA_TESTING_LIBRARIES_VALUES, a as ANALYTICS_VALUES, ar as RUST_LIBRARIES_VALUES, c as API_VALUES, cr as RUST_WEB_FRAMEWORK_VALUES, dn as MOBILE_OTA_VALUES, er as RUST_AUTH_VALUES, et as ELIXIR_WEB_FRAMEWORK_VALUES, fn as MOBILE_PUSH_VALUES, hn as MOBILE_UI_VALUES, i as AI_VALUES, ir as RUST_FRONTEND_VALUES, jn as PYTHON_AUTH_VALUES, k as CSS_FRAMEWORK_VALUES, kn as PYTHON_AI_VALUES, kr as SHADCN_STYLE_VALUES, l as ASTRO_INTEGRATION_VALUES, ln as MOBILE_DEEP_LINKING_VALUES, mn as MOBILE_TESTING_VALUES, nr as RUST_CLI_VALUES, o as ANIMATION_VALUES, or as RUST_LOGGING_VALUES, pn as MOBILE_STORAGE_VALUES, q as ELIXIR_JSON_VALUES, qr as VALIDATION_VALUES, qt as JAVA_AUTH_VALUES, r as AI_DOCS_VALUES, rr as RUST_ERROR_HANDLING_VALUES, sn as LOGGING_VALUES, sr as RUST_ORM_VALUES, tr as RUST_CACHING_VALUES, tt as EMAIL_VALUES, u as AUTH_VALUES, un as MOBILE_NAVIGATION_VALUES, w as CACHING_VALUES, wr as SHADCN_BASE_VALUES, wt as FILE_UPLOAD_VALUES, xr as SEARCH_VALUES, z as EFFECT_VALUES } from "./schemas-BHCZL3uR.mjs";
2
- import { t as createCliDefaultProjectConfigBase } from "./defaults-D23vxGYl.mjs";
1
+ import { $ as ELIXIR_VALIDATION_VALUES, $n as RUST_API_VALUES, $t as JOB_QUEUE_VALUES, An as PYTHON_API_VALUES, Ar as STATE_MANAGEMENT_VALUES, B as ELIXIR_API_VALUES, Cn as OBSERVABILITY_VALUES, Cr as SHADCN_BASE_COLOR_VALUES, Ct as FILE_STORAGE_VALUES, D as CMS_VALUES, Dn as PACKAGE_MANAGER_VALUES, Dr as SHADCN_ICON_LIBRARY_VALUES, Er as SHADCN_FONT_VALUES, Fn as PYTHON_TASK_QUEUE_VALUES, Ft as GO_LOGGING_VALUES, G as ELIXIR_HTTP_VALUES, H as ELIXIR_CACHING_VALUES, In as PYTHON_VALIDATION_VALUES, It as GO_ORM_VALUES, J as ELIXIR_OBSERVABILITY_VALUES, Jt as JAVA_BUILD_TOOL_VALUES, K as ELIXIR_JOBS_VALUES, Kr as TESTING_VALUES, Ln as PYTHON_WEB_FRAMEWORK_VALUES, Lt as GO_WEB_FRAMEWORK_VALUES, M as DATABASE_SETUP_VALUES, Mn as PYTHON_GRAPHQL_VALUES, Mt as GO_API_VALUES, N as DATABASE_VALUES, Nn as PYTHON_ORM_VALUES, Nt as GO_AUTH_VALUES, On as PAYMENTS_VALUES, Or as SHADCN_RADIUS_VALUES, Pn as PYTHON_QUALITY_VALUES, Pt as GO_CLI_VALUES, Q as ELIXIR_TESTING_VALUES, Qn as RUNTIME_VALUES, Qr as VERSION_CHANNEL_VALUES, Qt as JAVA_WEB_FRAMEWORK_VALUES, Sr as SERVER_DEPLOY_VALUES, St as FEATURE_FLAGS_VALUES, Tn as ORM_VALUES, Tr as SHADCN_COLOR_THEME_VALUES, Tt as FORMS_VALUES, U as ELIXIR_DEPLOY_VALUES, V as ELIXIR_AUTH_VALUES, W as ELIXIR_EMAIL_VALUES, Wt as I18N_VALUES, X as ELIXIR_QUALITY_VALUES, Xr as UI_LIBRARY_VALUES, Xt as JAVA_ORM_VALUES, Y as ELIXIR_ORM_VALUES, Yt as JAVA_LIBRARIES_VALUES, Z as ELIXIR_REALTIME_VALUES, Zn as REALTIME_VALUES, Zr as VALIDATION_VALUES, Zt as JAVA_TESTING_LIBRARIES_VALUES, a as ANALYTICS_VALUES, ar as RUST_LIBRARIES_VALUES, c as API_VALUES, cr as RUST_WEB_FRAMEWORK_VALUES, dn as MOBILE_OTA_VALUES, er as RUST_AUTH_VALUES, et as ELIXIR_WEB_FRAMEWORK_VALUES, fn as MOBILE_PUSH_VALUES, hn as MOBILE_UI_VALUES, i as AI_VALUES, ir as RUST_FRONTEND_VALUES, jn as PYTHON_AUTH_VALUES, k as CSS_FRAMEWORK_VALUES, kn as PYTHON_AI_VALUES, kr as SHADCN_STYLE_VALUES, l as ASTRO_INTEGRATION_VALUES, ln as MOBILE_DEEP_LINKING_VALUES, mn as MOBILE_TESTING_VALUES, nr as RUST_CLI_VALUES, o as ANIMATION_VALUES, or as RUST_LOGGING_VALUES, pn as MOBILE_STORAGE_VALUES, q as ELIXIR_JSON_VALUES, qt as JAVA_AUTH_VALUES, r as AI_DOCS_VALUES, rr as RUST_ERROR_HANDLING_VALUES, sn as LOGGING_VALUES, sr as RUST_ORM_VALUES, ti as WEB_DEPLOY_VALUES, tr as RUST_CACHING_VALUES, tt as EMAIL_VALUES, u as AUTH_VALUES, un as MOBILE_NAVIGATION_VALUES, w as CACHING_VALUES, wr as SHADCN_BASE_VALUES, wt as FILE_UPLOAD_VALUES, xr as SEARCH_VALUES, z as EFFECT_VALUES } from "./schemas-DnEGgQzA.mjs";
2
+ import { t as createCliDefaultProjectConfigBase } from "./defaults-DNmNiuxG.mjs";
3
+ import { d as stackPartsToLegacyProjectConfigPartial, f as validateStackParts, i as formatStackPartSpec, u as parseStackPartSpecs } from "./stack-graph-C2tzuzRe.mjs";
3
4
 
4
5
  //#region src/capabilities.ts
5
6
  const CAPABILITY_DEFINITIONS = { auth: [
@@ -1124,19 +1125,10 @@ const analyzeStackCompatibility = (stack) => {
1124
1125
  changed = true;
1125
1126
  changes.push({
1126
1127
  category: "nativeFrontend",
1127
- message: "Native frontend set to 'Expo + Bare' (React Native ecosystem)"
1128
+ message: "Native frontend set to 'Expo + StyleSheet' (React Native ecosystem)"
1128
1129
  });
1129
1130
  }
1130
1131
  }
1131
- if (nextStack.ecosystem === "typescript" && nextStack.nativeFrontend.some((frontend) => frontend !== "none")) {
1132
- nextStack.nativeFrontend = ["none"];
1133
- hasNativeFrontend = false;
1134
- changed = true;
1135
- changes.push({
1136
- category: "nativeFrontend",
1137
- message: "Native frontend set to 'None' (use React Native ecosystem for Expo apps)"
1138
- });
1139
- }
1140
1132
  if (!hasNativeFrontend) {
1141
1133
  for (const [category, value, message] of [
1142
1134
  [
@@ -1218,6 +1210,7 @@ const analyzeStackCompatibility = (stack) => {
1218
1210
  }
1219
1211
  if ([
1220
1212
  "shadcn-ui",
1213
+ "shadcn-svelte",
1221
1214
  "daisyui",
1222
1215
  "nextui"
1223
1216
  ].includes(nextStack.uiLibrary) && nextStack.cssFramework !== "tailwind") {
@@ -1256,6 +1249,18 @@ const analyzeStackCompatibility = (stack) => {
1256
1249
  });
1257
1250
  }
1258
1251
  }
1252
+ if (nextStack.uiLibrary === "shadcn-svelte") {
1253
+ const hasSvelteFrontend = nextStack.webFrontend.includes("svelte");
1254
+ const hasAstroSvelte = nextStack.webFrontend.includes("astro") && nextStack.astroIntegration === "svelte";
1255
+ if (!hasSvelteFrontend && !hasAstroSvelte && nextStack.webFrontend.some((f) => f !== "none")) {
1256
+ nextStack.uiLibrary = "daisyui";
1257
+ changed = true;
1258
+ changes.push({
1259
+ category: "uiLibrary",
1260
+ message: "UI library changed to 'daisyUI' (shadcn-svelte requires SvelteKit or Astro + Svelte)"
1261
+ });
1262
+ }
1263
+ }
1259
1264
  if (nextStack.uiLibrary === "headless-ui") {
1260
1265
  const hasReactFrontend = nextStack.webFrontend.some((f) => reactFrontends.includes(f));
1261
1266
  const hasVueFrontend = nextStack.webFrontend.includes("nuxt");
@@ -1849,9 +1854,10 @@ const getDisabledReason = (currentStack, category, optionId) => {
1849
1854
  }
1850
1855
  if ([
1851
1856
  "shadcn-ui",
1857
+ "shadcn-svelte",
1852
1858
  "daisyui",
1853
1859
  "nextui"
1854
- ].includes(currentStack.uiLibrary) && optionId !== "tailwind") return `${currentStack.uiLibrary === "shadcn-ui" ? "shadcn/ui" : currentStack.uiLibrary === "daisyui" ? "daisyUI" : "NextUI"} requires Tailwind CSS`;
1860
+ ].includes(currentStack.uiLibrary) && optionId !== "tailwind") return `${currentStack.uiLibrary === "shadcn-ui" ? "shadcn/ui" : currentStack.uiLibrary === "shadcn-svelte" ? "shadcn-svelte" : currentStack.uiLibrary === "daisyui" ? "daisyUI" : "NextUI"} requires Tailwind CSS`;
1855
1861
  }
1856
1862
  if (new Set([
1857
1863
  "mobileNavigation",
@@ -1867,7 +1873,7 @@ const getDisabledReason = (currentStack, category, optionId) => {
1867
1873
  if (category === "mobileUI") {
1868
1874
  if (optionId === "uniwind" && !currentStack.nativeFrontend.includes("native-uniwind")) return "Uniwind mobile UI requires Expo + Uniwind frontend";
1869
1875
  if (optionId === "unistyles" && !currentStack.nativeFrontend.includes("native-unistyles")) return "Unistyles mobile UI requires Expo + Unistyles frontend";
1870
- if (["tamagui", "gluestack-ui"].includes(optionId) && currentStack.nativeFrontend.some((f) => ["native-uniwind", "native-unistyles"].includes(f))) return "Tamagui and Gluestack UI require Expo + Bare to avoid conflicting styling setup";
1876
+ if (["tamagui", "gluestack-ui"].includes(optionId) && currentStack.nativeFrontend.some((f) => ["native-uniwind", "native-unistyles"].includes(f))) return "Tamagui and Gluestack UI require Expo + StyleSheet to avoid conflicting styling setup";
1871
1877
  }
1872
1878
  if (category === "mobilePush" && optionId === "expo-notifications" || category === "mobileOTA" && optionId === "expo-updates" || category === "mobileDeepLinking" && optionId === "expo-linking") return null;
1873
1879
  }
@@ -1895,6 +1901,11 @@ const getDisabledReason = (currentStack, category, optionId) => {
1895
1901
  const hasAstroReact = currentStack.webFrontend.includes("astro") && currentStack.astroIntegration === "react";
1896
1902
  if (!hasReactFrontend && !hasAstroReact) return `${optionId === "shadcn-ui" ? "shadcn/ui" : optionId === "radix-ui" ? "Radix UI" : optionId === "chakra-ui" ? "Chakra UI" : optionId === "mui" ? "MUI" : optionId === "antd" ? "Ant Design" : "NextUI"} requires a React-based frontend`;
1897
1903
  }
1904
+ if (optionId === "shadcn-svelte") {
1905
+ const hasSvelteFrontend = currentStack.webFrontend.includes("svelte");
1906
+ const hasAstroSvelte = currentStack.webFrontend.includes("astro") && currentStack.astroIntegration === "svelte";
1907
+ if (!hasSvelteFrontend && !hasAstroSvelte) return "shadcn-svelte requires SvelteKit or Astro with Svelte integration";
1908
+ }
1898
1909
  if (optionId === "headless-ui") {
1899
1910
  const hasReactFrontend = currentStack.webFrontend.some((f) => reactFrontends.includes(f));
1900
1911
  const hasVueFrontend = currentStack.webFrontend.includes("nuxt");
@@ -1915,10 +1926,11 @@ const getDisabledReason = (currentStack, category, optionId) => {
1915
1926
  }
1916
1927
  if ([
1917
1928
  "shadcn-ui",
1929
+ "shadcn-svelte",
1918
1930
  "daisyui",
1919
1931
  "nextui"
1920
1932
  ].includes(optionId)) {
1921
- if (currentStack.cssFramework !== "tailwind") return `${optionId === "shadcn-ui" ? "shadcn/ui" : optionId === "daisyui" ? "daisyUI" : "NextUI"} requires Tailwind CSS`;
1933
+ if (currentStack.cssFramework !== "tailwind") return `${optionId === "shadcn-ui" ? "shadcn/ui" : optionId === "shadcn-svelte" ? "shadcn-svelte" : optionId === "daisyui" ? "daisyUI" : "NextUI"} requires Tailwind CSS`;
1922
1934
  }
1923
1935
  }
1924
1936
  if (category === "webDeploy" && optionId !== "none") {
@@ -2082,6 +2094,10 @@ const UI_LIBRARY_COMPATIBILITY = {
2082
2094
  ],
2083
2095
  cssFrameworks: ["tailwind"]
2084
2096
  },
2097
+ "shadcn-svelte": {
2098
+ frontends: ["svelte", "astro"],
2099
+ cssFrameworks: ["tailwind"]
2100
+ },
2085
2101
  daisyui: {
2086
2102
  frontends: [
2087
2103
  "tanstack-router",
@@ -2360,6 +2376,16 @@ const ADDON_COMPATIBILITY = {
2360
2376
  "svelte",
2361
2377
  "solid"
2362
2378
  ],
2379
+ swr: [
2380
+ "tanstack-router",
2381
+ "react-router",
2382
+ "react-vite",
2383
+ "tanstack-start",
2384
+ "next",
2385
+ "vinext",
2386
+ "astro",
2387
+ "redwood"
2388
+ ],
2363
2389
  "tanstack-query": [
2364
2390
  "tanstack-router",
2365
2391
  "react-router",
@@ -2894,6 +2920,7 @@ const APP_PLATFORM_VALUES = [
2894
2920
  "skills",
2895
2921
  "msw",
2896
2922
  "storybook",
2923
+ "swr",
2897
2924
  "tanstack-query",
2898
2925
  "tanstack-table",
2899
2926
  "tanstack-virtual",
@@ -3037,7 +3064,7 @@ const EXACT_LABEL_OVERRIDES = {
3037
3064
  redwood: "RedwoodJS"
3038
3065
  },
3039
3066
  nativeFrontend: {
3040
- "native-bare": "Expo + Bare",
3067
+ "native-bare": "Expo + StyleSheet",
3041
3068
  "native-uniwind": "Expo + Uniwind",
3042
3069
  "native-unistyles": "Expo + Unistyles"
3043
3070
  },
@@ -3086,7 +3113,10 @@ const EXACT_LABEL_OVERRIDES = {
3086
3113
  sst: "SST",
3087
3114
  vercel: "Vercel"
3088
3115
  },
3089
- cms: { tinacms: "TinaCMS" },
3116
+ cms: {
3117
+ tinacms: "TinaCMS",
3118
+ directus: "Directus"
3119
+ },
3090
3120
  auth: {},
3091
3121
  payments: {
3092
3122
  "lemon-squeezy": "Lemon Squeezy",
@@ -3142,6 +3172,12 @@ const EXACT_LABEL_OVERRIDES = {
3142
3172
  elasticsearch: "Elasticsearch",
3143
3173
  algolia: "Algolia"
3144
3174
  },
3175
+ fileStorage: {
3176
+ s3: "AWS S3",
3177
+ r2: "Cloudflare R2",
3178
+ cloudinary: "Cloudinary"
3179
+ },
3180
+ logging: { evlog: "evlog" },
3145
3181
  cssFramework: {
3146
3182
  tailwind: "Tailwind CSS",
3147
3183
  scss: "SCSS",
@@ -3149,6 +3185,7 @@ const EXACT_LABEL_OVERRIDES = {
3149
3185
  },
3150
3186
  uiLibrary: {
3151
3187
  "shadcn-ui": "shadcn/ui",
3188
+ "shadcn-svelte": "shadcn-svelte",
3152
3189
  daisyui: "daisyUI",
3153
3190
  "radix-ui": "Radix UI",
3154
3191
  "headless-ui": "Headless UI",
@@ -3209,6 +3246,7 @@ const EXACT_LABEL_OVERRIDES = {
3209
3246
  opentui: "OpenTUI",
3210
3247
  mcp: "MCP",
3211
3248
  msw: "MSW",
3249
+ swr: "SWR",
3212
3250
  "tanstack-query": "TanStack Query",
3213
3251
  "tanstack-table": "TanStack Table",
3214
3252
  "tanstack-virtual": "TanStack Virtual",
@@ -3703,6 +3741,8 @@ function normalizeOptionId(category, value) {
3703
3741
  //#endregion
3704
3742
  //#region src/stack-translation.ts
3705
3743
  const DEFAULT_STACK_SELECTION = {
3744
+ stackMode: "solo",
3745
+ stackPartSpecs: [],
3706
3746
  ecosystem: "typescript",
3707
3747
  projectName: "my-app",
3708
3748
  webFrontend: ["tanstack-router"],
@@ -3812,6 +3852,8 @@ const DEFAULT_STACK_SELECTION = {
3812
3852
  elixirDeploy: "none"
3813
3853
  };
3814
3854
  const NON_OPTION_STACK_SELECTION_KEYS = [
3855
+ "stackMode",
3856
+ "stackPartSpecs",
3815
3857
  "ecosystem",
3816
3858
  "projectName",
3817
3859
  "yolo"
@@ -3933,6 +3975,8 @@ function usesVirtualNoneStackSelection(key) {
3933
3975
  return VIRTUAL_NONE_MULTI_SELECT_STACK_SELECTION_KEYS.includes(key);
3934
3976
  }
3935
3977
  const STACK_SELECTION_URL_KEYS = {
3978
+ stackMode: "mode",
3979
+ stackPartSpecs: "part",
3936
3980
  ecosystem: "eco",
3937
3981
  projectName: "name",
3938
3982
  webFrontend: "fe-w",
@@ -4070,8 +4114,12 @@ function normalizeStackSelectionValue(key, value) {
4070
4114
  if (typeof value === "string") return normalizeOptionId(category, value);
4071
4115
  return value;
4072
4116
  }
4117
+ function normalizeStackSelectionMode(value) {
4118
+ return value === "multi" || value === "graph" ? "multi" : "solo";
4119
+ }
4073
4120
  function normalizeStackSelection(selection) {
4074
4121
  const normalized = { ...selection };
4122
+ normalized.stackMode = normalizeStackSelectionMode(normalized.stackMode);
4075
4123
  for (const key of Object.keys(STACK_SELECTION_OPTION_CATEGORY_BY_KEY)) normalized[key] = normalizeStackSelectionValue(key, normalized[key]);
4076
4124
  return normalized;
4077
4125
  }
@@ -4342,6 +4390,7 @@ const COMMAND_ADDONS = new Set([
4342
4390
  "wxt",
4343
4391
  "msw",
4344
4392
  "storybook",
4393
+ "swr",
4345
4394
  "tanstack-query",
4346
4395
  "tanstack-table",
4347
4396
  "tanstack-virtual",
@@ -4371,11 +4420,122 @@ function formatTypeScriptAddonsFlag(selection) {
4371
4420
  if (addons.length === 0) return "--addons none";
4372
4421
  return `--addons ${addons.filter((addon) => COMMAND_ADDONS.has(addon)).join(" ") || "none"}`;
4373
4422
  }
4423
+ const GRAPH_TYPESCRIPT_FRONTEND_FLAG_KEYS = [
4424
+ ["cssFramework", "css-framework"],
4425
+ ["uiLibrary", "ui-library"],
4426
+ ["stateManagement", "state-management"],
4427
+ ["forms", "forms"],
4428
+ ["validation", "validation"],
4429
+ ["testing", "testing"],
4430
+ ["animation", "animation"]
4431
+ ];
4432
+ const GRAPH_SHADCN_FLAG_KEYS = [
4433
+ ["shadcnBase", "shadcn-base"],
4434
+ ["shadcnStyle", "shadcn-style"],
4435
+ ["shadcnIconLibrary", "shadcn-icon-library"],
4436
+ ["shadcnColorTheme", "shadcn-color-theme"],
4437
+ ["shadcnBaseColor", "shadcn-base-color"],
4438
+ ["shadcnFont", "shadcn-font"],
4439
+ ["shadcnRadius", "shadcn-radius"]
4440
+ ];
4441
+ const GRAPH_MOBILE_FLAG_KEYS = [
4442
+ ["mobileNavigation", "mobile-navigation"],
4443
+ ["mobileUI", "mobile-ui"],
4444
+ ["mobileStorage", "mobile-storage"],
4445
+ ["mobileTesting", "mobile-testing"],
4446
+ ["mobilePush", "mobile-push"],
4447
+ ["mobileOTA", "mobile-ota"],
4448
+ ["mobileDeepLinking", "mobile-deep-linking"]
4449
+ ];
4450
+ const GRAPH_GLOBAL_FLAG_KEYS = [
4451
+ ["dbSetup", "db-setup"],
4452
+ ["webDeploy", "web-deploy"],
4453
+ ["serverDeploy", "server-deploy"]
4454
+ ];
4455
+ const GRAPH_TYPESCRIPT_BACKEND_FLAG_KEYS = [
4456
+ ["payments", "payments"],
4457
+ ["email", "email"],
4458
+ ["fileUpload", "file-upload"],
4459
+ ["backendLibraries", "effect"],
4460
+ ["aiSdk", "ai"],
4461
+ ["realtime", "realtime"],
4462
+ ["jobQueue", "job-queue"],
4463
+ ["logging", "logging"],
4464
+ ["observability", "observability"],
4465
+ ["featureFlags", "feature-flags"],
4466
+ ["caching", "caching"],
4467
+ ["i18n", "i18n"],
4468
+ ["cms", "cms"],
4469
+ ["search", "search"],
4470
+ ["fileStorage", "file-storage"]
4471
+ ];
4472
+ const GRAPH_SHARED_BACKEND_FLAG_KEYS = [
4473
+ ["email", "email"],
4474
+ ["observability", "observability"],
4475
+ ["caching", "caching"],
4476
+ ["search", "search"]
4477
+ ];
4478
+ const GRAPH_RUST_BACKEND_FLAG_KEYS = [
4479
+ ["rustCli", "rust-cli"],
4480
+ ["rustLogging", "rust-logging"],
4481
+ ["rustErrorHandling", "rust-error-handling"],
4482
+ ["rustCaching", "rust-caching"]
4483
+ ];
4484
+ const GRAPH_PYTHON_BACKEND_FLAG_KEYS = [
4485
+ ["pythonValidation", "python-validation"],
4486
+ ["pythonTaskQueue", "python-task-queue"],
4487
+ ["pythonGraphql", "python-graphql"],
4488
+ ["pythonQuality", "python-quality"]
4489
+ ];
4490
+ const GRAPH_GO_BACKEND_FLAG_KEYS = [["goCli", "go-cli"], ["goLogging", "go-logging"]];
4491
+ const GRAPH_JAVA_BACKEND_FLAG_KEYS = [["javaBuildTool", "java-build-tool"]];
4492
+ const GRAPH_ELIXIR_BACKEND_FLAG_KEYS = [
4493
+ ["elixirRealtime", "elixir-realtime"],
4494
+ ["elixirJobs", "elixir-jobs"],
4495
+ ["elixirValidation", "elixir-validation"],
4496
+ ["elixirHttp", "elixir-http"],
4497
+ ["elixirJson", "elixir-json"],
4498
+ ["elixirEmail", "elixir-email"],
4499
+ ["elixirCaching", "elixir-caching"],
4500
+ ["elixirObservability", "elixir-observability"],
4501
+ ["elixirTesting", "elixir-testing"],
4502
+ ["elixirQuality", "elixir-quality"],
4503
+ ["elixirDeploy", "elixir-deploy"]
4504
+ ];
4505
+ function formatChangedStringFlag(selection, key, flag) {
4506
+ return selection[key] === DEFAULT_STACK_SELECTION[key] ? void 0 : `--${flag} ${selection[key]}`;
4507
+ }
4508
+ function formatChangedArraySelectionFlag(selection, key, flag) {
4509
+ return areStringArraysEqual(selection[key], DEFAULT_STACK_SELECTION[key]) ? void 0 : formatArrayFlag(flag, selection[key]);
4510
+ }
4511
+ function formatChangedStringFlags(selection, keys) {
4512
+ return keys.flatMap(([key, flag]) => {
4513
+ const formattedFlag = formatChangedStringFlag(selection, key, flag);
4514
+ return formattedFlag ? [formattedFlag] : [];
4515
+ });
4516
+ }
4517
+ function hasGraphPrimaryPart(parts, role, ecosystem, toolId) {
4518
+ return parts.some((part) => part.role === role && !part.ownerPartId && (!ecosystem || part.ecosystem === ecosystem) && (!toolId || part.toolId === toolId));
4519
+ }
4374
4520
  function mapBackendToCli(backend) {
4375
4521
  return SELF_BACKENDS.has(backend) ? "self" : backend;
4376
4522
  }
4523
+ function isGraphStackSelection(selection) {
4524
+ return (selection.stackMode === "multi" || String(selection.stackMode) === "graph") && selection.stackPartSpecs.length > 0;
4525
+ }
4526
+ function getGraphStackParts(selection) {
4527
+ const stackParts = parseStackPartSpecs(selection.stackPartSpecs, "selected");
4528
+ const validation = validateStackParts(stackParts);
4529
+ if (validation.issues.length > 0) throw new Error(validation.issues.map((issue) => issue.message).join("\n"));
4530
+ return stackParts;
4531
+ }
4377
4532
  function getAdjustedSelection(selection) {
4378
- return analyzeStackCompatibility(selection).adjustedStack ?? selection;
4533
+ const compatibility = analyzeStackCompatibility(selection);
4534
+ if (!compatibility.adjustedStack) return selection;
4535
+ return {
4536
+ ...selection,
4537
+ ...compatibility.adjustedStack
4538
+ };
4379
4539
  }
4380
4540
  function getProjectName(selection, projectName) {
4381
4541
  return projectName?.trim() || selection.projectName?.trim() || "my-app";
@@ -4385,6 +4545,9 @@ function areStringArraysEqual(left, right) {
4385
4545
  const sortedRight = [...right].sort();
4386
4546
  return sortedLeft.length === sortedRight.length && sortedLeft.every((value, index) => value === sortedRight[index]);
4387
4547
  }
4548
+ function isStringArray(value) {
4549
+ return value.every((item) => typeof item === "string");
4550
+ }
4388
4551
  function isStackSelectionDefault(selection, key, value) {
4389
4552
  const defaultValue = DEFAULT_STACK_SELECTION[key];
4390
4553
  if (selection.backend === "convex") {
@@ -4414,12 +4577,16 @@ function cliInputToProjectConfigPartial(input, projectName) {
4414
4577
  const value = input[inputKey];
4415
4578
  if (Array.isArray(value)) assignableConfig[configKey] = processCliArrayOption(value);
4416
4579
  }
4580
+ if (Array.isArray(input.part) && input.part.length > 0) {
4581
+ const stackParts = parseStackPartSpecs(input.part, "selected");
4582
+ Object.assign(config, stackPartsToLegacyProjectConfigPartial(stackParts), { stackParts });
4583
+ }
4417
4584
  return config;
4418
4585
  }
4419
4586
  function buildProjectConfigBase(selection, projectName, relativePath, install) {
4420
4587
  const stack = getAdjustedSelection(selection);
4421
4588
  const frontend = [...toUniqueNonNoneArray(stack.webFrontend), ...toUniqueNonNoneArray(stack.nativeFrontend)];
4422
- return {
4589
+ const baseConfig = {
4423
4590
  projectName,
4424
4591
  relativePath,
4425
4592
  ecosystem: stack.ecosystem,
@@ -4529,6 +4696,21 @@ function buildProjectConfigBase(selection, projectName, relativePath, install) {
4529
4696
  elixirDeploy: stack.elixirDeploy,
4530
4697
  aiDocs: toUniqueNonNoneArray(stack.aiDocs)
4531
4698
  };
4699
+ if (!isGraphStackSelection(stack)) return baseConfig;
4700
+ const stackParts = getGraphStackParts(stack);
4701
+ const loweredGraphConfig = stackPartsToLegacyProjectConfigPartial(stackParts);
4702
+ return {
4703
+ ...baseConfig,
4704
+ ...loweredGraphConfig,
4705
+ projectName,
4706
+ relativePath,
4707
+ git: stack.git === "true",
4708
+ packageManager: stack.packageManager,
4709
+ versionChannel: stack.versionChannel,
4710
+ install,
4711
+ aiDocs: toUniqueNonNoneArray(stack.aiDocs),
4712
+ stackParts
4713
+ };
4532
4714
  }
4533
4715
  function stackSelectionToProjectConfig(selection, options) {
4534
4716
  const projectName = getProjectName(selection);
@@ -4542,6 +4724,7 @@ function stackSelectionToCliComparableConfig(selection, projectName = getProject
4542
4724
  return buildProjectConfigBase(selection, projectName, projectName, selection.install === "true");
4543
4725
  }
4544
4726
  function isCliDefaultStackSelection(selection, projectName = getProjectName(selection)) {
4727
+ if (isGraphStackSelection(selection)) return false;
4545
4728
  const comparableConfig = stackSelectionToCliComparableConfig(selection, projectName);
4546
4729
  const cliDefaults = {
4547
4730
  ...createCliDefaultProjectConfigBase(selection.packageManager),
@@ -4560,13 +4743,67 @@ function isCliDefaultStackSelection(selection, projectName = getProjectName(sele
4560
4743
  if (ignoredKeys.has(key)) return true;
4561
4744
  const currentValue = comparableConfig[key];
4562
4745
  const defaultValue = cliDefaults[key];
4563
- if (Array.isArray(currentValue) && Array.isArray(defaultValue)) return areStringArraysEqual(currentValue, defaultValue);
4746
+ if (Array.isArray(currentValue) && Array.isArray(defaultValue)) {
4747
+ const currentArray = currentValue;
4748
+ const defaultArray = defaultValue;
4749
+ if (isStringArray(currentArray) && isStringArray(defaultArray)) return areStringArraysEqual(currentArray, defaultArray);
4750
+ return JSON.stringify(currentValue) === JSON.stringify(defaultValue);
4751
+ }
4564
4752
  return currentValue === defaultValue;
4565
4753
  });
4566
4754
  }
4567
4755
  function getBaseCommand(selection) {
4568
4756
  return PACKAGE_MANAGER_COMMANDS[selection.packageManager] ?? PACKAGE_MANAGER_COMMANDS.bun;
4569
4757
  }
4758
+ function generateGraphCommand(selection, projectName) {
4759
+ const stackParts = getGraphStackParts(selection);
4760
+ const hasTypeScriptFrontend = hasGraphPrimaryPart(stackParts, "frontend", "typescript");
4761
+ const hasAstroFrontend = hasGraphPrimaryPart(stackParts, "frontend", "typescript", "astro");
4762
+ const hasTypeScriptBackend = hasGraphPrimaryPart(stackParts, "backend", "typescript");
4763
+ const hasRustBackend = hasGraphPrimaryPart(stackParts, "backend", "rust");
4764
+ const hasPythonBackend = hasGraphPrimaryPart(stackParts, "backend", "python");
4765
+ const hasGoBackend = hasGraphPrimaryPart(stackParts, "backend", "go");
4766
+ const hasJavaBackend = hasGraphPrimaryPart(stackParts, "backend", "java");
4767
+ const hasElixirBackend = hasGraphPrimaryPart(stackParts, "backend", "elixir");
4768
+ const hasNonTypeScriptBackend = hasRustBackend || hasPythonBackend || hasGoBackend || hasJavaBackend || hasElixirBackend;
4769
+ const hasMobile = hasGraphPrimaryPart(stackParts, "mobile");
4770
+ const flags = [
4771
+ ...stackParts.filter((part) => part.source !== "provided").map((part) => `--part ${formatStackPartSpec(part, stackParts)}`),
4772
+ ...hasTypeScriptFrontend ? formatChangedStringFlags(selection, GRAPH_TYPESCRIPT_FRONTEND_FLAG_KEYS) : [],
4773
+ ...hasAstroFrontend && selection.astroIntegration !== "none" ? [`--astro-integration ${selection.astroIntegration}`] : [],
4774
+ ...hasTypeScriptFrontend && selection.uiLibrary === "shadcn-ui" ? formatChangedStringFlags(selection, GRAPH_SHADCN_FLAG_KEYS) : [],
4775
+ ...hasTypeScriptBackend ? formatChangedStringFlags(selection, GRAPH_TYPESCRIPT_BACKEND_FLAG_KEYS) : [],
4776
+ ...hasNonTypeScriptBackend ? formatChangedStringFlags(selection, GRAPH_SHARED_BACKEND_FLAG_KEYS) : [],
4777
+ ...hasRustBackend ? [...formatChangedStringFlags(selection, GRAPH_RUST_BACKEND_FLAG_KEYS), formatChangedArraySelectionFlag(selection, "rustLibraries", "rust-libraries")].filter((flag) => Boolean(flag)) : [],
4778
+ ...hasPythonBackend ? [...formatChangedStringFlags(selection, GRAPH_PYTHON_BACKEND_FLAG_KEYS), formatChangedArraySelectionFlag(selection, "pythonAi", "python-ai")].filter((flag) => Boolean(flag)) : [],
4779
+ ...hasGoBackend ? formatChangedStringFlags(selection, GRAPH_GO_BACKEND_FLAG_KEYS) : [],
4780
+ ...hasJavaBackend ? [
4781
+ ...formatChangedStringFlags(selection, GRAPH_JAVA_BACKEND_FLAG_KEYS),
4782
+ formatChangedArraySelectionFlag(selection, "javaLibraries", "java-libraries"),
4783
+ formatChangedArraySelectionFlag(selection, "javaTestingLibraries", "java-testing-libraries")
4784
+ ].filter((flag) => Boolean(flag)) : [],
4785
+ ...hasElixirBackend ? formatChangedStringFlags(selection, GRAPH_ELIXIR_BACKEND_FLAG_KEYS) : [],
4786
+ ...hasMobile ? formatChangedStringFlags(selection, GRAPH_MOBILE_FLAG_KEYS) : [],
4787
+ ...formatChangedStringFlags(selection, GRAPH_GLOBAL_FLAG_KEYS),
4788
+ ...areStringArraysEqual([
4789
+ ...selection.codeQuality,
4790
+ ...selection.documentation,
4791
+ ...selection.appPlatforms
4792
+ ], [
4793
+ ...DEFAULT_STACK_SELECTION.codeQuality,
4794
+ ...DEFAULT_STACK_SELECTION.documentation,
4795
+ ...DEFAULT_STACK_SELECTION.appPlatforms
4796
+ ]) ? [] : [formatTypeScriptAddonsFlag(selection)],
4797
+ ...areStringArraysEqual(selection.examples, DEFAULT_STACK_SELECTION.examples) ? [] : [formatArrayFlag("examples", selection.examples)],
4798
+ `--package-manager ${selection.packageManager}`,
4799
+ ...selection.versionChannel !== "stable" ? [`--version-channel ${selection.versionChannel}`] : [],
4800
+ selection.git === "false" ? "--no-git" : "--git",
4801
+ selection.install === "false" ? "--no-install" : "--install",
4802
+ formatArrayFlag("ai-docs", selection.aiDocs)
4803
+ ];
4804
+ if (selection.yolo === "true") flags.push("--yolo");
4805
+ return `${getBaseCommand(selection)} ${projectName} ${flags.join(" ")}`;
4806
+ }
4570
4807
  function generateTypeScriptCommand(selection, projectName) {
4571
4808
  const base = getBaseCommand(selection);
4572
4809
  if (isCliDefaultStackSelection(selection, projectName)) return `${base} ${projectName} --yes`;
@@ -4756,6 +4993,7 @@ function generateElixirCommand(selection, projectName) {
4756
4993
  }
4757
4994
  function generateStackSelectionCommand(selection) {
4758
4995
  const projectName = getProjectName(selection);
4996
+ if (isGraphStackSelection(selection)) return generateGraphCommand(selection, projectName);
4759
4997
  switch (selection.ecosystem) {
4760
4998
  case "react-native": return generateReactNativeCommand(selection, projectName);
4761
4999
  case "rust": return generateRustCommand(selection, projectName);
@@ -4769,5 +5007,5 @@ function generateStackSelectionCommand(selection) {
4769
5007
  }
4770
5008
 
4771
5009
  //#endregion
4772
- export { getCapabilityDefinitions as $, evaluateCompatibility as A, hasPWACompatibleFrontend as B, getCategoryCliValues as C, normalizeOptionId as D, isMultiSelectCategory as E, getCompatibleCSSFrameworks as F, isFrontendAllowedWithBackend as G, hasWebStyling as H, getCompatibleFormLibraries as I, requiresChatSdkVercelAI as J, isOptionCompatible as K, getCompatibleUILibraries as L, getApiFrontendCompatibilityIssue as M, getCategoryDisplayName as N, allowedApisForFrontends as O, getCompatibleAddons as P, validateProjectName as Q, getDisabledReason as R, OPTION_CATEGORY_METADATA as S, getOptionMetadata as T, isExampleAIAllowed as U, hasTauriCompatibleFrontend as V, isExampleChatSdkAllowed as W, splitFrontends as X, requiresChatSdkVercelAIForSelection as Y, validateAddonCompatibility as Z, parseStackSelectionFromUrlRecord as _, STACK_SELECTION_URL_KEYS as a, stackSelectionToProjectConfig as b, cloneDefaultStackSelection as c, isArrayStackSelectionKey as d, getCapabilityDisabledReason as et, isCliDefaultStackSelection as f, parseStackSelectionFromSearch as g, normalizeStackSelectionValue as h, STACK_SELECTION_OPTION_CATEGORY_BY_KEY as i, getAIFrontendCompatibilityIssue as j, analyzeStackCompatibility as k, createStackSelectionSearchParams as l, normalizeStackSelection as m, NON_OPTION_STACK_SELECTION_KEYS as n, normalizeCapabilitySelection as nt, VIRTUAL_NONE_MULTI_SELECT_STACK_SELECTION_KEYS as o, isStackSelectionDefault as p, isWebFrontend as q, STACK_SELECTION_KEYS as r, cliInputToProjectConfigPartial as s, DEFAULT_STACK_SELECTION as t, getSupportedCapabilityOptions as tt, generateStackSelectionCommand as u, processCliArrayOption as v, getCategoryOptionIds as w, usesVirtualNoneStackSelection as x, stackSelectionToCliComparableConfig as y, hasDockerComposeCompatibleFrontend as z };
4773
- //# sourceMappingURL=stack-translation-_uOX-Io0.mjs.map
5010
+ export { validateProjectName as $, analyzeStackCompatibility as A, hasDockerComposeCompatibleFrontend as B, OPTION_CATEGORY_METADATA as C, isMultiSelectCategory as D, getOptionMetadata as E, getCompatibleAddons as F, isExampleChatSdkAllowed as G, hasTauriCompatibleFrontend as H, getCompatibleCSSFrameworks as I, isWebFrontend as J, isFrontendAllowedWithBackend as K, getCompatibleFormLibraries as L, getAIFrontendCompatibilityIssue as M, getApiFrontendCompatibilityIssue as N, normalizeOptionId as O, getCategoryDisplayName as P, validateAddonCompatibility as Q, getCompatibleUILibraries as R, usesVirtualNoneStackSelection as S, getCategoryOptionIds as T, hasWebStyling as U, hasPWACompatibleFrontend as V, isExampleAIAllowed as W, requiresChatSdkVercelAIForSelection as X, requiresChatSdkVercelAI as Y, splitFrontends as Z, parseStackSelectionFromSearch as _, STACK_SELECTION_URL_KEYS as a, stackSelectionToCliComparableConfig as b, cloneDefaultStackSelection as c, isArrayStackSelectionKey as d, getCapabilityDefinitions as et, isCliDefaultStackSelection as f, normalizeStackSelectionValue as g, normalizeStackSelection as h, STACK_SELECTION_OPTION_CATEGORY_BY_KEY as i, evaluateCompatibility as j, allowedApisForFrontends as k, createStackSelectionSearchParams as l, isStackSelectionDefault as m, NON_OPTION_STACK_SELECTION_KEYS as n, getSupportedCapabilityOptions as nt, VIRTUAL_NONE_MULTI_SELECT_STACK_SELECTION_KEYS as o, isGraphStackSelection as p, isOptionCompatible as q, STACK_SELECTION_KEYS as r, normalizeCapabilitySelection as rt, cliInputToProjectConfigPartial as s, DEFAULT_STACK_SELECTION as t, getCapabilityDisabledReason as tt, generateStackSelectionCommand as u, parseStackSelectionFromUrlRecord as v, getCategoryCliValues as w, stackSelectionToProjectConfig as x, processCliArrayOption as y, getDisabledReason as z };
5011
+ //# sourceMappingURL=stack-translation-BcsaMRuV.mjs.map