cfsa-antigravity 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/bin/cli.mjs +324 -0
  2. package/package.json +34 -0
  3. package/template/.agent/instructions/commands.md +48 -0
  4. package/template/.agent/instructions/patterns.md +61 -0
  5. package/template/.agent/instructions/structure.md +29 -0
  6. package/template/.agent/instructions/tech-stack.md +43 -0
  7. package/template/.agent/instructions/workflow.md +41 -0
  8. package/template/.agent/kit-sync.md +15 -0
  9. package/template/.agent/rules/boundary-not-placeholder.md +146 -0
  10. package/template/.agent/rules/completion-checklist.md +48 -0
  11. package/template/.agent/rules/decision-classification.md +103 -0
  12. package/template/.agent/rules/extensibility.md +47 -0
  13. package/template/.agent/rules/question-vs-command.md +81 -0
  14. package/template/.agent/rules/security-first.md +43 -0
  15. package/template/.agent/rules/specificity-standards.md +54 -0
  16. package/template/.agent/rules/tdd-contract-first.md +57 -0
  17. package/template/.agent/rules/vertical-slices.md +42 -0
  18. package/template/.agent/skill-library/MANIFEST.md +480 -0
  19. package/template/.agent/skill-library/README.md +38 -0
  20. package/template/.agent/skill-library/meta/brand-guidelines/SKILL.md +73 -0
  21. package/template/.agent/skill-library/meta/claude-code/README.md +9 -0
  22. package/template/.agent/skill-library/meta/claude-code/agent-development/SKILL.md +415 -0
  23. package/template/.agent/skill-library/meta/claude-code/hook-development/SKILL.md +712 -0
  24. package/template/.agent/skill-library/meta/claude-code/plugin-structure/SKILL.md +476 -0
  25. package/template/.agent/skill-library/meta/git-advanced/SKILL.md +972 -0
  26. package/template/.agent/skill-library/meta/mcp-builder/SKILL.md +236 -0
  27. package/template/.agent/skill-library/meta/product-marketing-context/SKILL.md +241 -0
  28. package/template/.agent/skill-library/meta/regex-patterns/SKILL.md +751 -0
  29. package/template/.agent/skill-library/meta/tmux-processes/SKILL.md +210 -0
  30. package/template/.agent/skill-library/meta/using-tmux-for-interactive-commands/SKILL.md +178 -0
  31. package/template/.agent/skill-library/stack/3d/threejs-pro/SKILL.md +300 -0
  32. package/template/.agent/skill-library/stack/ai/ai-sdk/SKILL.md +77 -0
  33. package/template/.agent/skill-library/stack/ai/langchain/SKILL.md +530 -0
  34. package/template/.agent/skill-library/stack/ai/ollama/SKILL.md +321 -0
  35. package/template/.agent/skill-library/stack/ai/openai-sdk/SKILL.md +549 -0
  36. package/template/.agent/skill-library/stack/analytics/google-analytics/SKILL.md +153 -0
  37. package/template/.agent/skill-library/stack/api/graphql/SKILL.md +1061 -0
  38. package/template/.agent/skill-library/stack/api/trpc/SKILL.md +576 -0
  39. package/template/.agent/skill-library/stack/auth/authjs/SKILL.md +569 -0
  40. package/template/.agent/skill-library/stack/auth/clerk/SKILL.md +590 -0
  41. package/template/.agent/skill-library/stack/auth/firebase-auth/SKILL.md +734 -0
  42. package/template/.agent/skill-library/stack/cms/payload-cms/SKILL.md +573 -0
  43. package/template/.agent/skill-library/stack/cms/shopify/SKILL.md +1193 -0
  44. package/template/.agent/skill-library/stack/cms/wordpress/SKILL.md +1104 -0
  45. package/template/.agent/skill-library/stack/css/sass-scss/SKILL.md +1121 -0
  46. package/template/.agent/skill-library/stack/css/tailwind-css-patterns/SKILL.md +863 -0
  47. package/template/.agent/skill-library/stack/css/tailwind-design-system/SKILL.md +490 -0
  48. package/template/.agent/skill-library/stack/css/vanilla-css/SKILL.md +1078 -0
  49. package/template/.agent/skill-library/stack/databases/clickhouse/SKILL.md +311 -0
  50. package/template/.agent/skill-library/stack/databases/influxdb/SKILL.md +280 -0
  51. package/template/.agent/skill-library/stack/databases/lancedb/SKILL.md +415 -0
  52. package/template/.agent/skill-library/stack/databases/mongodb/SKILL.md +1169 -0
  53. package/template/.agent/skill-library/stack/databases/neo4j/SKILL.md +839 -0
  54. package/template/.agent/skill-library/stack/databases/pgvector/SKILL.md +241 -0
  55. package/template/.agent/skill-library/stack/databases/pinecone/SKILL.md +212 -0
  56. package/template/.agent/skill-library/stack/databases/postgresql/SKILL.md +658 -0
  57. package/template/.agent/skill-library/stack/databases/qdrant/SKILL.md +312 -0
  58. package/template/.agent/skill-library/stack/databases/redis/SKILL.md +1079 -0
  59. package/template/.agent/skill-library/stack/databases/spacetimedb/SKILL.md +532 -0
  60. package/template/.agent/skill-library/stack/databases/sqlite/SKILL.md +1132 -0
  61. package/template/.agent/skill-library/stack/databases/supabase/SKILL.md +640 -0
  62. package/template/.agent/skill-library/stack/databases/surrealdb-expert/SKILL.md +945 -0
  63. package/template/.agent/skill-library/stack/databases/timescaledb/SKILL.md +745 -0
  64. package/template/.agent/skill-library/stack/databases/weaviate/SKILL.md +218 -0
  65. package/template/.agent/skill-library/stack/devops/github-actions/SKILL.md +554 -0
  66. package/template/.agent/skill-library/stack/devops/kubernetes/SKILL.md +950 -0
  67. package/template/.agent/skill-library/stack/devops/nginx/SKILL.md +841 -0
  68. package/template/.agent/skill-library/stack/devops/terraform/SKILL.md +860 -0
  69. package/template/.agent/skill-library/stack/email/resend/SKILL.md +391 -0
  70. package/template/.agent/skill-library/stack/engines/godot/SKILL.md +488 -0
  71. package/template/.agent/skill-library/stack/extensions/chrome-extension/SKILL.md +375 -0
  72. package/template/.agent/skill-library/stack/extensions/vscode-extension/SKILL.md +453 -0
  73. package/template/.agent/skill-library/stack/frameworks/astro-framework/SKILL.md +162 -0
  74. package/template/.agent/skill-library/stack/frameworks/electron/SKILL.md +1286 -0
  75. package/template/.agent/skill-library/stack/frameworks/fastapi/SKILL.md +650 -0
  76. package/template/.agent/skill-library/stack/frameworks/hono/SKILL.md +90 -0
  77. package/template/.agent/skill-library/stack/frameworks/nestjs/SKILL.md +878 -0
  78. package/template/.agent/skill-library/stack/frameworks/nextjs/SKILL.md +635 -0
  79. package/template/.agent/skill-library/stack/frameworks/nuxt/SKILL.md +564 -0
  80. package/template/.agent/skill-library/stack/frameworks/sveltekit/SKILL.md +614 -0
  81. package/template/.agent/skill-library/stack/frameworks/tauri/SKILL.md +920 -0
  82. package/template/.agent/skill-library/stack/gamedev/godot/SKILL.md +1032 -0
  83. package/template/.agent/skill-library/stack/gamedev/unity/SKILL.md +1175 -0
  84. package/template/.agent/skill-library/stack/hosting/aws/SKILL.md +467 -0
  85. package/template/.agent/skill-library/stack/hosting/cloudflare/SKILL.md +201 -0
  86. package/template/.agent/skill-library/stack/hosting/docker-expert/SKILL.md +409 -0
  87. package/template/.agent/skill-library/stack/hosting/vercel/SKILL.md +484 -0
  88. package/template/.agent/skill-library/stack/languages/bash-scripting/SKILL.md +773 -0
  89. package/template/.agent/skill-library/stack/languages/c-cpp/SKILL.md +712 -0
  90. package/template/.agent/skill-library/stack/languages/gdscript/SKILL.md +789 -0
  91. package/template/.agent/skill-library/stack/languages/go/SKILL.md +664 -0
  92. package/template/.agent/skill-library/stack/languages/java/SKILL.md +778 -0
  93. package/template/.agent/skill-library/stack/languages/kotlin/SKILL.md +665 -0
  94. package/template/.agent/skill-library/stack/languages/python/SKILL.md +678 -0
  95. package/template/.agent/skill-library/stack/languages/rust/SKILL.md +673 -0
  96. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/SKILL.md +141 -0
  97. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/advanced-generics.md +90 -0
  98. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/branded-types.md +57 -0
  99. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/builder-pattern.md +71 -0
  100. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/common-pitfalls.md +135 -0
  101. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/conditional-types.md +27 -0
  102. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/decorators.md +98 -0
  103. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/discriminated-unions.md +62 -0
  104. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/mapped-types.md +53 -0
  105. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/performance-best-practices.md +104 -0
  106. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/template-literal-types.md +49 -0
  107. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/testing-types.md +112 -0
  108. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-guards.md +70 -0
  109. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-inference.md +101 -0
  110. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/utility-types.md +98 -0
  111. package/template/.agent/skill-library/stack/languages/vanilla-javascript/SKILL.md +803 -0
  112. package/template/.agent/skill-library/stack/messaging/kafka/SKILL.md +235 -0
  113. package/template/.agent/skill-library/stack/mobile/expo-react-native/SKILL.md +665 -0
  114. package/template/.agent/skill-library/stack/mobile/flutter/SKILL.md +316 -0
  115. package/template/.agent/skill-library/stack/mobile/react-native/SKILL.md +337 -0
  116. package/template/.agent/skill-library/stack/monitoring/posthog/SKILL.md +396 -0
  117. package/template/.agent/skill-library/stack/monitoring/sentry/SKILL.md +509 -0
  118. package/template/.agent/skill-library/stack/observability/datadog/SKILL.md +179 -0
  119. package/template/.agent/skill-library/stack/observability/distributed-tracing/SKILL.md +140 -0
  120. package/template/.agent/skill-library/stack/observability/logging-best-practices/SKILL.md +168 -0
  121. package/template/.agent/skill-library/stack/observability/opentelemetry/SKILL.md +164 -0
  122. package/template/.agent/skill-library/stack/observability/prometheus-grafana/SKILL.md +246 -0
  123. package/template/.agent/skill-library/stack/observability/python-observability/SKILL.md +158 -0
  124. package/template/.agent/skill-library/stack/orm/drizzle-orm/SKILL.md +613 -0
  125. package/template/.agent/skill-library/stack/orm/prisma/SKILL.md +744 -0
  126. package/template/.agent/skill-library/stack/payments/lemonsqueezy/SKILL.md +393 -0
  127. package/template/.agent/skill-library/stack/payments/stripe-integration/SKILL.md +457 -0
  128. package/template/.agent/skill-library/stack/queue/bullmq/SKILL.md +385 -0
  129. package/template/.agent/skill-library/stack/queue/inngest/SKILL.md +438 -0
  130. package/template/.agent/skill-library/stack/realtime/socketio/SKILL.md +595 -0
  131. package/template/.agent/skill-library/stack/search/elasticsearch/SKILL.md +248 -0
  132. package/template/.agent/skill-library/stack/search/meilisearch/SKILL.md +385 -0
  133. package/template/.agent/skill-library/stack/security/crypto-patterns/SKILL.md +437 -0
  134. package/template/.agent/skill-library/stack/security/csp-cors-headers/SKILL.md +588 -0
  135. package/template/.agent/skill-library/stack/security/dependency-auditing/SKILL.md +560 -0
  136. package/template/.agent/skill-library/stack/security/input-sanitization/SKILL.md +430 -0
  137. package/template/.agent/skill-library/stack/security/owasp-web-security/SKILL.md +421 -0
  138. package/template/.agent/skill-library/stack/state/tanstack-query/SKILL.md +637 -0
  139. package/template/.agent/skill-library/stack/state/zustand/SKILL.md +483 -0
  140. package/template/.agent/skill-library/stack/storage/aws-s3/SKILL.md +415 -0
  141. package/template/.agent/skill-library/stack/testing/playwright/SKILL.md +641 -0
  142. package/template/.agent/skill-library/stack/testing/storybook/SKILL.md +923 -0
  143. package/template/.agent/skill-library/stack/testing/testing-library/SKILL.md +872 -0
  144. package/template/.agent/skill-library/stack/testing/vitest/SKILL.md +714 -0
  145. package/template/.agent/skill-library/stack/ui/react-best-practices/SKILL.md +877 -0
  146. package/template/.agent/skill-library/stack/ui/react-composition-patterns/SKILL.md +1107 -0
  147. package/template/.agent/skill-library/stack/ui/react-flow/SKILL.md +425 -0
  148. package/template/.agent/skill-library/stack/ui/shadcn-ui/SKILL.md +703 -0
  149. package/template/.agent/skill-library/surface/api/api-caching/SKILL.md +458 -0
  150. package/template/.agent/skill-library/surface/api/api-documentation-openapi/SKILL.md +697 -0
  151. package/template/.agent/skill-library/surface/api/api-error-handling/SKILL.md +478 -0
  152. package/template/.agent/skill-library/surface/api/api-security-checklist/SKILL.md +147 -0
  153. package/template/.agent/skill-library/surface/api/api-versioning/SKILL.md +420 -0
  154. package/template/.agent/skill-library/surface/api/email-best-practices/SKILL.md +59 -0
  155. package/template/.agent/skill-library/surface/api/rate-limiting-abuse-protection/SKILL.md +147 -0
  156. package/template/.agent/skill-library/surface/api/rest-api-design/SKILL.md +478 -0
  157. package/template/.agent/skill-library/surface/api/webhook-design/SKILL.md +752 -0
  158. package/template/.agent/skill-library/surface/cli/cli-configuration-management/SKILL.md +445 -0
  159. package/template/.agent/skill-library/surface/cli/cli-error-diagnostics/SKILL.md +515 -0
  160. package/template/.agent/skill-library/surface/cli/cli-shell-integration/SKILL.md +479 -0
  161. package/template/.agent/skill-library/surface/cli/cli-ux-design/SKILL.md +477 -0
  162. package/template/.agent/skill-library/surface/desktop/desktop-app-distribution/SKILL.md +416 -0
  163. package/template/.agent/skill-library/surface/desktop/desktop-security-sandboxing/SKILL.md +407 -0
  164. package/template/.agent/skill-library/surface/desktop/desktop-ux-conventions/SKILL.md +361 -0
  165. package/template/.agent/skill-library/surface/desktop/native-os-integration/SKILL.md +563 -0
  166. package/template/.agent/skill-library/surface/extension/browser-extension-patterns/SKILL.md +482 -0
  167. package/template/.agent/skill-library/surface/extension/plugin-architecture-design/SKILL.md +632 -0
  168. package/template/.agent/skill-library/surface/extension/vscode-extension-development/SKILL.md +728 -0
  169. package/template/.agent/skill-library/surface/mobile/app-store-submission/SKILL.md +304 -0
  170. package/template/.agent/skill-library/surface/mobile/mobile-offline-sync/SKILL.md +443 -0
  171. package/template/.agent/skill-library/surface/mobile/mobile-responsive-patterns/SKILL.md +432 -0
  172. package/template/.agent/skill-library/surface/mobile/push-notifications/SKILL.md +495 -0
  173. package/template/.agent/skill-library/surface/web/accessibility-compliance/SKILL.md +827 -0
  174. package/template/.agent/skill-library/surface/web/ai-seo/SKILL.md +398 -0
  175. package/template/.agent/skill-library/surface/web/ai-seo/references/content-patterns.md +285 -0
  176. package/template/.agent/skill-library/surface/web/ai-seo/references/platform-ranking-factors.md +152 -0
  177. package/template/.agent/skill-library/surface/web/analytics-tracking/SKILL.md +309 -0
  178. package/template/.agent/skill-library/surface/web/analytics-tracking/references/event-library.md +260 -0
  179. package/template/.agent/skill-library/surface/web/analytics-tracking/references/ga4-implementation.md +300 -0
  180. package/template/.agent/skill-library/surface/web/analytics-tracking/references/gtm-implementation.md +390 -0
  181. package/template/.agent/skill-library/surface/web/authentication-ui-flows/SKILL.md +530 -0
  182. package/template/.agent/skill-library/surface/web/dark-mode-theming/SKILL.md +516 -0
  183. package/template/.agent/skill-library/surface/web/design-reference-data/SKILL.md +105 -0
  184. package/template/.agent/skill-library/surface/web/design-reference-data/data/charts.csv +26 -0
  185. package/template/.agent/skill-library/surface/web/design-reference-data/data/colors.csv +97 -0
  186. package/template/.agent/skill-library/surface/web/design-reference-data/data/landing.csv +31 -0
  187. package/template/.agent/skill-library/surface/web/design-reference-data/data/styles.csv +59 -0
  188. package/template/.agent/skill-library/surface/web/design-reference-data/data/typography.csv +58 -0
  189. package/template/.agent/skill-library/surface/web/design-reference-data/data/ux-guidelines.csv +100 -0
  190. package/template/.agent/skill-library/surface/web/design-reference-data/scripts/core.py +258 -0
  191. package/template/.agent/skill-library/surface/web/design-reference-data/scripts/design_system.py +1067 -0
  192. package/template/.agent/skill-library/surface/web/design-reference-data/scripts/search.py +106 -0
  193. package/template/.agent/skill-library/surface/web/form-handling-validation/SKILL.md +675 -0
  194. package/template/.agent/skill-library/surface/web/frontend-design/SKILL.md +1393 -0
  195. package/template/.agent/skill-library/surface/web/frontend-design/templates/cppn-hero.tsx +299 -0
  196. package/template/.agent/skill-library/surface/web/frontend-design/templates/wave-hero.tsx +875 -0
  197. package/template/.agent/skill-library/surface/web/frontend-verification/SKILL.md +111 -0
  198. package/template/.agent/skill-library/surface/web/frontend-verification/scripts/ux_audit.py +739 -0
  199. package/template/.agent/skill-library/surface/web/i18n-localization/SKILL.md +154 -0
  200. package/template/.agent/skill-library/surface/web/offline-first-pwa/SKILL.md +657 -0
  201. package/template/.agent/skill-library/surface/web/page-cro/SKILL.md +182 -0
  202. package/template/.agent/skill-library/surface/web/page-cro/references/experiments.md +248 -0
  203. package/template/.agent/skill-library/surface/web/programmatic-seo/SKILL.md +238 -0
  204. package/template/.agent/skill-library/surface/web/programmatic-seo/references/playbooks.md +308 -0
  205. package/template/.agent/skill-library/surface/web/schema-markup/SKILL.md +179 -0
  206. package/template/.agent/skill-library/surface/web/schema-markup/references/schema-examples.md +398 -0
  207. package/template/.agent/skill-library/surface/web/seo-audit/SKILL.md +394 -0
  208. package/template/.agent/skill-library/surface/web/seo-audit/references/ai-writing-detection.md +200 -0
  209. package/template/.agent/skill-library/surface/web/web-performance-optimization/SKILL.md +646 -0
  210. package/template/.agent/skill-library/surface/web/web-scraping/SKILL.md +58 -0
  211. package/template/.agent/skills/accessibility/SKILL.md +522 -0
  212. package/template/.agent/skills/accessibility/references/WCAG.md +162 -0
  213. package/template/.agent/skills/adversarial-review/SKILL.md +90 -0
  214. package/template/.agent/skills/antigravity-workflows/SKILL.md +81 -0
  215. package/template/.agent/skills/antigravity-workflows/resources/implementation-playbook.md +36 -0
  216. package/template/.agent/skills/api-design-principles/SKILL.md +37 -0
  217. package/template/.agent/skills/api-design-principles/assets/api-design-checklist.md +155 -0
  218. package/template/.agent/skills/api-design-principles/assets/rest-api-template.py +182 -0
  219. package/template/.agent/skills/api-design-principles/references/graphql-schema-design.md +583 -0
  220. package/template/.agent/skills/api-design-principles/references/rest-best-practices.md +408 -0
  221. package/template/.agent/skills/api-design-principles/resources/implementation-playbook.md +513 -0
  222. package/template/.agent/skills/api-versioning/SKILL.md +420 -0
  223. package/template/.agent/skills/architecture-mapping/SKILL.md +219 -0
  224. package/template/.agent/skills/bootstrap-agents/SKILL.md +259 -0
  225. package/template/.agent/skills/brainstorming/SKILL.md +236 -0
  226. package/template/.agent/skills/brand-guidelines/SKILL.md +44 -0
  227. package/template/.agent/skills/clean-code/SKILL.md +94 -0
  228. package/template/.agent/skills/code-review-pro/SKILL.md +152 -0
  229. package/template/.agent/skills/concise-planning/SKILL.md +68 -0
  230. package/template/.agent/skills/cross-layer-consistency/SKILL.md +117 -0
  231. package/template/.agent/skills/database-schema-design/SKILL.md +429 -0
  232. package/template/.agent/skills/deployment-procedures/SKILL.md +241 -0
  233. package/template/.agent/skills/design-anti-cliche/SKILL.md +159 -0
  234. package/template/.agent/skills/design-direction/SKILL.md +45 -0
  235. package/template/.agent/skills/error-handling-patterns/SKILL.md +721 -0
  236. package/template/.agent/skills/find-skills/SKILL.md +145 -0
  237. package/template/.agent/skills/git-advanced/SKILL.md +972 -0
  238. package/template/.agent/skills/git-workflow/SKILL.md +420 -0
  239. package/template/.agent/skills/idea-extraction/SKILL.md +271 -0
  240. package/template/.agent/skills/logging-best-practices/SKILL.md +851 -0
  241. package/template/.agent/skills/migration-management/SKILL.md +384 -0
  242. package/template/.agent/skills/minimalist-surgical-development/SKILL.md +69 -0
  243. package/template/.agent/skills/parallel-agents/SKILL.md +165 -0
  244. package/template/.agent/skills/parallel-debugging/SKILL.md +135 -0
  245. package/template/.agent/skills/parallel-feature-development/SKILL.md +166 -0
  246. package/template/.agent/skills/performance-budgeting/SKILL.md +144 -0
  247. package/template/.agent/skills/pipeline-rubrics/SKILL.md +51 -0
  248. package/template/.agent/skills/pipeline-rubrics/references/architecture-rubric.md +19 -0
  249. package/template/.agent/skills/pipeline-rubrics/references/be-rubric.md +21 -0
  250. package/template/.agent/skills/pipeline-rubrics/references/fe-rubric.md +20 -0
  251. package/template/.agent/skills/pipeline-rubrics/references/ia-rubric.md +19 -0
  252. package/template/.agent/skills/pipeline-rubrics/references/scoring.md +28 -0
  253. package/template/.agent/skills/pipeline-rubrics/references/vision-rubric.md +11 -0
  254. package/template/.agent/skills/prd-templates/SKILL.md +88 -0
  255. package/template/.agent/skills/prd-templates/references/architecture-design-template.md +88 -0
  256. package/template/.agent/skills/prd-templates/references/be-spec-template.md +101 -0
  257. package/template/.agent/skills/prd-templates/references/data-placement-template.md +74 -0
  258. package/template/.agent/skills/prd-templates/references/decomposition-templates.md +211 -0
  259. package/template/.agent/skills/prd-templates/references/design-system-decisions.md +198 -0
  260. package/template/.agent/skills/prd-templates/references/engineering-standards-template.md +124 -0
  261. package/template/.agent/skills/prd-templates/references/fe-classification-procedures.md +47 -0
  262. package/template/.agent/skills/prd-templates/references/fe-spec-template.md +84 -0
  263. package/template/.agent/skills/prd-templates/references/infrastructure-report-template.md +71 -0
  264. package/template/.agent/skills/prd-templates/references/operational-templates.md +116 -0
  265. package/template/.agent/skills/prd-templates/references/placeholder-guard-template.md +21 -0
  266. package/template/.agent/skills/prd-templates/references/surface-model.md +61 -0
  267. package/template/.agent/skills/prd-templates/references/vision-template.md +66 -0
  268. package/template/.agent/skills/prompt-engineer/README.md +659 -0
  269. package/template/.agent/skills/prompt-engineer/SKILL.md +249 -0
  270. package/template/.agent/skills/regex-patterns/SKILL.md +751 -0
  271. package/template/.agent/skills/resolve-ambiguity/SKILL.md +278 -0
  272. package/template/.agent/skills/rest-api-design/SKILL.md +478 -0
  273. package/template/.agent/skills/security-scanning-security-hardening/SKILL.md +231 -0
  274. package/template/.agent/skills/session-continuity/SKILL.md +730 -0
  275. package/template/.agent/skills/session-continuity/protocols/01-session-resumption.md +38 -0
  276. package/template/.agent/skills/session-continuity/protocols/02-progress-generation.md +85 -0
  277. package/template/.agent/skills/session-continuity/protocols/03-progress-update.md +70 -0
  278. package/template/.agent/skills/session-continuity/protocols/04-pattern-extraction.md +60 -0
  279. package/template/.agent/skills/session-continuity/protocols/05-session-close.md +37 -0
  280. package/template/.agent/skills/session-continuity/protocols/06-decision-analysis.md +84 -0
  281. package/template/.agent/skills/session-continuity/protocols/07-spec-pipeline-generation.md +48 -0
  282. package/template/.agent/skills/session-continuity/protocols/08-spec-pipeline-update.md +43 -0
  283. package/template/.agent/skills/session-continuity/protocols/09-parallel-claim.md +122 -0
  284. package/template/.agent/skills/session-continuity/protocols/10-placeholder-verification-gate.md +104 -0
  285. package/template/.agent/skills/session-continuity/protocols/ambiguity-gates.md +48 -0
  286. package/template/.agent/skills/skill-creator/LICENSE.txt +202 -0
  287. package/template/.agent/skills/skill-creator/README.md +270 -0
  288. package/template/.agent/skills/skill-creator/SKILL.md +590 -0
  289. package/template/.agent/skills/skill-creator/references/output-patterns.md +82 -0
  290. package/template/.agent/skills/skill-creator/references/workflows.md +28 -0
  291. package/template/.agent/skills/skill-creator/scripts/init_skill.py +303 -0
  292. package/template/.agent/skills/skill-creator/scripts/package_skill.py +110 -0
  293. package/template/.agent/skills/skill-creator/scripts/quick_validate.py +95 -0
  294. package/template/.agent/skills/spec-writing/SKILL.md +110 -0
  295. package/template/.agent/skills/systematic-debugging/CREATION-LOG.md +119 -0
  296. package/template/.agent/skills/systematic-debugging/SKILL.md +297 -0
  297. package/template/.agent/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  298. package/template/.agent/skills/systematic-debugging/condition-based-waiting.md +115 -0
  299. package/template/.agent/skills/systematic-debugging/defense-in-depth.md +122 -0
  300. package/template/.agent/skills/systematic-debugging/find-polluter.sh +63 -0
  301. package/template/.agent/skills/systematic-debugging/root-cause-tracing.md +169 -0
  302. package/template/.agent/skills/systematic-debugging/test-academic.md +14 -0
  303. package/template/.agent/skills/systematic-debugging/test-pressure-1.md +58 -0
  304. package/template/.agent/skills/systematic-debugging/test-pressure-2.md +68 -0
  305. package/template/.agent/skills/systematic-debugging/test-pressure-3.md +69 -0
  306. package/template/.agent/skills/tdd-workflow/SKILL.md +409 -0
  307. package/template/.agent/skills/tech-stack-catalog/SKILL.md +49 -0
  308. package/template/.agent/skills/tech-stack-catalog/references/constraint-questions.md +21 -0
  309. package/template/.agent/skills/tech-stack-catalog/references/dev-tooling-decisions.md +37 -0
  310. package/template/.agent/skills/tech-stack-catalog/references/surface-decision-tables.md +69 -0
  311. package/template/.agent/skills/technical-writer/SKILL.md +242 -0
  312. package/template/.agent/skills/testing-strategist/SKILL.md +932 -0
  313. package/template/.agent/skills/verification-before-completion/SKILL.md +145 -0
  314. package/template/.agent/skills/workflow-automation/SKILL.md +73 -0
  315. package/template/.agent/workflows/audit-ambiguity-execute.md +165 -0
  316. package/template/.agent/workflows/audit-ambiguity-rubrics.md +83 -0
  317. package/template/.agent/workflows/audit-ambiguity.md +64 -0
  318. package/template/.agent/workflows/bootstrap-agents-fill.md +201 -0
  319. package/template/.agent/workflows/bootstrap-agents-provision.md +197 -0
  320. package/template/.agent/workflows/bootstrap-agents.md +66 -0
  321. package/template/.agent/workflows/create-prd-architecture.md +119 -0
  322. package/template/.agent/workflows/create-prd-compile.md +138 -0
  323. package/template/.agent/workflows/create-prd-design-system.md +135 -0
  324. package/template/.agent/workflows/create-prd-security.md +113 -0
  325. package/template/.agent/workflows/create-prd-stack.md +91 -0
  326. package/template/.agent/workflows/create-prd.md +168 -0
  327. package/template/.agent/workflows/decompose-architecture-structure.md +82 -0
  328. package/template/.agent/workflows/decompose-architecture-validate.md +119 -0
  329. package/template/.agent/workflows/decompose-architecture.md +111 -0
  330. package/template/.agent/workflows/evolve-contract.md +98 -0
  331. package/template/.agent/workflows/evolve-feature-cascade.md +140 -0
  332. package/template/.agent/workflows/evolve-feature-classify.md +116 -0
  333. package/template/.agent/workflows/evolve-feature.md +56 -0
  334. package/template/.agent/workflows/ideate-discover.md +144 -0
  335. package/template/.agent/workflows/ideate-extract.md +129 -0
  336. package/template/.agent/workflows/ideate-validate.md +117 -0
  337. package/template/.agent/workflows/ideate.md +113 -0
  338. package/template/.agent/workflows/implement-slice-setup.md +113 -0
  339. package/template/.agent/workflows/implement-slice-tdd.md +198 -0
  340. package/template/.agent/workflows/implement-slice.md +50 -0
  341. package/template/.agent/workflows/plan-phase.md +202 -0
  342. package/template/.agent/workflows/propagate-decision-apply.md +135 -0
  343. package/template/.agent/workflows/propagate-decision-scan.md +147 -0
  344. package/template/.agent/workflows/propagate-decision.md +56 -0
  345. package/template/.agent/workflows/remediate-pipeline-assess.md +138 -0
  346. package/template/.agent/workflows/remediate-pipeline-execute.md +135 -0
  347. package/template/.agent/workflows/remediate-pipeline.md +55 -0
  348. package/template/.agent/workflows/resolve-ambiguity.md +82 -0
  349. package/template/.agent/workflows/sync-kit.md +209 -0
  350. package/template/.agent/workflows/update-architecture-map.md +74 -0
  351. package/template/.agent/workflows/validate-phase.md +219 -0
  352. package/template/.agent/workflows/verify-infrastructure.md +207 -0
  353. package/template/.agent/workflows/write-architecture-spec-deepen.md +139 -0
  354. package/template/.agent/workflows/write-architecture-spec-design.md +202 -0
  355. package/template/.agent/workflows/write-architecture-spec.md +63 -0
  356. package/template/.agent/workflows/write-be-spec-classify.md +165 -0
  357. package/template/.agent/workflows/write-be-spec-write.md +98 -0
  358. package/template/.agent/workflows/write-be-spec.md +76 -0
  359. package/template/.agent/workflows/write-fe-spec-classify.md +170 -0
  360. package/template/.agent/workflows/write-fe-spec-write.md +94 -0
  361. package/template/.agent/workflows/write-fe-spec.md +71 -0
  362. package/template/AGENTS.md +176 -0
  363. package/template/GEMINI.md +177 -0
  364. package/template/docs/README.md +187 -0
  365. package/template/docs/audits/.gitkeep +0 -0
  366. package/template/docs/audits/README.md +10 -0
  367. package/template/docs/plans/.gitkeep +0 -0
  368. package/template/docs/plans/README.md +21 -0
  369. package/template/docs/plans/be/.gitkeep +0 -0
  370. package/template/docs/plans/be/README.md +11 -0
  371. package/template/docs/plans/fe/.gitkeep +0 -0
  372. package/template/docs/plans/fe/README.md +11 -0
  373. package/template/docs/plans/ia/.gitkeep +0 -0
  374. package/template/docs/plans/ia/README.md +17 -0
  375. package/template/docs/plans/ia/deep-dives/.gitkeep +0 -0
  376. package/template/docs/plans/ia/deep-dives/README.md +5 -0
  377. package/template/docs/plans/phases/.gitkeep +0 -0
  378. package/template/docs/plans/phases/README.md +11 -0
