sqlew 3.2.5 → 3.6.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 (291) hide show
  1. package/CHANGELOG.md +288 -1011
  2. package/README.md +80 -263
  3. package/assets/config.example.toml +97 -0
  4. package/assets/schema.sql +6 -1
  5. package/dist/adapters/index.d.ts +11 -0
  6. package/dist/adapters/index.d.ts.map +1 -0
  7. package/dist/adapters/index.js +21 -0
  8. package/dist/adapters/index.js.map +1 -0
  9. package/dist/adapters/mysql-adapter.d.ts +31 -0
  10. package/dist/adapters/mysql-adapter.d.ts.map +1 -0
  11. package/dist/adapters/mysql-adapter.js +63 -0
  12. package/dist/adapters/mysql-adapter.js.map +1 -0
  13. package/dist/adapters/postgresql-adapter.d.ts +31 -0
  14. package/dist/adapters/postgresql-adapter.d.ts.map +1 -0
  15. package/dist/adapters/postgresql-adapter.js +63 -0
  16. package/dist/adapters/postgresql-adapter.js.map +1 -0
  17. package/dist/adapters/sqlite-adapter.d.ts +37 -0
  18. package/dist/adapters/sqlite-adapter.d.ts.map +1 -0
  19. package/dist/adapters/sqlite-adapter.js +129 -0
  20. package/dist/adapters/sqlite-adapter.js.map +1 -0
  21. package/dist/adapters/types.d.ts +33 -0
  22. package/dist/adapters/types.d.ts.map +1 -0
  23. package/dist/adapters/types.js +2 -0
  24. package/dist/adapters/types.js.map +1 -0
  25. package/dist/cli.js +55 -54
  26. package/dist/cli.js.map +1 -1
  27. package/dist/config/example-generator.d.ts +11 -0
  28. package/dist/config/example-generator.d.ts.map +1 -0
  29. package/dist/config/example-generator.js +48 -0
  30. package/dist/config/example-generator.js.map +1 -0
  31. package/dist/config/loader.d.ts +46 -0
  32. package/dist/config/loader.d.ts.map +1 -0
  33. package/dist/config/loader.js +155 -0
  34. package/dist/config/loader.js.map +1 -0
  35. package/dist/config/types.d.ts +86 -0
  36. package/dist/config/types.d.ts.map +1 -0
  37. package/dist/config/types.js +28 -0
  38. package/dist/config/types.js.map +1 -0
  39. package/dist/constants.d.ts +9 -0
  40. package/dist/constants.d.ts.map +1 -1
  41. package/dist/constants.js +10 -0
  42. package/dist/constants.js.map +1 -1
  43. package/dist/database.d.ts +44 -122
  44. package/dist/database.d.ts.map +1 -1
  45. package/dist/database.js +145 -349
  46. package/dist/database.js.map +1 -1
  47. package/dist/index.js +223 -175
  48. package/dist/index.js.map +1 -1
  49. package/dist/knexfile.d.ts +6 -0
  50. package/dist/knexfile.d.ts.map +1 -0
  51. package/dist/knexfile.js +85 -0
  52. package/dist/knexfile.js.map +1 -0
  53. package/dist/migrations/add-help-system-tables.d.ts +35 -0
  54. package/dist/migrations/add-help-system-tables.d.ts.map +1 -0
  55. package/dist/migrations/add-help-system-tables.js +206 -0
  56. package/dist/migrations/add-help-system-tables.js.map +1 -0
  57. package/dist/migrations/add-token-tracking.d.ts +28 -0
  58. package/dist/migrations/add-token-tracking.d.ts.map +1 -0
  59. package/dist/migrations/add-token-tracking.js +108 -0
  60. package/dist/migrations/add-token-tracking.js.map +1 -0
  61. package/dist/migrations/add-v3.5.0-pruned-files.d.ts +26 -0
  62. package/dist/migrations/add-v3.5.0-pruned-files.d.ts.map +1 -0
  63. package/dist/migrations/add-v3.5.0-pruned-files.js +107 -0
  64. package/dist/migrations/add-v3.5.0-pruned-files.js.map +1 -0
  65. package/dist/migrations/index.d.ts +26 -12
  66. package/dist/migrations/index.d.ts.map +1 -1
  67. package/dist/migrations/index.js +162 -20
  68. package/dist/migrations/index.js.map +1 -1
  69. package/dist/migrations/knex/20251025020452_create_master_tables.d.ts +4 -0
  70. package/dist/migrations/knex/20251025020452_create_master_tables.d.ts.map +1 -0
  71. package/dist/migrations/knex/20251025020452_create_master_tables.js +65 -0
  72. package/dist/migrations/knex/20251025020452_create_master_tables.js.map +1 -0
  73. package/dist/migrations/knex/20251025021152_create_transaction_tables.d.ts +4 -0
  74. package/dist/migrations/knex/20251025021152_create_transaction_tables.d.ts.map +1 -0
  75. package/dist/migrations/knex/20251025021152_create_transaction_tables.js +235 -0
  76. package/dist/migrations/knex/20251025021152_create_transaction_tables.js.map +1 -0
  77. package/dist/migrations/knex/20251025021351_create_indexes.d.ts +4 -0
  78. package/dist/migrations/knex/20251025021351_create_indexes.d.ts.map +1 -0
  79. package/dist/migrations/knex/20251025021351_create_indexes.js +62 -0
  80. package/dist/migrations/knex/20251025021351_create_indexes.js.map +1 -0
  81. package/dist/migrations/knex/20251025021416_seed_master_data.d.ts +4 -0
  82. package/dist/migrations/knex/20251025021416_seed_master_data.d.ts.map +1 -0
  83. package/dist/migrations/knex/20251025021416_seed_master_data.js +58 -0
  84. package/dist/migrations/knex/20251025021416_seed_master_data.js.map +1 -0
  85. package/dist/migrations/knex/20251025070349_create_views.d.ts +4 -0
  86. package/dist/migrations/knex/20251025070349_create_views.d.ts.map +1 -0
  87. package/dist/migrations/knex/20251025070349_create_views.js +143 -0
  88. package/dist/migrations/knex/20251025070349_create_views.js.map +1 -0
  89. package/dist/migrations/knex/20251025081221_add_link_type_to_task_decision_links.d.ts +4 -0
  90. package/dist/migrations/knex/20251025081221_add_link_type_to_task_decision_links.d.ts.map +1 -0
  91. package/dist/migrations/knex/20251025081221_add_link_type_to_task_decision_links.js +15 -0
  92. package/dist/migrations/knex/20251025081221_add_link_type_to_task_decision_links.js.map +1 -0
  93. package/dist/migrations/knex/20251025082220_fix_task_dependencies_columns.d.ts +8 -0
  94. package/dist/migrations/knex/20251025082220_fix_task_dependencies_columns.d.ts.map +1 -0
  95. package/dist/migrations/knex/20251025082220_fix_task_dependencies_columns.js +12 -0
  96. package/dist/migrations/knex/20251025082220_fix_task_dependencies_columns.js.map +1 -0
  97. package/dist/migrations/knex/20251025090000_create_help_system_tables.d.ts +19 -0
  98. package/dist/migrations/knex/20251025090000_create_help_system_tables.d.ts.map +1 -0
  99. package/dist/migrations/knex/20251025090000_create_help_system_tables.js +115 -0
  100. package/dist/migrations/knex/20251025090000_create_help_system_tables.js.map +1 -0
  101. package/dist/migrations/knex/20251025090100_seed_help_categories_and_use_cases.d.ts +13 -0
  102. package/dist/migrations/knex/20251025090100_seed_help_categories_and_use_cases.d.ts.map +1 -0
  103. package/dist/migrations/knex/20251025090100_seed_help_categories_and_use_cases.js +377 -0
  104. package/dist/migrations/knex/20251025090100_seed_help_categories_and_use_cases.js.map +1 -0
  105. package/dist/migrations/knex/20251025100000_seed_help_metadata.d.ts +15 -0
  106. package/dist/migrations/knex/20251025100000_seed_help_metadata.d.ts.map +1 -0
  107. package/dist/migrations/knex/20251025100000_seed_help_metadata.js +253 -0
  108. package/dist/migrations/knex/20251025100000_seed_help_metadata.js.map +1 -0
  109. package/dist/migrations/knex/20251025100100_seed_remaining_use_cases.d.ts +16 -0
  110. package/dist/migrations/knex/20251025100100_seed_remaining_use_cases.d.ts.map +1 -0
  111. package/dist/migrations/knex/20251025100100_seed_remaining_use_cases.js +276 -0
  112. package/dist/migrations/knex/20251025100100_seed_remaining_use_cases.js.map +1 -0
  113. package/dist/migrations/knex/20251025120000_add_cascade_to_task_dependencies.d.ts +8 -0
  114. package/dist/migrations/knex/20251025120000_add_cascade_to_task_dependencies.d.ts.map +1 -0
  115. package/dist/migrations/knex/20251025120000_add_cascade_to_task_dependencies.js +64 -0
  116. package/dist/migrations/knex/20251025120000_add_cascade_to_task_dependencies.js.map +1 -0
  117. package/dist/migrations/seed-help-data.d.ts +48 -0
  118. package/dist/migrations/seed-help-data.d.ts.map +1 -0
  119. package/dist/migrations/seed-help-data.js +1466 -0
  120. package/dist/migrations/seed-help-data.js.map +1 -0
  121. package/dist/migrations/seed-tool-metadata.d.ts +24 -0
  122. package/dist/migrations/seed-tool-metadata.d.ts.map +1 -0
  123. package/dist/migrations/seed-tool-metadata.js +392 -0
  124. package/dist/migrations/seed-tool-metadata.js.map +1 -0
  125. package/dist/migrations/v3.6.0-help-system-refactor.d.ts +46 -0
  126. package/dist/migrations/v3.6.0-help-system-refactor.d.ts.map +1 -0
  127. package/dist/migrations/v3.6.0-help-system-refactor.js +223 -0
  128. package/dist/migrations/v3.6.0-help-system-refactor.js.map +1 -0
  129. package/dist/schema.d.ts.map +1 -1
  130. package/dist/schema.js +2 -0
  131. package/dist/schema.js.map +1 -1
  132. package/dist/tests/git-aware-completion.test.d.ts +6 -0
  133. package/dist/tests/git-aware-completion.test.d.ts.map +1 -0
  134. package/dist/tests/git-aware-completion.test.js +160 -0
  135. package/dist/tests/git-aware-completion.test.js.map +1 -0
  136. package/dist/tests/help-system.test.d.ts +23 -0
  137. package/dist/tests/help-system.test.d.ts.map +1 -0
  138. package/dist/tests/help-system.test.js +374 -0
  139. package/dist/tests/help-system.test.js.map +1 -0
  140. package/dist/tests/tasks.auto-pruning-decision-link.test.d.ts +6 -0
  141. package/dist/tests/tasks.auto-pruning-decision-link.test.d.ts.map +1 -0
  142. package/dist/tests/tasks.auto-pruning-decision-link.test.js +264 -0
  143. package/dist/tests/tasks.auto-pruning-decision-link.test.js.map +1 -0
  144. package/dist/tests/tasks.auto-pruning-partial.test.d.ts +6 -0
  145. package/dist/tests/tasks.auto-pruning-partial.test.d.ts.map +1 -0
  146. package/dist/tests/tasks.auto-pruning-partial.test.js +285 -0
  147. package/dist/tests/tasks.auto-pruning-partial.test.js.map +1 -0
  148. package/dist/tests/tasks.auto-pruning-persistence.test.d.ts +6 -0
  149. package/dist/tests/tasks.auto-pruning-persistence.test.d.ts.map +1 -0
  150. package/dist/tests/tasks.auto-pruning-persistence.test.js +250 -0
  151. package/dist/tests/tasks.auto-pruning-persistence.test.js.map +1 -0
  152. package/dist/tests/tasks.auto-pruning-safety.test.d.ts +12 -0
  153. package/dist/tests/tasks.auto-pruning-safety.test.d.ts.map +1 -0
  154. package/dist/tests/tasks.auto-pruning-safety.test.js +217 -0
  155. package/dist/tests/tasks.auto-pruning-safety.test.js.map +1 -0
  156. package/dist/tests/tasks.dependencies.test.js +338 -307
  157. package/dist/tests/tasks.dependencies.test.js.map +1 -1
  158. package/dist/tests/tasks.link-file-backward-compat.test.d.ts +6 -0
  159. package/dist/tests/tasks.link-file-backward-compat.test.d.ts.map +1 -0
  160. package/dist/tests/tasks.link-file-backward-compat.test.js +247 -0
  161. package/dist/tests/tasks.link-file-backward-compat.test.js.map +1 -0
  162. package/dist/tests/tasks.watch-files-action.test.d.ts +6 -0
  163. package/dist/tests/tasks.watch-files-action.test.d.ts.map +1 -0
  164. package/dist/tests/tasks.watch-files-action.test.js +372 -0
  165. package/dist/tests/tasks.watch-files-action.test.js.map +1 -0
  166. package/dist/tests/tasks.watch-files-parameter.test.d.ts +6 -0
  167. package/dist/tests/tasks.watch-files-parameter.test.d.ts.map +1 -0
  168. package/dist/tests/tasks.watch-files-parameter.test.js +260 -0
  169. package/dist/tests/tasks.watch-files-parameter.test.js.map +1 -0
  170. package/dist/tests/two-step-git-completion.test.d.ts +6 -0
  171. package/dist/tests/two-step-git-completion.test.d.ts.map +1 -0
  172. package/dist/tests/two-step-git-completion.test.js +326 -0
  173. package/dist/tests/two-step-git-completion.test.js.map +1 -0
  174. package/dist/tests/vcs-staging.test.d.ts +6 -0
  175. package/dist/tests/vcs-staging.test.d.ts.map +1 -0
  176. package/dist/tests/vcs-staging.test.js +137 -0
  177. package/dist/tests/vcs-staging.test.js.map +1 -0
  178. package/dist/tools/config.d.ts +9 -4
  179. package/dist/tools/config.d.ts.map +1 -1
  180. package/dist/tools/config.js +16 -12
  181. package/dist/tools/config.js.map +1 -1
  182. package/dist/tools/constraints.d.ts +9 -3
  183. package/dist/tools/constraints.d.ts.map +1 -1
  184. package/dist/tools/constraints.js +66 -45
  185. package/dist/tools/constraints.js.map +1 -1
  186. package/dist/tools/context.d.ts +35 -16
  187. package/dist/tools/context.d.ts.map +1 -1
  188. package/dist/tools/context.js +374 -314
  189. package/dist/tools/context.js.map +1 -1
  190. package/dist/tools/files.d.ts +11 -4
  191. package/dist/tools/files.d.ts.map +1 -1
  192. package/dist/tools/files.js +173 -91
  193. package/dist/tools/files.js.map +1 -1
  194. package/dist/tools/help-queries.d.ts +130 -0
  195. package/dist/tools/help-queries.d.ts.map +1 -0
  196. package/dist/tools/help-queries.js +393 -0
  197. package/dist/tools/help-queries.js.map +1 -0
  198. package/dist/tools/messaging.d.ts +13 -6
  199. package/dist/tools/messaging.d.ts.map +1 -1
  200. package/dist/tools/messaging.js +217 -129
  201. package/dist/tools/messaging.js.map +1 -1
  202. package/dist/tools/tasks.d.ts +42 -12
  203. package/dist/tools/tasks.d.ts.map +1 -1
  204. package/dist/tools/tasks.js +809 -347
  205. package/dist/tools/tasks.js.map +1 -1
  206. package/dist/tools/utils.d.ts +13 -5
  207. package/dist/tools/utils.d.ts.map +1 -1
  208. package/dist/tools/utils.js +92 -115
  209. package/dist/tools/utils.js.map +1 -1
  210. package/dist/types.d.ts +4 -0
  211. package/dist/types.d.ts.map +1 -1
  212. package/dist/utils/activity-logging.d.ts +114 -0
  213. package/dist/utils/activity-logging.d.ts.map +1 -0
  214. package/dist/utils/activity-logging.js +162 -0
  215. package/dist/utils/activity-logging.js.map +1 -0
  216. package/dist/utils/batch.d.ts +2 -2
  217. package/dist/utils/batch.d.ts.map +1 -1
  218. package/dist/utils/batch.js +8 -8
  219. package/dist/utils/batch.js.map +1 -1
  220. package/dist/utils/cleanup.d.ts +21 -13
  221. package/dist/utils/cleanup.d.ts.map +1 -1
  222. package/dist/utils/cleanup.js +31 -24
  223. package/dist/utils/cleanup.js.map +1 -1
  224. package/dist/utils/debug-logger.d.ts +44 -0
  225. package/dist/utils/debug-logger.d.ts.map +1 -0
  226. package/dist/utils/debug-logger.js +116 -0
  227. package/dist/utils/debug-logger.js.map +1 -0
  228. package/dist/utils/file-pruning.d.ts +69 -0
  229. package/dist/utils/file-pruning.d.ts.map +1 -0
  230. package/dist/utils/file-pruning.js +185 -0
  231. package/dist/utils/file-pruning.js.map +1 -0
  232. package/dist/utils/help-tracking.d.ts +55 -0
  233. package/dist/utils/help-tracking.d.ts.map +1 -0
  234. package/dist/utils/help-tracking.js +88 -0
  235. package/dist/utils/help-tracking.js.map +1 -0
  236. package/dist/utils/quality-checks.d.ts +60 -0
  237. package/dist/utils/quality-checks.d.ts.map +1 -0
  238. package/dist/utils/quality-checks.js +228 -0
  239. package/dist/utils/quality-checks.js.map +1 -0
  240. package/dist/utils/retention.d.ts +13 -5
  241. package/dist/utils/retention.d.ts.map +1 -1
  242. package/dist/utils/retention.js +20 -8
  243. package/dist/utils/retention.js.map +1 -1
  244. package/dist/utils/task-stale-detection.d.ts +77 -7
  245. package/dist/utils/task-stale-detection.d.ts.map +1 -1
  246. package/dist/utils/task-stale-detection.js +309 -34
  247. package/dist/utils/task-stale-detection.js.map +1 -1
  248. package/dist/utils/token-estimation.d.ts +72 -0
  249. package/dist/utils/token-estimation.d.ts.map +1 -0
  250. package/dist/utils/token-estimation.js +71 -0
  251. package/dist/utils/token-estimation.js.map +1 -0
  252. package/dist/utils/token-logging.d.ts +48 -0
  253. package/dist/utils/token-logging.d.ts.map +1 -0
  254. package/dist/utils/token-logging.js +112 -0
  255. package/dist/utils/token-logging.js.map +1 -0
  256. package/dist/utils/vcs-adapter.d.ts +68 -0
  257. package/dist/utils/vcs-adapter.d.ts.map +1 -0
  258. package/dist/utils/vcs-adapter.js +187 -0
  259. package/dist/utils/vcs-adapter.js.map +1 -0
  260. package/dist/utils/view-queries.d.ts +34 -0
  261. package/dist/utils/view-queries.d.ts.map +1 -0
  262. package/dist/utils/view-queries.js +192 -0
  263. package/dist/utils/view-queries.js.map +1 -0
  264. package/dist/watcher/file-watcher.d.ts +54 -4
  265. package/dist/watcher/file-watcher.d.ts.map +1 -1
  266. package/dist/watcher/file-watcher.js +329 -33
  267. package/dist/watcher/file-watcher.js.map +1 -1
  268. package/dist/watcher/gitignore-parser.d.ts +70 -0
  269. package/dist/watcher/gitignore-parser.d.ts.map +1 -0
  270. package/dist/watcher/gitignore-parser.js +191 -0
  271. package/dist/watcher/gitignore-parser.js.map +1 -0
  272. package/dist/watcher/index.d.ts +1 -0
  273. package/dist/watcher/index.d.ts.map +1 -1
  274. package/dist/watcher/index.js +1 -0
  275. package/dist/watcher/index.js.map +1 -1
  276. package/docs/AI_AGENT_GUIDE.md +1 -1
  277. package/docs/ARCHITECTURE.md +12 -0
  278. package/docs/AUTO_FILE_TRACKING.md +486 -82
  279. package/docs/BEST_PRACTICES.md +56 -448
  280. package/docs/CONFIGURATION.md +908 -0
  281. package/docs/GIT_AWARE_AUTO_COMPLETE.md +645 -0
  282. package/docs/MIGRATION_v3.3.md +602 -0
  283. package/docs/MIGRATION_v3.6.0.md +170 -0
  284. package/docs/SHARED_CONCEPTS.md +65 -209
  285. package/docs/TASK_ACTIONS.md +12 -0
  286. package/docs/TASK_OVERVIEW.md +125 -24
  287. package/docs/TASK_PRUNING.md +589 -0
  288. package/docs/TASK_SYSTEM.md +83 -13
  289. package/docs/TOOL_REFERENCE.md +94 -6
  290. package/docs/TOOL_SELECTION.md +41 -248
  291. package/package.json +21 -7
