@libredb/studio 0.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (572) hide show
  1. package/.claude/settings.local.json +127 -0
  2. package/.cursorrules +426 -0
  3. package/.devin/wiki.json +143 -0
  4. package/.dockerignore +80 -0
  5. package/.env.example +159 -0
  6. package/.github/ISSUE_TEMPLATE/bug_report.md +49 -0
  7. package/.github/ISSUE_TEMPLATE/feature_request.md +29 -0
  8. package/.github/PULL_REQUEST_TEMPLATE.md +57 -0
  9. package/.github/workflows/ci.yml +185 -0
  10. package/.github/workflows/codeql.yml +57 -0
  11. package/.github/workflows/docker-build-push.yml +118 -0
  12. package/.github/workflows/helm-release.yml +113 -0
  13. package/CLAUDE.md +265 -0
  14. package/CODE_OF_CONDUCT.md +124 -0
  15. package/CONTRIBUTING.md +154 -0
  16. package/Dockerfile +73 -0
  17. package/LICENSE +21 -0
  18. package/README.md +614 -0
  19. package/SECURITY.md +107 -0
  20. package/artifacthub-repo.yml +4 -0
  21. package/bun.lock +1714 -0
  22. package/bunfig.toml +3 -0
  23. package/charts/libredb-studio/.helmignore +11 -0
  24. package/charts/libredb-studio/Chart.lock +6 -0
  25. package/charts/libredb-studio/Chart.yaml +50 -0
  26. package/charts/libredb-studio/README.md +206 -0
  27. package/charts/libredb-studio/templates/NOTES.txt +59 -0
  28. package/charts/libredb-studio/templates/_helpers.tpl +135 -0
  29. package/charts/libredb-studio/templates/configmap.yaml +37 -0
  30. package/charts/libredb-studio/templates/deployment.yaml +184 -0
  31. package/charts/libredb-studio/templates/hpa.yaml +32 -0
  32. package/charts/libredb-studio/templates/ingress.yaml +41 -0
  33. package/charts/libredb-studio/templates/networkpolicy.yaml +50 -0
  34. package/charts/libredb-studio/templates/pdb.yaml +18 -0
  35. package/charts/libredb-studio/templates/pvc.yaml +23 -0
  36. package/charts/libredb-studio/templates/secret.yaml +30 -0
  37. package/charts/libredb-studio/templates/seed-configmap.yaml +11 -0
  38. package/charts/libredb-studio/templates/service.yaml +22 -0
  39. package/charts/libredb-studio/templates/serviceaccount.yaml +13 -0
  40. package/charts/libredb-studio/values.schema.json +246 -0
  41. package/charts/libredb-studio/values.yaml +286 -0
  42. package/components.json +22 -0
  43. package/conductor/code_styleguides/typescript.md +43 -0
  44. package/conductor/product-guidelines.md +43 -0
  45. package/conductor/product.md +3 -0
  46. package/conductor/setup_state.json +1 -0
  47. package/conductor/tech-stack.md +39 -0
  48. package/conductor/tracks/enhance_postgres_monitoring_20251227/metadata.json +8 -0
  49. package/conductor/tracks/enhance_postgres_monitoring_20251227/plan.md +44 -0
  50. package/conductor/tracks/enhance_postgres_monitoring_20251227/spec.md +31 -0
  51. package/conductor/tracks.md +8 -0
  52. package/conductor/workflow.md +333 -0
  53. package/database-compose.yml +55 -0
  54. package/docker/postgres-init/01-extensions.sql +10 -0
  55. package/docker/postgres-init/02-sample-data.sql +585 -0
  56. package/docker/postgres.yml +68 -0
  57. package/docker-compose.yml +38 -0
  58. package/docs/AI_PLAN.md +74 -0
  59. package/docs/API_DOCS.md +875 -0
  60. package/docs/ARCHITECTURE.md +218 -0
  61. package/docs/DATABASE_PROVIDERS.md +358 -0
  62. package/docs/FEATURES.md +116 -0
  63. package/docs/HELM_CHART.md +252 -0
  64. package/docs/LOGIN_PAGE.md +178 -0
  65. package/docs/MONACO_EDITOR_PERFORMANCE.md +315 -0
  66. package/docs/OIDC_ARCH.md +681 -0
  67. package/docs/OIDC_SETUP.md +322 -0
  68. package/docs/POSTGRES_METRICS.md +516 -0
  69. package/docs/QUERY_OPTIMIZATION.md +370 -0
  70. package/docs/SEED_CONNECTIONS.md +468 -0
  71. package/docs/SQL_ALIAS_COMPLETION.md +190 -0
  72. package/docs/STORAGE_ARCHITECTURE.md +565 -0
  73. package/docs/STORAGE_QUICK_SETUP.md +419 -0
  74. package/docs/TECHNICAL_PLAN.md +36 -0
  75. package/docs/THEMING.md +345 -0
  76. package/docs/adding-a-new-database-provider.md +642 -0
  77. package/docs/backlogs/000-PLATFORM_DATA_SYNC_DATABASE.md +360 -0
  78. package/docs/backlogs/001-INLINE_DATA_EDITING.md +118 -0
  79. package/docs/backlogs/002-DATA_IMPORT.md +215 -0
  80. package/docs/backlogs/003-QUERY_TIME_MACHINE.md +183 -0
  81. package/docs/backlogs/004-AI_DATA_STORYTELLER.md +292 -0
  82. package/docs/backlogs/005-QUERY_PLAYGROUND.md +352 -0
  83. package/docs/backlogs/006-DATA_MASKING.md +418 -0
  84. package/docs/enterprise-features.md +718 -0
  85. package/docs/kubernetes-helm-chart-artifacthub-plan.md +803 -0
  86. package/docs/medium-koyeb-article-en.md +215 -0
  87. package/docs/plans/test-plans.md +445 -0
  88. package/docs/releases/RELEASE.V0.3.0.md +22 -0
  89. package/docs/releases/RELEASE.V0.4.0.md +154 -0
  90. package/docs/releases/RELEASE.V0.5.0.md +252 -0
  91. package/docs/releases/RELEASE_v0.5.6.md +145 -0
  92. package/docs/releases/RELEASE_v0.6.1.md +303 -0
  93. package/docs/releases/RELEASE_v0.6.7.md +292 -0
  94. package/docs/releases/RELEASE_v0.7.0.md +332 -0
  95. package/docs/releases/RELEASE_v0.8.0.md +521 -0
  96. package/docs/sampledb/titanic.sql +1379 -0
  97. package/docs/superpowers/plans/2026-03-25-seed-connections.md +1362 -0
  98. package/docs/superpowers/specs/2026-03-25-seed-connections-design.md +590 -0
  99. package/e2e/admin-dashboard.spec.ts +64 -0
  100. package/e2e/connection-management.spec.ts +58 -0
  101. package/e2e/export.spec.ts +34 -0
  102. package/e2e/login.spec.ts +85 -0
  103. package/e2e/query-execution.spec.ts +35 -0
  104. package/e2e/tab-management.spec.ts +64 -0
  105. package/eslint.config.mjs +28 -0
  106. package/fly.toml +43 -0
  107. package/next.config.ts +32 -0
  108. package/package.json +130 -0
  109. package/playwright.config.ts +34 -0
  110. package/postcss.config.mjs +7 -0
  111. package/public/favicon-32x32.png +0 -0
  112. package/public/favicon.ico +0 -0
  113. package/public/file.svg +1 -0
  114. package/public/globe.svg +1 -0
  115. package/public/logo.svg +32 -0
  116. package/public/next.svg +1 -0
  117. package/public/screenshots/code-generator.png +0 -0
  118. package/public/screenshots/connection-modal.png +0 -0
  119. package/public/screenshots/data-profiler.png +0 -0
  120. package/public/screenshots/erd-diagram.png +0 -0
  121. package/public/screenshots/hero-editor.png +0 -0
  122. package/public/screenshots/nl2sql.png +0 -0
  123. package/public/vercel.svg +1 -0
  124. package/public/window.svg +1 -0
  125. package/render.yaml +58 -0
  126. package/scripts/merge-lcov.mjs +239 -0
  127. package/sonar-project.properties +16 -0
  128. package/src/app/admin/error.tsx +46 -0
  129. package/src/app/admin/page.tsx +10 -0
  130. package/src/app/api/admin/audit/route.ts +52 -0
  131. package/src/app/api/admin/fleet-health/route.ts +81 -0
  132. package/src/app/api/ai/autopilot/route.ts +105 -0
  133. package/src/app/api/ai/chat/route.ts +132 -0
  134. package/src/app/api/ai/describe-schema/route.ts +52 -0
  135. package/src/app/api/ai/explain/route.ts +86 -0
  136. package/src/app/api/ai/impact/route.ts +97 -0
  137. package/src/app/api/ai/index-advisor/route.ts +98 -0
  138. package/src/app/api/ai/nl2sql/route.ts +87 -0
  139. package/src/app/api/ai/query-safety/route.ts +87 -0
  140. package/src/app/api/auth/login/route.ts +62 -0
  141. package/src/app/api/auth/logout/route.ts +25 -0
  142. package/src/app/api/auth/me/route.ts +10 -0
  143. package/src/app/api/auth/oidc/callback/route.ts +82 -0
  144. package/src/app/api/auth/oidc/login/route.ts +43 -0
  145. package/src/app/api/connections/managed/route.ts +35 -0
  146. package/src/app/api/db/cancel/route.ts +42 -0
  147. package/src/app/api/db/disconnect/route.ts +28 -0
  148. package/src/app/api/db/health/route.ts +49 -0
  149. package/src/app/api/db/maintenance/route.ts +72 -0
  150. package/src/app/api/db/monitoring/route.ts +62 -0
  151. package/src/app/api/db/multi-query/route.ts +116 -0
  152. package/src/app/api/db/pool-stats/route.ts +37 -0
  153. package/src/app/api/db/profile/route.ts +144 -0
  154. package/src/app/api/db/provider-meta/route.ts +49 -0
  155. package/src/app/api/db/query/route.ts +50 -0
  156. package/src/app/api/db/schema/route.ts +47 -0
  157. package/src/app/api/db/schema-snapshot/route.ts +42 -0
  158. package/src/app/api/db/test-connection/route.ts +55 -0
  159. package/src/app/api/db/transaction/route.ts +111 -0
  160. package/src/app/api/storage/[collection]/route.ts +67 -0
  161. package/src/app/api/storage/config/route.ts +17 -0
  162. package/src/app/api/storage/migrate/route.ts +45 -0
  163. package/src/app/api/storage/route.ts +32 -0
  164. package/src/app/error.tsx +49 -0
  165. package/src/app/global-error.tsx +55 -0
  166. package/src/app/globals.css +146 -0
  167. package/src/app/icon.svg +42 -0
  168. package/src/app/layout.tsx +34 -0
  169. package/src/app/login/login-form.tsx +301 -0
  170. package/src/app/login/page.tsx +11 -0
  171. package/src/app/monitoring/page.tsx +8 -0
  172. package/src/app/not-found.tsx +29 -0
  173. package/src/app/page.tsx +5 -0
  174. package/src/components/AIAutopilotPanel.tsx +238 -0
  175. package/src/components/CodeGenerator.tsx +271 -0
  176. package/src/components/CommandPalette.tsx +227 -0
  177. package/src/components/ConnectionModal.tsx +759 -0
  178. package/src/components/CreateTableModal.tsx +281 -0
  179. package/src/components/DataCharts.tsx +962 -0
  180. package/src/components/DataImportModal.tsx +582 -0
  181. package/src/components/DataProfiler.tsx +335 -0
  182. package/src/components/DatabaseDocs.tsx +251 -0
  183. package/src/components/MaskingSettings.tsx +414 -0
  184. package/src/components/MobileNav.tsx +50 -0
  185. package/src/components/NL2SQLPanel.tsx +281 -0
  186. package/src/components/PivotTable.tsx +257 -0
  187. package/src/components/QueryEditor.tsx +760 -0
  188. package/src/components/QueryHistory.tsx +344 -0
  189. package/src/components/QuerySafetyDialog.tsx +290 -0
  190. package/src/components/ResultsGrid.tsx +644 -0
  191. package/src/components/SaveQueryModal.tsx +104 -0
  192. package/src/components/SavedQueries.tsx +128 -0
  193. package/src/components/SchemaDiagram.tsx +473 -0
  194. package/src/components/SchemaDiff.tsx +473 -0
  195. package/src/components/SnapshotTimeline.tsx +116 -0
  196. package/src/components/Studio.tsx +639 -0
  197. package/src/components/TestDataGenerator.tsx +261 -0
  198. package/src/components/VisualExplain.tsx +820 -0
  199. package/src/components/admin/AdminDashboard.tsx +163 -0
  200. package/src/components/admin/tabs/AuditTab.tsx +531 -0
  201. package/src/components/admin/tabs/MonitoringEmbed.tsx +11 -0
  202. package/src/components/admin/tabs/OperationsTab.tsx +646 -0
  203. package/src/components/admin/tabs/OverviewTab.tsx +1328 -0
  204. package/src/components/admin/tabs/SecurityTab.tsx +284 -0
  205. package/src/components/community-section.tsx +92 -0
  206. package/src/components/icons/db-icons.tsx +84 -0
  207. package/src/components/libredb-logo.tsx +61 -0
  208. package/src/components/monitoring/MonitoringDashboard.tsx +345 -0
  209. package/src/components/monitoring/tabs/MetricChart.tsx +82 -0
  210. package/src/components/monitoring/tabs/OverviewTab.tsx +263 -0
  211. package/src/components/monitoring/tabs/PerformanceTab.tsx +254 -0
  212. package/src/components/monitoring/tabs/PoolTab.tsx +174 -0
  213. package/src/components/monitoring/tabs/QueriesTab.tsx +287 -0
  214. package/src/components/monitoring/tabs/SessionsTab.tsx +316 -0
  215. package/src/components/monitoring/tabs/StorageTab.tsx +335 -0
  216. package/src/components/monitoring/tabs/TablesTab.tsx +300 -0
  217. package/src/components/results-grid/ResultCard.tsx +111 -0
  218. package/src/components/results-grid/RowDetailSheet.tsx +178 -0
  219. package/src/components/results-grid/StatsBar.tsx +201 -0
  220. package/src/components/results-grid/index.ts +1 -0
  221. package/src/components/results-grid/utils.ts +23 -0
  222. package/src/components/schema-explorer/ColumnList.tsx +53 -0
  223. package/src/components/schema-explorer/SchemaExplorer.tsx +182 -0
  224. package/src/components/schema-explorer/TableItem.tsx +210 -0
  225. package/src/components/schema-explorer/index.ts +1 -0
  226. package/src/components/sidebar/ConnectionItem.tsx +105 -0
  227. package/src/components/sidebar/ConnectionsList.tsx +62 -0
  228. package/src/components/sidebar/Sidebar.tsx +130 -0
  229. package/src/components/sidebar/index.ts +2 -0
  230. package/src/components/studio/BottomPanel.tsx +286 -0
  231. package/src/components/studio/QueryToolbar.tsx +180 -0
  232. package/src/components/studio/StudioDesktopHeader.tsx +114 -0
  233. package/src/components/studio/StudioMobileHeader.tsx +340 -0
  234. package/src/components/studio/StudioTabBar.tsx +82 -0
  235. package/src/components/studio/index.ts +5 -0
  236. package/src/components/ui/accordion.tsx +66 -0
  237. package/src/components/ui/alert-dialog.tsx +157 -0
  238. package/src/components/ui/alert.tsx +66 -0
  239. package/src/components/ui/aspect-ratio.tsx +11 -0
  240. package/src/components/ui/avatar.tsx +53 -0
  241. package/src/components/ui/badge.tsx +46 -0
  242. package/src/components/ui/breadcrumb.tsx +109 -0
  243. package/src/components/ui/button-group.tsx +83 -0
  244. package/src/components/ui/button.tsx +60 -0
  245. package/src/components/ui/calendar.tsx +216 -0
  246. package/src/components/ui/card.tsx +92 -0
  247. package/src/components/ui/carousel.tsx +241 -0
  248. package/src/components/ui/chart.tsx +357 -0
  249. package/src/components/ui/checkbox.tsx +32 -0
  250. package/src/components/ui/collapsible.tsx +33 -0
  251. package/src/components/ui/command.tsx +184 -0
  252. package/src/components/ui/context-menu.tsx +252 -0
  253. package/src/components/ui/dialog.tsx +143 -0
  254. package/src/components/ui/drawer.tsx +135 -0
  255. package/src/components/ui/dropdown-menu.tsx +257 -0
  256. package/src/components/ui/empty.tsx +104 -0
  257. package/src/components/ui/field.tsx +248 -0
  258. package/src/components/ui/form.tsx +167 -0
  259. package/src/components/ui/hover-card.tsx +44 -0
  260. package/src/components/ui/input-group.tsx +170 -0
  261. package/src/components/ui/input-otp.tsx +77 -0
  262. package/src/components/ui/input.tsx +21 -0
  263. package/src/components/ui/item.tsx +193 -0
  264. package/src/components/ui/kbd.tsx +28 -0
  265. package/src/components/ui/label.tsx +24 -0
  266. package/src/components/ui/menubar.tsx +276 -0
  267. package/src/components/ui/navigation-menu.tsx +168 -0
  268. package/src/components/ui/pagination.tsx +127 -0
  269. package/src/components/ui/popover.tsx +48 -0
  270. package/src/components/ui/progress.tsx +31 -0
  271. package/src/components/ui/radio-group.tsx +45 -0
  272. package/src/components/ui/resizable.tsx +56 -0
  273. package/src/components/ui/scroll-area.tsx +58 -0
  274. package/src/components/ui/select.tsx +187 -0
  275. package/src/components/ui/separator.tsx +28 -0
  276. package/src/components/ui/sheet.tsx +139 -0
  277. package/src/components/ui/sidebar.tsx +726 -0
  278. package/src/components/ui/skeleton.tsx +13 -0
  279. package/src/components/ui/slider.tsx +63 -0
  280. package/src/components/ui/sonner.tsx +40 -0
  281. package/src/components/ui/spinner.tsx +16 -0
  282. package/src/components/ui/switch.tsx +31 -0
  283. package/src/components/ui/table.tsx +116 -0
  284. package/src/components/ui/tabs.tsx +66 -0
  285. package/src/components/ui/textarea.tsx +18 -0
  286. package/src/components/ui/toggle-group.tsx +83 -0
  287. package/src/components/ui/toggle.tsx +47 -0
  288. package/src/components/ui/tooltip.tsx +61 -0
  289. package/src/exports/components.ts +15 -0
  290. package/src/exports/index.ts +4 -0
  291. package/src/exports/providers.ts +4 -0
  292. package/src/exports/types.ts +26 -0
  293. package/src/hooks/use-ai-chat.ts +182 -0
  294. package/src/hooks/use-all-connections.ts +66 -0
  295. package/src/hooks/use-api-call.ts +71 -0
  296. package/src/hooks/use-auth.ts +51 -0
  297. package/src/hooks/use-connection-form.ts +349 -0
  298. package/src/hooks/use-connection-manager.ts +169 -0
  299. package/src/hooks/use-connection-payload.ts +15 -0
  300. package/src/hooks/use-inline-editing.ts +109 -0
  301. package/src/hooks/use-mobile.ts +20 -0
  302. package/src/hooks/use-monitoring-data.ts +270 -0
  303. package/src/hooks/use-provider-metadata.ts +62 -0
  304. package/src/hooks/use-query-execution.ts +478 -0
  305. package/src/hooks/use-storage-sync.ts +259 -0
  306. package/src/hooks/use-tab-manager.ts +231 -0
  307. package/src/hooks/use-toast.ts +20 -0
  308. package/src/hooks/use-transaction-control.ts +64 -0
  309. package/src/lib/api/error-codes.ts +30 -0
  310. package/src/lib/api/errors.ts +236 -0
  311. package/src/lib/api/with-error-handler.ts +41 -0
  312. package/src/lib/audit.ts +105 -0
  313. package/src/lib/auth.ts +87 -0
  314. package/src/lib/connection-string-parser.ts +172 -0
  315. package/src/lib/data-masking.ts +385 -0
  316. package/src/lib/db/base-provider.ts +325 -0
  317. package/src/lib/db/errors.ts +317 -0
  318. package/src/lib/db/factory.ts +324 -0
  319. package/src/lib/db/index.ts +123 -0
  320. package/src/lib/db/providers/document/index.ts +6 -0
  321. package/src/lib/db/providers/document/mongodb.ts +992 -0
  322. package/src/lib/db/providers/keyvalue/redis.ts +554 -0
  323. package/src/lib/db/providers/sql/index.ts +11 -0
  324. package/src/lib/db/providers/sql/mssql.ts +1065 -0
  325. package/src/lib/db/providers/sql/mysql.ts +978 -0
  326. package/src/lib/db/providers/sql/oracle.ts +1044 -0
  327. package/src/lib/db/providers/sql/postgres.ts +1179 -0
  328. package/src/lib/db/providers/sql/sql-base.ts +174 -0
  329. package/src/lib/db/providers/sql/sqlite.ts +721 -0
  330. package/src/lib/db/types.ts +437 -0
  331. package/src/lib/db/utils/pool-manager.ts +287 -0
  332. package/src/lib/db/utils/query-limiter.ts +239 -0
  333. package/src/lib/db-ui-config.ts +86 -0
  334. package/src/lib/editor/mongodb-completions.ts +172 -0
  335. package/src/lib/editor/sql-completions.ts +280 -0
  336. package/src/lib/llm/base-provider.ts +117 -0
  337. package/src/lib/llm/factory.ts +102 -0
  338. package/src/lib/llm/index.ts +90 -0
  339. package/src/lib/llm/providers/custom.ts +181 -0
  340. package/src/lib/llm/providers/gemini.ts +126 -0
  341. package/src/lib/llm/providers/ollama.ts +154 -0
  342. package/src/lib/llm/providers/openai.ts +146 -0
  343. package/src/lib/llm/types.ts +173 -0
  344. package/src/lib/llm/utils/config.ts +187 -0
  345. package/src/lib/llm/utils/retry.ts +119 -0
  346. package/src/lib/llm/utils/streaming.ts +202 -0
  347. package/src/lib/logger.ts +127 -0
  348. package/src/lib/monitoring-thresholds.ts +44 -0
  349. package/src/lib/oidc.ts +262 -0
  350. package/src/lib/query-generators.ts +61 -0
  351. package/src/lib/schema-diff/diff-engine.ts +273 -0
  352. package/src/lib/schema-diff/migration-generator.ts +208 -0
  353. package/src/lib/schema-diff/types.ts +55 -0
  354. package/src/lib/seed/config-loader.ts +79 -0
  355. package/src/lib/seed/connection-filter.ts +49 -0
  356. package/src/lib/seed/credential-resolver.ts +62 -0
  357. package/src/lib/seed/index.ts +40 -0
  358. package/src/lib/seed/resolve-connection.ts +57 -0
  359. package/src/lib/seed/types.ts +69 -0
  360. package/src/lib/sql/alias-extractor.ts +267 -0
  361. package/src/lib/sql/index.ts +8 -0
  362. package/src/lib/sql/statement-splitter.ts +167 -0
  363. package/src/lib/sql/types.ts +40 -0
  364. package/src/lib/ssh/tunnel.ts +142 -0
  365. package/src/lib/storage/factory.ts +84 -0
  366. package/src/lib/storage/index.ts +14 -0
  367. package/src/lib/storage/local-storage.ts +99 -0
  368. package/src/lib/storage/providers/postgres.ts +225 -0
  369. package/src/lib/storage/providers/sqlite.ts +153 -0
  370. package/src/lib/storage/storage-facade.ts +272 -0
  371. package/src/lib/storage/types.ts +75 -0
  372. package/src/lib/time-series-buffer.ts +58 -0
  373. package/src/lib/types.ts +173 -0
  374. package/src/lib/utils.ts +6 -0
  375. package/src/proxy.ts +104 -0
  376. package/src/types/db-drivers.d.ts +23 -0
  377. package/src/types/html2canvas.d.ts +9 -0
  378. package/tests/api/admin/audit.test.ts +178 -0
  379. package/tests/api/admin/fleet-health.test.ts +183 -0
  380. package/tests/api/ai/autopilot.test.ts +174 -0
  381. package/tests/api/ai/chat.test.ts +250 -0
  382. package/tests/api/ai/describe-schema.test.ts +266 -0
  383. package/tests/api/ai/explain.test.ts +199 -0
  384. package/tests/api/ai/impact.test.ts +168 -0
  385. package/tests/api/ai/index-advisor.test.ts +171 -0
  386. package/tests/api/ai/nl2sql.test.ts +202 -0
  387. package/tests/api/ai/query-safety.test.ts +196 -0
  388. package/tests/api/auth/login.test.ts +170 -0
  389. package/tests/api/auth/logout.test.ts +140 -0
  390. package/tests/api/auth/me.test.ts +73 -0
  391. package/tests/api/auth/oidc-callback.test.ts +215 -0
  392. package/tests/api/auth/oidc-login.test.ts +127 -0
  393. package/tests/api/db/cancel.test.ts +198 -0
  394. package/tests/api/db/disconnect.test.ts +124 -0
  395. package/tests/api/db/health.test.ts +222 -0
  396. package/tests/api/db/maintenance.test.ts +263 -0
  397. package/tests/api/db/monitoring.test.ts +221 -0
  398. package/tests/api/db/multi-query.test.ts +316 -0
  399. package/tests/api/db/pool-stats.test.ts +135 -0
  400. package/tests/api/db/profile.test.ts +330 -0
  401. package/tests/api/db/provider-meta.test.ts +193 -0
  402. package/tests/api/db/query.test.ts +314 -0
  403. package/tests/api/db/schema-snapshot.test.ts +170 -0
  404. package/tests/api/db/schema.test.ts +191 -0
  405. package/tests/api/db/test-connection.test.ts +185 -0
  406. package/tests/api/db/transaction.test.ts +314 -0
  407. package/tests/api/proxy.test.ts +191 -0
  408. package/tests/api/seed/managed-route.test.ts +113 -0
  409. package/tests/api/storage/config.test.ts +42 -0
  410. package/tests/api/storage/storage-routes.test.ts +309 -0
  411. package/tests/components/AIAutopilotPanel.test.tsx +756 -0
  412. package/tests/components/AdminPage.test.tsx +33 -0
  413. package/tests/components/CodeGenerator.test.tsx +182 -0
  414. package/tests/components/CommandPalette.test.tsx +428 -0
  415. package/tests/components/CommunitySection.test.tsx +91 -0
  416. package/tests/components/ConnectionModal.mobile.test.tsx +284 -0
  417. package/tests/components/ConnectionModal.test.tsx +570 -0
  418. package/tests/components/CreateTableModal.test.tsx +383 -0
  419. package/tests/components/DataCharts.test.tsx +739 -0
  420. package/tests/components/DataImportModal.test.tsx +751 -0
  421. package/tests/components/DataProfiler.test.tsx +589 -0
  422. package/tests/components/DatabaseDocs.test.tsx +353 -0
  423. package/tests/components/LoginPage.test.tsx +163 -0
  424. package/tests/components/LoginPageOIDC.test.tsx +92 -0
  425. package/tests/components/MaskingSettings.test.tsx +498 -0
  426. package/tests/components/MobileNav.test.tsx +30 -0
  427. package/tests/components/MonitoringPage.test.tsx +32 -0
  428. package/tests/components/NL2SQLPanel.test.tsx +621 -0
  429. package/tests/components/Page.test.tsx +33 -0
  430. package/tests/components/PivotTable.test.tsx +350 -0
  431. package/tests/components/QueryEditor.test.tsx +1730 -0
  432. package/tests/components/QueryHistory.test.tsx +572 -0
  433. package/tests/components/QuerySafetyDialog.test.tsx +586 -0
  434. package/tests/components/ResultsGrid.test.tsx +804 -0
  435. package/tests/components/RootLayout.test.tsx +83 -0
  436. package/tests/components/SaveQueryModal.test.tsx +25 -0
  437. package/tests/components/SavedQueries.test.tsx +43 -0
  438. package/tests/components/SchemaDiagram.test.tsx +1034 -0
  439. package/tests/components/SchemaDiff.test.tsx +906 -0
  440. package/tests/components/SnapshotTimeline.test.tsx +174 -0
  441. package/tests/components/Studio.test.tsx +1030 -0
  442. package/tests/components/TestDataGenerator.test.tsx +291 -0
  443. package/tests/components/VisualExplain.test.tsx +704 -0
  444. package/tests/components/admin/AdminDashboard.test.tsx +205 -0
  445. package/tests/components/admin/AuditTab.test.tsx +220 -0
  446. package/tests/components/admin/MonitoringEmbed.test.tsx +58 -0
  447. package/tests/components/admin/OperationsTab.test.tsx +975 -0
  448. package/tests/components/admin/OverviewTab.test.tsx +254 -0
  449. package/tests/components/admin/SecurityTab.test.tsx +467 -0
  450. package/tests/components/monitoring/MetricChart.test.tsx +111 -0
  451. package/tests/components/monitoring/MonitoringDashboard.test.tsx +259 -0
  452. package/tests/components/monitoring/OverviewTab.test.tsx +78 -0
  453. package/tests/components/monitoring/PerformanceTab.test.tsx +87 -0
  454. package/tests/components/monitoring/PoolTab.test.tsx +42 -0
  455. package/tests/components/monitoring/QueriesTab.test.tsx +80 -0
  456. package/tests/components/monitoring/SessionsTab.test.tsx +154 -0
  457. package/tests/components/monitoring/StorageTab.test.tsx +127 -0
  458. package/tests/components/monitoring/TablesTab.test.tsx +153 -0
  459. package/tests/components/results-grid/ResultCard.test.tsx +105 -0
  460. package/tests/components/results-grid/RowDetailSheet.test.tsx +308 -0
  461. package/tests/components/results-grid/StatsBar.test.tsx +162 -0
  462. package/tests/components/schema-explorer/ColumnList.test.tsx +151 -0
  463. package/tests/components/schema-explorer/SchemaExplorer.test.tsx +461 -0
  464. package/tests/components/schema-explorer/TableItem.test.tsx +415 -0
  465. package/tests/components/sidebar/ConnectionItem.test.tsx +201 -0
  466. package/tests/components/sidebar/ConnectionsList.test.tsx +176 -0
  467. package/tests/components/sidebar/Sidebar.test.tsx +187 -0
  468. package/tests/components/studio/BottomPanel.test.tsx +383 -0
  469. package/tests/components/studio/QueryToolbar.test.tsx +321 -0
  470. package/tests/components/studio/StudioDesktopHeader.test.tsx +377 -0
  471. package/tests/components/studio/StudioMobileHeader.test.tsx +198 -0
  472. package/tests/components/studio/StudioTabBar.test.tsx +331 -0
  473. package/tests/fixtures/connections.ts +96 -0
  474. package/tests/fixtures/masking-configs.ts +86 -0
  475. package/tests/fixtures/query-results.ts +71 -0
  476. package/tests/fixtures/schemas.ts +64 -0
  477. package/tests/fixtures/seed-connections/invalid-config.yaml +7 -0
  478. package/tests/fixtures/seed-connections/minimal-config.yaml +8 -0
  479. package/tests/fixtures/seed-connections/mixed-credentials.yaml +23 -0
  480. package/tests/fixtures/seed-connections/multi-role-config.yaml +30 -0
  481. package/tests/fixtures/seed-connections/valid-config.json +15 -0
  482. package/tests/fixtures/seed-connections/valid-config.yaml +51 -0
  483. package/tests/helpers/mock-fetch.ts +59 -0
  484. package/tests/helpers/mock-monaco.ts +112 -0
  485. package/tests/helpers/mock-navigation.ts +28 -0
  486. package/tests/helpers/mock-next.ts +80 -0
  487. package/tests/helpers/mock-provider.ts +133 -0
  488. package/tests/helpers/mock-sonner.ts +29 -0
  489. package/tests/helpers/render-with-providers.tsx +19 -0
  490. package/tests/hooks/use-ai-chat.test.ts +600 -0
  491. package/tests/hooks/use-auth.test.ts +371 -0
  492. package/tests/hooks/use-connection-form.test.ts +743 -0
  493. package/tests/hooks/use-connection-manager.test.ts +466 -0
  494. package/tests/hooks/use-inline-editing.test.ts +321 -0
  495. package/tests/hooks/use-mobile.test.ts +177 -0
  496. package/tests/hooks/use-monitoring-data.test.ts +819 -0
  497. package/tests/hooks/use-provider-metadata.test.ts +228 -0
  498. package/tests/hooks/use-query-execution.test.ts +1212 -0
  499. package/tests/hooks/use-tab-manager.test.ts +756 -0
  500. package/tests/hooks/use-toast.test.ts +74 -0
  501. package/tests/hooks/use-transaction-control.test.ts +211 -0
  502. package/tests/integration/db/mongodb-provider.test.ts +698 -0
  503. package/tests/integration/db/mssql-provider.test.ts +840 -0
  504. package/tests/integration/db/mysql-provider.test.ts +872 -0
  505. package/tests/integration/db/oracle-provider.test.ts +843 -0
  506. package/tests/integration/db/postgres-provider.test.ts +1382 -0
  507. package/tests/integration/db/redis-provider.test.ts +526 -0
  508. package/tests/integration/db/sqlite-provider.test.ts +480 -0
  509. package/tests/integration/seed/seed-pipeline.test.ts +102 -0
  510. package/tests/isolated/factory-singleton.test.ts +150 -0
  511. package/tests/isolated/use-storage-sync.test.ts +389 -0
  512. package/tests/run-components.sh +196 -0
  513. package/tests/setup-dom.ts +58 -0
  514. package/tests/setup.ts +40 -0
  515. package/tests/unit/api-errors.test.ts +210 -0
  516. package/tests/unit/code-generator-functions.test.ts +271 -0
  517. package/tests/unit/components/column-list.test.tsx +190 -0
  518. package/tests/unit/components/data-import-modal.test.tsx +441 -0
  519. package/tests/unit/components/studio-mobile-header.test.tsx +327 -0
  520. package/tests/unit/data-charts-functions.test.ts +496 -0
  521. package/tests/unit/data-import-functions.test.ts +320 -0
  522. package/tests/unit/data-import-utils.test.ts +125 -0
  523. package/tests/unit/db/base-provider.test.ts +517 -0
  524. package/tests/unit/db/errors.test.ts +403 -0
  525. package/tests/unit/db/factory.test.ts +436 -0
  526. package/tests/unit/db/pool-manager.test.ts +440 -0
  527. package/tests/unit/db/query-limiter.test.ts +387 -0
  528. package/tests/unit/db/sql-base.test.ts +438 -0
  529. package/tests/unit/lib/api/error-codes.test.ts +39 -0
  530. package/tests/unit/lib/audit.test.ts +326 -0
  531. package/tests/unit/lib/auth.test.ts +146 -0
  532. package/tests/unit/lib/connection-string-parser.test.ts +424 -0
  533. package/tests/unit/lib/data-masking.test.ts +583 -0
  534. package/tests/unit/lib/db-icons.test.tsx +41 -0
  535. package/tests/unit/lib/monitoring-thresholds.test.ts +133 -0
  536. package/tests/unit/lib/oidc.test.ts +509 -0
  537. package/tests/unit/lib/query-generators.test.ts +127 -0
  538. package/tests/unit/lib/storage/factory.test.ts +71 -0
  539. package/tests/unit/lib/storage/local-storage.test.ts +114 -0
  540. package/tests/unit/lib/storage/providers/postgres.test.ts +312 -0
  541. package/tests/unit/lib/storage/providers/sqlite.test.ts +232 -0
  542. package/tests/unit/lib/storage/storage-facade-extended.test.ts +331 -0
  543. package/tests/unit/lib/storage/storage-facade.test.ts +184 -0
  544. package/tests/unit/lib/storage.test.ts +317 -0
  545. package/tests/unit/lib/time-series-buffer.test.ts +212 -0
  546. package/tests/unit/lib/utils.test.ts +24 -0
  547. package/tests/unit/llm/base-provider.test.ts +238 -0
  548. package/tests/unit/llm/config.test.ts +262 -0
  549. package/tests/unit/llm/custom-provider.test.ts +281 -0
  550. package/tests/unit/llm/gemini-provider.test.ts +248 -0
  551. package/tests/unit/llm/llm-factory.test.ts +155 -0
  552. package/tests/unit/llm/ollama-provider.test.ts +288 -0
  553. package/tests/unit/llm/openai-provider.test.ts +324 -0
  554. package/tests/unit/llm/retry.test.ts +180 -0
  555. package/tests/unit/llm/streaming.test.ts +355 -0
  556. package/tests/unit/logger.test.ts +198 -0
  557. package/tests/unit/mongodb-completions.test.ts +516 -0
  558. package/tests/unit/pivot-table-functions.test.ts +76 -0
  559. package/tests/unit/query-cancelled-error.test.ts +81 -0
  560. package/tests/unit/schema-diff/diff-engine.test.ts +367 -0
  561. package/tests/unit/schema-diff/migration-generator.test.ts +513 -0
  562. package/tests/unit/seed/config-loader.test.ts +73 -0
  563. package/tests/unit/seed/connection-filter.test.ts +91 -0
  564. package/tests/unit/seed/credential-resolver.test.ts +85 -0
  565. package/tests/unit/seed/index.test.ts +72 -0
  566. package/tests/unit/seed/resolve-connection.test.ts +74 -0
  567. package/tests/unit/seed/types.test.ts +129 -0
  568. package/tests/unit/sql/alias-extractor.test.ts +444 -0
  569. package/tests/unit/sql/statement-splitter.test.ts +348 -0
  570. package/tests/unit/sql-completions.test.ts +463 -0
  571. package/tests/unit/ssh-tunnel.test.ts +465 -0
  572. package/tsconfig.json +42 -0
