@better-fullstack/types 1.8.1 → 2.0.1

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-05kDqAVs.d.mts → defaults-ByJzfP7_.d.mts} +2 -2
  2. package/dist/defaults-ByJzfP7_.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 +522 -46
  12. package/dist/json-schema.d.mts.map +1 -1
  13. package/dist/json-schema.mjs +1 -1
  14. package/dist/{schemas-CUFM_Cdl.d.mts → schemas-62dqb8iS.d.mts} +510 -46
  15. package/dist/schemas-62dqb8iS.d.mts.map +1 -0
  16. package/dist/{schemas-Hj_Gbdf0.mjs → schemas-DnEGgQzA.mjs} +68 -6
  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-UgPd4sup.d.mts +68 -0
  23. package/dist/stack-graph-UgPd4sup.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-BpsvxDrw.mjs → stack-translation-COVG5IPm.mjs} +248 -16
  27. package/dist/stack-translation-COVG5IPm.mjs.map +1 -0
  28. package/dist/{stack-translation-D7H3h8Vs.d.mts → stack-translation-CYNMQUUu.d.mts} +13 -6
  29. package/dist/stack-translation-CYNMQUUu.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-C0KHWyJI.d.mts → types-CWpfWGSN.d.mts} +7 -3
  33. package/dist/{types-C0KHWyJI.d.mts.map → types-CWpfWGSN.d.mts.map} +1 -1
  34. package/dist/types.d.mts +3 -3
  35. package/package.json +5 -1
  36. package/dist/defaults-05kDqAVs.d.mts.map +0 -1
  37. package/dist/schemas-CUFM_Cdl.d.mts.map +0 -1
  38. package/dist/schemas-Hj_Gbdf0.mjs.map +0 -1
  39. package/dist/stack-translation-BpsvxDrw.mjs.map +0 -1
  40. package/dist/stack-translation-D7H3h8Vs.d.mts.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack-graph-C2tzuzRe.mjs","names":["ROLE_TARGET_PATHS: Record<StackPrimaryRole, string>","STACK_TOOL_DEFINITIONS: readonly ToolDefinition[]","parts: StackPart[]","backendPart: StackPart | undefined","config: Partial<ProjectConfig>","diagnostics: StackGraphDiagnostic[]","issues: StackGraphIssue[]","primaryToolIdsByRole: Partial<Record<StackPrimaryRole, string>>","siblingToolIdsByRole: Partial<Record<StackPartRole, string>>"],"sources":["../src/stack-graph.ts"],"sourcesContent":["import type {\n Ecosystem,\n ProjectConfig,\n StackPart,\n StackPartEcosystem,\n StackPartRole,\n StackPartSource,\n} from \"./types\";\n\nimport {\n API_VALUES,\n AUTH_VALUES,\n BACKEND_VALUES,\n DATABASE_VALUES,\n ELIXIR_API_VALUES,\n ELIXIR_AUTH_VALUES,\n ELIXIR_CACHING_VALUES,\n ELIXIR_DEPLOY_VALUES,\n ELIXIR_EMAIL_VALUES,\n ELIXIR_JOBS_VALUES,\n ELIXIR_OBSERVABILITY_VALUES,\n ELIXIR_ORM_VALUES,\n ELIXIR_REALTIME_VALUES,\n ELIXIR_TESTING_VALUES,\n ELIXIR_VALIDATION_VALUES,\n ELIXIR_WEB_FRAMEWORK_VALUES,\n FRONTEND_VALUES,\n GO_API_VALUES,\n GO_AUTH_VALUES,\n GO_ORM_VALUES,\n GO_WEB_FRAMEWORK_VALUES,\n JAVA_AUTH_VALUES,\n JAVA_ORM_VALUES,\n JAVA_WEB_FRAMEWORK_VALUES,\n ORM_VALUES,\n PYTHON_API_VALUES,\n PYTHON_AUTH_VALUES,\n PYTHON_GRAPHQL_VALUES,\n PYTHON_ORM_VALUES,\n PYTHON_TASK_QUEUE_VALUES,\n PYTHON_VALIDATION_VALUES,\n PYTHON_WEB_FRAMEWORK_VALUES,\n RUST_API_VALUES,\n RUST_AUTH_VALUES,\n RUST_CACHING_VALUES,\n RUST_FRONTEND_VALUES,\n RUST_ORM_VALUES,\n RUST_WEB_FRAMEWORK_VALUES,\n StackPartRoleSchema,\n} from \"./schemas\";\n\nexport type StackPrimaryRole = Extract<\n StackPartRole,\n \"frontend\" | \"backend\" | \"mobile\" | \"database\"\n>;\n\nexport type ProvidedCapabilityDefinition = {\n role: StackPartRole;\n toolId: string;\n ecosystem?: StackPartEcosystem;\n overrideable?: boolean;\n};\n\nexport type ToolDefinition = {\n toolId: string;\n label?: string;\n roles: readonly StackPartRole[];\n ecosystems: readonly StackPartEcosystem[];\n legacyCategory?: keyof ProjectConfig;\n selectable?: boolean;\n provides?: readonly ProvidedCapabilityDefinition[];\n};\n\nexport type StackPartOptionContext = {\n role: StackPartRole;\n ecosystem?: StackPartEcosystem;\n ownerRole?: StackPrimaryRole;\n ownerToolId?: string;\n ownerEcosystem?: StackPartEcosystem;\n siblingToolIdsByRole?: Partial<Record<StackPartRole, string | undefined>>;\n primaryToolIdsByRole?: Partial<Record<StackPrimaryRole, string | undefined>>;\n};\n\nexport type StackGraphIssue = {\n code: string;\n message: string;\n partId?: string;\n role?: StackPartRole;\n toolId?: string;\n};\n\nexport type StackGraphValidationResult = {\n issues: StackGraphIssue[];\n};\n\nexport type StackGraphDiagnostic = {\n code: string;\n message: string;\n path?: string;\n};\n\nconst PRIMARY_ROLES = new Set<StackPartRole>([\"frontend\", \"backend\", \"mobile\", \"database\"]);\nconst NATIVE_FRONTENDS = new Set([\"native-bare\", \"native-uniwind\", \"native-unistyles\"]);\nconst WEB_FRONTENDS = FRONTEND_VALUES.filter(\n (value) => value !== \"none\" && !NATIVE_FRONTENDS.has(value),\n);\nconst DJANGO_API_TOOLS = new Set([\"django-rest-framework\", \"django-ninja\"]);\nconst JAVA_SPRING_CAPABILITY_TOOLS = new Set([\"spring-data-jpa\", \"spring-security\"]);\nconst TYPESCRIPT_TRPC_INCOMPATIBLE_FRONTENDS = new Set([\n \"nuxt\",\n \"svelte\",\n \"solid\",\n \"solid-start\",\n]);\nconst BETTER_AUTH_UNSUPPORTED_ORM_TOOLS = new Set([\"typeorm\", \"mikroorm\", \"sequelize\"]);\nconst ELIXIR_ECTO_REQUIRED_TOOLS = new Set([\"absinthe\", \"phx-gen-auth\"]);\nconst ELIXIR_ECTO_SQL_REQUIRED_TOOLS = new Set([\"oban\"]);\nconst ELIXIR_UNSUPPORTED_GRAPH_TOOLS = new Set([\n \"ecto\",\n \"ueberauth\",\n \"guardian\",\n \"nimble-options\",\n \"nebulex\",\n \"opentelemetry\",\n \"prom_ex\",\n \"mox\",\n \"bypass\",\n \"wallaby\",\n \"fly\",\n \"gigalixir\",\n]);\n\nconst ROLE_TARGET_PATHS: Record<StackPrimaryRole, string> = {\n frontend: \"apps/web\",\n backend: \"apps/server\",\n mobile: \"apps/native\",\n database: \"packages/database\",\n};\n\nfunction defineTools(\n values: readonly string[],\n role: StackPartRole,\n ecosystem: StackPartEcosystem,\n legacyCategory?: keyof ProjectConfig,\n): ToolDefinition[] {\n return values\n .filter((toolId) => toolId !== \"none\")\n .map((toolId) => ({\n toolId,\n roles: [role],\n ecosystems: [ecosystem],\n legacyCategory,\n }));\n}\n\nexport const STACK_TOOL_DEFINITIONS: readonly ToolDefinition[] = [\n ...defineTools(WEB_FRONTENDS, \"frontend\", \"typescript\", \"frontend\"),\n ...defineTools([...NATIVE_FRONTENDS], \"mobile\", \"react-native\", \"frontend\"),\n ...defineTools(\n BACKEND_VALUES.filter((value) => value !== \"convex\"),\n \"backend\",\n \"typescript\",\n \"backend\",\n ),\n ...defineTools(DATABASE_VALUES, \"database\", \"universal\", \"database\"),\n ...defineTools(DATABASE_VALUES, \"database\", \"typescript\", \"database\"),\n ...defineTools(ORM_VALUES, \"orm\", \"typescript\", \"orm\"),\n ...defineTools(API_VALUES, \"api\", \"typescript\", \"api\"),\n ...defineTools(AUTH_VALUES, \"auth\", \"typescript\", \"auth\"),\n ...defineTools(AUTH_VALUES, \"auth\", \"react-native\", \"auth\"),\n ...defineTools(RUST_WEB_FRAMEWORK_VALUES, \"backend\", \"rust\", \"rustWebFramework\"),\n ...defineTools(RUST_FRONTEND_VALUES, \"frontend\", \"rust\", \"rustFrontend\"),\n ...defineTools(RUST_ORM_VALUES, \"orm\", \"rust\", \"rustOrm\"),\n ...defineTools(RUST_API_VALUES, \"api\", \"rust\", \"rustApi\"),\n ...defineTools(RUST_AUTH_VALUES, \"auth\", \"rust\", \"rustAuth\"),\n ...defineTools(RUST_CACHING_VALUES, \"caching\", \"rust\", \"rustCaching\"),\n ...defineTools(PYTHON_WEB_FRAMEWORK_VALUES, \"backend\", \"python\", \"pythonWebFramework\"),\n ...defineTools(PYTHON_ORM_VALUES, \"orm\", \"python\", \"pythonOrm\"),\n ...defineTools(PYTHON_VALIDATION_VALUES, \"validation\", \"python\", \"pythonValidation\"),\n ...defineTools(PYTHON_API_VALUES, \"api\", \"python\", \"pythonApi\"),\n ...defineTools(PYTHON_AUTH_VALUES, \"auth\", \"python\", \"pythonAuth\"),\n ...defineTools(PYTHON_TASK_QUEUE_VALUES, \"jobQueue\", \"python\", \"pythonTaskQueue\"),\n ...defineTools(PYTHON_GRAPHQL_VALUES, \"api\", \"python\", \"pythonGraphql\"),\n ...defineTools(GO_WEB_FRAMEWORK_VALUES, \"backend\", \"go\", \"goWebFramework\"),\n ...defineTools(GO_ORM_VALUES, \"orm\", \"go\", \"goOrm\"),\n ...defineTools(GO_API_VALUES, \"api\", \"go\", \"goApi\"),\n ...defineTools(GO_AUTH_VALUES, \"auth\", \"go\", \"goAuth\"),\n ...defineTools(JAVA_WEB_FRAMEWORK_VALUES, \"backend\", \"java\", \"javaWebFramework\"),\n ...defineTools(JAVA_ORM_VALUES, \"orm\", \"java\", \"javaOrm\"),\n ...defineTools(JAVA_AUTH_VALUES, \"auth\", \"java\", \"javaAuth\"),\n ...defineTools(ELIXIR_WEB_FRAMEWORK_VALUES, \"backend\", \"elixir\", \"elixirWebFramework\"),\n ...defineTools(ELIXIR_ORM_VALUES, \"orm\", \"elixir\", \"elixirOrm\"),\n ...defineTools(ELIXIR_AUTH_VALUES, \"auth\", \"elixir\", \"elixirAuth\"),\n ...defineTools(ELIXIR_API_VALUES, \"api\", \"elixir\", \"elixirApi\"),\n ...defineTools(ELIXIR_REALTIME_VALUES, \"api\", \"elixir\", \"elixirRealtime\"),\n ...defineTools(ELIXIR_JOBS_VALUES, \"jobQueue\", \"elixir\", \"elixirJobs\"),\n ...defineTools(ELIXIR_VALIDATION_VALUES, \"validation\", \"elixir\", \"elixirValidation\"),\n ...defineTools(ELIXIR_EMAIL_VALUES, \"email\", \"elixir\", \"elixirEmail\"),\n ...defineTools(ELIXIR_CACHING_VALUES, \"caching\", \"elixir\", \"elixirCaching\"),\n ...defineTools(ELIXIR_OBSERVABILITY_VALUES, \"observability\", \"elixir\", \"elixirObservability\"),\n ...defineTools(ELIXIR_TESTING_VALUES, \"testing\", \"elixir\", \"elixirTesting\"),\n ...defineTools(ELIXIR_DEPLOY_VALUES, \"deploy\", \"elixir\", \"elixirDeploy\"),\n {\n toolId: \"convex\",\n roles: [\"backend\"],\n ecosystems: [\"typescript\"],\n legacyCategory: \"backend\",\n provides: [\n { role: \"database\", toolId: \"convex\", ecosystem: \"typescript\", overrideable: false },\n { role: \"api\", toolId: \"convex\", ecosystem: \"typescript\", overrideable: false },\n ],\n },\n {\n toolId: \"convex\",\n roles: [\"database\", \"api\"],\n ecosystems: [\"typescript\"],\n selectable: false,\n },\n];\n\nfunction sanitizePartId(input: string): string {\n return input\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9:._-]+/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\nexport function getRoleTargetPath(role: StackPartRole): string | undefined {\n return PRIMARY_ROLES.has(role) ? ROLE_TARGET_PATHS[role as StackPrimaryRole] : undefined;\n}\n\nexport function createStackPart(input: {\n role: StackPartRole;\n toolId: string;\n ecosystem: StackPartEcosystem;\n ownerPartId?: string;\n source?: StackPartSource;\n providedByPartId?: string;\n id?: string;\n targetPath?: string;\n settings?: Record<string, unknown>;\n}): StackPart {\n const roleKey = input.ownerPartId ? `${input.ownerPartId}.${input.role}` : input.role;\n return {\n id: input.id ?? sanitizePartId(`${roleKey}:${input.ecosystem}:${input.toolId}`),\n role: input.role,\n toolId: input.toolId,\n ecosystem: input.ecosystem,\n ownerPartId: input.ownerPartId,\n source: input.source ?? \"selected\",\n providedByPartId: input.providedByPartId,\n targetPath: input.targetPath ?? getRoleTargetPath(input.role),\n settings: input.settings,\n };\n}\n\nfunction isNoneTool(toolId: string | undefined) {\n return !toolId || toolId === \"none\";\n}\n\nfunction allowsCrossEcosystemOwner(\n part: Pick<StackPart, \"role\" | \"ecosystem\">,\n context: StackPartOptionContext,\n) {\n if (part.ecosystem === \"universal\") return true;\n if (\n part.role === \"auth\" &&\n context.ownerRole === \"mobile\" &&\n part.ecosystem === \"react-native\"\n ) {\n return true;\n }\n return false;\n}\n\nfunction createStackGraphIssue(input: {\n code: string;\n message: string;\n partId?: string;\n role: StackPartRole;\n toolId: string;\n}): StackGraphIssue {\n return {\n code: input.code,\n message: input.message,\n partId: input.partId,\n role: input.role,\n toolId: input.toolId,\n };\n}\n\nfunction getStackPartCompatibilityIssue(\n part: Pick<StackPart, \"id\" | \"role\" | \"toolId\" | \"ecosystem\">,\n context: StackPartOptionContext,\n): StackGraphIssue | undefined {\n if (\n context.ownerEcosystem &&\n part.ecosystem !== context.ownerEcosystem &&\n !allowsCrossEcosystemOwner(part, context)\n ) {\n return createStackGraphIssue({\n code: \"INCOMPATIBLE_OWNER_ECOSYSTEM\",\n partId: part.id,\n role: part.role,\n toolId: part.toolId,\n message: `'${part.toolId}' uses the ${part.ecosystem} adapter but its owner uses ${context.ownerEcosystem}.`,\n });\n }\n\n if (part.ecosystem === \"python\" && part.role === \"api\" && DJANGO_API_TOOLS.has(part.toolId)) {\n if (context.ownerToolId !== \"django\") {\n return createStackGraphIssue({\n code: \"INCOMPATIBLE_OWNER_TOOL\",\n partId: part.id,\n role: part.role,\n toolId: part.toolId,\n message: `'${part.toolId}' can only be selected for a Django backend.`,\n });\n }\n }\n\n if (\n part.ecosystem === \"java\" &&\n (part.role === \"orm\" || part.role === \"auth\") &&\n JAVA_SPRING_CAPABILITY_TOOLS.has(part.toolId)\n ) {\n if (context.ownerToolId !== \"spring-boot\") {\n return createStackGraphIssue({\n code: \"INCOMPATIBLE_OWNER_TOOL\",\n partId: part.id,\n role: part.role,\n toolId: part.toolId,\n message: `'${part.toolId}' can only be selected for a Spring Boot backend.`,\n });\n }\n }\n\n if (part.ecosystem === \"typescript\" && part.role === \"api\" && part.toolId === \"trpc\") {\n const frontendTool = context.primaryToolIdsByRole?.frontend;\n if (frontendTool && TYPESCRIPT_TRPC_INCOMPATIBLE_FRONTENDS.has(frontendTool)) {\n return createStackGraphIssue({\n code: \"INCOMPATIBLE_GRAPH_SELECTION\",\n partId: part.id,\n role: part.role,\n toolId: part.toolId,\n message: `'trpc' cannot be selected with the '${frontendTool}' frontend.`,\n });\n }\n }\n\n if (part.ecosystem === \"typescript\" && part.role === \"auth\" && part.toolId === \"better-auth\") {\n const databaseTool = context.primaryToolIdsByRole?.database;\n if (databaseTool === \"redis\") {\n return createStackGraphIssue({\n code: \"INCOMPATIBLE_GRAPH_SELECTION\",\n partId: part.id,\n role: part.role,\n toolId: part.toolId,\n message: \"'better-auth' cannot use Redis as the primary database.\",\n });\n }\n\n const ormTool = context.siblingToolIdsByRole?.orm;\n if (ormTool && BETTER_AUTH_UNSUPPORTED_ORM_TOOLS.has(ormTool)) {\n return createStackGraphIssue({\n code: \"INCOMPATIBLE_GRAPH_SELECTION\",\n partId: part.id,\n role: part.role,\n toolId: part.toolId,\n message: `'better-auth' is not compatible with the '${ormTool}' ORM selection.`,\n });\n }\n }\n\n if (\n part.ecosystem === \"elixir\" &&\n ELIXIR_ECTO_REQUIRED_TOOLS.has(part.toolId) &&\n (part.role === \"api\" || part.role === \"auth\")\n ) {\n const ormTool = context.siblingToolIdsByRole?.orm;\n if (isNoneTool(ormTool)) {\n return createStackGraphIssue({\n code: \"INCOMPATIBLE_GRAPH_SELECTION\",\n partId: part.id,\n role: part.role,\n toolId: part.toolId,\n message: `'${part.toolId}' requires an Ecto database layer.`,\n });\n }\n }\n\n if (part.ecosystem === \"elixir\" && ELIXIR_ECTO_SQL_REQUIRED_TOOLS.has(part.toolId)) {\n const ormTool = context.siblingToolIdsByRole?.orm;\n if (ormTool !== \"ecto-sql\") {\n return createStackGraphIssue({\n code: \"INCOMPATIBLE_GRAPH_SELECTION\",\n partId: part.id,\n role: part.role,\n toolId: part.toolId,\n message: `'${part.toolId}' requires the Ecto SQL database layer.`,\n });\n }\n }\n\n if (part.ecosystem === \"elixir\" && part.toolId === \"live-view-streams\") {\n if (context.ownerToolId !== \"phoenix-live-view\") {\n return createStackGraphIssue({\n code: \"INCOMPATIBLE_OWNER_TOOL\",\n partId: part.id,\n role: part.role,\n toolId: part.toolId,\n message: \"'live-view-streams' can only be selected for a Phoenix LiveView backend.\",\n });\n }\n }\n\n if (part.ecosystem === \"elixir\" && ELIXIR_UNSUPPORTED_GRAPH_TOOLS.has(part.toolId)) {\n return createStackGraphIssue({\n code: \"UNSUPPORTED_GRAPH_TOOL\",\n partId: part.id,\n role: part.role,\n toolId: part.toolId,\n message: `'${part.toolId}' is not generated by the current Elixir scaffold.`,\n });\n }\n\n return undefined;\n}\n\nexport function getStackToolDefinitions(context?: StackPartOptionContext): ToolDefinition[] {\n if (!context) return [...STACK_TOOL_DEFINITIONS];\n return STACK_TOOL_DEFINITIONS.filter((definition) => {\n if (!definition.roles.includes(context.role)) return false;\n if (context.ecosystem && !definition.ecosystems.includes(context.ecosystem)) return false;\n if (definition.selectable === false) return false;\n const ecosystem = context.ecosystem ?? definition.ecosystems[0];\n if (\n getStackPartCompatibilityIssue(\n {\n id: `${context.ownerRole ?? \"root\"}:${context.role}:${definition.toolId}`,\n role: context.role,\n toolId: definition.toolId,\n ecosystem,\n },\n context,\n )\n ) {\n return false;\n }\n return true;\n });\n}\n\nexport function getStackPartOptions(context: StackPartOptionContext): string[] {\n return [...new Set(getStackToolDefinitions(context).map((definition) => definition.toolId))];\n}\n\nfunction findDefinition(part: Pick<StackPart, \"role\" | \"toolId\" | \"ecosystem\">) {\n return STACK_TOOL_DEFINITIONS.find(\n (definition) =>\n definition.toolId === part.toolId &&\n definition.roles.includes(part.role) &&\n definition.ecosystems.includes(part.ecosystem),\n );\n}\n\nfunction parseRolePath(rolePath: string): { role: StackPartRole; ownerRole?: StackPrimaryRole } {\n const segments = rolePath.split(\".\");\n const rawRole = segments.length === 1 ? segments[0] : segments[segments.length - 1];\n const rawOwnerRole = segments.length > 1 ? segments[0] : undefined;\n const role = StackPartRoleSchema.parse(rawRole);\n const ownerRole = rawOwnerRole ? StackPartRoleSchema.parse(rawOwnerRole) : undefined;\n\n if (ownerRole && !PRIMARY_ROLES.has(ownerRole)) {\n throw new Error(`Stack part owner role '${ownerRole}' must be a primary role.`);\n }\n\n return { role, ownerRole: ownerRole as StackPrimaryRole | undefined };\n}\n\nexport function parseStackPartSpecs(\n specs: readonly string[],\n source: StackPartSource = \"selected\",\n): StackPart[] {\n const unresolved = specs.map((spec) => {\n const [rolePath, ecosystem, toolId, customId] = spec.split(\":\");\n if (!rolePath || !ecosystem || !toolId || spec.split(\":\").length > 4) {\n throw new Error(\n `Invalid --part '${spec}'. Use role:ecosystem:tool or owner.role:ecosystem:tool.`,\n );\n }\n const { role, ownerRole } = parseRolePath(rolePath);\n return {\n role,\n ownerRole,\n ecosystem: ecosystem as StackPartEcosystem,\n toolId,\n customId,\n };\n });\n\n const primaryParts = unresolved\n .filter((part) => !part.ownerRole)\n .map((part) =>\n createStackPart({\n role: part.role,\n ecosystem: part.ecosystem,\n toolId: part.toolId,\n source,\n id: part.customId,\n }),\n );\n\n const primaryByRole = new Map(primaryParts.map((part) => [part.role, part]));\n const scopedParts = unresolved\n .filter(\n (part): part is typeof part & { ownerRole: StackPrimaryRole } =>\n part.ownerRole !== undefined,\n )\n .map((part) =>\n createStackPart({\n role: part.role,\n ecosystem: part.ecosystem,\n toolId: part.toolId,\n ownerPartId: primaryByRole.get(part.ownerRole)?.id,\n source,\n id: part.customId,\n }),\n );\n\n return materializeProvidedStackParts([...primaryParts, ...scopedParts]);\n}\n\nexport function formatStackPartSpec(part: StackPart, parts: readonly StackPart[] = []): string {\n const owner = part.ownerPartId\n ? parts.find((candidate) => candidate.id === part.ownerPartId)\n : undefined;\n const rolePath = owner ? `${owner.role}.${part.role}` : part.role;\n return `${rolePath}:${part.ecosystem}:${part.toolId}`;\n}\n\nexport function materializeProvidedStackParts(parts: readonly StackPart[]): StackPart[] {\n const next = [...parts];\n\n for (const part of parts) {\n const definition = findDefinition(part);\n for (const provided of definition?.provides ?? []) {\n next.push(\n createStackPart({\n role: provided.role,\n toolId: provided.toolId,\n ecosystem: provided.ecosystem ?? part.ecosystem,\n ownerPartId: part.id,\n source: \"provided\",\n providedByPartId: part.id,\n }),\n );\n }\n }\n\n return next;\n}\n\nfunction getPrimaryPart(parts: readonly StackPart[], role: StackPrimaryRole) {\n return parts.find((part) => part.role === role && !part.ownerPartId);\n}\n\nfunction addLegacyPart(\n parts: StackPart[],\n role: StackPartRole,\n ecosystem: StackPartEcosystem,\n toolId: string | undefined,\n source: StackPartSource,\n ownerPartId?: string,\n) {\n if (!toolId || toolId === \"none\") return undefined;\n const part = createStackPart({ role, ecosystem, toolId, source, ownerPartId });\n parts.push(part);\n return part;\n}\n\nexport function legacyProjectConfigToStackParts(\n config: Partial<ProjectConfig>,\n source: StackPartSource = \"legacy\",\n): StackPart[] {\n const parts: StackPart[] = [];\n const frontends = config.frontend ?? [];\n const webFrontends = frontends.filter(\n (frontend) => frontend !== \"none\" && !NATIVE_FRONTENDS.has(frontend),\n );\n const nativeFrontends = frontends.filter((frontend) => NATIVE_FRONTENDS.has(frontend));\n\n if (webFrontends.length > 1) {\n throw new Error(\"Multiple primary web frontends are not supported in the stack graph.\");\n }\n if (nativeFrontends.length > 1) {\n throw new Error(\"Multiple primary mobile frontends are not supported in the stack graph.\");\n }\n\n const webFrontend = webFrontends[0];\n const nativeFrontend = nativeFrontends[0];\n const frontendPart = addLegacyPart(parts, \"frontend\", \"typescript\", webFrontend, source);\n addLegacyPart(parts, \"mobile\", \"react-native\", nativeFrontend, source);\n\n let backendPart: StackPart | undefined;\n if (\n (config.ecosystem === undefined || config.ecosystem === \"typescript\") &&\n config.backend &&\n config.backend !== \"none\"\n ) {\n backendPart = addLegacyPart(parts, \"backend\", \"typescript\", config.backend, source);\n }\n\n if (\n config.ecosystem === \"rust\" &&\n config.rustWebFramework &&\n config.rustWebFramework !== \"none\"\n ) {\n backendPart = addLegacyPart(parts, \"backend\", \"rust\", config.rustWebFramework, source);\n }\n if (config.ecosystem === \"rust\" && config.rustFrontend && config.rustFrontend !== \"none\") {\n addLegacyPart(parts, \"frontend\", \"rust\", config.rustFrontend, source);\n }\n if (\n config.ecosystem === \"python\" &&\n config.pythonWebFramework &&\n config.pythonWebFramework !== \"none\"\n ) {\n backendPart = addLegacyPart(parts, \"backend\", \"python\", config.pythonWebFramework, source);\n }\n if (config.ecosystem === \"go\" && config.goWebFramework && config.goWebFramework !== \"none\") {\n backendPart = addLegacyPart(parts, \"backend\", \"go\", config.goWebFramework, source);\n }\n if (\n config.ecosystem === \"java\" &&\n config.javaWebFramework &&\n config.javaWebFramework !== \"none\"\n ) {\n backendPart = addLegacyPart(parts, \"backend\", \"java\", config.javaWebFramework, source);\n }\n if (\n config.ecosystem === \"elixir\" &&\n config.elixirWebFramework &&\n config.elixirWebFramework !== \"none\"\n ) {\n backendPart = addLegacyPart(parts, \"backend\", \"elixir\", config.elixirWebFramework, source);\n }\n\n const databasePart = addLegacyPart(parts, \"database\", \"universal\", config.database, source);\n const capabilityOwner = backendPart?.id ?? frontendPart?.id ?? databasePart?.id;\n\n // The generic `orm`/`api`/`auth` fields only describe TypeScript and React Native\n // stacks. For other ecosystems these are inert TS defaults and the ecosystem-specific\n // blocks below own the real bindings — mapping the generic fields there would emit\n // invalid or duplicate capability parts (e.g. `auth:go:better-auth` alongside `goAuth`).\n if (\n config.ecosystem === undefined ||\n config.ecosystem === \"typescript\" ||\n config.ecosystem === \"react-native\"\n ) {\n addLegacyPart(parts, \"orm\", \"typescript\", config.orm, source, capabilityOwner);\n addLegacyPart(parts, \"api\", \"typescript\", config.api, source, capabilityOwner);\n addLegacyPart(\n parts,\n \"auth\",\n config.ecosystem ?? \"typescript\",\n config.auth,\n source,\n capabilityOwner,\n );\n }\n if (config.ecosystem === \"rust\") {\n addLegacyPart(parts, \"orm\", \"rust\", config.rustOrm, source, backendPart?.id);\n addLegacyPart(parts, \"api\", \"rust\", config.rustApi, source, backendPart?.id);\n addLegacyPart(parts, \"auth\", \"rust\", config.rustAuth, source, backendPart?.id);\n }\n if (config.ecosystem === \"python\") {\n addLegacyPart(parts, \"orm\", \"python\", config.pythonOrm, source, backendPart?.id);\n addLegacyPart(parts, \"api\", \"python\", config.pythonApi, source, backendPart?.id);\n addLegacyPart(parts, \"auth\", \"python\", config.pythonAuth, source, backendPart?.id);\n }\n if (config.ecosystem === \"go\") {\n addLegacyPart(parts, \"orm\", \"go\", config.goOrm, source, backendPart?.id);\n addLegacyPart(parts, \"api\", \"go\", config.goApi, source, backendPart?.id);\n addLegacyPart(parts, \"auth\", \"go\", config.goAuth, source, backendPart?.id);\n }\n if (config.ecosystem === \"java\") {\n addLegacyPart(parts, \"orm\", \"java\", config.javaOrm, source, backendPart?.id);\n addLegacyPart(parts, \"auth\", \"java\", config.javaAuth, source, backendPart?.id);\n }\n if (config.ecosystem === \"elixir\") {\n addLegacyPart(parts, \"orm\", \"elixir\", config.elixirOrm, source, backendPart?.id);\n addLegacyPart(parts, \"api\", \"elixir\", config.elixirApi, source, backendPart?.id);\n addLegacyPart(parts, \"auth\", \"elixir\", config.elixirAuth, source, backendPart?.id);\n }\n\n return materializeProvidedStackParts(parts);\n}\n\nfunction ecosystemForLegacy(parts: readonly StackPart[]): Ecosystem {\n const frontend = getPrimaryPart(parts, \"frontend\");\n if (frontend?.ecosystem && frontend.ecosystem !== \"universal\") return frontend.ecosystem;\n const mobile = getPrimaryPart(parts, \"mobile\");\n if (mobile) return \"react-native\";\n const backend = getPrimaryPart(parts, \"backend\");\n if (backend?.ecosystem && backend.ecosystem !== \"universal\") return backend.ecosystem;\n return \"typescript\";\n}\n\nexport function stackPartsToLegacyProjectConfigPartial(\n parts: readonly StackPart[],\n): Partial<ProjectConfig> {\n const config: Partial<ProjectConfig> = {\n stackParts: [...parts],\n ecosystem: ecosystemForLegacy(parts),\n frontend: [],\n backend: \"none\",\n database: \"none\",\n orm: \"none\",\n api: \"none\",\n auth: \"none\",\n };\n\n for (const part of parts) {\n if (part.source === \"provided\") continue;\n if (!part.ownerPartId) {\n if (part.role === \"frontend\" && part.ecosystem === \"typescript\") {\n config.frontend = [\n ...(config.frontend ?? []),\n part.toolId as ProjectConfig[\"frontend\"][number],\n ];\n } else if (part.role === \"frontend\" && part.ecosystem === \"rust\") {\n config.rustFrontend = part.toolId as ProjectConfig[\"rustFrontend\"];\n } else if (part.role === \"mobile\") {\n config.frontend = [\n ...(config.frontend ?? []),\n part.toolId as ProjectConfig[\"frontend\"][number],\n ];\n } else if (part.role === \"backend\") {\n if (part.ecosystem === \"typescript\")\n config.backend = part.toolId as ProjectConfig[\"backend\"];\n if (part.ecosystem === \"rust\")\n config.rustWebFramework = part.toolId as ProjectConfig[\"rustWebFramework\"];\n if (part.ecosystem === \"python\")\n config.pythonWebFramework = part.toolId as ProjectConfig[\"pythonWebFramework\"];\n if (part.ecosystem === \"go\")\n config.goWebFramework = part.toolId as ProjectConfig[\"goWebFramework\"];\n if (part.ecosystem === \"java\")\n config.javaWebFramework = part.toolId as ProjectConfig[\"javaWebFramework\"];\n if (part.ecosystem === \"elixir\")\n config.elixirWebFramework = part.toolId as ProjectConfig[\"elixirWebFramework\"];\n } else if (part.role === \"database\") {\n config.database = part.toolId as ProjectConfig[\"database\"];\n }\n continue;\n }\n\n const definition = findDefinition(part);\n if (definition?.legacyCategory) {\n (config as Record<string, unknown>)[definition.legacyCategory] = part.toolId;\n continue;\n }\n\n if (part.role === \"orm\") {\n if (part.ecosystem === \"typescript\") config.orm = part.toolId as ProjectConfig[\"orm\"];\n if (part.ecosystem === \"rust\") config.rustOrm = part.toolId as ProjectConfig[\"rustOrm\"];\n if (part.ecosystem === \"python\") config.pythonOrm = part.toolId as ProjectConfig[\"pythonOrm\"];\n if (part.ecosystem === \"go\") config.goOrm = part.toolId as ProjectConfig[\"goOrm\"];\n if (part.ecosystem === \"java\") config.javaOrm = part.toolId as ProjectConfig[\"javaOrm\"];\n if (part.ecosystem === \"elixir\") config.elixirOrm = part.toolId as ProjectConfig[\"elixirOrm\"];\n }\n if (part.role === \"api\") {\n if (part.ecosystem === \"typescript\") config.api = part.toolId as ProjectConfig[\"api\"];\n if (part.ecosystem === \"rust\") config.rustApi = part.toolId as ProjectConfig[\"rustApi\"];\n if (part.ecosystem === \"python\") config.pythonApi = part.toolId as ProjectConfig[\"pythonApi\"];\n if (part.ecosystem === \"go\") config.goApi = part.toolId as ProjectConfig[\"goApi\"];\n if (part.ecosystem === \"elixir\") config.elixirApi = part.toolId as ProjectConfig[\"elixirApi\"];\n }\n if (part.role === \"auth\") {\n if (part.ecosystem === \"typescript\" || part.ecosystem === \"react-native\") {\n config.auth = part.toolId as ProjectConfig[\"auth\"];\n }\n if (part.ecosystem === \"rust\") config.rustAuth = part.toolId as ProjectConfig[\"rustAuth\"];\n if (part.ecosystem === \"python\")\n config.pythonAuth = part.toolId as ProjectConfig[\"pythonAuth\"];\n if (part.ecosystem === \"go\") config.goAuth = part.toolId as ProjectConfig[\"goAuth\"];\n if (part.ecosystem === \"java\") config.javaAuth = part.toolId as ProjectConfig[\"javaAuth\"];\n if (part.ecosystem === \"elixir\")\n config.elixirAuth = part.toolId as ProjectConfig[\"elixirAuth\"];\n }\n }\n\n return config;\n}\n\nexport function compareLegacyConfigToStackParts(\n config: Partial<ProjectConfig>,\n stackParts: readonly StackPart[],\n): StackGraphDiagnostic[] {\n const derived = stackPartsToLegacyProjectConfigPartial(stackParts);\n const diagnostics: StackGraphDiagnostic[] = [];\n for (const key of [\n \"ecosystem\",\n \"frontend\",\n \"backend\",\n \"database\",\n \"orm\",\n \"api\",\n \"auth\",\n \"rustWebFramework\",\n \"pythonWebFramework\",\n \"goWebFramework\",\n \"javaWebFramework\",\n \"elixirWebFramework\",\n ] as const) {\n const current = config[key];\n const next = derived[key];\n if (current === undefined || next === undefined) continue;\n if (JSON.stringify(current) !== JSON.stringify(next)) {\n diagnostics.push({\n code: \"LEGACY_CONFIG_MISMATCH\",\n path: key,\n message: `Legacy field '${key}' differs from stackParts and will be derived from the graph.`,\n });\n }\n }\n return diagnostics;\n}\n\nexport function validateStackParts(parts: readonly StackPart[]): StackGraphValidationResult {\n const issues: StackGraphIssue[] = [];\n const partsById = new Map(parts.map((part) => [part.id, part]));\n const primaryToolIdsByRole: Partial<Record<StackPrimaryRole, string>> = {};\n\n for (const role of PRIMARY_ROLES) {\n const primaryPart = getPrimaryPart(parts, role as StackPrimaryRole);\n if (primaryPart) primaryToolIdsByRole[role as StackPrimaryRole] = primaryPart.toolId;\n }\n\n for (const role of PRIMARY_ROLES) {\n const matching = parts.filter((part) => part.role === role && !part.ownerPartId);\n if (matching.length > 1) {\n issues.push({\n code: \"DUPLICATE_PRIMARY_ROLE\",\n role,\n message: `Only one primary '${role}' stack part is supported in v1.`,\n });\n }\n }\n\n for (const part of parts) {\n const definition = findDefinition(part);\n if (!definition) {\n issues.push({\n code: \"UNSUPPORTED_ROLE_BINDING\",\n partId: part.id,\n role: part.role,\n toolId: part.toolId,\n message: `'${part.toolId}' is not a valid ${part.ecosystem} tool for role '${part.role}'.`,\n });\n }\n\n if (!PRIMARY_ROLES.has(part.role) && !part.ownerPartId) {\n issues.push({\n code: \"MISSING_OWNER_PART\",\n partId: part.id,\n role: part.role,\n toolId: part.toolId,\n message: `Capability stack part '${part.id}' must reference an owning primary part.`,\n });\n }\n\n if (part.ownerPartId && !partsById.has(part.ownerPartId)) {\n issues.push({\n code: \"MISSING_OWNER_PART\",\n partId: part.id,\n role: part.role,\n toolId: part.toolId,\n message: `Stack part '${part.id}' references missing owner '${part.ownerPartId}'.`,\n });\n }\n\n const owner = part.ownerPartId ? partsById.get(part.ownerPartId) : undefined;\n if (definition && (PRIMARY_ROLES.has(part.role) || owner)) {\n const siblingToolIdsByRole: Partial<Record<StackPartRole, string>> = {};\n for (const sibling of parts) {\n if (sibling.ownerPartId !== part.ownerPartId || sibling.source === \"provided\") continue;\n siblingToolIdsByRole[sibling.role] = sibling.toolId;\n }\n\n const compatibilityIssue = getStackPartCompatibilityIssue(part, {\n role: part.role,\n ecosystem: part.ecosystem,\n ownerRole:\n owner && PRIMARY_ROLES.has(owner.role) ? (owner.role as StackPrimaryRole) : undefined,\n ownerToolId: owner?.toolId,\n ownerEcosystem: owner?.ecosystem,\n siblingToolIdsByRole,\n primaryToolIdsByRole,\n });\n\n if (compatibilityIssue) {\n issues.push(compatibilityIssue);\n }\n }\n }\n\n const byScope = new Map<string, StackPart[]>();\n for (const part of parts) {\n const key = `${part.ownerPartId ?? \"root\"}:${part.role}`;\n byScope.set(key, [...(byScope.get(key) ?? []), part]);\n }\n\n for (const scopedParts of byScope.values()) {\n const selectedParts = scopedParts.filter((part) => part.source !== \"provided\");\n if (selectedParts.length > 1) {\n const [first] = selectedParts;\n issues.push({\n code: \"DUPLICATE_ROLE_SCOPE\",\n partId: first?.id,\n role: first?.role,\n toolId: first?.toolId,\n message: `Only one selected '${first?.role}' stack part is supported per owner scope.`,\n });\n }\n\n const selected = scopedParts.find((part) => part.source !== \"provided\");\n const provided = scopedParts.find((part) => part.source === \"provided\");\n if (!selected || !provided || selected.toolId === provided.toolId) continue;\n\n const provider = provided.providedByPartId\n ? partsById.get(provided.providedByPartId)\n : undefined;\n const providerDefinition = provider ? findDefinition(provider) : undefined;\n const providedDefinition = providerDefinition?.provides?.find(\n (capability) => capability.role === provided.role && capability.toolId === provided.toolId,\n );\n\n if (!providedDefinition?.overrideable) {\n issues.push({\n code: \"PROVIDED_CAPABILITY_CONFLICT\",\n partId: selected.id,\n role: selected.role,\n toolId: selected.toolId,\n message: `'${selected.toolId}' conflicts with '${provided.toolId}' provided by '${provider?.toolId ?? \"another part\"}'.`,\n });\n }\n }\n\n return { issues };\n}\n"],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import { $t as StackPartRole, Qt as StackPartEcosystem, Zt as StackPart, en as StackPartSource, yt as ProjectConfig } from "./types-CWpfWGSN.mjs";
