robodev 0.47.3 → 0.48.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 (172) hide show
  1. package/package.json +3 -3
  2. package/src/emit-starter.test.ts +6 -3
  3. package/templates/auth-chat/ROBODEV.md +7 -1
  4. package/templates/auth-chat/package.json +2 -2
  5. package/templates/backend/ROBODEV.md +7 -1
  6. package/templates/backend/package.json +2 -2
  7. package/templates/catalog.json +5 -0
  8. package/templates/empty/ROBODEV.md +7 -1
  9. package/templates/empty/package.json +2 -2
  10. package/templates/marketplace/ROBODEV.md +7 -1
  11. package/templates/marketplace/package.json +2 -2
  12. package/templates/povio/.config/local.spa.template.yml +27 -0
  13. package/templates/povio/.oxlint-base.json +29 -0
  14. package/templates/povio/.oxlintrc.json +78 -0
  15. package/templates/povio/.rulesync/rules/frontend-api-boundary.md +36 -0
  16. package/templates/povio/.rulesync/rules/frontend-component-structure.md +40 -0
  17. package/templates/povio/.rulesync/rules/frontend-forms.md +27 -0
  18. package/templates/povio/.rulesync/rules/frontend-notifications.md +24 -0
  19. package/templates/povio/.rulesync/rules/frontend-povio-components.md +42 -0
  20. package/templates/povio/.rulesync/rules/frontend-povio-ui.md +45 -0
  21. package/templates/povio/.rulesync/rules/frontend-query-autocomplete.md +24 -0
  22. package/templates/povio/.rulesync/rules/frontend-tables-and-lists.md +26 -0
  23. package/templates/povio/.rulesync/rules/frontend-translations.md +25 -0
  24. package/templates/povio/.rulesync/rules/project-overview.md +32 -0
  25. package/templates/povio/.rulesync/rules/robodev-api.md +30 -0
  26. package/templates/povio/.rulesync/rules/robodev-auth.md +40 -0
  27. package/templates/povio/.rulesync/rules/robodev-database.md +22 -0
  28. package/templates/povio/.rulesync/rules/role-based-app-structure.md +36 -0
  29. package/templates/povio/.rulesync/skills/media-feature/SKILL.md +21 -0
  30. package/templates/povio/.rulesync/skills/povio-ui-styling/SKILL.md +211 -0
  31. package/templates/povio/.rulesync/skills/povio-ui-styling/agents/openai.yaml +4 -0
  32. package/templates/povio/.rulesync/skills/robodev-api-route/SKILL.md +13 -0
  33. package/templates/povio/.rulesync/skills/robodev-table/SKILL.md +12 -0
  34. package/templates/povio/README.md +40 -0
  35. package/templates/povio/ROBODEV.md +84 -0
  36. package/templates/povio/apps/fe/index.html +24 -0
  37. package/templates/povio/apps/fe/openapi-codegen.config.ts +72 -0
  38. package/templates/povio/apps/fe/package.json +71 -0
  39. package/templates/povio/apps/fe/public/apple-touch-icon.png +0 -0
  40. package/templates/povio/apps/fe/public/favicon-96x96.png +0 -0
  41. package/templates/povio/apps/fe/public/favicon.ico +0 -0
  42. package/templates/povio/apps/fe/public/favicon.svg +3 -0
  43. package/templates/povio/apps/fe/public/site.webmanifest +21 -0
  44. package/templates/povio/apps/fe/public/web-app-manifest-192x192.png +0 -0
  45. package/templates/povio/apps/fe/public/web-app-manifest-512x512.png +0 -0
  46. package/templates/povio/apps/fe/src/assets/locales/en/translation.json +166 -0
  47. package/templates/povio/apps/fe/src/clients/app-rest-client.ts +15 -0
  48. package/templates/povio/apps/fe/src/clients/auth-token-store.ts +101 -0
  49. package/templates/povio/apps/fe/src/clients/rest/app-error-handler.ts +31 -0
  50. package/templates/povio/apps/fe/src/clients/rest/interceptors/authorization-header.interceptor.ts +15 -0
  51. package/templates/povio/apps/fe/src/clients/rest/interceptors/refresh-token.interceptor.ts +45 -0
  52. package/templates/povio/apps/fe/src/clients/rest/interceptors/response.interceptor.ts +17 -0
  53. package/templates/povio/apps/fe/src/components/404.tsx +18 -0
  54. package/templates/povio/apps/fe/src/components/features/auth/AuthBrandPanel.tsx +60 -0
  55. package/templates/povio/apps/fe/src/components/features/auth/AuthLayout.tsx +23 -0
  56. package/templates/povio/apps/fe/src/components/features/auth/LoginPage.tsx +111 -0
  57. package/templates/povio/apps/fe/src/components/features/auth/RegisterPage.tsx +143 -0
  58. package/templates/povio/apps/fe/src/components/features/home/HomePage.tsx +21 -0
  59. package/templates/povio/apps/fe/src/components/features/profile/ProfilePage.tsx +96 -0
  60. package/templates/povio/apps/fe/src/components/layout/AppLayout.tsx +19 -0
  61. package/templates/povio/apps/fe/src/components/layout/app-header/AppHeader.tsx +91 -0
  62. package/templates/povio/apps/fe/src/components/layout/app-header/MobileNavigation.tsx +51 -0
  63. package/templates/povio/apps/fe/src/components/layout/app-header/NavLink.tsx +29 -0
  64. package/templates/povio/apps/fe/src/components/shared/branding/BrandLogo.tsx +13 -0
  65. package/templates/povio/apps/fe/src/components/shared/error/ErrorFallback.tsx +43 -0
  66. package/templates/povio/apps/fe/src/components/shared/error/ErrorText.tsx +20 -0
  67. package/templates/povio/apps/fe/src/components/shared/error/NotFound.tsx +36 -0
  68. package/templates/povio/apps/fe/src/components/shared/forms/RequiredLabel.tsx +21 -0
  69. package/templates/povio/apps/fe/src/components/shared/forms/RowInputWrapper.tsx +50 -0
  70. package/templates/povio/apps/fe/src/components/shared/head/AppHead.tsx +32 -0
  71. package/templates/povio/apps/fe/src/components/shared/head/DefaultAppHead.tsx +34 -0
  72. package/templates/povio/apps/fe/src/components/shared/layout/LoadingState.tsx +9 -0
  73. package/templates/povio/apps/fe/src/components/shared/layout/ThinPageWrapper.tsx +5 -0
  74. package/templates/povio/apps/fe/src/components/shared/page/PageHeader.tsx +69 -0
  75. package/templates/povio/apps/fe/src/components/shared/ui/Card.tsx +60 -0
  76. package/templates/povio/apps/fe/src/components/shared/ui/GoogleLoginButton.tsx +19 -0
  77. package/templates/povio/apps/fe/src/components/shared/ui/RequiredLabel.tsx +22 -0
  78. package/templates/povio/apps/fe/src/components/shared/ui/TableActions.tsx +22 -0
  79. package/templates/povio/apps/fe/src/config/app.config.ts +23 -0
  80. package/templates/povio/apps/fe/src/config/i18n.ts +37 -0
  81. package/templates/povio/apps/fe/src/config/inits/logger.ts +7 -0
  82. package/templates/povio/apps/fe/src/config/jwt.config.ts +2 -0
  83. package/templates/povio/apps/fe/src/config/query.config.ts +20 -0
  84. package/templates/povio/apps/fe/src/hooks/useAuth.ts +5 -0
  85. package/templates/povio/apps/fe/src/main.tsx +52 -0
  86. package/templates/povio/apps/fe/src/pages/(guest)/login.tsx +23 -0
  87. package/templates/povio/apps/fe/src/pages/(guest)/register.tsx +23 -0
  88. package/templates/povio/apps/fe/src/pages/(guest)/route.tsx +18 -0
  89. package/templates/povio/apps/fe/src/pages/(private)/index.tsx +23 -0
  90. package/templates/povio/apps/fe/src/pages/(private)/profile.tsx +23 -0
  91. package/templates/povio/apps/fe/src/pages/(private)/route.tsx +18 -0
  92. package/templates/povio/apps/fe/src/pages/(public)/auth.tsx +37 -0
  93. package/templates/povio/apps/fe/src/pages/(public)/route.tsx +9 -0
  94. package/templates/povio/apps/fe/src/pages/__root.tsx +133 -0
  95. package/templates/povio/apps/fe/src/providers/AppErrorBoundary.tsx +44 -0
  96. package/templates/povio/apps/fe/src/providers/OpenApiRuntimeProvider.tsx +31 -0
  97. package/templates/povio/apps/fe/src/providers/index.tsx +44 -0
  98. package/templates/povio/apps/fe/src/providers/jwt.provider.tsx +95 -0
  99. package/templates/povio/apps/fe/src/routeTree.gen.ts +225 -0
  100. package/templates/povio/apps/fe/src/styles/base.css +84 -0
  101. package/templates/povio/apps/fe/src/styles/fonts/fonts.tsx +10 -0
  102. package/templates/povio/apps/fe/src/styles/globals.css +26 -0
  103. package/templates/povio/apps/fe/src/styles/overrides/defaults/button.override.ts +536 -0
  104. package/templates/povio/apps/fe/src/styles/overrides/defaults/checkbox.override.ts +71 -0
  105. package/templates/povio/apps/fe/src/styles/overrides/defaults/input.override.ts +252 -0
  106. package/templates/povio/apps/fe/src/styles/overrides/defaults/label.override.ts +91 -0
  107. package/templates/povio/apps/fe/src/styles/overrides/defaults/modal.override.ts +62 -0
  108. package/templates/povio/apps/fe/src/styles/overrides/defaults/radio.override.ts +46 -0
  109. package/templates/povio/apps/fe/src/styles/overrides/defaults/table.override.ts +104 -0
  110. package/templates/povio/apps/fe/src/styles/overrides/defaults/tag.override.ts +66 -0
  111. package/templates/povio/apps/fe/src/styles/overrides/defaults/typography.override.ts +115 -0
  112. package/templates/povio/apps/fe/src/styles/overrides/outline.clsx.ts +10 -0
  113. package/templates/povio/apps/fe/src/styles/overrides/uiOverrides.override.ts +60 -0
  114. package/templates/povio/apps/fe/src/styles/theme.css +2177 -0
  115. package/templates/povio/apps/fe/src/types/i18next.d.ts +12 -0
  116. package/templates/povio/apps/fe/src/types/table.d.ts +17 -0
  117. package/templates/povio/apps/fe/src/types/ui.d.ts +26 -0
  118. package/templates/povio/apps/fe/src/types/vite-env.d.ts +13 -0
  119. package/templates/povio/apps/fe/src/utils/date.utils.ts +17 -0
  120. package/templates/povio/apps/fe/src/utils/image-fallback.ts +9 -0
  121. package/templates/povio/apps/fe/src/utils/number.utils.ts +12 -0
  122. package/templates/povio/apps/fe/src/utils/string.utils.ts +5 -0
  123. package/templates/povio/apps/fe/src/vite-env.d.ts +1 -0
  124. package/templates/povio/apps/fe/tsconfig.app.json +32 -0
  125. package/templates/povio/apps/fe/tsconfig.json +9 -0
  126. package/templates/povio/apps/fe/tsconfig.node.json +31 -0
  127. package/templates/povio/apps/fe/vite.config.ts +150 -0
  128. package/templates/povio/openapi.json +911 -0
  129. package/templates/povio/oxfmt.config.js +23 -0
  130. package/templates/povio/package.json +19 -0
  131. package/templates/povio/robodev/api/_lib.ts +99 -0
  132. package/templates/povio/robodev/api/health.ts +7 -0
  133. package/templates/povio/robodev/database.ts +28 -0
  134. package/templates/povio/robodev/package.json +4 -0
  135. package/templates/povio/rulesync.jsonc +18 -0
  136. package/templates/povio/tsconfig.json +11 -0
  137. package/templates/shadcn/.rulesync/rules/frontend-api-boundary.md +29 -0
  138. package/templates/shadcn/.rulesync/rules/frontend-component-structure.md +19 -0
  139. package/templates/shadcn/.rulesync/rules/frontend-hosted-ui.md +38 -0
  140. package/templates/shadcn/.rulesync/rules/project-overview.md +29 -0
  141. package/templates/shadcn/.rulesync/rules/robodev-api.md +22 -0
  142. package/templates/shadcn/.rulesync/rules/robodev-auth.md +47 -0
  143. package/templates/shadcn/.rulesync/rules/robodev-database.md +21 -0
  144. package/templates/shadcn/.rulesync/skills/robodev-crud-page/SKILL.md +181 -0
  145. package/templates/shadcn/README.md +9 -4
  146. package/templates/shadcn/ROBODEV.md +14 -6
  147. package/templates/shadcn/package.json +4 -6
  148. package/templates/shadcn/rulesync.jsonc +18 -0
  149. package/templates/shadcn/src/App.tsx +12 -3
  150. package/templates/shadcn/src/app.css +359 -0
  151. package/templates/shadcn/src/components/auth/AuthCard.tsx +29 -0
  152. package/templates/shadcn/src/components/ui/badge.tsx +17 -0
  153. package/templates/shadcn/src/components/ui/card.tsx +28 -0
  154. package/templates/shadcn/src/components/ui/dialog.tsx +38 -0
  155. package/templates/shadcn/src/components/ui/empty-state.tsx +17 -0
  156. package/templates/shadcn/src/components/ui/input.tsx +8 -0
  157. package/templates/shadcn/src/components/ui/label.tsx +8 -0
  158. package/templates/shadcn/src/components/ui/skeleton.tsx +6 -0
  159. package/templates/shadcn/src/components/ui/spinner.tsx +3 -0
  160. package/templates/shadcn/src/components/ui/table.tsx +30 -0
  161. package/templates/shadcn/src/components/ui/textarea.tsx +8 -0
  162. package/templates/shadcn/src/lib/auth.tsx +72 -0
  163. package/templates/shadcn/src/lib/client.ts +8 -0
  164. package/templates/shadcn/src/pages/Home.tsx +15 -0
  165. package/templates/shadcn/src/pages/Login.tsx +70 -0
  166. package/templates/shadcn/src/pages/NotFound.tsx +14 -0
  167. package/templates/shadcn/src/pages/Register.tsx +82 -0
  168. package/templates/space/ROBODEV.md +7 -1
  169. package/templates/space/package.json +2 -2
  170. package/templates/shadcn/components.json +0 -21
  171. package/templates/shadcn/postcss.config.js +0 -6
  172. package/templates/shadcn/tailwind.config.ts +0 -42