@@ -0,0 +1,215 @@
1
+ # Zero-Cost SaaS: How I Deployed My Project with Koyeb.com
2
+
3
+ *A side-project developer's serverless discovery journey*
4
+
5
+ **Tags:** #SaaS #CloudComputing #Koyeb #Startup #WebDevelopment #FreeTier #Serverless
6
+
7
+ ---
8
+
9
+ ## I Had an Idea and Was Looking for the Right Tool
10
+
11
+ Every developer has that moment: the idea is ready, the code is ready, everything works perfectly on localhost. Then the question comes — "Where do I deploy this?"
12
+
13
+ Sound familiar?
14
+
15
+ I've been actively using platforms like AWS, Azure, GCP, DigitalOcean, Heroku, Render, Railway, and Fly.io for years, and I continue to use many of them. Each has its strengths — AWS's flexibility, Azure's enterprise integrations, DigitalOcean's simplicity, Fly.io's edge computing approach... I love these platforms and run most of my projects on them.
16
+
17
+ But this time I had a different need. For a SaaS application I was building as a side project, I was looking for a **free web service and database**, **quick setup**, and a **clean interface**. Something that didn't require heavy configuration, had no complex billing model, and could go live in minutes.
18
+
19
+ That's when I came across Koyeb. I created an account, connected my GitHub repo, and within minutes my project — database included — was live. And my bill? Zero.
20
+
21
+ In this post, I'll share my experience with Koyeb.com, what the platform offers, and why it's a great option for side projects and MVPs.
22
+
23
+ ---
24
+
25
+ ## What Is Koyeb?
26
+
27
+ Koyeb is a serverless Platform-as-a-Service (PaaS) built for developers who want to run applications without dealing with infrastructure management. In the simplest terms, it offers two paths:
28
+
29
+ > **Push to GitHub, let Koyeb deploy it. Or provide a Docker image, and it runs.**
30
+
31
+ First path: you connect your GitHub repo, and with every push, Koyeb automatically builds and deploys. Second path: you provide a Docker image from your container registry — like `ghcr.io/user/project:latest` — and Koyeb pulls and runs it directly. No server setup, no nginx configuration, no SSL certificates to manage... None of that. Automatic build, automatic deploy, automatic HTTPS.
32
+
33
+ What really surprised me was the **deployment speed**. Even on the first deploy, it was incredibly fast. You provide the image, and within seconds the service is ready. I've waited minutes for builds and provisioning on other platforms — on Koyeb, it was done in the blink of an eye.
34
+
35
+ What truly sets Koyeb apart is a major development from February 2026: **its acquisition by Mistral AI**. This was the French AI giant's first-ever acquisition, and it sends a strong signal of confidence in Koyeb's future. Mistral is positioning Koyeb as a core component of its AI cloud infrastructure. This means the platform won't just survive — it will grow with serious investment behind it.
36
+
37
+ Who is Koyeb for?
38
+
39
+ - **Indie hackers**: Those who want to validate ideas quickly
40
+ - **Startup founders**: Those who want to launch an MVP at zero cost
41
+ - **Students**: Those who want to host portfolio projects
42
+ - **Side project developers**: Those who keep saying "I'll deploy it someday"
43
+ - **AI developers**: Those who want to run GPU-powered inference workloads
44
+
45
+ ---
46
+
47
+ ## The Power of the Free Plan
48
+
49
+ The first thing that drew me to Koyeb was the value of the Starter plan.
50
+
51
+ Koyeb's Starter plan is **$0** and includes:
52
+
53
+ - **1 web service** (512MB RAM, 0.1 vCPU, 2GB SSD)
54
+ - **1 managed PostgreSQL database** (1GB storage)
55
+ - **No time limit** — there's no trial period
56
+ - **Commercial use allowed** — even if your side project generates revenue
57
+ - **Custom domain support** — you can connect up to 5 domains
58
+ - **100GB monthly bandwidth** — included
59
+
60
+ This is more than enough for an MVP or side project. My SaaS project ran smoothly with these resources.
61
+
62
+ > *I entered my credit card during registration. A small amount was charged and refunded for verification — I didn't see any charges on my statement.*
63
+
64
+ ### What Makes Koyeb Stand Out for Side Projects?
65
+
66
+ Every platform has its strengths. AWS and Azure are indispensable for enterprise projects, DigitalOcean is great for its simplicity, Fly.io excels at edge computing, and Railway and Render have made serious strides in developer experience. I actively use most of these platforms across different projects.
67
+
68
+ What made Koyeb different for me was that it **offers both a web service and a PostgreSQL database together on the free plan**, with an extremely clean interface. Instead of setting up separate services and managing accounts across different platforms for a side project, I could handle everything from one place.
69
+
70
+ ---
71
+
72
+ ## 5 Features That Impressed Me
73
+
74
+ The free plan is nice, but what really kept me on Koyeb was the user experience. Here are the 5 features that impressed me the most:
75
+
76
+ ### 1. Two Easy Deploy Paths: Git Push or Docker Image
77
+
78
+ Koyeb offers two deployment paths, both extremely simple:
79
+
80
+ **Path A — Git Push:**
81
+ 1. Connect your GitHub repo
82
+ 2. Select a branch, confirm build settings
83
+ 3. Deploy — every `git push` now triggers an automatic deployment
84
+
85
+ **Path B — Docker Image:**
86
+ 1. Enter your container registry and image name (e.g., `ghcr.io/user/project:latest`)
87
+ 2. Set port and environment variables
88
+ 3. Deploy — Koyeb pulls the image and runs it
89
+
90
+ I chose the Docker image path for my project. I provided my image from GitHub Container Registry, entered my environment variables, and hit deploy. You can also integrate with GitHub Actions or your own CI/CD pipeline, but for a simple side project, this level of simplicity is exactly right.
91
+
92
+ My first deploy? It was live within **a few minutes** of providing the image. No exaggeration — the startup speed genuinely surprised me.
93
+
94
+ ### 2. Scale-to-Zero: Pay Only for What You Use
95
+
96
+ This is, in my opinion, Koyeb's strongest feature. When your project isn't receiving traffic, the instance automatically goes to sleep. When a request comes in, it wakes up automatically. (Hugging Face Spaces and Render work similarly, but Koyeb still wins on simplicity and speed.)
97
+
98
+ Koyeb does this in two tiers:
99
+
100
+ - **Light Sleep**: The instance stays in memory, waking up within 200ms. Users feel no delay. (On other platforms, you really notice the cold start.)
101
+ - **Deep Sleep**: The instance shuts down completely, waking up in 1-5 seconds. For longer idle periods.
102
+
103
+ This is especially great for side projects. Why consume resources when your project isn't getting traffic at 3 AM? With Scale-to-Zero, you only pay for actual usage. On the free plan, you're already paying nothing — but when you move to paid plans, this means real savings.
104
+
105
+ ### 3. Managed PostgreSQL
106
+
107
+ If you're building a SaaS project, you almost certainly need a database. Koyeb provides one out of the box. (This became my favorite feature. Yugabyte, Neon, Supabase, Heroku, and MongoDB Atlas all offer free tiers too — but having everything in one place is wonderful.)
108
+
109
+ You get your connection string, paste it into your app, done.
110
+
111
+ ### 4. Clean and Modern Dashboard
112
+
113
+ Koyeb's dashboard is clean, intuitive, and modern. You can view real-time logs, track deployment history, and easily manage environment variables. (You can copy-paste your .env file — no need to enter variables one by one.) Larger cloud platforms naturally have more comprehensive dashboards because they offer a much wider range of services. Koyeb, by focusing on a narrower scope, keeps its interface extremely clean. I found exactly the information I needed, right where I needed it, for managing a side project.
114
+
115
+ ---
116
+
117
+ ## Koyeb's Future: The Mistral AI Effect
118
+
119
+ In February 2026, Mistral AI announced its acquisition of Koyeb. This was Mistral's **first-ever acquisition**. Koyeb's 13-person team and three co-founders joined Mistral's engineering team, led by CTO Timothée Lacroix.
120
+
121
+ Why does this matter?
122
+
123
+ **Strategic positioning**: Mistral is moving beyond being just an LLM company to become a full-stack AI cloud provider. The Mistral Compute platform announced in June 2025 will be accelerated by Koyeb's infrastructure.
124
+
125
+ **AI-focused infrastructure**: Koyeb's serverless GPU support (L4, L40S, V100) aligns perfectly with Mistral's AI inference needs. We can expect more powerful GPU options and AI-native features in the future.
126
+
127
+ **European AI independence**: Mistral is part of Europe's vision to build alternatives to US tech giants. Combined with its $1.4 billion data center investment in Sweden, Koyeb's European-based infrastructure carries strategic value.
128
+
129
+ **Platform continuity commitment**: Koyeb's blog post made it clear — the existing platform and free plan will continue. The acquisition means growth, not shutdown.
130
+
131
+ ---
132
+
133
+ ## Pricing: Pay as You Grow
134
+
135
+ Koyeb's free Starter plan offers 1 web service + 1 PostgreSQL. If your project grows, there are Pro ($29/month), Scale ($299/month), and Enterprise options — but at the side project stage, you don't need to think about any of that.
136
+
137
+ What mattered to me was this: no commitment, no hidden costs. You can start without thinking "What if it doesn't take off?" — because if it doesn't, it costs you absolutely nothing.
138
+
139
+ ---
140
+
141
+ ## Practical Deploy Flow
142
+
143
+ I want to show how easy it is to get a project live on Koyeb. Both paths take just a few steps:
144
+
145
+ ### With GitHub:
146
+
147
+ **Step 1** — Go to [koyeb.com](https://www.koyeb.com), sign up.
148
+
149
+ **Step 2** — Select "Create Web Service" > "GitHub", connect your repo.
150
+
151
+ **Step 3** — Confirm branch and build settings. Koyeb auto-detects popular frameworks like Next.js, Node.js, Python, Go, and Rust.
152
+
153
+ **Step 4** — Add your environment variables, hit "Deploy".
154
+
155
+ ### With Docker Image:
156
+
157
+ **Step 1** — Select "Create Web Service" > "Docker".
158
+
159
+ **Step 2** — Enter your image address, e.g.: `ghcr.io/user/project:latest`
160
+
161
+ **Step 3** — Set port, environment variables, and health check settings, hit "Deploy".
162
+
163
+ With both paths, your project is live at `xxx.koyeb.app` within minutes. Want to add PostgreSQL? One click from the dashboard via "Create Database". The connection string is auto-generated. That's it.
164
+
165
+ ---
166
+
167
+ ## Is Koyeb Perfect? An Honest Assessment
168
+
169
+ Every platform has strengths and weaknesses. I want to be honest while praising Koyeb:
170
+
171
+ **Things to keep in mind:**
172
+
173
+ - **Free tier resources are limited**: 512MB RAM and 0.1 vCPU aren't enough for heavy traffic. But it's free — ideal for MVPs and prototypes.
174
+ - **PostgreSQL uptime**: The free database goes to sleep when idle. If you need an always-on DB, you may need to upgrade to a paid plan.
175
+ - **Region limitations (free)**: On the free plan, you can only choose Frankfurt or Washington D.C.
176
+ - **Younger ecosystem**: It doesn't yet have as wide a service range as platforms that have been around for many years. But it's rapidly growing with Mistral's backing.
177
+
178
+ **Standout strengths:**
179
+
180
+ - Zero-cost start (web service + DB together)
181
+ - Remarkably simple deploy process
182
+ - Smart resource management with Scale-to-Zero
183
+ - Clean and focused dashboard
184
+ - Secure future with Mistral AI backing
185
+
186
+ ---
187
+
188
+ ## Conclusion: The Right Tool for the Right Job
189
+
190
+ Platforms like AWS, Azure, and GCP remain indispensable for my larger projects. But for a side project, for a quick and free start, Koyeb was exactly what I was looking for.
191
+
192
+ I deployed my project at zero cost, in minutes. I didn't have to get my database from a separate service. All I needed was my code and my GitHub repo. And my bill reflected nothing.
193
+
194
+ In 2026, cloud platform options are so rich that there's a solution for every need. Koyeb is a great option, especially for side projects, MVPs, and rapid prototyping. With its free web service and database bundled together, its clean interface, and easy setup, it's tailor-made for those "let me try this live" moments.
195
+
196
+ If you have an idea, if you have an unfinished project, if you have code that works on localhost but has never gone live — **give it a shot**. It's free to try.
197
+
198
+ And who knows, maybe the next big SaaS story will be yours.
199
+
200
+ ---
201
+
202
+ *This post is not sponsored. There are no discount codes or referral links. I used Koyeb for my own project and wanted to share my experience. As someone who loves open source: a thank you to Koyeb, and a roadmap for you.*
203
+
204
+ ---
205
+
206
+ ## Resources
207
+
208
+ - [Koyeb Official Site](https://www.koyeb.com/)
209
+ - [Koyeb Pricing](https://www.koyeb.com/pricing)
210
+ - [Koyeb Docs](https://www.koyeb.com/docs)
211
+ - [Koyeb Scale-to-Zero](https://www.koyeb.com/docs/run-and-scale/scale-to-zero)
212
+ - [Mistral AI + Koyeb (TechCrunch)](https://techcrunch.com/2026/02/17/mistral-ai-buys-koyeb-in-first-acquisition-to-back-its-cloud-ambitions/)
213
+ - [Koyeb Blog: Joining Mistral AI](https://www.koyeb.com/blog/koyeb-is-joining-mistral-ai-to-build-the-future-of-ai-infrastructure)
214
+ - [Scale-to-Zero with Light Sleep](https://www.koyeb.com/blog/avoid-cold-starts-with-scale-to-zero-light-sleep)
215
+ - [Koyeb Regions](https://www.koyeb.com/docs/reference/regions)
@@ -0,0 +1,445 @@
1
+ # LibreDB Studio — Kapsamlı Test Altyapısı Planı
2
+
3
+ ## Bağlam
4
+
5
+ LibreDB Studio enterprise-grade, open-source bir SQL IDE'dir. ~146 kaynak dosya, ~36,000+ satır kod var ve test altyapısı neredeyse sıfır (tek bir `postgres.test.ts` dosyası `bun:test` kullanıyor). Yeni katılımcıların güvenle geliştirme yapabilmesi ve production-ready kaliteyi korumak için kapsamlı bir test altyapısı şart.
6
+
7
+ **Yaklaşım:** Coverage-first değil, **risk-first + coverage floor** modeli. Coverage tek başına kaliteyi temsil etmez — branch coverage, critical-path zorunluluğu ve E2E akış başarı oranı birlikte kalite kapılarını oluşturur.
8
+
9
+ ---
10
+
11
+ ## Kalite Kapıları (Quality Gates)
12
+
13
+ ### Katman Bazlı Eşikler — CI'da Enforce Edilir
14
+
15
+ | Katman | Line Coverage | Branch Coverage | Zorunluluk |
16
+ |--------|-------------|----------------|------------|
17
+ | `src/lib/` (Unit) | ≥ %95 | ≥ %90 | PR merge blocker |
18
+ | `src/app/api/` (API) | ≥ %90 | ≥ %85 | PR merge blocker |
19
+ | `src/hooks/` (Hooks) | ≥ %85 | ≥ %80 | PR merge blocker |
20
+ | `src/components/` (UI) | ≥ %80 | ≥ %70 | Warning (soft gate) |
21
+ | **Toplam Proje** | ≥ %90 | ≥ %85 | PR merge blocker |
22
+
23
+ ### E2E Kalite Kapısı (Bağımsız Metrik)
24
+
25
+ E2E testler `bun test --coverage` lcov çıktısına katkı **YAPMAZ** — Playwright ayrı bir süreçte tarayıcıda çalışır. E2E metrikleri ayrı takip edilir:
26
+
27
+ | Metrik | Eşik | Açıklama |
28
+ |--------|-------|----------|
29
+ | Kritik akış başarı oranı | %100 | Login, query execution, connection management |
30
+ | Toplam E2E pass oranı | ≥ %95 | Flaky tolerance: max %5 |
31
+ | Flaky test retry | ≤ 2 retry | CI'da `retries: 2`, 3. denemede de başarısızsa gerçek hata |
32
+
33
+ ### Gelecek İyileştirmeler (Phase 2 sonrası değerlendirilecek)
34
+
35
+ - **Mutation Testing**: Stryker.js entegrasyonu — testlerin gerçekten hataları yakalayıp yakalamadığını ölçer
36
+ - **SonarCloud Quality Gate**: Coverage + duplication + complexity birleşik kontrol
37
+ - **PR Coverage Delta**: Yeni eklenen kodun coverage'ı mevcut ortalamadan düşük olamaz
38
+
39
+ ---
40
+
41
+ ## Faz 0: Altyapı Kurulumu
42
+
43
+ ### 0.1 — Bağımlılıkları Yükle
44
+
45
+ ```bash
46
+ bun add -d @testing-library/react @testing-library/jest-dom @testing-library/user-event happy-dom @playwright/test
47
+ ```
48
+
49
+ ### 0.2 — `bunfig.toml` Oluştur (Yeni dosya)
50
+
51
+ ```toml
52
+ [test]
53
+ preload = ["./tests/setup.ts"]
54
+
55
+ [test.coverage]
56
+ enabled = true
57
+ reporter = ["lcov", "text"]
58
+ ```
59
+
60
+ ### 0.3 — `tests/setup.ts` Oluştur (Yeni dosya)
61
+
62
+ - `process.env.JWT_SECRET`, `ADMIN_PASSWORD`, `USER_PASSWORD` test değerleri
63
+ - `globalThis.localStorage` in-memory mock (SSR ortamı için)
64
+ - `afterEach` → `localStorage.clear()` cleanup
65
+
66
+ ### 0.4 — Test Fixture'ları Oluştur
67
+
68
+ | Dosya | İçerik |
69
+ |-------|--------|
70
+ | `tests/fixtures/connections.ts` | Her DB tipi için mock `DatabaseConnection` objeleri (postgres, mysql, sqlite, mongodb, redis, oracle, mssql) |
71
+ | `tests/fixtures/schemas.ts` | Mock `TableSchema[]` objeleri |
72
+ | `tests/fixtures/query-results.ts` | Mock `QueryResult` objeleri |
73
+ | `tests/fixtures/masking-configs.ts` | Mock `MaskingConfig` objeleri |
74
+
75
+ ### 0.5 — Test Helper'ları Oluştur
76
+
77
+ | Dosya | İçerik |
78
+ |-------|--------|
79
+ | `tests/helpers/mock-provider.ts` | `createMockProvider()` — tüm `DatabaseProvider` metodlarını mock'layan factory |
80
+ | `tests/helpers/mock-next.ts` | `createMockRequest()`, `createMockCookies()` — Next.js API test helper'ları |
81
+ | `tests/helpers/mock-fetch.ts` | Global `fetch` mock helper |
82
+ | `tests/helpers/mock-monaco.ts` | Monaco Editor'ü `<textarea>` olarak mock'la |
83
+ | `tests/helpers/render-with-providers.tsx` | Component test wrapper (theme, toast, router provider) |
84
+
85
+ ### 0.6 — `package.json` Script'leri Ekle
86
+
87
+ ```json
88
+ {
89
+ "test": "bun test",
90
+ "test:unit": "bun test tests/unit",
91
+ "test:integration": "bun test tests/integration",
92
+ "test:hooks": "bun test tests/hooks",
93
+ "test:api": "bun test tests/api",
94
+ "test:components": "bun test tests/components",
95
+ "test:e2e": "bunx playwright test",
96
+ "test:coverage": "bun test --coverage --coverage-reporter=lcov --coverage-dir=coverage"
97
+ }
98
+ ```
99
+
100
+ ### 0.7 — `playwright.config.ts` Oluştur (Yeni dosya)
101
+
102
+ - `testDir: './e2e'`, `baseURL: 'http://localhost:3000'`
103
+ - Chromium projesi, `webServer` → `bun run build && bun start`
104
+ - CI'da `retries: 2`, `workers: 1`
105
+
106
+ ### 0.8 — Mevcut Test Dosyası Taşı
107
+
108
+ - `src/lib/db/providers/sql/postgres.test.ts` → `tests/integration/db/postgres-provider.test.ts`
109
+
110
+ ### 0.9 — `.github/workflows/ci.yml` Güncelle
111
+
112
+ Mevcut `lint-and-build` job korunur. Eklenenler:
113
+
114
+ **Yeni `test` job:**
115
+ ```yaml
116
+ test:
117
+ name: Unit & Integration Tests
118
+ runs-on: ubuntu-latest
119
+ steps:
120
+ - uses: actions/checkout@v6
121
+ - uses: oven-sh/setup-bun@v2
122
+ with:
123
+ bun-version: latest
124
+ - run: bun install --frozen-lockfile
125
+ - run: bun test --coverage --coverage-reporter=lcov --coverage-dir=coverage
126
+ env:
127
+ JWT_SECRET: test-secret-for-ci-build-only-32ch
128
+ ADMIN_PASSWORD: test-admin
129
+ USER_PASSWORD: test-user
130
+ - uses: actions/upload-artifact@v4
131
+ with:
132
+ name: coverage
133
+ path: coverage/lcov.info
134
+ ```
135
+
136
+ **Yeni `e2e` job (lint-and-build'e bağımlı):**
137
+ ```yaml
138
+ e2e:
139
+ name: E2E Tests
140
+ needs: [lint-and-build]
141
+ runs-on: ubuntu-latest
142
+ steps:
143
+ - uses: actions/checkout@v6
144
+ - uses: oven-sh/setup-bun@v2
145
+ - run: bun install --frozen-lockfile
146
+ - run: bunx playwright install --with-deps chromium
147
+ - run: bunx playwright test
148
+ env:
149
+ JWT_SECRET: test-secret-for-ci-build-only-32ch
150
+ ADMIN_PASSWORD: test-admin
151
+ USER_PASSWORD: test-user
152
+ - uses: actions/upload-artifact@v4
153
+ if: always()
154
+ with:
155
+ name: playwright-report
156
+ path: playwright-report/
157
+ ```
158
+
159
+ **`sonarcloud` job güncelleme:**
160
+ ```yaml
161
+ sonarcloud:
162
+ name: SonarCloud Analysis
163
+ needs: [test] # coverage artifact'ını bekle
164
+ runs-on: ubuntu-latest
165
+ steps:
166
+ - uses: actions/checkout@v6
167
+ with:
168
+ fetch-depth: 0
169
+ - uses: actions/download-artifact@v4
170
+ with:
171
+ name: coverage
172
+ path: coverage
173
+ - uses: SonarSource/sonarqube-scan-action@v6
174
+ env:
175
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
176
+ ```
177
+
178
+ ### 0.10 — `sonar-project.properties` Güncelle
179
+
180
+ ```properties
181
+ sonar.projectKey=libredb_libredb-studio
182
+ sonar.organization=libredb
183
+
184
+ sonar.projectName=libredb-studio
185
+ sonar.projectVersion=0.6.18
186
+
187
+ sonar.sources=src
188
+ sonar.tests=tests,e2e
189
+ sonar.test.inclusions=tests/**/*.test.ts,tests/**/*.test.tsx,e2e/**/*.spec.ts
190
+
191
+ # Sadece runtime/generate edilmiş kodu hariç tut, test dosyalarını DEĞİL
192
+ sonar.exclusions=**/node_modules/**,**/.next/**,**/build/**,**/out/**,src/components/ui/**
193
+
194
+ sonar.javascript.lcov.reportPaths=coverage/lcov.info
195
+ sonar.typescript.tsconfigPath=tsconfig.json
196
+ sonar.sourceEncoding=UTF-8
197
+ ```
198
+
199
+ **Önemli:** `tests/**` ve `e2e/**` artık `sonar.exclusions` içinde DEĞİL. Bunlar `sonar.tests` olarak tanımlanır → SonarCloud bunları test kodu olarak algılar, coverage hesaplamasından hariç tutar ama analiz eder.
200
+
201
+ ---
202
+
203
+ ## Faz 1: Unit Testler — Saf Fonksiyonlar
204
+
205
+ **En yüksek ROI:** Saf fonksiyonlar, sıfır mocking, en kritik iş mantığı.
206
+
207
+ | # | Test Dosyası | Kaynak Dosya | ~Test | Açıklama |
208
+ |---|---|---|---|---|
209
+ | 1 | `tests/unit/sql/statement-splitter.test.ts` | `src/lib/sql/statement-splitter.ts` | 40 | Tek/çoklu statement, `''` string literal, `"identifiers"`, `--` ve `/* */` yorumlar, `$$dollar-quote$$`, unterminated string, boş input, `isMultiStatement()` |
210
+ | 2 | `tests/unit/lib/connection-string-parser.test.ts` | `src/lib/connection-string-parser.ts` | 45 | `postgres://`, `mysql://`, `mongodb://`, `mongodb+srv://`, `redis://`, `oracle://`, `mssql://`, `sqlserver://`, ADO.NET `Server=`, URL encoding, özel karakter, eksik parça, `detectConnectionStringType()` |
211
+ | 3 | `tests/unit/lib/data-masking.test.ts` | `src/lib/data-masking.ts` | 60 | 10 mask tipi, `maskByType()`, `detectSensitiveColumnsFromConfig()`, `shouldMask()` RBAC, `canToggleMasking()`, `canReveal()`, `applyMaskingToRows()`, null/undefined edge case |
212
+ | 4 | `tests/unit/db/query-limiter.test.ts` | `src/lib/db/utils/query-limiter.ts` | 50 | `analyzeQuery()` tüm query tipleri, LIMIT/OFFSET tespiti, MySQL `LIMIT x,y`, Oracle `FETCH FIRST`, MSSQL `TOP N`, `ROWNUM`, UNION, CTE, subquery, `applyQueryLimit()`, `forceLimit` |
213
+ | 5 | `tests/unit/db/errors.test.ts` | `src/lib/db/errors.ts` | 35 | 6 error class, `toJSON()`, 5 type guard, `isRetryableError()`, `mapDatabaseError()` pattern matching, Oracle ORA-*, MSSQL pattern |
214
+ | 6 | `tests/unit/sql/alias-extractor.test.ts` | `src/lib/sql/alias-extractor.ts` | 30 | FROM/JOIN alias, CTE, schema.table, `resolveAlias()`, `getAliasSchema()`, comment/string içindeki SQL |
215
+ | 7 | `tests/unit/schema-diff/diff-engine.test.ts` | `src/lib/schema-diff/diff-engine.ts` | 25 | Eklenen/silinen/değiştirilen tablo ve kolon, index diff, FK diff, aynı schema, boş schema |
216
+ | 8 | `tests/unit/schema-diff/migration-generator.test.ts` | `src/lib/schema-diff/migration-generator.ts` | 20 | CREATE/DROP/ALTER TABLE her dialect (PG, MySQL, SQLite, Oracle, MSSQL), identifier escaping |
217
+ | 9 | `tests/unit/lib/query-generators.test.ts` | `src/lib/query-generators.ts` | 12 | `generateTableQuery()` SQL/JSON/Oracle/MSSQL, `generateSelectQuery()`, `shouldRefreshSchema()` DDL pattern |
218
+ | 10 | `tests/unit/lib/storage.test.ts` | `src/lib/storage.ts` | 20 | CRUD: connections, history (max limit), saved queries, schema snapshots (max 50), charts, active connection ID, bozuk JSON handling |
219
+ | 11 | `tests/unit/lib/time-series-buffer.test.ts` | `src/lib/time-series-buffer.ts` | 15 | push, getAll, getRange, getLast, clear, circular overflow, size |
220
+ | 12 | `tests/unit/lib/audit.test.ts` | `src/lib/audit.ts` | 15 | RingBuffer push/getAll/getRecent/filter/clear/size/toJSON/loadFrom, max size |
221
+ | 13 | `tests/unit/lib/monitoring-thresholds.test.ts` | `src/lib/monitoring-thresholds.ts` | 12 | `evaluateThreshold()` above/below, healthy/warning/critical, `getThresholdColor()`, `getThresholdBadgeVariant()` |
222
+ | 14 | `tests/unit/db/pool-manager.test.ts` | `src/lib/db/utils/pool-manager.ts` | 20 | `mergePoolConfig()`, `validatePoolConfig()`, `withTimeout()`, `formatBytes()`, `formatDuration()`, `escapeIdentifier()` per dialect |
223
+ | 15 | `tests/unit/llm/config.test.ts` | `src/lib/llm/utils/config.ts` | 20 | `resolveConfig()`, `validateConfig()` her provider, `requiresApiKey()`, `requiresApiUrl()`, `getSafeConfigForLogging()` |
224
+ | 16 | `tests/unit/llm/retry.test.ts` | `src/lib/llm/utils/retry.ts` | 10 | `withRetry()` ilk seferde başarı, retry+başarı, tüm retry tükenme, non-retryable error |
225
+ | 17 | `tests/unit/llm/streaming.test.ts` | `src/lib/llm/utils/streaming.ts` | 10 | `encodeText()`/`decodeText()`, `createSSEParser()`, `[DONE]`, malformed JSON, `createErrorStream()` |
226
+
227
+ **Faz 1 Toplam:** 17 test dosyası, ~409 test case
228
+ **Beklenen line coverage (bun test):** ~%30
229
+
230
+ ---
231
+
232
+ ## Faz 2: API Route Testleri
233
+
234
+ Route handler fonksiyonları doğrudan import edilip mock `NextRequest` ile çağrılır.
235
+
236
+ **Mock Stratejisi:**
237
+ - `mock.module('@/lib/db')` → `getOrCreateProvider()` mock provider döndürür
238
+ - `mock.module('@/lib/auth')` → `getSession()` kontrol edilir (admin/user/null)
239
+ - Her HTTP metod, başarı/hata path'i, validasyon, status code test edilir
240
+
241
+ | # | Test Dosyası | Kaynak Dosya | ~Test |
242
+ |---|---|---|---|
243
+ | 1 | `tests/api/auth/login.test.ts` | `src/app/api/auth/login/route.ts` | 8 |
244
+ | 2 | `tests/api/auth/me.test.ts` | `src/app/api/auth/me/route.ts` | 4 |
245
+ | 3 | `tests/api/auth/logout.test.ts` | `src/app/api/auth/logout/route.ts` | 3 |
246
+ | 4 | `tests/api/db/query.test.ts` | `src/app/api/db/query/route.ts` | 12 |
247
+ | 5 | `tests/api/db/multi-query.test.ts` | `src/app/api/db/multi-query/route.ts` | 10 |
248
+ | 6 | `tests/api/db/schema.test.ts` | `src/app/api/db/schema/route.ts` | 6 |
249
+ | 7 | `tests/api/db/health.test.ts` | `src/app/api/db/health/route.ts` | 6 |
250
+ | 8 | `tests/api/db/test-connection.test.ts` | `src/app/api/db/test-connection/route.ts` | 8 |
251
+ | 9 | `tests/api/db/transaction.test.ts` | `src/app/api/db/transaction/route.ts` | 12 |
252
+ | 10 | `tests/api/db/cancel.test.ts` | `src/app/api/db/cancel/route.ts` | 6 |
253
+ | 11 | `tests/api/db/maintenance.test.ts` | `src/app/api/db/maintenance/route.ts` | 8 |
254
+ | 12 | `tests/api/db/monitoring.test.ts` | `src/app/api/db/monitoring/route.ts` | 6 |
255
+ | 13 | `tests/api/db/provider-meta.test.ts` | `src/app/api/db/provider-meta/route.ts` | 6 |
256
+ | 14 | `tests/api/db/pool-stats.test.ts` | `src/app/api/db/pool-stats/route.ts` | 4 |
257
+ | 15 | `tests/api/db/profile.test.ts` | `src/app/api/db/profile/route.ts` | 8 |
258
+ | 16 | `tests/api/db/schema-snapshot.test.ts` | `src/app/api/db/schema-snapshot/route.ts` | 6 |
259
+ | 17 | `tests/api/ai/chat.test.ts` | `src/app/api/ai/chat/route.ts` | 10 |
260
+ | 18 | `tests/api/ai/nl2sql.test.ts` | `src/app/api/ai/nl2sql/route.ts` | 8 |
261
+ | 19 | `tests/api/ai/explain.test.ts` | `src/app/api/ai/explain/route.ts` | 8 |
262
+ | 20 | `tests/api/ai/query-safety.test.ts` | `src/app/api/ai/query-safety/route.ts` | 8 |
263
+ | 21 | `tests/api/ai/autopilot.test.ts` | `src/app/api/ai/autopilot/route.ts` | 6 |
264
+ | 22 | `tests/api/ai/index-advisor.test.ts` | `src/app/api/ai/index-advisor/route.ts` | 6 |
265
+ | 23 | `tests/api/ai/impact.test.ts` | `src/app/api/ai/impact/route.ts` | 6 |
266
+ | 24 | `tests/api/ai/describe-schema.test.ts` | `src/app/api/ai/describe-schema/route.ts` | 4 |
267
+ | 25 | `tests/api/admin/fleet-health.test.ts` | `src/app/api/admin/fleet-health/route.ts` | 6 |
268
+ | 26 | `tests/api/admin/audit.test.ts` | `src/app/api/admin/audit/route.ts` | 6 |
269
+ | 28 | `tests/api/middleware.test.ts` | `src/middleware.ts` | 15 |
270
+
271
+ **Faz 2 Toplam:** 28 test dosyası, ~207 test case
272
+ **Beklenen kümülatif line coverage (bun test):** ~%55
273
+
274
+ ---
275
+
276
+ ## Faz 3: Provider Integration Testleri
277
+
278
+ Her provider'ın native DB client'ı `mock.module()` ile mock'lanır. Mevcut `postgres.test.ts` pattern'i takip edilir.
279
+
280
+ **Test edilen metodlar:** `connect()`, `disconnect()`, `query()`, `getSchema()`, `getHealth()`, `runMaintenance()`, `prepareQuery()`, `getCapabilities()`, `getLabels()`, error mapping.
281
+
282
+ | # | Test Dosyası | Kaynak Dosya | Mock Target | ~Test |
283
+ |---|---|---|---|---|
284
+ | 2 | `tests/integration/db/postgres-provider.test.ts` | `src/lib/db/providers/sql/postgres.ts` | `pg` → mock Pool | 20 |
285
+ | 3 | `tests/integration/db/mysql-provider.test.ts` | `src/lib/db/providers/sql/mysql.ts` | `mysql2/promise` | 18 |
286
+ | 4 | `tests/integration/db/sqlite-provider.test.ts` | `src/lib/db/providers/sql/sqlite.ts` | `better-sqlite3` | 15 |
287
+ | 5 | `tests/integration/db/mongodb-provider.test.ts` | `src/lib/db/providers/document/mongodb.ts` | `mongodb` → mock MongoClient | 18 |
288
+ | 6 | `tests/integration/db/redis-provider.test.ts` | `src/lib/db/providers/keyvalue/redis.ts` | `ioredis` | 15 |
289
+ | 7 | `tests/integration/db/oracle-provider.test.ts` | `src/lib/db/providers/sql/oracle.ts` | `oracledb` | 18 |
290
+ | 8 | `tests/integration/db/mssql-provider.test.ts` | `src/lib/db/providers/sql/mssql.ts` | `mssql` | 18 |
291
+ | 9 | `tests/unit/db/factory.test.ts` | `src/lib/db/factory.ts` | Dynamic imports + SSH tunnel | 15 |
292
+ | 10 | `tests/unit/db/base-provider.test.ts` | `src/lib/db/base-provider.ts` | Concrete mock impl | 12 |
293
+
294
+ **Faz 3 Toplam:** 10 test dosyası, ~164 test case
295
+ **Beklenen kümülatif line coverage (bun test):** ~%70
296
+
297
+ ---
298
+
299
+ ## Faz 4: React Hook Testleri
300
+
301
+ `@testing-library/react` `renderHook` + `act` kullanılır. `globalThis.fetch` mock'lanır.
302
+
303
+ | # | Test Dosyası | Kaynak Dosya | ~Test |
304
+ |---|---|---|---|
305
+ | 1 | `tests/hooks/use-auth.test.ts` | `src/hooks/use-auth.ts` | 8 |
306
+ | 2 | `tests/hooks/use-connection-manager.test.ts` | `src/hooks/use-connection-manager.ts` | 15 |
307
+ | 3 | `tests/hooks/use-tab-manager.test.ts` | `src/hooks/use-tab-manager.ts` | 12 |
308
+ | 4 | `tests/hooks/use-query-execution.test.ts` | `src/hooks/use-query-execution.ts` | 20 |
309
+ | 5 | `tests/hooks/use-transaction-control.test.ts` | `src/hooks/use-transaction-control.ts` | 8 |
310
+ | 6 | `tests/hooks/use-inline-editing.test.ts` | `src/hooks/use-inline-editing.ts` | 10 |
311
+ | 7 | `tests/hooks/use-connection-form.test.ts` | `src/hooks/use-connection-form.ts` | 15 |
312
+ | 8 | `tests/hooks/use-provider-metadata.test.ts` | `src/hooks/use-provider-metadata.ts` | 8 |
313
+ | 9 | `tests/hooks/use-monitoring-data.test.ts` | `src/hooks/use-monitoring-data.ts` | 12 |
314
+ | 10 | `tests/hooks/use-ai-chat.test.ts` | `src/hooks/use-ai-chat.ts` | 10 |
315
+ | 11 | `tests/hooks/use-mobile.test.ts` | `src/hooks/use-mobile.ts` | 4 |
316
+ | 12 | `tests/hooks/use-toast.test.ts` | `src/hooks/use-toast.ts` | 4 |
317
+
318
+ **Faz 4 Toplam:** 12 test dosyası, ~126 test case
319
+ **Beklenen kümülatif line coverage (bun test):** ~%80
320
+
321
+ ---
322
+
323
+ ## Faz 5: Component Testleri
324
+
325
+ `happy-dom` ortamı, `@testing-library/react`, heavy dependency mock'ları.
326
+
327
+ **Mock Stratejisi:**
328
+ - `@monaco-editor/react` → `<textarea data-testid="mock-monaco-editor">`
329
+ - `recharts` → basit `<div>` wrapper'ları
330
+ - `@xyflow/react` → `<div>` wrapper
331
+ - `framer-motion` → children pass-through (animasyonsuz)
332
+
333
+ | # | Test Dosyası | Kaynak Dosya | ~Test |
334
+ |---|---|---|---|
335
+ | 1 | `tests/components/ConnectionModal.test.tsx` | `src/components/ConnectionModal.tsx` | 15 |
336
+ | 2 | `tests/components/ResultsGrid.test.tsx` | `src/components/ResultsGrid.tsx` | 12 |
337
+ | 3 | `tests/components/Studio.test.tsx` | `src/components/Studio.tsx` | 10 |
338
+ | 4 | `tests/components/CommandPalette.test.tsx` | `src/components/CommandPalette.tsx` | 8 |
339
+ | 5 | `tests/components/QueryEditor.test.tsx` | `src/components/QueryEditor.tsx` | 8 |
340
+ | 6 | `tests/components/sidebar/Sidebar.test.tsx` | `src/components/sidebar/Sidebar.tsx` | 8 |
341
+ | 7 | `tests/components/sidebar/ConnectionItem.test.tsx` | `src/components/sidebar/ConnectionItem.tsx` | 6 |
342
+ | 8 | `tests/components/sidebar/ConnectionsList.test.tsx` | `src/components/sidebar/ConnectionsList.tsx` | 6 |
343
+ | 9 | `tests/components/QueryHistory.test.tsx` | `src/components/QueryHistory.tsx` | 8 |
344
+ | 10 | `tests/components/DataCharts.test.tsx` | `src/components/DataCharts.tsx` | 10 |
345
+ | 11 | `tests/components/SchemaDiagram.test.tsx` | `src/components/SchemaDiagram.tsx` | 8 |
346
+ | 12 | `tests/components/SchemaDiff.test.tsx` | `src/components/SchemaDiff.tsx` | 8 |
347
+ | 13 | `tests/components/MaskingSettings.test.tsx` | `src/components/MaskingSettings.tsx` | 8 |
348
+ | 14 | `tests/components/DataProfiler.test.tsx` | `src/components/DataProfiler.tsx` | 6 |
349
+ | 15 | `tests/components/schema-explorer/SchemaExplorer.test.tsx` | `src/components/schema-explorer/SchemaExplorer.tsx` | 6 |
350
+ | 16 | `tests/components/admin/AdminDashboard.test.tsx` | `src/components/admin/AdminDashboard.tsx` | 8 |
351
+ | 17 | `tests/components/admin/OverviewTab.test.tsx` | `src/components/admin/tabs/OverviewTab.tsx` | 8 |
352
+ | 18 | `tests/components/admin/OperationsTab.test.tsx` | `src/components/admin/tabs/OperationsTab.tsx` | 6 |
353
+ | 19 | `tests/components/admin/SecurityTab.test.tsx` | `src/components/admin/tabs/SecurityTab.tsx` | 6 |
354
+ | 20 | `tests/components/admin/AuditTab.test.tsx` | `src/components/admin/tabs/AuditTab.tsx` | 6 |
355
+ | 21 | `tests/components/monitoring/MonitoringDashboard.test.tsx` | `src/components/monitoring/MonitoringDashboard.tsx` | 8 |
356
+ | 22 | `tests/components/studio/BottomPanel.test.tsx` | `src/components/studio/BottomPanel.tsx` | 6 |
357
+ | 23 | `tests/components/studio/QueryToolbar.test.tsx` | `src/components/studio/QueryToolbar.tsx` | 6 |
358
+ | 24 | `tests/components/studio/StudioTabBar.test.tsx` | `src/components/studio/StudioTabBar.tsx` | 6 |
359
+
360
+ **Faz 5 Toplam:** 24 test dosyası, ~187 test case
361
+ **Beklenen kümülatif line coverage (bun test):** ~%90-92
362
+
363
+ ---
364
+
365
+ ## Faz 6: E2E Testler (Playwright)
366
+
367
+ Tam tarayıcı testleri, çalışan Next.js server'a karşı. **Bu testler `bun test --coverage` lcov'a katkı YAPMAZ** — bağımsız kalite kapısı olarak izlenir.
368
+
369
+ | # | Test Dosyası | Senaryo | Kritiklik |
370
+ |---|---|---|---|
371
+ | 1 | `e2e/login.spec.ts` | Admin/user login, yanlış şifre, redirect, logout | Kritik |
372
+ | 3 | `e2e/connection-management.spec.ts` | Connection ekle/düzenle/sil, test connection | Kritik |
373
+ | 4 | `e2e/query-execution.spec.ts` | Query yaz, çalıştır, sonuç gör, cancel | Kritik |
374
+ | 5 | `e2e/tab-management.spec.ts` | Tab ekle/kapat/yeniden adlandır/değiştir | Normal |
375
+ | 6 | `e2e/export.spec.ts` | CSV/JSON/SQL export | Normal |
376
+ | 7 | `e2e/admin-dashboard.spec.ts` | Admin erişim, tab'lar, fleet health | Normal |
377
+
378
+ **Faz 6 Toplam:** 7 test dosyası, ~40 test case
379
+ **E2E kritik akış başarı oranı hedefi:** %100
380
+
381
+ ---
382
+
383
+ ## Toplam Özet
384
+
385
+ | Faz | Kapsam | Dosya | Test Case | Bun Coverage (lcov) |
386
+ |-----|--------|-------|-----------|---------------------|
387
+ | 0 | Altyapı + CI/CD | 12 (setup) | 0 | — |
388
+ | 1 | Saf Fonksiyonlar | 17 | ~409 | ~%30 |
389
+ | 2 | API Routes | 28 | ~207 | ~%55 |
390
+ | 3 | DB Providers | 10 | ~164 | ~%70 |
391
+ | 4 | React Hooks | 12 | ~126 | ~%80 |
392
+ | 5 | Components | 24 | ~187 | ~%90-92 |
393
+ | 6 | E2E (ayrı metrik) | 7 | ~40 | N/A |
394
+ | **Toplam** | | **110** | **~1,133** | **≥%90 line + ≥%85 branch** |
395
+
396
+ Faz 5 sonrası lcov raporundan kalan uncovered branch'ler tespit edilip ek edge-case testleri yazılarak %95+ hedefine ulaşılır.
397
+
398
+ ---
399
+
400
+ ## Framework Seçim Gerekçesi
401
+
402
+ | Katman | Araç | Neden |
403
+ |--------|------|-------|
404
+ | Unit/Integration | `bun:test` | Mevcut pattern, sıfır ek bağımlılık, native TS, Jest-uyumlu API, lcov desteği |
405
+ | Component/Hook | `@testing-library/react` + `happy-dom` | React standartı, `renderHook`, Bun ESM uyumlu, jsdom'dan hızlı |
406
+ | E2E | `@playwright/test` | Multi-browser, Next.js App Router desteği, HTML reporter, retries |
407
+ | Coverage | `bun test --coverage` | Built-in lcov reporter → SonarCloud entegrasyonu |
408
+
409
+ ---
410
+
411
+ ## Doğrulama Planı
412
+
413
+ Her faz sonunda:
414
+ 1. `bun test` — tüm testler geçmeli (exit code 0)
415
+ 2. `bun test --coverage` — line ve branch coverage eşikler kontrol edilmeli
416
+ 3. `bun run lint` — test dosyaları lint'ten geçmeli
417
+ 4. `bun run typecheck` — type hatası olmamalı
418
+ 5. Faz 6 için: `bunx playwright test` — kritik akışlar %100 pass
419
+ 6. CI pipeline'da tüm job'lar başarılı olmalı
420
+
421
+ ---
422
+
423
+ ## Değiştirilecek Mevcut Dosyalar
424
+
425
+ | Dosya | Değişiklik |
426
+ |-------|-----------|
427
+ | `package.json` | Test script'leri eklenir |
428
+ | `.github/workflows/ci.yml` | `test`, `e2e` job eklenir, `sonarcloud` güncellenir |
429
+ | `sonar-project.properties` | `sonar.tests`, `sonar.test.inclusions`, `sonar.exclusions` düzenlenir |
430
+
431
+ ## Oluşturulacak Yeni Dosyalar
432
+
433
+ | Dosya | Amaç |
434
+ |-------|------|
435
+ | `bunfig.toml` | Bun test runner config |
436
+ | `playwright.config.ts` | Playwright E2E config |
437
+ | `tests/setup.ts` | Global test setup |
438
+ | `tests/fixtures/*.ts` (4 dosya) | Mock veri objeleri |
439
+ | `tests/helpers/*.ts` (5 dosya) | Test utility'leri |
440
+ | `tests/unit/**/*.test.ts` (17 dosya) | Unit testler |
441
+ | `tests/api/**/*.test.ts` (28 dosya) | API route testleri |
442
+ | `tests/integration/**/*.test.ts` (8 dosya) | Provider testleri |
443
+ | `tests/hooks/**/*.test.ts` (12 dosya) | Hook testleri |
444
+ | `tests/components/**/*.test.tsx` (24 dosya) | Component testleri |
445
+ | `e2e/**/*.spec.ts` (7 dosya) | E2E testler |