@@ -0,0 +1,1132 @@
1
+ ---
2
+ name: sqlite
3
+ description: "Expert SQLite development guide covering when to use SQLite, WAL mode, PRAGMA tuning, full-text search (FTS5), JSON support, window functions, CTEs, better-sqlite3 (Node.js), LMDB comparison, Turso/libSQL for distributed SQLite, Litestream for replication, database-per-tenant patterns, testing with in-memory SQLite, file locking, backup strategies, and migration patterns."
4
+ version: 1.0.0
5
+ ---
6
+
7
+ # SQLite Expert
8
+
9
+ ## 1. When to Use SQLite
10
+
11
+ ### Ideal Use Cases
12
+
13
+ ```
14
+ Edge computing -- Embedded in IoT devices, Cloudflare Workers (D1), edge functions
15
+ Embedded apps -- Desktop apps (Electron), mobile apps (iOS, Android)
16
+ CLI tools -- Local data storage for command-line applications
17
+ Testing -- In-memory databases as test doubles for PostgreSQL/MySQL
18
+ Single-server apps -- Web apps with moderate traffic on a single server
19
+ Prototyping -- Rapid development before migrating to a client-server DB
20
+ Data analysis -- Ad-hoc queries on local datasets, CSV/JSON imports
21
+ Configuration stores -- Application settings, feature flags, local state
22
+ Personal projects -- Blogs, small SaaS, internal tools with < 100K daily requests
23
+ ```
24
+
25
+ ### When NOT to Use SQLite
26
+
27
+ ```
28
+ High write concurrency -- Many concurrent writers (SQLite serializes writes)
29
+ Multi-server deployments -- Multiple app servers writing to the same database
30
+ Very large datasets -- Databases approaching 281 TB limit (practical limit is lower)
31
+ Client-server needs -- When multiple applications must access the same database over a network
32
+ Real-time replication -- Built-in replication does not exist (use Turso/Litestream as workarounds)
33
+ Heavy analytics -- OLAP workloads with full table scans on 100M+ rows
34
+ ```
35
+
36
+ ### Capacity Guidelines
37
+
38
+ ```
39
+ Max database size: 281 TB (theoretical), practical limit depends on filesystem
40
+ Max row size: 1 GB (default page size limits practical row size)
41
+ Max columns per table: 2000
42
+ Concurrent readers: Unlimited (with WAL mode)
43
+ Concurrent writers: 1 at a time (writes are serialized)
44
+ Typical sweet spot: < 1 TB database, < 100K writes/day, unlimited reads
45
+ ```
46
+
47
+ ---
48
+
49
+ ## 2. WAL Mode
50
+
51
+ Write-Ahead Logging mode is essential for production SQLite. It allows concurrent reads during writes and improves performance significantly.
52
+
53
+ ```sql
54
+ -- Enable WAL mode (do this once, it persists across connections)
55
+ PRAGMA journal_mode = WAL;
56
+
57
+ -- Check current journal mode
58
+ PRAGMA journal_mode;
59
+ ```
60
+
61
+ ### How WAL Works
62
+
63
+ ```
64
+ Default (DELETE) mode:
65
+ - Writes lock the entire database
66
+ - Readers blocked during writes
67
+ - Safe but slow
68
+
69
+ WAL mode:
70
+ - Writes go to a separate WAL file
71
+ - Readers see the last committed state (snapshot isolation)
72
+ - Multiple readers can run concurrently with one writer
73
+ - WAL file is periodically checkpointed (merged back into main DB)
74
+ ```
75
+
76
+ ### WAL Configuration
77
+
78
+ ```sql
79
+ -- Auto-checkpoint threshold (pages, default 1000)
80
+ -- Set to 0 to disable auto-checkpoint (manual control)
81
+ PRAGMA wal_autocheckpoint = 1000;
82
+
83
+ -- Manual checkpoint
84
+ PRAGMA wal_checkpoint(TRUNCATE); -- Checkpoint and truncate WAL file
85
+ PRAGMA wal_checkpoint(PASSIVE); -- Checkpoint without blocking
86
+ PRAGMA wal_checkpoint(FULL); -- Checkpoint, block new writers until done
87
+ ```
88
+
89
+ ### WAL Caveats
90
+
91
+ ```
92
+ - WAL file can grow large if checkpoints are infrequent or long transactions hold a snapshot
93
+ - WAL mode does not work over network filesystems (NFS, SMB)
94
+ - WAL mode creates two extra files: .db-wal and .db-shm
95
+ - All three files (.db, .db-wal, .db-shm) must be backed up together
96
+ - WAL mode is slightly slower for write-heavy workloads with no concurrent reads
97
+ ```
98
+
99
+ ---
100
+
101
+ ## 3. PRAGMA Settings for Performance
102
+
103
+ ```sql
104
+ -- Essential production PRAGMAs (run at connection open)
105
+ PRAGMA journal_mode = WAL; -- Write-ahead logging
106
+ PRAGMA synchronous = NORMAL; -- Balance between safety and speed
107
+ PRAGMA cache_size = -64000; -- 64 MB page cache (negative = KB)
108
+ PRAGMA foreign_keys = ON; -- Enforce foreign key constraints
109
+ PRAGMA busy_timeout = 5000; -- Wait 5 seconds for locks instead of failing immediately
110
+ PRAGMA temp_store = MEMORY; -- Store temp tables in memory
111
+ PRAGMA mmap_io = 268435456; -- Memory-map up to 256 MB of the database file
112
+
113
+ -- Analysis and optimization
114
+ PRAGMA optimize; -- Run on connection close (SQLite 3.18+)
115
+ ANALYZE; -- Update query planner statistics
116
+ ```
117
+
118
+ ### PRAGMA Reference
119
+
120
+ ```
121
+ journal_mode:
122
+ DELETE -- Default. Delete journal after commit. Safest, slowest.
123
+ WAL -- Write-ahead log. Best for concurrent reads. Recommended.
124
+ MEMORY -- Journal in memory. Fast but not crash-safe.
125
+ OFF -- No journal. Fastest, no crash recovery. Testing only.
126
+
127
+ synchronous:
128
+ FULL -- Sync after every write. Slowest, safest.
129
+ NORMAL -- Sync at critical moments. Good balance. Recommended with WAL.
130
+ OFF -- No syncing. Fastest. Data loss on power failure.
131
+
132
+ cache_size:
133
+ Positive -- Number of pages (default page size 4096 bytes)
134
+ Negative -- Size in KB (e.g., -64000 = 64 MB)
135
+
136
+ busy_timeout:
137
+ 0 -- Return SQLITE_BUSY immediately (default)
138
+ N -- Wait N milliseconds for the lock before returning SQLITE_BUSY
139
+
140
+ temp_store:
141
+ DEFAULT -- Use compile-time default
142
+ FILE -- Temp data on disk
143
+ MEMORY -- Temp data in memory (faster for temp tables and sorting)
144
+ ```
145
+
146
+ ---
147
+
148
+ ## 4. Full-Text Search (FTS5)
149
+
150
+ ```sql
151
+ -- Create an FTS5 virtual table
152
+ CREATE VIRTUAL TABLE articles_fts USING fts5(
153
+ title,
154
+ body,
155
+ tags,
156
+ content='articles', -- Content table (external content FTS)
157
+ content_rowid='id', -- Map to the real table's rowid
158
+ tokenize='porter unicode61' -- Porter stemmer + Unicode tokenizer
159
+ );
160
+
161
+ -- Populate FTS index from existing data
162
+ INSERT INTO articles_fts(articles_fts) VALUES('rebuild');
163
+
164
+ -- Keep FTS in sync with triggers
165
+ CREATE TRIGGER articles_ai AFTER INSERT ON articles BEGIN
166
+ INSERT INTO articles_fts(rowid, title, body, tags)
167
+ VALUES (new.id, new.title, new.body, new.tags);
168
+ END;
169
+
170
+ CREATE TRIGGER articles_ad AFTER DELETE ON articles BEGIN
171
+ INSERT INTO articles_fts(articles_fts, rowid, title, body, tags)
172
+ VALUES ('delete', old.id, old.title, old.body, old.tags);
173
+ END;
174
+
175
+ CREATE TRIGGER articles_au AFTER UPDATE ON articles BEGIN
176
+ INSERT INTO articles_fts(articles_fts, rowid, title, body, tags)
177
+ VALUES ('delete', old.id, old.title, old.body, old.tags);
178
+ INSERT INTO articles_fts(rowid, title, body, tags)
179
+ VALUES (new.id, new.title, new.body, new.tags);
180
+ END;
181
+
182
+ -- Search queries
183
+ SELECT a.*, rank
184
+ FROM articles_fts
185
+ JOIN articles a ON a.id = articles_fts.rowid
186
+ WHERE articles_fts MATCH 'sqlite AND performance'
187
+ ORDER BY rank;
188
+
189
+ -- Phrase search
190
+ SELECT * FROM articles_fts WHERE articles_fts MATCH '"full text search"';
191
+
192
+ -- Column-specific search
193
+ SELECT * FROM articles_fts WHERE articles_fts MATCH 'title:sqlite OR body:optimization';
194
+
195
+ -- Prefix search
196
+ SELECT * FROM articles_fts WHERE articles_fts MATCH 'optim*';
197
+
198
+ -- NEAR operator
199
+ SELECT * FROM articles_fts WHERE articles_fts MATCH 'NEAR(sqlite performance, 5)';
200
+
201
+ -- BM25 ranking (built into FTS5)
202
+ SELECT *, bm25(articles_fts, 10.0, 1.0, 5.0) AS score
203
+ FROM articles_fts
204
+ WHERE articles_fts MATCH 'database optimization'
205
+ ORDER BY score;
206
+ -- Weights: title=10, body=1, tags=5
207
+
208
+ -- Highlight snippets
209
+ SELECT highlight(articles_fts, 1, '<mark>', '</mark>') AS snippet
210
+ FROM articles_fts
211
+ WHERE articles_fts MATCH 'sqlite';
212
+
213
+ -- Snippet with context
214
+ SELECT snippet(articles_fts, 1, '<mark>', '</mark>', '...', 20) AS snippet
215
+ FROM articles_fts
216
+ WHERE articles_fts MATCH 'sqlite';
217
+ ```
218
+
219
+ ---
220
+
221
+ ## 5. JSON Support
222
+
223
+ ```sql
224
+ -- SQLite has built-in JSON functions (3.9+) and JSON operators (3.38+)
225
+
226
+ -- Create a table with JSON data
227
+ CREATE TABLE products (
228
+ id INTEGER PRIMARY KEY,
229
+ name TEXT NOT NULL,
230
+ data JSON NOT NULL DEFAULT '{}'
231
+ );
232
+
233
+ -- Insert JSON data
234
+ INSERT INTO products (name, data) VALUES (
235
+ 'Widget',
236
+ '{"price": 29.99, "specs": {"weight": 1.5, "color": "blue"}, "tags": ["sale", "featured"]}'
237
+ );
238
+
239
+ -- Extract values with json_extract()
240
+ SELECT
241
+ name,
242
+ json_extract(data, '$.price') AS price,
243
+ json_extract(data, '$.specs.weight') AS weight,
244
+ json_extract(data, '$.specs.color') AS color
245
+ FROM products;
246
+
247
+ -- Arrow operators (3.38+)
248
+ SELECT
249
+ name,
250
+ data ->> '$.price' AS price, -- Extract as SQL value (text, int, float)
251
+ data -> '$.specs' AS specs -- Extract as JSON string
252
+ FROM products;
253
+
254
+ -- Query JSON arrays
255
+ SELECT * FROM products
256
+ WHERE EXISTS (
257
+ SELECT 1 FROM json_each(json_extract(data, '$.tags'))
258
+ WHERE value = 'sale'
259
+ );
260
+
261
+ -- json_each: expand JSON array to rows
262
+ SELECT p.name, tag.value AS tag
263
+ FROM products p, json_each(json_extract(p.data, '$.tags')) tag;
264
+
265
+ -- json_tree: recursively expand JSON
266
+ SELECT * FROM json_tree('{"a": {"b": [1, 2, 3]}}');
267
+
268
+ -- Modify JSON
269
+ UPDATE products
270
+ SET data = json_set(data, '$.price', 24.99)
271
+ WHERE id = 1;
272
+
273
+ UPDATE products
274
+ SET data = json_insert(data, '$.inStock', true)
275
+ WHERE id = 1;
276
+
277
+ UPDATE products
278
+ SET data = json_remove(data, '$.tags[0]')
279
+ WHERE id = 1;
280
+
281
+ -- JSON aggregation
282
+ SELECT json_group_array(name) AS names FROM products;
283
+ SELECT json_group_object(name, json_extract(data, '$.price')) AS price_map FROM products;
284
+
285
+ -- Index on JSON value (generated column approach)
286
+ ALTER TABLE products ADD COLUMN price_indexed REAL
287
+ GENERATED ALWAYS AS (json_extract(data, '$.price')) STORED;
288
+ CREATE INDEX idx_products_price ON products (price_indexed);
289
+ ```
290
+
291
+ ---
292
+
293
+ ## 6. Window Functions
294
+
295
+ ```sql
296
+ -- ROW_NUMBER, RANK, DENSE_RANK
297
+ SELECT
298
+ name,
299
+ category,
300
+ price,
301
+ ROW_NUMBER() OVER (ORDER BY price DESC) AS row_num,
302
+ RANK() OVER (ORDER BY price DESC) AS rank,
303
+ DENSE_RANK() OVER (ORDER BY price DESC) AS dense_rank
304
+ FROM products;
305
+
306
+ -- Partitioned ranking
307
+ SELECT
308
+ name,
309
+ category,
310
+ price,
311
+ ROW_NUMBER() OVER (PARTITION BY category ORDER BY price DESC) AS rank_in_category
312
+ FROM products;
313
+
314
+ -- Running totals
315
+ SELECT
316
+ date,
317
+ revenue,
318
+ SUM(revenue) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_total
319
+ FROM daily_revenue;
320
+
321
+ -- Moving average
322
+ SELECT
323
+ date,
324
+ revenue,
325
+ AVG(revenue) OVER (ORDER BY date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS avg_7day
326
+ FROM daily_revenue;
327
+
328
+ -- LAG and LEAD (previous/next row values)
329
+ SELECT
330
+ date,
331
+ revenue,
332
+ LAG(revenue, 1) OVER (ORDER BY date) AS prev_day_revenue,
333
+ LEAD(revenue, 1) OVER (ORDER BY date) AS next_day_revenue,
334
+ revenue - LAG(revenue, 1) OVER (ORDER BY date) AS day_over_day_change
335
+ FROM daily_revenue;
336
+
337
+ -- FIRST_VALUE and LAST_VALUE
338
+ SELECT
339
+ name,
340
+ category,
341
+ price,
342
+ FIRST_VALUE(name) OVER (PARTITION BY category ORDER BY price DESC) AS most_expensive,
343
+ price * 1.0 / FIRST_VALUE(price) OVER (PARTITION BY category ORDER BY price DESC) AS pct_of_max
344
+ FROM products;
345
+
346
+ -- NTILE (divide into buckets)
347
+ SELECT
348
+ name,
349
+ price,
350
+ NTILE(4) OVER (ORDER BY price) AS price_quartile
351
+ FROM products;
352
+ ```
353
+
354
+ ---
355
+
356
+ ## 7. CTEs (Common Table Expressions)
357
+
358
+ ```sql
359
+ -- Basic CTE for readability
360
+ WITH active_users AS (
361
+ SELECT id, name, email
362
+ FROM users
363
+ WHERE active = 1
364
+ ),
365
+ recent_orders AS (
366
+ SELECT user_id, COUNT(*) AS order_count, SUM(total) AS total_spent
367
+ FROM orders
368
+ WHERE created_at > datetime('now', '-30 days')
369
+ GROUP BY user_id
370
+ )
371
+ SELECT
372
+ au.name,
373
+ au.email,
374
+ COALESCE(ro.order_count, 0) AS orders,
375
+ COALESCE(ro.total_spent, 0) AS spent
376
+ FROM active_users au
377
+ LEFT JOIN recent_orders ro ON ro.user_id = au.id
378
+ ORDER BY spent DESC;
379
+
380
+ -- Recursive CTE: hierarchical data (org chart, categories, threads)
381
+ WITH RECURSIVE category_tree AS (
382
+ -- Base case: root categories
383
+ SELECT id, name, parent_id, 0 AS depth, name AS path
384
+ FROM categories
385
+ WHERE parent_id IS NULL
386
+
387
+ UNION ALL
388
+
389
+ -- Recursive case: child categories
390
+ SELECT c.id, c.name, c.parent_id, ct.depth + 1, ct.path || ' > ' || c.name
391
+ FROM categories c
392
+ JOIN category_tree ct ON c.parent_id = ct.id
393
+ )
394
+ SELECT * FROM category_tree ORDER BY path;
395
+
396
+ -- Recursive CTE: generate a date series
397
+ WITH RECURSIVE dates AS (
398
+ SELECT date('2025-01-01') AS d
399
+ UNION ALL
400
+ SELECT date(d, '+1 day')
401
+ FROM dates
402
+ WHERE d < date('2025-01-31')
403
+ )
404
+ SELECT d AS date, COALESCE(r.revenue, 0) AS revenue
405
+ FROM dates
406
+ LEFT JOIN daily_revenue r ON r.date = dates.d;
407
+ ```
408
+
409
+ ---
410
+
411
+ ## 8. better-sqlite3 (Node.js)
412
+
413
+ ### Setup and Configuration
414
+
415
+ ```typescript
416
+ import Database from "better-sqlite3";
417
+ import path from "path";
418
+
419
+ const DB_PATH = path.resolve(process.env.DB_PATH || "./data/app.db");
420
+
421
+ // Open database with recommended options
422
+ const db = new Database(DB_PATH, {
423
+ verbose: process.env.NODE_ENV === "development" ? console.log : undefined,
424
+ fileMustExist: false, // Create if not exists
425
+ });
426
+
427
+ // Apply production PRAGMAs
428
+ db.pragma("journal_mode = WAL");
429
+ db.pragma("synchronous = NORMAL");
430
+ db.pragma("cache_size = -64000");
431
+ db.pragma("foreign_keys = ON");
432
+ db.pragma("busy_timeout = 5000");
433
+ db.pragma("temp_store = MEMORY");
434
+
435
+ // Enable optimize on close
436
+ process.on("exit", () => {
437
+ db.pragma("optimize");
438
+ db.close();
439
+ });
440
+
441
+ // Graceful shutdown
442
+ process.on("SIGINT", () => process.exit(0));
443
+ process.on("SIGTERM", () => process.exit(0));
444
+ ```
445
+
446
+ ### CRUD Operations
447
+
448
+ ```typescript
449
+ // Prepared statements (compiled once, executed many times -- much faster)
450
+ const insertUser = db.prepare(`
451
+ INSERT INTO users (name, email, created_at)
452
+ VALUES (@name, @email, datetime('now'))
453
+ `);
454
+
455
+ const getUserById = db.prepare(`
456
+ SELECT * FROM users WHERE id = ?
457
+ `);
458
+
459
+ const getUsersByStatus = db.prepare(`
460
+ SELECT * FROM users WHERE active = ? ORDER BY created_at DESC LIMIT ?
461
+ `);
462
+
463
+ const updateUser = db.prepare(`
464
+ UPDATE users SET name = @name, email = @email WHERE id = @id
465
+ `);
466
+
467
+ const deleteUser = db.prepare(`
468
+ DELETE FROM users WHERE id = ?
469
+ `);
470
+
471
+ // Execute
472
+ const result = insertUser.run({ name: "Alice", email: "alice@example.com" });
473
+ console.log("Inserted ID:", result.lastInsertRowid);
474
+ console.log("Changes:", result.changes);
475
+
476
+ const user = getUserById.get(1); // Returns a single row or undefined
477
+ const users = getUsersByStatus.all(1, 20); // Returns array of rows
478
+
479
+ updateUser.run({ id: 1, name: "Alice Smith", email: "alice@example.com" });
480
+ deleteUser.run(1);
481
+ ```
482
+
483
+ ### Transactions
484
+
485
+ ```typescript
486
+ // Transactions in better-sqlite3 are synchronous and fast
487
+ const transferFunds = db.transaction((fromId: number, toId: number, amount: number) => {
488
+ const from = db.prepare("SELECT balance FROM accounts WHERE id = ?").get(fromId);
489
+ if (!from || from.balance < amount) {
490
+ throw new Error("Insufficient funds");
491
+ }
492
+
493
+ db.prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?").run(amount, fromId);
494
+ db.prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?").run(amount, toId);
495
+
496
+ return { fromId, toId, amount };
497
+ });
498
+
499
+ // Transactions automatically rollback on error
500
+ try {
501
+ const result = transferFunds(1, 2, 100);
502
+ console.log("Transfer complete:", result);
503
+ } catch (err) {
504
+ console.error("Transfer failed:", err.message);
505
+ }
506
+
507
+ // Bulk insert (wrap in transaction for massive speedup)
508
+ const insertMany = db.transaction((items: { name: string; value: number }[]) => {
509
+ const stmt = db.prepare("INSERT INTO items (name, value) VALUES (@name, @value)");
510
+ for (const item of items) {
511
+ stmt.run(item);
512
+ }
513
+ return items.length;
514
+ });
515
+
516
+ // Without transaction: ~50 inserts/second
517
+ // With transaction: ~50,000 inserts/second
518
+ const count = insertMany(largeArray);
519
+ ```
520
+
521
+ ### Custom Functions
522
+
523
+ ```typescript
524
+ // Register custom SQL functions
525
+ db.function("generate_slug", (text: string) => {
526
+ return text
527
+ .toLowerCase()
528
+ .replace(/[^a-z0-9]+/g, "-")
529
+ .replace(/(^-|-$)/g, "");
530
+ });
531
+
532
+ // Use in queries
533
+ db.prepare("INSERT INTO posts (title, slug) VALUES (?, generate_slug(?))").run(title, title);
534
+
535
+ // Aggregate function
536
+ db.aggregate("median", {
537
+ start: () => [] as number[],
538
+ step: (acc: number[], value: number) => {
539
+ acc.push(value);
540
+ },
541
+ result: (acc: number[]) => {
542
+ acc.sort((a, b) => a - b);
543
+ const mid = Math.floor(acc.length / 2);
544
+ return acc.length % 2 === 0 ? (acc[mid - 1] + acc[mid]) / 2 : acc[mid];
545
+ },
546
+ });
547
+
548
+ const result = db.prepare("SELECT median(price) AS median_price FROM products").get();
549
+ ```
550
+
551
+ ---
552
+
553
+ ## 9. Turso / libSQL (Distributed SQLite)
554
+
555
+ ### What It Is
556
+
557
+ ```
558
+ Turso is a hosted SQLite-compatible database built on libSQL (a fork of SQLite):
559
+ - Edge deployment: database replicas close to users worldwide
560
+ - Embedded replicas: sync a local SQLite copy for zero-latency reads
561
+ - HTTP API: access from serverless environments (no persistent connections needed)
562
+ - SQLite compatibility: use standard SQLite syntax and tools
563
+ - Multi-tenancy: one database per tenant, or shared database with RLS
564
+ ```
565
+
566
+ ### Client Usage
567
+
568
+ ```typescript
569
+ import { createClient } from "@libsql/client";
570
+
571
+ // Remote connection (Turso hosted)
572
+ const db = createClient({
573
+ url: process.env.TURSO_DATABASE_URL, // libsql://mydb-myorg.turso.io
574
+ authToken: process.env.TURSO_AUTH_TOKEN,
575
+ });
576
+
577
+ // Embedded replica (local copy with remote sync)
578
+ const db = createClient({
579
+ url: "file:./local-replica.db",
580
+ syncUrl: process.env.TURSO_DATABASE_URL,
581
+ authToken: process.env.TURSO_AUTH_TOKEN,
582
+ syncInterval: 60, // Sync every 60 seconds
583
+ });
584
+
585
+ // Queries
586
+ const result = await db.execute("SELECT * FROM users WHERE active = ?", [true]);
587
+ console.log(result.rows);
588
+
589
+ // Batch (transaction)
590
+ await db.batch([
591
+ { sql: "INSERT INTO users (name, email) VALUES (?, ?)", args: ["Alice", "alice@example.com"] },
592
+ { sql: "INSERT INTO audit_log (action, user_email) VALUES (?, ?)", args: ["user_created", "alice@example.com"] },
593
+ ], "write");
594
+
595
+ // Interactive transaction
596
+ const tx = await db.transaction("write");
597
+ try {
598
+ await tx.execute("UPDATE accounts SET balance = balance - ? WHERE id = ?", [100, fromId]);
599
+ await tx.execute("UPDATE accounts SET balance = balance + ? WHERE id = ?", [100, toId]);
600
+ await tx.commit();
601
+ } catch {
602
+ await tx.rollback();
603
+ }
604
+ ```
605
+
606
+ ---
607
+
608
+ ## 10. Litestream (Continuous Replication)
609
+
610
+ ### What It Is
611
+
612
+ ```
613
+ Litestream continuously replicates a SQLite database to S3-compatible storage:
614
+ - Streaming WAL replication (near real-time, sub-second lag)
615
+ - Point-in-time recovery
616
+ - No changes to application code required
617
+ - Works with any SQLite database
618
+ - Restore to any point in time within retention period
619
+ ```
620
+
621
+ ### Configuration
622
+
623
+ ```yaml
624
+ # litestream.yml
625
+ dbs:
626
+ - path: /data/app.db
627
+ replicas:
628
+ - type: s3
629
+ bucket: my-backup-bucket
630
+ path: app-db
631
+ region: us-west-2
632
+ access-key-id: ${AWS_ACCESS_KEY_ID}
633
+ secret-access-key: ${AWS_SECRET_ACCESS_KEY}
634
+ retention: 720h # Keep 30 days of WAL segments
635
+ retention-check-interval: 1h
636
+ sync-interval: 1s # Replicate every second
637
+
638
+ # Multiple replicas supported
639
+ - type: abs # Azure Blob Storage
640
+ bucket: my-container
641
+ path: app-db
642
+ account-name: ${AZURE_ACCOUNT_NAME}
643
+ account-key: ${AZURE_ACCOUNT_KEY}
644
+ ```
645
+
646
+ ### Commands
647
+
648
+ ```bash
649
+ # Start replication (runs as a daemon alongside your app)
650
+ litestream replicate -config litestream.yml
651
+
652
+ # Restore from replica
653
+ litestream restore -config litestream.yml -o /data/restored.db /data/app.db
654
+
655
+ # Restore to a specific point in time
656
+ litestream restore -config litestream.yml -timestamp "2025-02-15T10:30:00Z" -o /data/restored.db /data/app.db
657
+
658
+ # List available snapshots and WAL segments
659
+ litestream snapshots -config litestream.yml /data/app.db
660
+ litestream wal -config litestream.yml /data/app.db
661
+ ```
662
+
663
+ ### Dockerfile Pattern
664
+
665
+ ```dockerfile
666
+ FROM node:20-slim
667
+
668
+ # Install Litestream
669
+ RUN apt-get update && apt-get install -y wget && \
670
+ wget https://github.com/benbjohnson/litestream/releases/download/v0.3.13/litestream-v0.3.13-linux-amd64.deb && \
671
+ dpkg -i litestream-v0.3.13-linux-amd64.deb && \
672
+ rm litestream-v0.3.13-linux-amd64.deb
673
+
674
+ COPY litestream.yml /etc/litestream.yml
675
+ COPY . /app
676
+ WORKDIR /app
677
+
678
+ # Restore database on startup, then run app with replication
679
+ CMD ["sh", "-c", "litestream restore -if-db-not-exists -config /etc/litestream.yml /data/app.db && litestream replicate -config /etc/litestream.yml -exec 'node server.js'"]
680
+ ```
681
+
682
+ ---
683
+
684
+ ## 11. Database-per-Tenant Pattern
685
+
686
+ ```typescript
687
+ import Database from "better-sqlite3";
688
+ import path from "path";
689
+ import fs from "fs";
690
+
691
+ const TENANT_DB_DIR = path.resolve("./data/tenants");
692
+
693
+ // Cache open database connections
694
+ const dbPool = new Map<string, Database.Database>();
695
+
696
+ function getTenantDB(tenantId: string): Database.Database {
697
+ // Validate tenant ID (prevent path traversal)
698
+ if (!/^[a-zA-Z0-9_-]+$/.test(tenantId)) {
699
+ throw new Error("Invalid tenant ID");
700
+ }
701
+
702
+ if (dbPool.has(tenantId)) {
703
+ return dbPool.get(tenantId)!;
704
+ }
705
+
706
+ const dbPath = path.join(TENANT_DB_DIR, `${tenantId}.db`);
707
+ const isNew = !fs.existsSync(dbPath);
708
+
709
+ const db = new Database(dbPath);
710
+ db.pragma("journal_mode = WAL");
711
+ db.pragma("synchronous = NORMAL");
712
+ db.pragma("foreign_keys = ON");
713
+ db.pragma("busy_timeout = 5000");
714
+
715
+ if (isNew) {
716
+ // Run migrations for new tenant
717
+ applyMigrations(db);
718
+ }
719
+
720
+ dbPool.set(tenantId, db);
721
+ return db;
722
+ }
723
+
724
+ function closeTenantDB(tenantId: string): void {
725
+ const db = dbPool.get(tenantId);
726
+ if (db) {
727
+ db.pragma("optimize");
728
+ db.close();
729
+ dbPool.delete(tenantId);
730
+ }
731
+ }
732
+
733
+ // Close all on shutdown
734
+ function closeAllTenantDBs(): void {
735
+ for (const [tenantId] of dbPool) {
736
+ closeTenantDB(tenantId);
737
+ }
738
+ }
739
+
740
+ process.on("exit", closeAllTenantDBs);
741
+ ```
742
+
743
+ ### Benefits and Trade-offs
744
+
745
+ ```
746
+ Benefits:
747
+ - Complete data isolation between tenants
748
+ - Easy to backup, restore, or delete a single tenant's data
749
+ - Easy to move a tenant to a different server
750
+ - No noisy neighbor problems (one tenant's queries do not affect others)
751
+ - Different tenants can run different schema versions during migrations
752
+ - Simple per-tenant data export (just copy the .db file)
753
+
754
+ Trade-offs:
755
+ - More files to manage (one .db + .db-wal + .db-shm per tenant)
756
+ - Cross-tenant queries require opening multiple databases
757
+ - Connection pool management (open file descriptor limits)
758
+ - Schema migrations must be applied to every tenant database
759
+ - Monitoring and alerting is more complex
760
+ ```
761
+
762
+ ---
763
+
764
+ ## 12. Testing with In-Memory SQLite
765
+
766
+ ```typescript
767
+ import Database from "better-sqlite3";
768
+
769
+ function createTestDB(): Database.Database {
770
+ const db = new Database(":memory:"); // In-memory, no disk I/O
771
+ db.pragma("foreign_keys = ON");
772
+
773
+ // Apply schema
774
+ db.exec(`
775
+ CREATE TABLE users (
776
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
777
+ name TEXT NOT NULL,
778
+ email TEXT NOT NULL UNIQUE,
779
+ active INTEGER NOT NULL DEFAULT 1,
780
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
781
+ );
782
+
783
+ CREATE TABLE orders (
784
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
785
+ user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
786
+ total REAL NOT NULL CHECK (total >= 0),
787
+ status TEXT NOT NULL DEFAULT 'pending'
788
+ CHECK (status IN ('pending', 'confirmed', 'shipped', 'delivered', 'cancelled')),
789
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
790
+ );
791
+
792
+ CREATE INDEX idx_orders_user_id ON orders (user_id);
793
+ CREATE INDEX idx_orders_status ON orders (status);
794
+ `);
795
+
796
+ return db;
797
+ }
798
+
799
+ // Vitest example
800
+ import { describe, it, expect, beforeEach } from "vitest";
801
+
802
+ describe("User Repository", () => {
803
+ let db: Database.Database;
804
+
805
+ beforeEach(() => {
806
+ db = createTestDB(); // Fresh database per test (fast, isolated)
807
+ });
808
+
809
+ it("should create a user", () => {
810
+ const stmt = db.prepare("INSERT INTO users (name, email) VALUES (?, ?)");
811
+ const result = stmt.run("Alice", "alice@example.com");
812
+ expect(result.lastInsertRowid).toBe(1);
813
+ expect(result.changes).toBe(1);
814
+ });
815
+
816
+ it("should enforce unique email", () => {
817
+ const stmt = db.prepare("INSERT INTO users (name, email) VALUES (?, ?)");
818
+ stmt.run("Alice", "alice@example.com");
819
+ expect(() => stmt.run("Bob", "alice@example.com")).toThrow(/UNIQUE constraint failed/);
820
+ });
821
+
822
+ it("should cascade delete orders when user is deleted", () => {
823
+ db.prepare("INSERT INTO users (name, email) VALUES (?, ?)").run("Alice", "alice@example.com");
824
+ db.prepare("INSERT INTO orders (user_id, total) VALUES (?, ?)").run(1, 49.99);
825
+ db.prepare("INSERT INTO orders (user_id, total) VALUES (?, ?)").run(1, 29.99);
826
+
827
+ db.prepare("DELETE FROM users WHERE id = ?").run(1);
828
+
829
+ const orders = db.prepare("SELECT * FROM orders WHERE user_id = ?").all(1);
830
+ expect(orders).toHaveLength(0);
831
+ });
832
+ });
833
+ ```
834
+
835
+ ### Using SQLite as a PostgreSQL Test Double
836
+
837
+ ```typescript
838
+ // If your production DB is PostgreSQL, you can use SQLite for fast unit tests.
839
+ // Key differences to account for:
840
+ //
841
+ // 1. Type system: SQLite is dynamically typed, PostgreSQL is strict
842
+ // 2. Date functions: datetime('now') vs now(), date arithmetic differs
843
+ // 3. String functions: Some PostgreSQL functions do not exist in SQLite
844
+ // 4. RETURNING clause: SQLite 3.35+ supports RETURNING
845
+ // 5. UPSERT: SQLite supports ON CONFLICT, syntax is slightly different
846
+ // 6. JSON: SQLite uses json_extract(), PostgreSQL uses -> and ->>
847
+ //
848
+ // Strategy: Write a thin adapter layer that translates between the two.
849
+ // Use SQLite for fast unit tests, PostgreSQL for integration tests.
850
+ ```
851
+
852
+ ---
853
+
854
+ ## 13. File Locking
855
+
856
+ ```
857
+ SQLite uses file-level locking to manage concurrent access:
858
+
859
+ Lock levels (in order of escalation):
860
+ UNLOCKED -- No lock held
861
+ SHARED -- Reading, multiple readers allowed
862
+ RESERVED -- Planning to write, one writer allowed, readers continue
863
+ PENDING -- Waiting for readers to finish before writing
864
+ EXCLUSIVE -- Writing, no other access allowed
865
+
866
+ WAL mode changes this significantly:
867
+ - Readers never block writers
868
+ - Writers never block readers
869
+ - Only one writer at a time (other writers wait based on busy_timeout)
870
+
871
+ Common SQLITE_BUSY errors:
872
+ - Multiple processes writing simultaneously
873
+ - Long-running read transactions holding a snapshot
874
+ - WAL file growing because a reader holds an old snapshot
875
+
876
+ Solutions:
877
+ - Set PRAGMA busy_timeout = 5000 (wait before failing)
878
+ - Keep write transactions short
879
+ - Use a single write connection and multiple read connections
880
+ - In WAL mode, close long-running read transactions promptly
881
+ ```
882
+
883
+ ### Connection Pool Pattern
884
+
885
+ ```typescript
886
+ import Database from "better-sqlite3";
887
+
888
+ class SQLitePool {
889
+ private writer: Database.Database;
890
+ private readers: Database.Database[];
891
+ private readerIndex = 0;
892
+
893
+ constructor(dbPath: string, readerCount = 4) {
894
+ // Single writer connection
895
+ this.writer = new Database(dbPath);
896
+ this.writer.pragma("journal_mode = WAL");
897
+ this.writer.pragma("synchronous = NORMAL");
898
+ this.writer.pragma("foreign_keys = ON");
899
+ this.writer.pragma("busy_timeout = 5000");
900
+
901
+ // Multiple reader connections
902
+ this.readers = Array.from({ length: readerCount }, () => {
903
+ const reader = new Database(dbPath, { readonly: true });
904
+ reader.pragma("cache_size = -32000");
905
+ return reader;
906
+ });
907
+ }
908
+
909
+ getWriter(): Database.Database {
910
+ return this.writer;
911
+ }
912
+
913
+ getReader(): Database.Database {
914
+ const reader = this.readers[this.readerIndex % this.readers.length];
915
+ this.readerIndex++;
916
+ return reader;
917
+ }
918
+
919
+ close(): void {
920
+ this.writer.pragma("optimize");
921
+ this.writer.close();
922
+ for (const reader of this.readers) {
923
+ reader.close();
924
+ }
925
+ }
926
+ }
927
+ ```
928
+
929
+ ---
930
+
931
+ ## 14. Backup Strategies
932
+
933
+ ```bash
934
+ # Online backup using SQLite's backup API (safe with concurrent access)
935
+ sqlite3 /data/app.db ".backup /backups/app-$(date +%Y%m%d-%H%M%S).db"
936
+
937
+ # With better-sqlite3 in Node.js:
938
+ ```
939
+
940
+ ```typescript
941
+ const db = new Database("/data/app.db");
942
+
943
+ // Backup to a file
944
+ db.backup("/backups/app-backup.db")
945
+ .then(() => console.log("Backup complete"))
946
+ .catch((err) => console.error("Backup failed:", err));
947
+
948
+ // Backup with progress
949
+ await db.backup("/backups/app-backup.db", {
950
+ progress({ totalPages, remainingPages }) {
951
+ const pct = ((totalPages - remainingPages) / totalPages * 100).toFixed(1);
952
+ console.log(`Backup progress: ${pct}%`);
953
+ return 200; // Sleep 200ms between steps (reduce I/O pressure)
954
+ },
955
+ });
956
+ ```
957
+
958
+ ```bash
959
+ # NEVER just copy the .db file while the database is in use
960
+ # The .db-wal file may contain uncommitted data
961
+
962
+ # If you must copy files, checkpoint first:
963
+ sqlite3 /data/app.db "PRAGMA wal_checkpoint(TRUNCATE);"
964
+ # Then copy the .db file (WAL is now empty)
965
+
966
+ # For continuous backup, use Litestream (see section 10)
967
+ ```
968
+
969
+ ---
970
+
971
+ ## 15. Migration Patterns
972
+
973
+ ```typescript
974
+ interface Migration {
975
+ version: number;
976
+ description: string;
977
+ up: string;
978
+ }
979
+
980
+ const migrations: Migration[] = [
981
+ {
982
+ version: 1,
983
+ description: "Create users table",
984
+ up: `
985
+ CREATE TABLE users (
986
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
987
+ name TEXT NOT NULL,
988
+ email TEXT NOT NULL UNIQUE,
989
+ active INTEGER NOT NULL DEFAULT 1,
990
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
991
+ );
992
+ `,
993
+ },
994
+ {
995
+ version: 2,
996
+ description: "Create orders table",
997
+ up: `
998
+ CREATE TABLE orders (
999
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
1000
+ user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
1001
+ total REAL NOT NULL CHECK (total >= 0),
1002
+ status TEXT NOT NULL DEFAULT 'pending',
1003
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
1004
+ );
1005
+ CREATE INDEX idx_orders_user_id ON orders (user_id);
1006
+ `,
1007
+ },
1008
+ {
1009
+ version: 3,
1010
+ description: "Add phone column to users",
1011
+ up: `
1012
+ ALTER TABLE users ADD COLUMN phone TEXT;
1013
+ `,
1014
+ },
1015
+ ];
1016
+
1017
+ function applyMigrations(db: Database.Database): void {
1018
+ // Create migrations tracking table
1019
+ db.exec(`
1020
+ CREATE TABLE IF NOT EXISTS _migrations (
1021
+ version INTEGER PRIMARY KEY,
1022
+ description TEXT NOT NULL,
1023
+ applied_at TEXT NOT NULL DEFAULT (datetime('now'))
1024
+ );
1025
+ `);
1026
+
1027
+ const currentVersion = db.prepare(
1028
+ "SELECT COALESCE(MAX(version), 0) AS version FROM _migrations"
1029
+ ).get() as { version: number };
1030
+
1031
+ const pending = migrations.filter((m) => m.version > currentVersion.version);
1032
+
1033
+ if (pending.length === 0) {
1034
+ return;
1035
+ }
1036
+
1037
+ const applyAll = db.transaction(() => {
1038
+ for (const migration of pending) {
1039
+ db.exec(migration.up);
1040
+ db.prepare(
1041
+ "INSERT INTO _migrations (version, description) VALUES (?, ?)"
1042
+ ).run(migration.version, migration.description);
1043
+ console.log(`Applied migration ${migration.version}: ${migration.description}`);
1044
+ }
1045
+ });
1046
+
1047
+ applyAll();
1048
+ }
1049
+ ```
1050
+
1051
+ ---
1052
+
1053
+ ## 16. Common Anti-Patterns
1054
+
1055
+ ### Missing WAL Mode
1056
+
1057
+ ```typescript
1058
+ // BAD: Default journal mode (readers blocked during writes)
1059
+ const db = new Database("app.db");
1060
+
1061
+ // GOOD: Enable WAL for concurrent access
1062
+ const db = new Database("app.db");
1063
+ db.pragma("journal_mode = WAL");
1064
+ ```
1065
+
1066
+ ### Missing busy_timeout
1067
+
1068
+ ```typescript
1069
+ // BAD: No busy timeout (SQLITE_BUSY errors on contention)
1070
+ const db = new Database("app.db");
1071
+
1072
+ // GOOD: Wait for locks instead of failing immediately
1073
+ const db = new Database("app.db");
1074
+ db.pragma("busy_timeout = 5000");
1075
+ ```
1076
+
1077
+ ### Unbatched Inserts
1078
+
1079
+ ```typescript
1080
+ // BAD: 10,000 individual transactions (~50 inserts/second)
1081
+ for (const item of items) {
1082
+ db.prepare("INSERT INTO items (name) VALUES (?)").run(item.name);
1083
+ }
1084
+
1085
+ // GOOD: Single transaction (~50,000 inserts/second)
1086
+ const insertAll = db.transaction((items: { name: string }[]) => {
1087
+ const stmt = db.prepare("INSERT INTO items (name) VALUES (?)");
1088
+ for (const item of items) {
1089
+ stmt.run(item.name);
1090
+ }
1091
+ });
1092
+ insertAll(items);
1093
+ ```
1094
+
1095
+ ### Using SQLite Over NFS
1096
+
1097
+ ```
1098
+ # BAD: SQLite on a network filesystem
1099
+ # WAL mode does not work, file locking is unreliable, data corruption risk
1100
+
1101
+ # GOOD: Keep the database on a local filesystem
1102
+ # Use Turso or Litestream if you need remote access or replication
1103
+ ```
1104
+
1105
+ ---
1106
+
1107
+ ## 17. Critical Reminders
1108
+
1109
+ ### ALWAYS
1110
+
1111
+ - Enable WAL mode for any production use
1112
+ - Set `PRAGMA foreign_keys = ON` (it is off by default)
1113
+ - Set `PRAGMA busy_timeout` to a reasonable value (e.g., 5000 ms)
1114
+ - Use prepared statements (compiled once, faster execution)
1115
+ - Wrap bulk operations in transactions (orders of magnitude faster)
1116
+ - Use parameterized queries -- never interpolate user input into SQL
1117
+ - Run `PRAGMA optimize` periodically or on connection close
1118
+ - Back up using the SQLite backup API or Litestream, not file copy
1119
+ - Close database connections on application shutdown
1120
+ - Validate tenant IDs when using database-per-tenant pattern (prevent path traversal)
1121
+
1122
+ ### NEVER
1123
+
1124
+ - Copy a `.db` file while the database is in use (use backup API instead)
1125
+ - Use SQLite over a network filesystem (NFS, SMB, CIFS)
1126
+ - Assume SQLite supports concurrent writes (it serializes them)
1127
+ - Skip foreign key PRAGMA (it is disabled by default, constraints will not be enforced)
1128
+ - Insert thousands of rows without a wrapping transaction
1129
+ - Store the database in a temporary or world-writable directory
1130
+ - Use `PRAGMA synchronous = OFF` in production (data loss on crash)
1131
+ - Ignore the `.db-wal` and `.db-shm` files during backup
1132
+ - Use SQLite as a message queue with high concurrency (use Redis or a proper queue)