@@ -0,0 +1,12 @@
1
+ import "i18next";
2
+
3
+ import type { defaultNS, resources } from "@/config/i18n";
4
+
5
+ declare module "i18next" {
6
+ interface CustomTypeOptions {
7
+ enableSelector: true;
8
+ returnNull: false;
9
+ defaultNS: typeof defaultNS;
10
+ resources: (typeof resources)["en"];
11
+ }
12
+ }
@@ -0,0 +1,17 @@
1
+ /* oxlint-disable unused-imports/no-unused-vars */
2
+ import "@tanstack/react-table";
3
+
4
+ declare module "@tanstack/react-table" {
5
+ interface ColumnMeta<TData extends RowData, TValue> {
6
+ width?: string;
7
+ headerClass?: string;
8
+ cellClass?: string;
9
+ sortClass?: string;
10
+ }
11
+
12
+ interface CellContext<TData extends RowData, TValue> {
13
+ original: TData;
14
+ data: TData;
15
+ value: TValue;
16
+ }
17
+ }
@@ -0,0 +1,26 @@
1
+ import "@povio/ui";
2
+ import type { UIOverrides } from "@povio/ui";
3
+ import type { LinkProps } from "@tanstack/react-router";
4
+ import type { RowData } from "@tanstack/react-table";
5
+
6
+ import type { tableRowOverride } from "@/styles/overrides/defaults/table.override";
7
+ import type { typographyOverride } from "@/styles/overrides/defaults/typography.override";
8
+
9
+ declare module "@povio/ui" {
10
+ interface LinkNavigationProps extends LinkProps {}
11
+
12
+ interface TypographyVariantProps {
13
+ size?: UIOverrides.VariantProps<typeof typographyOverride>["size"];
14
+ sizeMobile?: UIOverrides.VariantProps<typeof typographyOverride>["sizeMobile"];
15
+ }
16
+
17
+ interface TableRowVariantProps {
18
+ rowSize?: UIOverrides.VariantProps<typeof tableRowOverride>["rowSize"];
19
+ }
20
+ }
21
+
22
+ declare module "@tanstack/react-table" {
23
+ interface ColumnMeta<TData extends RowData, TValue> {
24
+ filterKey?: string;
25
+ }
26
+ }
@@ -0,0 +1,13 @@
1
+ /// <reference types="vite/client" />
2
+
3
+ interface ImportMetaEnv {
4
+ readonly VITE_PUBLIC_API_URL: string;
5
+ readonly VITE_PUBLIC_API_MODE?: "fake" | "real";
6
+ readonly VITE_PUBLIC_FAKE_BE_SEED_VERSION?: string;
7
+ readonly VITE_PUBLIC_LOG_LEVEL: "error" | "warn";
8
+ readonly VITE_PUBLIC_AUTH_CUSTOM_JWT_ENABLE_MAGIC_LINK: string;
9
+ }
10
+
11
+ interface ImportMeta {
12
+ readonly env: ImportMetaEnv;
13
+ }
@@ -0,0 +1,17 @@
1
+ import { DateUtils as PovioDateUtils } from "@povio/ui";
2
+
3
+ export namespace DateUtils {
4
+ export const parseDate = (date: string | Date): Date => (typeof date === "string" ? new Date(date) : date);
5
+
6
+ export const formatDate = (date: string | Date, format = "dd/MM/yyyy") => {
7
+ const parsedDate = parseDate(date);
8
+
9
+ return PovioDateUtils.formatDate(parsedDate, format);
10
+ };
11
+
12
+ export const formatDateTime = (date: string | Date, format = "dd/MM/yyyy HH:mm") => {
13
+ const parsedDate = parseDate(date);
14
+
15
+ return PovioDateUtils.formatDate(parsedDate, format);
16
+ };
17
+ }
@@ -0,0 +1,9 @@
1
+ interface ImageFallbackOptions {
2
+ width: number;
3
+ height: number;
4
+ text?: string;
5
+ }
6
+
7
+ export function getFallbackImageUrl({ width, height, text = "No image" }: ImageFallbackOptions): string {
8
+ return `https://placehold.co/${width}x${height}?text=${encodeURIComponent(text)}`;
9
+ }
@@ -0,0 +1,12 @@
1
+ export namespace NumberUtils {
2
+ export function formatNumber(value: number, options?: Intl.NumberFormatOptions): string {
3
+ return new Intl.NumberFormat(undefined, options).format(value);
4
+ }
5
+
6
+ export function formatInteger(value: number, options?: Intl.NumberFormatOptions): string {
7
+ return formatNumber(value, {
8
+ maximumFractionDigits: 0,
9
+ ...options,
10
+ });
11
+ }
12
+ }
@@ -0,0 +1,5 @@
1
+ export namespace StringUtils {
2
+ export function emptyToUndefined(value: string | null | undefined): string | undefined {
3
+ return value || undefined;
4
+ }
5
+ }
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
@@ -0,0 +1,32 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4
+ "target": "ES2022",
5
+ "useDefineForClassFields": true,
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "module": "ESNext",
8
+ "types": ["vite/client", "node"],
9
+ "skipLibCheck": true,
10
+
11
+ /* Bundler mode */
12
+ "moduleResolution": "bundler",
13
+ "allowImportingTsExtensions": true,
14
+ "verbatimModuleSyntax": false,
15
+ "moduleDetection": "force",
16
+ "noEmit": true,
17
+ "jsx": "react-jsx",
18
+
19
+ /* Absolute imports */
20
+ "paths": {
21
+ "@/*": ["./src/*"]
22
+ },
23
+
24
+ /* Linting */
25
+ "strict": true,
26
+ "noUnusedLocals": true,
27
+ "noUnusedParameters": true,
28
+ "noFallthroughCasesInSwitch": true,
29
+ "noUncheckedSideEffectImports": true
30
+ },
31
+ "include": ["src", "node_modules/@povio/ui/dist/index.d.ts"]
32
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "files": [],
3
+ "compilerOptions": {
4
+ "paths": {
5
+ "@/*": ["./src/*"]
6
+ }
7
+ },
8
+ "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }]
9
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
+ "target": "ES2023",
5
+ "lib": ["ES2023"],
6
+ "module": "ESNext",
7
+ "types": ["node"],
8
+ "skipLibCheck": true,
9
+
10
+ /* Bundler mode */
11
+ "moduleResolution": "bundler",
12
+ "allowImportingTsExtensions": true,
13
+ "verbatimModuleSyntax": true,
14
+ "moduleDetection": "force",
15
+ "noEmit": true,
16
+
17
+ /* Absolute imports */
18
+ "paths": {
19
+ "@/*": ["./src/*"]
20
+ },
21
+
22
+ /* Linting */
23
+ "strict": true,
24
+ "noUnusedLocals": true,
25
+ "noUnusedParameters": true,
26
+ "erasableSyntaxOnly": true,
27
+ "noFallthroughCasesInSwitch": true,
28
+ "noUncheckedSideEffectImports": true
29
+ },
30
+ "include": ["vite.config.ts"]
31
+ }
@@ -0,0 +1,150 @@
1
+ import { applyEnv, resolveConfigSync, getNumber, getString } from "@povio/resolve-config";
2
+ import tailwindCSS from "@tailwindcss/vite";
3
+ import { tanstackRouter } from "@tanstack/router-plugin/vite";
4
+ import viteReact from "@vitejs/plugin-react";
5
+ import { copyFileSync, existsSync, readdirSync, readFileSync } from "node:fs";
6
+ import { join } from "node:path";
7
+ import { defineConfig as defineViteConfig, mergeConfig, type Plugin } from "vite";
8
+ import { defineConfig as defineVitestConfig } from "vitest/config";
9
+ import { reactIconsSprite } from "react-icons-sprite/vite";
10
+
11
+ /** react-icons-sprite maps Trash2 → trash2.mjs and MenuIcon → menu-icon.mjs; lucide ships trash-2.mjs / menu.mjs. */
12
+ function lucideSpriteIconAliases(): Plugin {
13
+ return {
14
+ name: "lucide-sprite-icon-aliases",
15
+ enforce: "pre",
16
+ apply: "build",
17
+ buildStart() {
18
+ const iconsDir = join(process.cwd(), "node_modules", "lucide-react", "dist", "esm", "icons");
19
+ if (!existsSync(iconsDir)) {
20
+ return;
21
+ }
22
+ for (const file of readdirSync(iconsDir)) {
23
+ if (!file.endsWith(".mjs")) {
24
+ continue;
25
+ }
26
+ const src = join(iconsDir, file);
27
+ const digit = /^(.+)-(\d+)\.mjs$/.exec(file);
28
+ if (digit) {
29
+ const dest = join(iconsDir, `${digit[1]}${digit[2]}.mjs`);
30
+ if (!existsSync(dest)) {
31
+ copyFileSync(src, dest);
32
+ }
33
+ }
34
+ if (!file.endsWith("-icon.mjs")) {
35
+ const dest = join(iconsDir, file.replace(/\.mjs$/, "-icon.mjs"));
36
+ if (!existsSync(dest)) {
37
+ copyFileSync(src, dest);
38
+ }
39
+ }
40
+ }
41
+ },
42
+ };
43
+ }
44
+
45
+ const repoRoot = new URL("../..", import.meta.url).pathname;
46
+
47
+ function readDotEnvKey(root: string, key: string): string | undefined {
48
+ try {
49
+ const content = readFileSync(join(root, ".env"), "utf8");
50
+ const line = content.split(/\r?\n/).find((row) => row.startsWith(`${key}=`));
51
+ const value = line?.slice(key.length + 1).trim();
52
+ return value || undefined;
53
+ } catch {
54
+ return undefined;
55
+ }
56
+ }
57
+
58
+ function loadResolvedSpaEnv(cwd: string): ReturnType<typeof resolveConfigSync> {
59
+ try {
60
+ const resolved = resolveConfigSync({ cwd, module: "spa", target: "resolved" });
61
+ if (resolved && typeof resolved === "object") {
62
+ return resolved;
63
+ }
64
+ } catch {
65
+ // unnamed or missing spa manifest
66
+ }
67
+ return {};
68
+ }
69
+
70
+ const env = loadResolvedSpaEnv(repoRoot);
71
+ applyEnv(env, "__");
72
+
73
+ const apiUrl =
74
+ getString(env, "VITE_PUBLIC_API_URL") ||
75
+ process.env.VITE_PUBLIC_API_URL ||
76
+ readDotEnvKey(repoRoot, "VITE_PUBLIC_API_URL") ||
77
+ "http://localhost:4000";
78
+
79
+ const isInTestMode = process.env.VITEST === "true";
80
+ const iconsSpritePlugin = reactIconsSprite();
81
+ const iconsSpriteTransform = iconsSpritePlugin.transform;
82
+
83
+ if (typeof iconsSpriteTransform === "function") {
84
+ iconsSpritePlugin.transform = function transformAppIcons(code, id, ...args) {
85
+ if (id.includes("/node_modules/")) {
86
+ return null;
87
+ }
88
+
89
+ return iconsSpriteTransform.call(this, code, id, ...args);
90
+ };
91
+ }
92
+
93
+ const createViteConfig = () => ({
94
+ plugins: [
95
+ !isInTestMode &&
96
+ tanstackRouter({
97
+ target: "react",
98
+ autoCodeSplitting: true,
99
+ routesDirectory: "./src/pages",
100
+ }),
101
+ lucideSpriteIconAliases(),
102
+ iconsSpritePlugin,
103
+ viteReact({
104
+ babel: {
105
+ plugins: ["babel-plugin-react-compiler"],
106
+ },
107
+ }),
108
+ tailwindCSS(),
109
+ ],
110
+ server: {
111
+ open: false,
112
+ port: getNumber(env, "VITE_DEV_PORT") ?? 3000,
113
+ strictPort: false,
114
+ proxy: {
115
+ "^/api(?:/|$)": {
116
+ target: apiUrl,
117
+ changeOrigin: true,
118
+ secure: false,
119
+ },
120
+ },
121
+ },
122
+ build: {
123
+ target: "esnext",
124
+ },
125
+ optimizeDeps: {
126
+ entries: ["src/**/*.{ts,tsx}"],
127
+ },
128
+ worker: {
129
+ format: "es",
130
+ },
131
+ resolve: {
132
+ alias: {
133
+ "@": new URL("src", import.meta.url).pathname,
134
+ },
135
+ dedupe: ["react", "react-dom", "i18next", "react-i18next"],
136
+ tsconfigPaths: true,
137
+ },
138
+ });
139
+
140
+ const vitestConfig = defineVitestConfig({
141
+ test: {
142
+ root: "./",
143
+ include: ["src/**/*.test.{ts,tsx}"],
144
+ watch: false,
145
+ globals: true,
146
+ reporters: ["default"],
147
+ },
148
+ });
149
+
150
+ export default defineViteConfig(() => mergeConfig(createViteConfig(), vitestConfig));