package/dist/database.js CHANGED
@@ -1,163 +1,67 @@
1
1
  /**
2
2
  * Database connection and initialization module
3
- * Handles SQLite database setup with configurable path
3
+ * Handles database setup with Knex.js and DatabaseAdapter pattern
4
4
  */
5
- import Database from 'better-sqlite3';
6
- import { mkdirSync, existsSync } from 'fs';
7
- import { dirname, resolve, isAbsolute } from 'path';
8
- import { initializeSchema, isSchemaInitialized, verifySchemaIntegrity } from './schema.js';
9
- import { DEFAULT_DB_PATH, DB_BUSY_TIMEOUT } from './constants.js';
10
- import { performAutoCleanup } from './utils/cleanup.js';
11
- import { runAllMigrations, needsAnyMigrations } from './migrations/index.js';
12
- let dbInstance = null;
5
+ import knexConfig from './knexfile.js';
6
+ import { createDatabaseAdapter } from './adapters/index.js';
7
+ // Global adapter instance
8
+ let adapterInstance = null;
13
9
  /**
14
- * Initialize database connection
15
- * Creates database file and folder if they don't exist
16
- * Initializes schema on first run
17
- *
18
- * @param dbPath - Optional database path (defaults to .sqlew/sqlew.db)
19
- * @returns SQLite database instance
10
+ * Initialize database with adapter pattern
20
11
  */