2
+
3
+ //#region src/stack-graph.d.ts
4
+ type StackPrimaryRole = Extract<StackPartRole, "frontend" | "backend" | "mobile" | "database">;
5
+ type ProvidedCapabilityDefinition = {
6
+ role: StackPartRole;
7
+ toolId: string;
8
+ ecosystem?: StackPartEcosystem;
9
+ overrideable?: boolean;
10
+ };
11
+ type ToolDefinition = {
12
+ toolId: string;
13
+ label?: string;
14
+ roles: readonly StackPartRole[];
15
+ ecosystems: readonly StackPartEcosystem[];
16
+ legacyCategory?: keyof ProjectConfig;
17
+ selectable?: boolean;
18
+ provides?: readonly ProvidedCapabilityDefinition[];
19
+ };
20
+ type StackPartOptionContext = {
21
+ role: StackPartRole;
22
+ ecosystem?: StackPartEcosystem;
23
+ ownerRole?: StackPrimaryRole;
24
+ ownerToolId?: string;
25
+ ownerEcosystem?: StackPartEcosystem;
26
+ siblingToolIdsByRole?: Partial<Record<StackPartRole, string | undefined>>;
27
+ primaryToolIdsByRole?: Partial<Record<StackPrimaryRole, string | undefined>>;
28
+ };
29
+ type StackGraphIssue = {
30
+ code: string;
31
+ message: string;
32
+ partId?: string;
33
+ role?: StackPartRole;
34
+ toolId?: string;
35
+ };
36
+ type StackGraphValidationResult = {
37
+ issues: StackGraphIssue[];
38
+ };
39
+ type StackGraphDiagnostic = {
40
+ code: string;
41
+ message: string;
42
+ path?: string;
43
+ };
44
+ declare const STACK_TOOL_DEFINITIONS: readonly ToolDefinition[];
45
+ declare function getRoleTargetPath(role: StackPartRole): string | undefined;
46
+ declare function createStackPart(input: {
47
+ role: StackPartRole;
48
+ toolId: string;
49
+ ecosystem: StackPartEcosystem;
50
+ ownerPartId?: string;
51
+ source?: StackPartSource;
52
+ providedByPartId?: string;
53
+ id?: string;
54
+ targetPath?: string;
55
+ settings?: Record<string, unknown>;
56
+ }): StackPart;
57
+ declare function getStackToolDefinitions(context?: StackPartOptionContext): ToolDefinition[];
58
+ declare function getStackPartOptions(context: StackPartOptionContext): string[];
59
+ declare function parseStackPartSpecs(specs: readonly string[], source?: StackPartSource): StackPart[];
60
+ declare function formatStackPartSpec(part: StackPart, parts?: readonly StackPart[]): string;
61
+ declare function materializeProvidedStackParts(parts: readonly StackPart[]): StackPart[];
62
+ declare function legacyProjectConfigToStackParts(config: Partial<ProjectConfig>, source?: StackPartSource): StackPart[];
63
+ declare function stackPartsToLegacyProjectConfigPartial(parts: readonly StackPart[]): Partial<ProjectConfig>;
64
+ declare function compareLegacyConfigToStackParts(config: Partial<ProjectConfig>, stackParts: readonly StackPart[]): StackGraphDiagnostic[];
65
+ declare function validateStackParts(parts: readonly StackPart[]): StackGraphValidationResult;
66
+ //#endregion
67
+ export { parseStackPartSpecs as _, StackGraphValidationResult as a, ToolDefinition as c, formatStackPartSpec as d, getRoleTargetPath as f, materializeProvidedStackParts as g, legacyProjectConfigToStackParts as h, StackGraphIssue as i, compareLegacyConfigToStackParts as l, getStackToolDefinitions as m, STACK_TOOL_DEFINITIONS as n, StackPartOptionContext as o, getStackPartOptions as p, StackGraphDiagnostic as r, StackPrimaryRole as s, ProvidedCapabilityDefinition as t, createStackPart as u, stackPartsToLegacyProjectConfigPartial as v, validateStackParts as y };
68
+ //# sourceMappingURL=stack-graph-UgPd4sup.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack-graph-UgPd4sup.d.mts","names":[],"sources":["../src/stack-graph.ts"],"sourcesContent":[],"mappings":";;;KAmDY,gBAAA,GAAmB,QAC7B;KAIU,4BAAA;EALA,IAAA,EAMJ,aANoB;EAKhB,MAAA,EAAA,MAAA;EAOA,SAAA,CAAA,EAJE,kBAIY;EAGR,YAAA,CAAA,EAAA,OAAA;CACK;AACE,KALb,cAAA,GAKa;EAEH,MAAA,EAAA,MAAA;EAA4B,KAAA,CAAA,EAAA,MAAA;EAGtC,KAAA,EAAA,SAPM,aAOgB,EAAA;EAC1B,UAAA,EAAA,SAPe,kBAOf,EAAA;EACM,cAAA,CAAA,EAAA,MAPW,aAOX;EACA,UAAA,CAAA,EAAA,OAAA;EAEK,QAAA,CAAA,EAAA,SARG,4BAQH,EAAA;CACqB;AAAP,KANrB,sBAAA,GAMqB;EAAR,IAAA,EALjB,aAKiB;EACe,SAAA,CAAA,EAL1B,kBAK0B;EAAP,SAAA,CAAA,EAJnB,gBAImB;EAAR,WAAA,CAAA,EAAA,MAAA;EAAO,cAAA,CAAA,EAFb,kBAEa;EAGpB,oBAAe,CAAA,EAJF,OAIE,CAJM,MAQxB,CAR+B,aAQlB,EAAA,MAAA,GAAA,SAAA,CAAA,CAAA;EAIV,oBAAA,CAAA,EAXa,OAWa,CAXL,MAWK,CAXE,gBAY9B,EAAA,MAAe,GAAA,SAAA,CAAA,CAAA;AAGzB,CAAA;AA4Da,KAxED,eAAA,GAuIX;EAWe,IAAA,EAAA,MAAA;EAIA,OAAA,EAAA,MAAA;EACR,MAAA,CAAA,EAAA,MAAA;EAEK,IAAA,CAAA,EArJJ,aAqJI;EAEF,MAAA,CAAA,EAAA,MAAA;CAIE;AACT,KAxJQ,0BAAA,GAwJR;EAAS,MAAA,EAvJH,eAuJG,EAAA;AA4Lb,CAAA;AAwBgB,KAxWJ,oBAAA,GAwWuB;EA2BnB,IAAA,EAAA,MAAA;EAqDA,OAAA,EAAA,MAAA;EAQA,IAAA,CAAA,EAAA,MAAA;AAwChB,CAAA;AACkB,cA7aL,sBA6aK,EAAA,SA7a4B,cA6a5B,EAAA;AAAR,iBAnWM,iBAAA,CAmWN,IAAA,EAnW8B,aAmW9B,CAAA,EAAA,MAAA,GAAA,SAAA;AACA,iBAhWM,eAAA,CAgWN,KAAA,EAAA;EACP,IAAA,EAhWK,aAgWL;EAAS,MAAA,EAAA,MAAA;EA6HI,SAAA,EA3dH,kBA2dG;EACE,WAAA,CAAA,EAAA,MAAA;EACP,MAAA,CAAA,EA3dA,eA2dA;EAAR,gBAAA,CAAA,EAAA,MAAA;EAAO,EAAA,CAAA,EAAA,MAAA;EAoFM,UAAA,CAAA,EAAA,MAAA;EACE,QAAA,CAAA,EA5iBL,MA4iBK,CAAA,MAAA,EAAA,OAAA,CAAA;CAAR,CAAA,EA3iBN,SA2iBM;AACa,iBAhXP,uBAAA,CAgXO,OAAA,CAAA,EAhX2B,sBAgX3B,CAAA,EAhXoD,cAgXpD,EAAA;AACpB,iBAzVa,mBAAA,CAyVb,OAAA,EAzV0C,sBAyV1C,CAAA,EAAA,MAAA,EAAA;AAAoB,iBA9TP,mBAAA,CA8TO,KAAA,EAAA,SAAA,MAAA,EAAA,EAAA,MAAA,CAAA,EA5Tb,eA4Ta,CAAA,EA3TpB,SA2ToB,EAAA;AA+BP,iBAxSA,mBAAA,CAwSmC,IAAA,EAxST,SAwSuB,EAAA,KAA0B,CAA1B,EAAA,SAxSI,SAwSsB,EAAA,CAAA,EAAA,MAAA;iBAhS3E,6BAAA,iBAA8C,cAAc;iBAwC5D,+BAAA,SACN,QAAQ,yBACR,kBACP;iBA6Ha,sCAAA,iBACE,cACf,QAAQ;iBAoFK,+BAAA,SACN,QAAQ,qCACK,cACpB;iBA+Ba,kBAAA,iBAAmC,cAAc"}
@@ -0,0 +1,4 @@
1
+ import "./schemas-62dqb8iS.mjs";
2
+ import "./types-CWpfWGSN.mjs";
3
+ import { _ as parseStackPartSpecs, a as StackGraphValidationResult, c as ToolDefinition, d as formatStackPartSpec, f as getRoleTargetPath, g as materializeProvidedStackParts, h as legacyProjectConfigToStackParts, i as StackGraphIssue, l as compareLegacyConfigToStackParts, m as getStackToolDefinitions, n as STACK_TOOL_DEFINITIONS, o as StackPartOptionContext, p as getStackPartOptions, r as StackGraphDiagnostic, s as StackPrimaryRole, t as ProvidedCapabilityDefinition, u as createStackPart, v as stackPartsToLegacyProjectConfigPartial, y as validateStackParts } from "./stack-graph-UgPd4sup.mjs";
4
+ export { ProvidedCapabilityDefinition, STACK_TOOL_DEFINITIONS, StackGraphDiagnostic, StackGraphIssue, StackGraphValidationResult, StackPartOptionContext, StackPrimaryRole, ToolDefinition, compareLegacyConfigToStackParts, createStackPart, formatStackPartSpec, getRoleTargetPath, getStackPartOptions, getStackToolDefinitions, legacyProjectConfigToStackParts, materializeProvidedStackParts, parseStackPartSpecs, stackPartsToLegacyProjectConfigPartial, validateStackParts };
@@ -0,0 +1,4 @@
1
+ import "./schemas-DnEGgQzA.mjs";
2
+ import { a as getRoleTargetPath, c as legacyProjectConfigToStackParts, d as stackPartsToLegacyProjectConfigPartial, f as validateStackParts, i as formatStackPartSpec, l as materializeProvidedStackParts, n as compareLegacyConfigToStackParts, o as getStackPartOptions, r as createStackPart, s as getStackToolDefinitions, t as STACK_TOOL_DEFINITIONS, u as parseStackPartSpecs } from "./stack-graph-C2tzuzRe.mjs";
3
+
4
+ export { STACK_TOOL_DEFINITIONS, compareLegacyConfigToStackParts, createStackPart, formatStackPartSpec, getRoleTargetPath, getStackPartOptions, getStackToolDefinitions, legacyProjectConfigToStackParts, materializeProvidedStackParts, parseStackPartSpecs, stackPartsToLegacyProjectConfigPartial, validateStackParts };
@@ -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-Hj_Gbdf0.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: [
@@ -1128,15 +1129,6 @@ const analyzeStackCompatibility = (stack) => {
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
  [
@@ -3749,6 +3741,8 @@ function normalizeOptionId(category, value) {
3749
3741
  //#endregion
3750
3742
  //#region src/stack-translation.ts
3751
3743
  const DEFAULT_STACK_SELECTION = {
3744
+ stackMode: "solo",
3745
+ stackPartSpecs: [],
3752
3746
  ecosystem: "typescript",
3753
3747
  projectName: "my-app",
3754
3748
  webFrontend: ["tanstack-router"],
@@ -3858,6 +3852,8 @@ const DEFAULT_STACK_SELECTION = {
3858
3852
  elixirDeploy: "none"
3859
3853
  };
3860
3854
  const NON_OPTION_STACK_SELECTION_KEYS = [
3855
+ "stackMode",
3856
+ "stackPartSpecs",
3861
3857
  "ecosystem",
3862
3858
  "projectName",
3863
3859
  "yolo"
@@ -3979,6 +3975,8 @@ function usesVirtualNoneStackSelection(key) {
3979
3975
  return VIRTUAL_NONE_MULTI_SELECT_STACK_SELECTION_KEYS.includes(key);
3980
3976
  }
3981
3977
  const STACK_SELECTION_URL_KEYS = {
3978
+ stackMode: "mode",
3979
+ stackPartSpecs: "part",
3982
3980
  ecosystem: "eco",
3983
3981
  projectName: "name",
3984
3982
  webFrontend: "fe-w",
@@ -4116,8 +4114,12 @@ function normalizeStackSelectionValue(key, value) {
4116
4114
  if (typeof value === "string") return normalizeOptionId(category, value);
4117
4115
  return value;
4118
4116
  }
4117
+ function normalizeStackSelectionMode(value) {
4118
+ return value === "multi" || value === "graph" ? "multi" : "solo";
4119
+ }
4119
4120
  function normalizeStackSelection(selection) {
4120
4121
  const normalized = { ...selection };
4122
+ normalized.stackMode = normalizeStackSelectionMode(normalized.stackMode);
4121
4123
  for (const key of Object.keys(STACK_SELECTION_OPTION_CATEGORY_BY_KEY)) normalized[key] = normalizeStackSelectionValue(key, normalized[key]);
4122
4124
  return normalized;
4123
4125
  }
@@ -4418,11 +4420,122 @@ function formatTypeScriptAddonsFlag(selection) {
4418
4420
  if (addons.length === 0) return "--addons none";
4419
4421
  return `--addons ${addons.filter((addon) => COMMAND_ADDONS.has(addon)).join(" ") || "none"}`;
4420
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
+ }
4421
4520
  function mapBackendToCli(backend) {
4422
4521
  return SELF_BACKENDS.has(backend) ? "self" : backend;
4423
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
+ }
4424
4532
  function getAdjustedSelection(selection) {
4425
- return analyzeStackCompatibility(selection).adjustedStack ?? selection;
4533
+ const compatibility = analyzeStackCompatibility(selection);
4534
+ if (!compatibility.adjustedStack) return selection;
4535
+ return {
4536
+ ...selection,
4537
+ ...compatibility.adjustedStack
4538
+ };
4426
4539
  }
4427
4540
  function getProjectName(selection, projectName) {
4428
4541
  return projectName?.trim() || selection.projectName?.trim() || "my-app";
@@ -4432,6 +4545,9 @@ function areStringArraysEqual(left, right) {
4432
4545
  const sortedRight = [...right].sort();
4433
4546
  return sortedLeft.length === sortedRight.length && sortedLeft.every((value, index) => value === sortedRight[index]);
4434
4547
  }
4548
+ function isStringArray(value) {
4549
+ return value.every((item) => typeof item === "string");
4550
+ }
4435
4551
  function isStackSelectionDefault(selection, key, value) {
4436
4552
  const defaultValue = DEFAULT_STACK_SELECTION[key];
4437
4553
  if (selection.backend === "convex") {
@@ -4461,12 +4577,57 @@ function cliInputToProjectConfigPartial(input, projectName) {
4461
4577
  const value = input[inputKey];
4462
4578
  if (Array.isArray(value)) assignableConfig[configKey] = processCliArrayOption(value);
4463
4579
  }
4580
+ if (Array.isArray(input.part) && input.part.length > 0) {
4581
+ const stackParts = getCliGraphStackParts(input);
4582
+ Object.assign(config, stackPartsToLegacyProjectConfigPartial(stackParts), { stackParts });
4583
+ }
4464
4584
  return config;
4465
4585
  }
4586
+ function getCliGraphStackParts(input) {
4587
+ const stackParts = parseStackPartSpecs(input.part ?? [], "selected");
4588
+ const stackPartSpecs = stackParts.map((part) => formatStackPartSpec(part, stackParts));
4589
+ const stackPartSpecSet = new Set(stackPartSpecs);
4590
+ const hasPrimary = (role, ecosystem) => stackParts.some((part) => part.role === role && part.ecosystem === ecosystem && !part.ownerPartId && part.source !== "provided");
4591
+ const hasScoped = (role, ecosystem) => stackParts.some((part) => part.role === role && part.ecosystem === ecosystem && part.source !== "provided");
4592
+ const addScopedBackendPart = (ecosystem, role, value) => {
4593
+ if (!value || value === "none" || !hasPrimary("backend", ecosystem) || hasScoped(role, ecosystem)) return;
4594
+ const spec = `backend.${role}:${ecosystem}:${value}`;
4595
+ if (!stackPartSpecSet.has(spec)) {
4596
+ stackPartSpecs.push(spec);
4597
+ stackPartSpecSet.add(spec);
4598
+ }
4599
+ };
4600
+ if (input.database && input.database !== "none" && !hasPrimary("database", "universal")) {
4601
+ const spec = `database:universal:${input.database}`;
4602
+ if (!stackPartSpecSet.has(spec)) {
4603
+ stackPartSpecs.push(spec);
4604
+ stackPartSpecSet.add(spec);
4605
+ }
4606
+ }
4607
+ addScopedBackendPart("typescript", "orm", input.orm);
4608
+ addScopedBackendPart("typescript", "api", input.api);
4609
+ addScopedBackendPart("typescript", "auth", input.auth);
4610
+ addScopedBackendPart("rust", "orm", input.rustOrm);
4611
+ addScopedBackendPart("rust", "api", input.rustApi);
4612
+ addScopedBackendPart("rust", "auth", input.rustAuth);
4613
+ addScopedBackendPart("python", "orm", input.pythonOrm);
4614
+ addScopedBackendPart("python", "api", input.pythonApi);
4615
+ addScopedBackendPart("python", "api", input.pythonGraphql);
4616
+ addScopedBackendPart("python", "auth", input.pythonAuth);
4617
+ addScopedBackendPart("go", "orm", input.goOrm);
4618
+ addScopedBackendPart("go", "api", input.goApi);
4619
+ addScopedBackendPart("go", "auth", input.goAuth);
4620
+ addScopedBackendPart("java", "orm", input.javaOrm);
4621
+ addScopedBackendPart("java", "auth", input.javaAuth);
4622
+ addScopedBackendPart("elixir", "orm", input.elixirOrm);
4623
+ addScopedBackendPart("elixir", "api", input.elixirApi);
4624
+ addScopedBackendPart("elixir", "auth", input.elixirAuth);
4625
+ return parseStackPartSpecs(stackPartSpecs, "selected");
4626
+ }
4466
4627
  function buildProjectConfigBase(selection, projectName, relativePath, install) {
4467
4628
  const stack = getAdjustedSelection(selection);
4468
4629
  const frontend = [...toUniqueNonNoneArray(stack.webFrontend), ...toUniqueNonNoneArray(stack.nativeFrontend)];
4469
- return {
4630
+ const baseConfig = {
4470
4631
  projectName,
4471
4632
  relativePath,
4472
4633
  ecosystem: stack.ecosystem,
@@ -4576,6 +4737,21 @@ function buildProjectConfigBase(selection, projectName, relativePath, install) {
4576
4737
  elixirDeploy: stack.elixirDeploy,
4577
4738
  aiDocs: toUniqueNonNoneArray(stack.aiDocs)
4578
4739
  };
4740
+ if (!isGraphStackSelection(stack)) return baseConfig;
4741
+ const stackParts = getGraphStackParts(stack);
4742
+ const loweredGraphConfig = stackPartsToLegacyProjectConfigPartial(stackParts);
4743
+ return {
4744
+ ...baseConfig,
4745
+ ...loweredGraphConfig,
4746
+ projectName,
4747
+ relativePath,
4748
+ git: stack.git === "true",
4749
+ packageManager: stack.packageManager,
4750
+ versionChannel: stack.versionChannel,
4751
+ install,
4752
+ aiDocs: toUniqueNonNoneArray(stack.aiDocs),
4753
+ stackParts
4754
+ };
4579
4755
  }
4580
4756
  function stackSelectionToProjectConfig(selection, options) {
4581
4757
  const projectName = getProjectName(selection);
@@ -4589,6 +4765,7 @@ function stackSelectionToCliComparableConfig(selection, projectName = getProject
4589
4765
  return buildProjectConfigBase(selection, projectName, projectName, selection.install === "true");
4590
4766
  }
4591
4767
  function isCliDefaultStackSelection(selection, projectName = getProjectName(selection)) {
4768
+ if (isGraphStackSelection(selection)) return false;
4592
4769
  const comparableConfig = stackSelectionToCliComparableConfig(selection, projectName);
4593
4770
  const cliDefaults = {
4594
4771
  ...createCliDefaultProjectConfigBase(selection.packageManager),
@@ -4607,13 +4784,67 @@ function isCliDefaultStackSelection(selection, projectName = getProjectName(sele
4607
4784
  if (ignoredKeys.has(key)) return true;
4608
4785
  const currentValue = comparableConfig[key];
4609
4786
  const defaultValue = cliDefaults[key];
4610
- if (Array.isArray(currentValue) && Array.isArray(defaultValue)) return areStringArraysEqual(currentValue, defaultValue);
4787
+ if (Array.isArray(currentValue) && Array.isArray(defaultValue)) {
4788
+ const currentArray = currentValue;
4789
+ const defaultArray = defaultValue;
4790
+ if (isStringArray(currentArray) && isStringArray(defaultArray)) return areStringArraysEqual(currentArray, defaultArray);
4791
+ return JSON.stringify(currentValue) === JSON.stringify(defaultValue);
4792
+ }
4611
4793
  return currentValue === defaultValue;
4612
4794
  });
4613
4795
  }
4614
4796
  function getBaseCommand(selection) {
4615
4797
  return PACKAGE_MANAGER_COMMANDS[selection.packageManager] ?? PACKAGE_MANAGER_COMMANDS.bun;
4616
4798
  }
4799
+ function generateGraphCommand(selection, projectName) {
4800
+ const stackParts = getGraphStackParts(selection);
4801
+ const hasTypeScriptFrontend = hasGraphPrimaryPart(stackParts, "frontend", "typescript");
4802
+ const hasAstroFrontend = hasGraphPrimaryPart(stackParts, "frontend", "typescript", "astro");
4803
+ const hasTypeScriptBackend = hasGraphPrimaryPart(stackParts, "backend", "typescript");
4804
+ const hasRustBackend = hasGraphPrimaryPart(stackParts, "backend", "rust");
4805
+ const hasPythonBackend = hasGraphPrimaryPart(stackParts, "backend", "python");
4806
+ const hasGoBackend = hasGraphPrimaryPart(stackParts, "backend", "go");
4807
+ const hasJavaBackend = hasGraphPrimaryPart(stackParts, "backend", "java");
4808
+ const hasElixirBackend = hasGraphPrimaryPart(stackParts, "backend", "elixir");
4809
+ const hasNonTypeScriptBackend = hasRustBackend || hasPythonBackend || hasGoBackend || hasJavaBackend || hasElixirBackend;
4810
+ const hasMobile = hasGraphPrimaryPart(stackParts, "mobile");
4811
+ const flags = [
4812
+ ...stackParts.filter((part) => part.source !== "provided").map((part) => `--part ${formatStackPartSpec(part, stackParts)}`),
4813
+ ...hasTypeScriptFrontend ? formatChangedStringFlags(selection, GRAPH_TYPESCRIPT_FRONTEND_FLAG_KEYS) : [],
4814
+ ...hasAstroFrontend && selection.astroIntegration !== "none" ? [`--astro-integration ${selection.astroIntegration}`] : [],
4815
+ ...hasTypeScriptFrontend && selection.uiLibrary === "shadcn-ui" ? formatChangedStringFlags(selection, GRAPH_SHADCN_FLAG_KEYS) : [],
4816
+ ...hasTypeScriptBackend ? formatChangedStringFlags(selection, GRAPH_TYPESCRIPT_BACKEND_FLAG_KEYS) : [],
4817
+ ...hasNonTypeScriptBackend ? formatChangedStringFlags(selection, GRAPH_SHARED_BACKEND_FLAG_KEYS) : [],
4818
+ ...hasRustBackend ? [...formatChangedStringFlags(selection, GRAPH_RUST_BACKEND_FLAG_KEYS), formatChangedArraySelectionFlag(selection, "rustLibraries", "rust-libraries")].filter((flag) => Boolean(flag)) : [],
4819
+ ...hasPythonBackend ? [...formatChangedStringFlags(selection, GRAPH_PYTHON_BACKEND_FLAG_KEYS), formatChangedArraySelectionFlag(selection, "pythonAi", "python-ai")].filter((flag) => Boolean(flag)) : [],
4820
+ ...hasGoBackend ? formatChangedStringFlags(selection, GRAPH_GO_BACKEND_FLAG_KEYS) : [],
4821
+ ...hasJavaBackend ? [
4822
+ ...formatChangedStringFlags(selection, GRAPH_JAVA_BACKEND_FLAG_KEYS),
4823
+ formatChangedArraySelectionFlag(selection, "javaLibraries", "java-libraries"),
4824
+ formatChangedArraySelectionFlag(selection, "javaTestingLibraries", "java-testing-libraries")
4825
+ ].filter((flag) => Boolean(flag)) : [],
4826
+ ...hasElixirBackend ? formatChangedStringFlags(selection, GRAPH_ELIXIR_BACKEND_FLAG_KEYS) : [],
4827
+ ...hasMobile ? formatChangedStringFlags(selection, GRAPH_MOBILE_FLAG_KEYS) : [],
4828
+ ...formatChangedStringFlags(selection, GRAPH_GLOBAL_FLAG_KEYS),
4829
+ ...areStringArraysEqual([
4830
+ ...selection.codeQuality,
4831
+ ...selection.documentation,
4832
+ ...selection.appPlatforms
4833
+ ], [
4834
+ ...DEFAULT_STACK_SELECTION.codeQuality,
4835
+ ...DEFAULT_STACK_SELECTION.documentation,
4836
+ ...DEFAULT_STACK_SELECTION.appPlatforms
4837
+ ]) ? [] : [formatTypeScriptAddonsFlag(selection)],
4838
+ ...areStringArraysEqual(selection.examples, DEFAULT_STACK_SELECTION.examples) ? [] : [formatArrayFlag("examples", selection.examples)],
4839
+ `--package-manager ${selection.packageManager}`,
4840
+ ...selection.versionChannel !== "stable" ? [`--version-channel ${selection.versionChannel}`] : [],
4841
+ selection.git === "false" ? "--no-git" : "--git",
4842
+ selection.install === "false" ? "--no-install" : "--install",
4843
+ formatArrayFlag("ai-docs", selection.aiDocs)
4844
+ ];
4845
+ if (selection.yolo === "true") flags.push("--yolo");
4846
+ return `${getBaseCommand(selection)} ${projectName} ${flags.join(" ")}`;
4847
+ }
4617
4848
  function generateTypeScriptCommand(selection, projectName) {
4618
4849
  const base = getBaseCommand(selection);
4619
4850
  if (isCliDefaultStackSelection(selection, projectName)) return `${base} ${projectName} --yes`;
@@ -4803,6 +5034,7 @@ function generateElixirCommand(selection, projectName) {
4803
5034
  }
4804
5035
  function generateStackSelectionCommand(selection) {
4805
5036
  const projectName = getProjectName(selection);
5037
+ if (isGraphStackSelection(selection)) return generateGraphCommand(selection, projectName);
4806
5038
  switch (selection.ecosystem) {
4807
5039
  case "react-native": return generateReactNativeCommand(selection, projectName);
4808
5040
  case "rust": return generateRustCommand(selection, projectName);
@@ -4816,5 +5048,5 @@ function generateStackSelectionCommand(selection) {
4816
5048
  }
4817
5049
 
4818
5050
  //#endregion
4819
- 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 };
4820
- //# sourceMappingURL=stack-translation-BpsvxDrw.mjs.map
5051
+ 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 };
5052
+ //# sourceMappingURL=stack-translation-COVG5IPm.mjs.map