21
- export function initializeDatabase(dbPath) {
22
- // If already initialized, return existing instance
23
- if (dbInstance) {
24
- return dbInstance;
25
- }
26
- try {
27
- // Use provided path or default
28
- const finalPath = dbPath || DEFAULT_DB_PATH;
29
- // Convert to absolute path if relative
30
- const absolutePath = isAbsolute(finalPath)
31
- ? finalPath
32
- : resolve(process.cwd(), finalPath);
33
- // Create directory if it doesn't exist
34
- const dbDir = dirname(absolutePath);
35
- if (!existsSync(dbDir)) {
36
- mkdirSync(dbDir, { recursive: true });
37
- console.log(`✓ Created database directory: ${dbDir}`);
38
- }
39
- // Open database connection
40
- const db = new Database(absolutePath, {
41
- verbose: process.env.DEBUG_SQL ? console.log : undefined,
42
- });
43
- // Configure database
44
- db.pragma('journal_mode = WAL'); // Write-Ahead Logging for better concurrency
45
- db.pragma('foreign_keys = ON'); // Enforce foreign key constraints
46
- db.pragma('synchronous = NORMAL'); // Balance between safety and performance
47
- db.pragma(`busy_timeout = ${DB_BUSY_TIMEOUT}`); // Set busy timeout
48
- console.log(`✓ Connected to database: ${absolutePath}`);
49
- // Check if database has existing schema
50
- const schemaExists = isSchemaInitialized(db);
51
- if (schemaExists) {
52
- // Run all pending migrations using orchestrator
53
- // This handles upgrades from any version (v1.0.0, v1.1.x, v2.0.0, v2.1.x) to latest
54
- if (needsAnyMigrations(db)) {
55
- const migrationResults = runAllMigrations(db);
56
- // Check if any migration failed
57
- const failed = migrationResults.find(r => !r.success);
58
- if (failed) {
59
- console.error('\n❌ ERROR: Migration failed!');
60
- console.error(failed.message);
61
- db.close();
62
- process.exit(1);
63
- }
64
- // After table prefix migration, run schema initialization to create views/triggers
65
- // (tables already exist, CREATE TABLE IF NOT EXISTS will skip them)
66
- const hadPrefixMigration = migrationResults.some(r => r.message.toLowerCase().includes('table prefix') ||
67
- r.message.toLowerCase().includes('prefix'));
68
- if (hadPrefixMigration) {
69
- console.log('\n→ Creating views and triggers for new schema...');
70
- initializeSchema(db);
71
- }
72
- }
73
- // Validate existing schema integrity (after migrations)
74
- console.log('→ Validating existing database schema...');
75
- const validation = verifySchemaIntegrity(db);
76
- if (!validation.valid) {
77
- // Schema is invalid - display error and exit
78
- console.error('\n❌ ERROR: Database schema validation failed!');
79
- console.error('\nThe existing database file has an incompatible schema.');
80
- console.error(`Database location: ${absolutePath}`);
81
- if (validation.missing.length > 0) {
82
- console.error('\n📋 Missing components:');
83
- validation.missing.forEach(item => console.error(` - ${item}`));
84
- }
85
- if (validation.errors.length > 0) {
86
- console.error('\n⚠️ Validation errors:');
87
- validation.errors.forEach(error => console.error(` - ${error}`));
88
- }
89
- console.error('\n💡 Possible solutions:');
90
- console.error(' 1. Backup and delete the existing database file to start fresh');
91
- console.error(' 2. Use a different database path with --db-path option');
92
- console.error(' 3. Restore from a backup if available\n');
93
- // Close database and exit
94
- db.close();
95
- process.exit(1);
96
- }
97
- console.log('✓ Database schema validation passed');
98
- }
99
- else {
100
- // Initialize new schema
101
- console.log('→ Initializing database schema...');
102
- initializeSchema(db);
103
- }
104
- // Store instance
105
- dbInstance = db;
106
- // Perform initial cleanup
107
- try {
108
- const cleanupResult = performAutoCleanup(db);
109
- if (cleanupResult.messagesDeleted > 0 || cleanupResult.fileChangesDeleted > 0) {
110
- console.log(`✓ Cleanup: ${cleanupResult.messagesDeleted} messages, ${cleanupResult.fileChangesDeleted} file changes deleted`);
111
- }
112
- }
113
- catch (error) {
114
- console.warn('⚠️ Initial cleanup failed:', error instanceof Error ? error.message : String(error));
115
- }
116
- return db;
117
- }
118
- catch (error) {
119
- const message = error instanceof Error ? error.message : String(error);
120
- throw new Error(`Failed to initialize database: ${message}`);
12
+ export async function initializeDatabase(config) {
13
+ if (adapterInstance) {
14
+ return adapterInstance;
121
15
  }
16
+ const dbType = config?.databaseType || 'sqlite';
17
+ const adapter = createDatabaseAdapter(dbType);
18
+ // Determine if running from compiled code (dist/) or source (src/)
19
+ const isCompiledCode = import.meta.url.includes('/dist/');
20
+ const environment = isCompiledCode ? 'production' : 'development';
21
+ // Use config from knexfile or provided config
22
+ const baseConfig = knexConfig[environment] || knexConfig.development;
23
+ const knexConnConfig = config?.connection
24
+ ? { ...baseConfig, connection: config.connection }
25
+ : baseConfig;
26
+ await adapter.connect(knexConnConfig);
27
+ // Run migrations if needed
28
+ const knex = adapter.getKnex();
29
+ await knex.migrate.latest();
30
+ console.log(`✓ Database initialized with Knex adapter (${environment})`);
31
+ adapterInstance = adapter;
32
+ return adapter;
122
33
  }
123
34
  /**
124
- * Close database connection
35
+ * Get current database adapter
125
36
  */
126
- export function closeDatabase() {
127
- if (dbInstance) {
128
- dbInstance.close();
129
- dbInstance = null;
130
- console.log('✓ Database connection closed');
37
+ export function getAdapter() {
38
+ if (!adapterInstance) {
39
+ throw new Error('Database not initialized. Call initializeDatabase() first.');
131
40
  }
41
+ return adapterInstance;
132
42
  }
133
43
  /**
134
- * Get current database instance
135
- * Throws error if not initialized
136
- *
137
- * @returns Current database instance
44
+ * Close database connection
138
45
  */
139
- export function getDatabase() {
140
- if (!dbInstance) {
141
- throw new Error('Database not initialized. Call initializeDatabase() first.');
46
+ export async function closeDatabase() {
47
+ if (adapterInstance) {
48
+ await adapterInstance.disconnect();
49
+ adapterInstance = null;
50
+ console.log('✓ Database connection closed');
142
51
  }
143
- return dbInstance;
144
52
  }
145
53
  // ============================================================================
146
- // Helper Functions for Master Table Management
54
+ // Helper Functions for Master Table Management (Async)
147
55
  // ============================================================================
148
56
  /**
149
57
  * Get or create agent by name
150
- * Uses INSERT OR IGNORE for idempotent operation
151
- *
152
- * @param db - Database instance
153
- * @param name - Agent name
154
- * @returns Agent ID
155
58
  */
156
- export function getOrCreateAgent(db, name) {
157
- // Try to insert
158
- db.prepare('INSERT OR IGNORE INTO m_agents (name) VALUES (?)').run(name);
59
+ export async function getOrCreateAgent(adapter, name, trx) {
60
+ const knex = trx || adapter.getKnex();
61
+ // Try to insert (will be ignored if exists)
62
+ await knex('m_agents').insert({ name }).onConflict('name').ignore();
159
63
  // Get the ID
160
- const result = db.prepare('SELECT id FROM m_agents WHERE name = ?').get(name);
64
+ const result = await knex('m_agents').where({ name }).first('id');
161
65
  if (!result) {
162
66
  throw new Error(`Failed to get or create agent: ${name}`);
163
67
  }
@@ -165,14 +69,11 @@ export function getOrCreateAgent(db, name) {
165
69
  }
166
70
  /**
167
71
  * Get or create context key by name
168
- *
169
- * @param db - Database instance
170
- * @param key - Context key name
171
- * @returns Context key ID
172
72
  */
173
- export function getOrCreateContextKey(db, key) {
174
- db.prepare('INSERT OR IGNORE INTO m_context_keys (key) VALUES (?)').run(key);
175
- const result = db.prepare('SELECT id FROM m_context_keys WHERE key = ?').get(key);
73
+ export async function getOrCreateContextKey(adapter, key, trx) {
74
+ const knex = trx || adapter.getKnex();
75
+ await knex('m_context_keys').insert({ key }).onConflict('key').ignore();
76
+ const result = await knex('m_context_keys').where({ key }).first('id');
176
77
  if (!result) {
177
78
  throw new Error(`Failed to get or create context key: ${key}`);
178
79
  }
@@ -180,14 +81,11 @@ export function getOrCreateContextKey(db, key) {
180
81
  }
181
82
  /**
182
83
  * Get or create file by path
183
- *
184
- * @param db - Database instance
185
- * @param path - File path
186
- * @returns File ID
187
84
  */
188
- export function getOrCreateFile(db, path) {
189
- db.prepare('INSERT OR IGNORE INTO m_files (path) VALUES (?)').run(path);
190
- const result = db.prepare('SELECT id FROM m_files WHERE path = ?').get(path);
85
+ export async function getOrCreateFile(adapter, path, trx) {
86
+ const knex = trx || adapter.getKnex();
87
+ await knex('m_files').insert({ path }).onConflict('path').ignore();
88
+ const result = await knex('m_files').where({ path }).first('id');
191
89
  if (!result) {
192
90
  throw new Error(`Failed to get or create file: ${path}`);
193
91
  }
@@ -195,14 +93,11 @@ export function getOrCreateFile(db, path) {
195
93
  }
196
94
  /**
197
95
  * Get or create tag by name
198
- *
199
- * @param db - Database instance
200
- * @param name - Tag name
201
- * @returns Tag ID
202
96
  */
203
- export function getOrCreateTag(db, name) {
204
- db.prepare('INSERT OR IGNORE INTO m_tags (name) VALUES (?)').run(name);
205
- const result = db.prepare('SELECT id FROM m_tags WHERE name = ?').get(name);
97
+ export async function getOrCreateTag(adapter, name, trx) {
98
+ const knex = trx || adapter.getKnex();
99
+ await knex('m_tags').insert({ name }).onConflict('name').ignore();
100
+ const result = await knex('m_tags').where({ name }).first('id');
206
101
  if (!result) {
207
102
  throw new Error(`Failed to get or create tag: ${name}`);
208
103
  }
@@ -210,14 +105,11 @@ export function getOrCreateTag(db, name) {
210
105
  }
211
106
  /**
212
107
  * Get or create scope by name
213
- *
214
- * @param db - Database instance
215
- * @param name - Scope name
216
- * @returns Scope ID
217
108
  */
218
- export function getOrCreateScope(db, name) {
219
- db.prepare('INSERT OR IGNORE INTO m_scopes (name) VALUES (?)').run(name);
220
- const result = db.prepare('SELECT id FROM m_scopes WHERE name = ?').get(name);
109
+ export async function getOrCreateScope(adapter, name, trx) {
110
+ const knex = trx || adapter.getKnex();
111
+ await knex('m_scopes').insert({ name }).onConflict('name').ignore();
112
+ const result = await knex('m_scopes').where({ name }).first('id');
221
113
  if (!result) {
222
114
  throw new Error(`Failed to get or create scope: ${name}`);
223
115
  }
@@ -225,17 +117,11 @@ export function getOrCreateScope(db, name) {
225
117
  }
226
118
  /**
227
119
  * Get or create category ID
228
- * Uses INSERT to create if doesn't exist
229
- *
230
- * @param db - Database instance
231
- * @param category - Category name
232
- * @returns Category ID
233
120
  */
234
- export function getOrCreateCategoryId(db, category) {
235
- // Use INSERT OR IGNORE for idempotent operation
236
- db.prepare('INSERT OR IGNORE INTO m_constraint_categories (name) VALUES (?)').run(category);
237
- // Get the ID
238
- const result = db.prepare('SELECT id FROM m_constraint_categories WHERE name = ?').get(category);
121
+ export async function getOrCreateCategoryId(adapter, category, trx) {
122
+ const knex = trx || adapter.getKnex();
123
+ await knex('m_constraint_categories').insert({ name: category }).onConflict('name').ignore();
124
+ const result = await knex('m_constraint_categories').where({ name: category }).first('id');
239
125
  if (!result) {
240
126
  throw new Error(`Failed to get or create category: ${category}`);
241
127
  }
@@ -243,77 +129,56 @@ export function getOrCreateCategoryId(db, category) {
243
129
  }
244
130
  /**
245
131
  * Get layer ID by name
246
- * Does not auto-create (layers are predefined)
247
- *
248
- * @param db - Database instance
249
- * @param name - Layer name
250
- * @returns Layer ID or null if not found
251
132
  */
252
- export function getLayerId(db, name) {
253
- const result = db.prepare('SELECT id FROM m_layers WHERE name = ?').get(name);
133
+ export async function getLayerId(adapter, name, trx) {
134
+ const knex = trx || adapter.getKnex();
135
+ const result = await knex('m_layers').where({ name }).first('id');
254
136
  return result ? result.id : null;
255
137
  }
256
138
  /**
257
139
  * Get constraint category ID by name
258
- * Does not auto-create (categories are predefined)
259
- *
260
- * @param db - Database instance
261
- * @param name - Category name
262
- * @returns Category ID or null if not found
263
140
  */
264
- export function getCategoryId(db, name) {
265
- const result = db.prepare('SELECT id FROM m_constraint_categories WHERE name = ?').get(name);
141
+ export async function getCategoryId(adapter, name, trx) {
142
+ const knex = trx || adapter.getKnex();
143
+ const result = await knex('m_constraint_categories').where({ name }).first('id');
266
144
  return result ? result.id : null;
267
145
  }
268
146
  // ============================================================================
269
- // Configuration Management
147
+ // Configuration Management (Async)
270
148
  // ============================================================================
271
149
  /**
272
150
  * Get configuration value from m_config table
273
- *
274
- * @param db - Database instance
275
- * @param key - Config key
276
- * @returns Config value as string or null if not found
277
151
  */
278
- export function getConfigValue(db, key) {
279
- const result = db.prepare('SELECT value FROM m_config WHERE key = ?').get(key);
152
+ export async function getConfigValue(adapter, key) {
153
+ const knex = adapter.getKnex();
154
+ const result = await knex('m_config').where({ key }).first('value');
280
155
  return result ? result.value : null;
281
156
  }
282
157
  /**
283
158
  * Set configuration value in m_config table
284
- *
285
- * @param db - Database instance
286
- * @param key - Config key
287
- * @param value - Config value (will be converted to string)
288
159
  */
289
- export function setConfigValue(db, key, value) {
160
+ export async function setConfigValue(adapter, key, value) {
161
+ const knex = adapter.getKnex();
290
162
  const stringValue = String(value);
291
- db.prepare('INSERT OR REPLACE INTO m_config (key, value) VALUES (?, ?)').run(key, stringValue);
163
+ await knex('m_config')
164
+ .insert({ key, value: stringValue })
165
+ .onConflict('key')
166
+ .merge({ value: stringValue });
292
167
  }
293
168
  /**
294
169
  * Get configuration value as boolean
295
- *
296
- * @param db - Database instance
297
- * @param key - Config key
298
- * @param defaultValue - Default value if key not found
299
- * @returns Boolean value
300
170
  */
301
- export function getConfigBool(db, key, defaultValue = false) {
302
- const value = getConfigValue(db, key);
171
+ export async function getConfigBool(adapter, key, defaultValue = false) {
172
+ const value = await getConfigValue(adapter, key);
303
173
  if (value === null)
304
174
  return defaultValue;
305
175
  return value === '1' || value.toLowerCase() === 'true';
306
176
  }
307
177
  /**
308
178
  * Get configuration value as integer
309
- *
310
- * @param db - Database instance
311
- * @param key - Config key
312
- * @param defaultValue - Default value if key not found
313
- * @returns Integer value
314
179
  */
315
- export function getConfigInt(db, key, defaultValue = 0) {
316
- const value = getConfigValue(db, key);
180
+ export async function getConfigInt(adapter, key, defaultValue = 0) {
181
+ const value = await getConfigValue(adapter, key);
317
182
  if (value === null)
318
183
  return defaultValue;
319
184
  const parsed = parseInt(value, 10);
@@ -321,12 +186,10 @@ export function getConfigInt(db, key, defaultValue = 0) {
321
186
  }
322
187
  /**
323
188
  * Get all configuration as an object
324
- *
325
- * @param db - Database instance
326
- * @returns Object with all m_config key-value pairs
327
189
  */
328
- export function getAllConfig(db) {
329
- const rows = db.prepare('SELECT key, value FROM m_config').all();
190
+ export async function getAllConfig(adapter) {
191
+ const knex = adapter.getKnex();
192
+ const rows = await knex('m_config').select('key', 'value');
330
193
  const config = {};
331
194
  for (const row of rows) {
332
195
  config[row.key] = row.value;
@@ -334,35 +197,10 @@ export function getAllConfig(db) {
334
197
  return config;
335
198
  }
336
199
  // ============================================================================
337
- // Transaction Helpers
338
- // ============================================================================
339
- /**
340
- * Execute a function within a transaction
341
- * Automatically handles commit/rollback
342
- *
343
- * @param db - Database instance
344
- * @param fn - Function to execute in transaction
345
- * @returns Result from function
346
- */
347
- export function transaction(db, fn) {
348
- db.exec('BEGIN TRANSACTION');
349
- try {
350
- const result = fn();
351
- db.exec('COMMIT');
352
- return result;
353
- }
354
- catch (error) {
355
- db.exec('ROLLBACK');
356
- throw error;
357
- }
358
- }
359
- // ============================================================================
360
- // Decision Context Management (v3.2.2)
200
+ // Decision Context Management (Async - v3.2.2)
361
201
  // ============================================================================
362
202
  /**
363
203
  * Validate JSON structure for alternatives array
364
- * @param alternatives - JSON string or null
365
- * @throws Error if JSON is invalid or not an array
366
204
  */
367
205
  function validateAlternativesJson(alternatives) {
368
206
  if (alternatives === null || alternatives === undefined)
@@ -382,8 +220,6 @@ function validateAlternativesJson(alternatives) {
382
220
  }
383
221
  /**
384
222
  * Validate JSON structure for tradeoffs object
385
- * @param tradeoffs - JSON string or null
386
- * @throws Error if JSON is invalid or doesn't have pros/cons structure
387
223
  */
388
224
  function validateTradeoffsJson(tradeoffs) {
389
225
  if (tradeoffs === null || tradeoffs === undefined)
@@ -393,7 +229,6 @@ function validateTradeoffsJson(tradeoffs) {
393
229
  if (typeof parsed !== 'object' || parsed === null) {
394
230
  throw new Error('tradeoffs must be a JSON object');
395
231
  }
396
- // Optional: Check for pros/cons keys if provided
397
232
  if (parsed.pros !== undefined && !Array.isArray(parsed.pros)) {
398
233
  throw new Error('tradeoffs.pros must be an array');
399
234
  }
@@ -410,85 +245,54 @@ function validateTradeoffsJson(tradeoffs) {
410
245
  }
411
246
  /**
412
247
  * Add decision context to a decision
413
- *
414
- * @param db - Database instance
415
- * @param decisionKey - Decision key to attach context to
416
- * @param rationale - Rationale for the decision (required)
417
- * @param alternatives - JSON array of alternatives considered (optional)
418
- * @param tradeoffs - JSON object with pros/cons (optional)
419
- * @param decidedBy - Agent name who decided (optional)
420
- * @param relatedTaskId - Related task ID (optional)
421
- * @param relatedConstraintId - Related constraint ID (optional)
422
- * @returns Context ID
423
248
  */
424
- export function addDecisionContext(db, decisionKey, rationale, alternatives = null, tradeoffs = null, decidedBy = null, relatedTaskId = null, relatedConstraintId = null) {
249
+ export async function addDecisionContext(adapter, decisionKey, rationale, alternatives = null, tradeoffs = null, decidedBy = null, relatedTaskId = null, relatedConstraintId = null) {
425
250
  // Validate JSON inputs
426
251
  validateAlternativesJson(alternatives);
427
252
  validateTradeoffsJson(tradeoffs);
253
+ const knex = adapter.getKnex();
428
254
  // Get decision key ID
429
- const keyId = getOrCreateContextKey(db, decisionKey);
255
+ const keyId = await getOrCreateContextKey(adapter, decisionKey);
430
256
  // Get agent ID if provided
431
257
  let agentId = null;
432
258
  if (decidedBy) {
433
- agentId = getOrCreateAgent(db, decidedBy);
259
+ agentId = await getOrCreateAgent(adapter, decidedBy);
434
260
  }
435
261
  // Insert context
436
- const result = db.prepare(`
437
- INSERT INTO t_decision_context (
438
- decision_key_id,
439
- rationale,
440
- alternatives_considered,
441
- tradeoffs,
442
- decided_by_agent_id,
443
- related_task_id,
444
- related_constraint_id
445
- ) VALUES (?, ?, ?, ?, ?, ?, ?)
446
- `).run(keyId, rationale, alternatives, tradeoffs, agentId, relatedTaskId, relatedConstraintId);
447
- return result.lastInsertRowid;
262
+ const [id] = await knex('t_decision_context').insert({
263
+ decision_key_id: keyId,
264
+ rationale,
265
+ alternatives_considered: alternatives,
266
+ tradeoffs,
267
+ decided_by_agent_id: agentId,
268
+ related_task_id: relatedTaskId,
269
+ related_constraint_id: relatedConstraintId,
270
+ decision_date: Math.floor(Date.now() / 1000),
271
+ });
272
+ return id;
448
273
  }
449
274
  /**
450
275
  * Get decision with context
451
- *
452
- * @param db - Database instance
453
- * @param decisionKey - Decision key
454
- * @returns Decision with context or null if not found
455
276
  */
456
- export function getDecisionWithContext(db, decisionKey) {
277
+ export async function getDecisionWithContext(adapter, decisionKey) {
278
+ const knex = adapter.getKnex();
457
279
  // First get the decision
458
- const decision = db.prepare(`
459
- SELECT
460
- k.key,
461
- d.value,
462
- d.version,
463
- CASE d.status WHEN 1 THEN 'active' WHEN 2 THEN 'deprecated' ELSE 'draft' END as status,
464
- l.name as layer,
465
- a.name as decided_by,
466
- datetime(d.ts, 'unixepoch') as updated
467
- FROM t_decisions d
468
- JOIN m_context_keys k ON d.key_id = k.id
469
- LEFT JOIN m_layers l ON d.layer_id = l.id
470
- LEFT JOIN m_agents a ON d.agent_id = a.id
471
- WHERE k.key = ?
472
- `).get(decisionKey);
280
+ const decision = await knex('t_decisions as d')
281
+ .join('m_context_keys as k', 'd.key_id', 'k.id')
282
+ .leftJoin('m_layers as l', 'd.layer_id', 'l.id')
283
+ .leftJoin('m_agents as a', 'd.agent_id', 'a.id')
284
+ .where('k.key', decisionKey)
285
+ .select('k.key', 'd.value', 'd.version', knex.raw(`CASE d.status WHEN 1 THEN 'active' WHEN 2 THEN 'deprecated' ELSE 'draft' END as status`), 'l.name as layer', 'a.name as decided_by', knex.raw(`datetime(d.ts, 'unixepoch') as updated`))
286
+ .first();
473
287
  if (!decision)
474
288
  return null;
475
289
  // Get all contexts for this decision
476
- const contexts = db.prepare(`
477
- SELECT
478
- dc.id,
479
- dc.rationale,
480
- dc.alternatives_considered,
481
- dc.tradeoffs,
482
- a.name as decided_by,
483
- datetime(dc.decision_date, 'unixepoch') as decision_date,
484
- dc.related_task_id,
485
- dc.related_constraint_id
486
- FROM t_decision_context dc
487
- JOIN m_context_keys k ON dc.decision_key_id = k.id
488
- LEFT JOIN m_agents a ON dc.decided_by_agent_id = a.id
489
- WHERE k.key = ?
490
- ORDER BY dc.decision_date DESC
491
- `).all(decisionKey);
290
+ const contexts = await knex('t_decision_context as dc')
291
+ .join('m_context_keys as k', 'dc.decision_key_id', 'k.id')
292
+ .leftJoin('m_agents as a', 'dc.decided_by_agent_id', 'a.id')
293
+ .where('k.key', decisionKey)
294
+ .select('dc.id', 'dc.rationale', 'dc.alternatives_considered', 'dc.tradeoffs', 'a.name as decided_by', knex.raw(`datetime(dc.decision_date, 'unixepoch') as decision_date`), 'dc.related_task_id', 'dc.related_constraint_id')
295
+ .orderBy('dc.decision_date', 'desc');
492
296
  return {
493
297
  ...decision,
494
298
  context: contexts,
@@ -496,54 +300,46 @@ export function getDecisionWithContext(db, decisionKey) {
496
300
  }
497
301
  /**
498
302
  * List decision contexts with optional filters
499
- *
500
- * @param db - Database instance
501
- * @param filters - Optional filters
502
- * @returns Array of decision contexts
503
303
  */
504
- export function listDecisionContexts(db, filters) {
505
- let query = `
506
- SELECT
507
- dc.id,
508
- k.key as decision_key,
509
- dc.rationale,
510
- dc.alternatives_considered,
511
- dc.tradeoffs,
512
- a.name as decided_by,
513
- datetime(dc.decision_date, 'unixepoch') as decision_date,
514
- dc.related_task_id,
515
- dc.related_constraint_id
516
- FROM t_decision_context dc
517
- JOIN m_context_keys k ON dc.decision_key_id = k.id
518
- LEFT JOIN m_agents a ON dc.decided_by_agent_id = a.id
519
- WHERE 1=1
520
- `;
521
- const params = [];
304
+ export async function listDecisionContexts(adapter, filters) {
305
+ const knex = adapter.getKnex();
306
+ let query = knex('t_decision_context as dc')
307
+ .join('m_context_keys as k', 'dc.decision_key_id', 'k.id')
308
+ .leftJoin('m_agents as a', 'dc.decided_by_agent_id', 'a.id')
309
+ .select('dc.id', 'k.key as decision_key', 'dc.rationale', 'dc.alternatives_considered', 'dc.tradeoffs', 'a.name as decided_by', knex.raw(`datetime(dc.decision_date, 'unixepoch') as decision_date`), 'dc.related_task_id', 'dc.related_constraint_id');
522
310
  if (filters?.decisionKey) {
523
- query += ' AND k.key = ?';
524
- params.push(filters.decisionKey);
311
+ query = query.where('k.key', filters.decisionKey);
525
312
  }
526
313
  if (filters?.relatedTaskId !== undefined) {
527
- query += ' AND dc.related_task_id = ?';
528
- params.push(filters.relatedTaskId);
314
+ query = query.where('dc.related_task_id', filters.relatedTaskId);
529
315
  }
530
316
  if (filters?.relatedConstraintId !== undefined) {
531
- query += ' AND dc.related_constraint_id = ?';
532
- params.push(filters.relatedConstraintId);
317
+ query = query.where('dc.related_constraint_id', filters.relatedConstraintId);
533
318
  }
534
319
  if (filters?.decidedBy) {
535
- query += ' AND a.name = ?';
536
- params.push(filters.decidedBy);
320
+ query = query.where('a.name', filters.decidedBy);
537
321
  }
538
- query += ' ORDER BY dc.decision_date DESC';
322
+ query = query.orderBy('dc.decision_date', 'desc');
539
323
  if (filters?.limit) {
540
- query += ' LIMIT ?';
541
- params.push(filters.limit);
324
+ query = query.limit(filters.limit);
542
325
  }
543
326
  if (filters?.offset) {
544
- query += ' OFFSET ?';
545
- params.push(filters.offset);
327
+ query = query.offset(filters.offset);
546
328
  }
547
- return db.prepare(query).all(...params);
329
+ return await query;
330
+ }
331
+ /**
332
+ * Backwards compatibility alias for getAdapter
333
+ */
334
+ export function getDatabase() {
335
+ return getAdapter();
336
+ }
337
+ /**
338
+ * Execute a function within a database transaction
339
+ */
340
+ export async function transaction(callback) {
341
+ const adapter = getAdapter();
342
+ const knex = adapter.getKnex();
343
+ return await knex.transaction(callback);
548
344
  }
549
345
  //# sourceMappingURL=database.js.map