sqlew 3.6.10 → 3.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (372) hide show
  1. package/CHANGELOG.md +346 -0
  2. package/README.md +54 -39
  3. package/assets/config.example.toml +93 -0
  4. package/assets/kanban-visualizer.png +0 -0
  5. package/assets/sample-agents/sqlew-architect.md +32 -13
  6. package/assets/sample-agents/sqlew-researcher.md +70 -17
  7. package/assets/sample-agents/sqlew-scrum-master.md +60 -25
  8. package/assets/schema.sql +2 -2
  9. package/dist/adapters/auth/auth-factory.d.ts +86 -0
  10. package/dist/adapters/auth/auth-factory.d.ts.map +1 -0
  11. package/dist/adapters/auth/auth-factory.js +103 -0
  12. package/dist/adapters/auth/auth-factory.js.map +1 -0
  13. package/dist/adapters/auth/auth-types.d.ts +30 -0
  14. package/dist/adapters/auth/auth-types.d.ts.map +1 -0
  15. package/dist/adapters/auth/auth-types.js +30 -0
  16. package/dist/adapters/auth/auth-types.js.map +1 -0
  17. package/dist/adapters/auth/base-auth-provider.d.ts +327 -0
  18. package/dist/adapters/auth/base-auth-provider.d.ts.map +1 -0
  19. package/dist/adapters/auth/base-auth-provider.js +111 -0
  20. package/dist/adapters/auth/base-auth-provider.js.map +1 -0
  21. package/dist/adapters/auth/direct-auth-provider.d.ts +356 -0
  22. package/dist/adapters/auth/direct-auth-provider.d.ts.map +1 -0
  23. package/dist/adapters/auth/direct-auth-provider.js +406 -0
  24. package/dist/adapters/auth/direct-auth-provider.js.map +1 -0
  25. package/dist/adapters/base-adapter.d.ts +638 -0
  26. package/dist/adapters/base-adapter.d.ts.map +1 -0
  27. package/dist/adapters/base-adapter.js +557 -0
  28. package/dist/adapters/base-adapter.js.map +1 -0
  29. package/dist/adapters/index.d.ts +13 -2
  30. package/dist/adapters/index.d.ts.map +1 -1
  31. package/dist/adapters/index.js +27 -5
  32. package/dist/adapters/index.js.map +1 -1
  33. package/dist/adapters/mysql-adapter.d.ts +547 -6
  34. package/dist/adapters/mysql-adapter.d.ts.map +1 -1
  35. package/dist/adapters/mysql-adapter.js +651 -32
  36. package/dist/adapters/mysql-adapter.js.map +1 -1
  37. package/dist/adapters/postgresql-adapter.d.ts +15 -4
  38. package/dist/adapters/postgresql-adapter.d.ts.map +1 -1
  39. package/dist/adapters/postgresql-adapter.js +19 -2
  40. package/dist/adapters/postgresql-adapter.js.map +1 -1
  41. package/dist/adapters/sqlite-adapter.d.ts +35 -5
  42. package/dist/adapters/sqlite-adapter.d.ts.map +1 -1
  43. package/dist/adapters/sqlite-adapter.js +57 -18
  44. package/dist/adapters/sqlite-adapter.js.map +1 -1
  45. package/dist/cli/db-dump.d.ts +32 -0
  46. package/dist/cli/db-dump.d.ts.map +1 -0
  47. package/dist/cli/db-dump.js +409 -0
  48. package/dist/cli/db-dump.js.map +1 -0
  49. package/dist/cli.js +24 -14
  50. package/dist/cli.js.map +1 -1
  51. package/dist/config/knex/bootstrap/20251025020452_create_master_tables.d.ts.map +1 -0
  52. package/dist/{migrations → config}/knex/bootstrap/20251025020452_create_master_tables.js +7 -2
  53. package/dist/config/knex/bootstrap/20251025020452_create_master_tables.js.map +1 -0
  54. package/dist/config/knex/bootstrap/20251025021152_create_transaction_tables.d.ts.map +1 -0
  55. package/dist/{migrations → config}/knex/bootstrap/20251025021152_create_transaction_tables.js +49 -50
  56. package/dist/config/knex/bootstrap/20251025021152_create_transaction_tables.js.map +1 -0
  57. package/dist/config/knex/bootstrap/20251025021351_create_indexes.d.ts.map +1 -0
  58. package/dist/config/knex/bootstrap/20251025021351_create_indexes.js.map +1 -0
  59. package/dist/config/knex/bootstrap/20251025021416_seed_master_data.d.ts.map +1 -0
  60. package/dist/{migrations → config}/knex/bootstrap/20251025021416_seed_master_data.js +11 -6
  61. package/dist/config/knex/bootstrap/20251025021416_seed_master_data.js.map +1 -0
  62. package/dist/config/knex/bootstrap/20251025070349_create_views.d.ts.map +1 -0
  63. package/dist/{migrations → config}/knex/bootstrap/20251025070349_create_views.js +66 -14
  64. package/dist/config/knex/bootstrap/20251025070349_create_views.js.map +1 -0
  65. package/dist/config/knex/enhancements/20251025081221_add_link_type_to_task_decision_links.d.ts.map +1 -0
  66. package/dist/config/knex/enhancements/20251025081221_add_link_type_to_task_decision_links.js +22 -0
  67. package/dist/config/knex/enhancements/20251025081221_add_link_type_to_task_decision_links.js.map +1 -0
  68. package/dist/config/knex/enhancements/20251025082220_fix_task_dependencies_columns.d.ts.map +1 -0
  69. package/dist/config/knex/enhancements/20251025082220_fix_task_dependencies_columns.js.map +1 -0
  70. package/dist/config/knex/enhancements/20251025090000_create_help_system_tables.d.ts.map +1 -0
  71. package/dist/{migrations → config}/knex/enhancements/20251025090000_create_help_system_tables.js +6 -0
  72. package/dist/config/knex/enhancements/20251025090000_create_help_system_tables.js.map +1 -0
  73. package/dist/config/knex/enhancements/20251025090100_seed_help_categories_and_use_cases.d.ts.map +1 -0
  74. package/dist/{migrations → config}/knex/enhancements/20251025090100_seed_help_categories_and_use_cases.js +6 -0
  75. package/dist/config/knex/enhancements/20251025090100_seed_help_categories_and_use_cases.js.map +1 -0
  76. package/dist/config/knex/enhancements/20251025100000_seed_help_metadata.d.ts.map +1 -0
  77. package/dist/{migrations → config}/knex/enhancements/20251025100000_seed_help_metadata.js +6 -0
  78. package/dist/config/knex/enhancements/20251025100000_seed_help_metadata.js.map +1 -0
  79. package/dist/config/knex/enhancements/20251025100100_seed_remaining_use_cases.d.ts.map +1 -0
  80. package/dist/config/knex/enhancements/20251025100100_seed_remaining_use_cases.js.map +1 -0
  81. package/dist/config/knex/enhancements/20251025120000_add_cascade_to_task_dependencies.d.ts.map +1 -0
  82. package/dist/{migrations → config}/knex/enhancements/20251025120000_add_cascade_to_task_dependencies.js +7 -0
  83. package/dist/config/knex/enhancements/20251025120000_add_cascade_to_task_dependencies.js.map +1 -0
  84. package/dist/config/knex/enhancements/20251027000000_add_agent_reuse_system.d.ts.map +1 -0
  85. package/dist/config/knex/enhancements/20251027000000_add_agent_reuse_system.js +62 -0
  86. package/dist/config/knex/enhancements/20251027000000_add_agent_reuse_system.js.map +1 -0
  87. package/dist/config/knex/enhancements/20251027010000_add_task_constraint_to_decision_context.d.ts.map +1 -0
  88. package/dist/config/knex/enhancements/20251027010000_add_task_constraint_to_decision_context.js.map +1 -0
  89. package/dist/config/knex/enhancements/20251027020000_update_agent_reusability.d.ts.map +1 -0
  90. package/dist/{migrations → config}/knex/enhancements/20251027020000_update_agent_reusability.js +6 -0
  91. package/dist/config/knex/enhancements/20251027020000_update_agent_reusability.js.map +1 -0
  92. package/dist/config/knex/enhancements/20251028000000_simplify_agent_system.d.ts.map +1 -0
  93. package/dist/{migrations → config}/knex/enhancements/20251028000000_simplify_agent_system.js +6 -0
  94. package/dist/config/knex/enhancements/20251028000000_simplify_agent_system.js.map +1 -0
  95. package/dist/config/knex/enhancements/20251031000000_drop_orphaned_message_view.d.ts +13 -0
  96. package/dist/config/knex/enhancements/20251031000000_drop_orphaned_message_view.d.ts.map +1 -0
  97. package/dist/config/knex/enhancements/20251031000000_drop_orphaned_message_view.js +48 -0
  98. package/dist/config/knex/enhancements/20251031000000_drop_orphaned_message_view.js.map +1 -0
  99. package/dist/config/knex/enhancements/20251104000003_rename_constraints_created_by_to_agent_id.d.ts +24 -0
  100. package/dist/config/knex/enhancements/20251104000003_rename_constraints_created_by_to_agent_id.d.ts.map +1 -0
  101. package/dist/config/knex/enhancements/20251104000003_rename_constraints_created_by_to_agent_id.js +189 -0
  102. package/dist/config/knex/enhancements/20251104000003_rename_constraints_created_by_to_agent_id.js.map +1 -0
  103. package/dist/config/knex/enhancements/20251105000000_add_token_usage_table.d.ts +16 -0
  104. package/dist/config/knex/enhancements/20251105000000_add_token_usage_table.d.ts.map +1 -0
  105. package/dist/config/knex/enhancements/20251105000000_add_token_usage_table.js +65 -0
  106. package/dist/config/knex/enhancements/20251105000000_add_token_usage_table.js.map +1 -0
  107. package/dist/config/knex/enhancements/20251105000001_rename_decision_context_decided_by_to_agent_id.d.ts +23 -0
  108. package/dist/config/knex/enhancements/20251105000001_rename_decision_context_decided_by_to_agent_id.d.ts.map +1 -0
  109. package/dist/config/knex/enhancements/20251105000001_rename_decision_context_decided_by_to_agent_id.js +118 -0
  110. package/dist/config/knex/enhancements/20251105000001_rename_decision_context_decided_by_to_agent_id.js.map +1 -0
  111. package/dist/config/knex/upgrades/20251024010000_upgrade_v1_0_to_v1_1.d.ts.map +1 -0
  112. package/dist/config/knex/upgrades/20251024010000_upgrade_v1_0_to_v1_1.js.map +1 -0
  113. package/dist/config/knex/upgrades/20251024020000_upgrade_v2_0_to_v2_1.d.ts.map +1 -0
  114. package/dist/config/knex/upgrades/20251024020000_upgrade_v2_0_to_v2_1.js.map +1 -0
  115. package/dist/config/knex/upgrades/20251024030000_upgrade_v2_1_to_v3_0.d.ts.map +1 -0
  116. package/dist/config/knex/upgrades/20251024030000_upgrade_v2_1_to_v3_0.js.map +1 -0
  117. package/dist/config/knex/upgrades/20251024040000_upgrade_v3_0_to_v3_2.d.ts.map +1 -0
  118. package/dist/config/knex/upgrades/20251024040000_upgrade_v3_0_to_v3_2.js.map +1 -0
  119. package/dist/config/knex/upgrades/20251024050000_upgrade_v3_2_0_to_v3_2_2.d.ts.map +1 -0
  120. package/dist/config/knex/upgrades/20251024050000_upgrade_v3_2_0_to_v3_2_2.js.map +1 -0
  121. package/dist/config/knex/upgrades/20251024060000_upgrade_v3_4_to_v3_5.d.ts.map +1 -0
  122. package/dist/config/knex/upgrades/20251024060000_upgrade_v3_4_to_v3_5.js.map +1 -0
  123. package/dist/config/knex/upgrades/20251024070000_upgrade_v3_5_to_v3_6.d.ts.map +1 -0
  124. package/dist/config/knex/upgrades/20251024070000_upgrade_v3_5_to_v3_6.js.map +1 -0
  125. package/dist/config/knex/upgrades/20251104000000_add_multi_project_v3_7_0.d.ts +49 -0
  126. package/dist/config/knex/upgrades/20251104000000_add_multi_project_v3_7_0.d.ts.map +1 -0
  127. package/dist/config/knex/upgrades/20251104000000_add_multi_project_v3_7_0.js +864 -0
  128. package/dist/config/knex/upgrades/20251104000000_add_multi_project_v3_7_0.js.map +1 -0
  129. package/dist/config/loader.d.ts +19 -1
  130. package/dist/config/loader.d.ts.map +1 -1
  131. package/dist/config/loader.js +149 -4
  132. package/dist/config/loader.js.map +1 -1
  133. package/dist/config/types.d.ts +261 -2
  134. package/dist/config/types.d.ts.map +1 -1
  135. package/dist/config/types.js.map +1 -1
  136. package/dist/config/writer.d.ts +65 -0
  137. package/dist/config/writer.d.ts.map +1 -0
  138. package/dist/config/writer.js +139 -0
  139. package/dist/config/writer.js.map +1 -0
  140. package/dist/database.d.ts +11 -2
  141. package/dist/database.d.ts.map +1 -1
  142. package/dist/database.js +62 -6
  143. package/dist/database.js.map +1 -1
  144. package/dist/index.js +173 -39
  145. package/dist/index.js.map +1 -1
  146. package/dist/knexfile.d.ts.map +1 -1
  147. package/dist/knexfile.js +88 -12
  148. package/dist/knexfile.js.map +1 -1
  149. package/dist/tests/all-features.test.js +15 -3
  150. package/dist/tests/all-features.test.js.map +1 -1
  151. package/dist/tests/config-loader.test.d.ts +6 -0
  152. package/dist/tests/config-loader.test.d.ts.map +1 -0
  153. package/dist/tests/config-loader.test.js +201 -0
  154. package/dist/tests/config-loader.test.js.map +1 -0
  155. package/dist/tests/connection-manager-integration.test.d.ts +2 -0
  156. package/dist/tests/connection-manager-integration.test.d.ts.map +1 -0
  157. package/dist/tests/connection-manager-integration.test.js +431 -0
  158. package/dist/tests/connection-manager-integration.test.js.map +1 -0
  159. package/dist/tests/connection-manager.test.d.ts +2 -0
  160. package/dist/tests/connection-manager.test.d.ts.map +1 -0
  161. package/dist/tests/connection-manager.test.js +361 -0
  162. package/dist/tests/connection-manager.test.js.map +1 -0
  163. package/dist/tests/dump-import.test.d.ts +15 -0
  164. package/dist/tests/dump-import.test.d.ts.map +1 -0
  165. package/dist/tests/dump-import.test.js +430 -0
  166. package/dist/tests/dump-import.test.js.map +1 -0
  167. package/dist/tests/migration-idempotency.test.d.ts +2 -0
  168. package/dist/tests/migration-idempotency.test.d.ts.map +1 -0
  169. package/dist/tests/migration-idempotency.test.js +330 -0
  170. package/dist/tests/migration-idempotency.test.js.map +1 -0
  171. package/dist/tests/migration-upgrade-paths.test.d.ts +2 -0
  172. package/dist/tests/migration-upgrade-paths.test.d.ts.map +1 -0
  173. package/dist/tests/migration-upgrade-paths.test.js +248 -0
  174. package/dist/tests/migration-upgrade-paths.test.js.map +1 -0
  175. package/dist/tests/migrations/test-all-versions-real.js +3 -0
  176. package/dist/tests/migrations/test-all-versions-real.js.map +1 -1
  177. package/dist/tests/multi-project-migration.test.d.ts +17 -0
  178. package/dist/tests/multi-project-migration.test.d.ts.map +1 -0
  179. package/dist/tests/multi-project-migration.test.js +399 -0
  180. package/dist/tests/multi-project-migration.test.js.map +1 -0
  181. package/dist/tests/multi-project.test.d.ts +5 -0
  182. package/dist/tests/multi-project.test.d.ts.map +1 -0
  183. package/dist/tests/multi-project.test.js +238 -0
  184. package/dist/tests/multi-project.test.js.map +1 -0
  185. package/dist/tests/schema-migration.test.d.ts +8 -0
  186. package/dist/tests/schema-migration.test.d.ts.map +1 -0
  187. package/dist/tests/schema-migration.test.js +108 -0
  188. package/dist/tests/schema-migration.test.js.map +1 -0
  189. package/dist/tests/sql-dump-converters.test.d.ts +7 -0
  190. package/dist/tests/sql-dump-converters.test.d.ts.map +1 -0
  191. package/dist/tests/sql-dump-converters.test.js +314 -0
  192. package/dist/tests/sql-dump-converters.test.js.map +1 -0
  193. package/dist/tests/sql-dump-cross-database.test.d.ts +21 -0
  194. package/dist/tests/sql-dump-cross-database.test.d.ts.map +1 -0
  195. package/dist/tests/sql-dump-cross-database.test.js +314 -0
  196. package/dist/tests/sql-dump-cross-database.test.js.map +1 -0
  197. package/dist/tests/sql-dump-default-conversions.test.d.ts +8 -0
  198. package/dist/tests/sql-dump-default-conversions.test.d.ts.map +1 -0
  199. package/dist/tests/sql-dump-default-conversions.test.js +141 -0
  200. package/dist/tests/sql-dump-default-conversions.test.js.map +1 -0
  201. package/dist/tests/sql-dump-fk-constraints.test.d.ts +13 -0
  202. package/dist/tests/sql-dump-fk-constraints.test.d.ts.map +1 -0
  203. package/dist/tests/sql-dump-fk-constraints.test.js +381 -0
  204. package/dist/tests/sql-dump-fk-constraints.test.js.map +1 -0
  205. package/dist/tests/sql-dump-indexes.test.d.ts +12 -0
  206. package/dist/tests/sql-dump-indexes.test.d.ts.map +1 -0
  207. package/dist/tests/sql-dump-indexes.test.js +269 -0
  208. package/dist/tests/sql-dump-indexes.test.js.map +1 -0
  209. package/dist/tests/sql-dump-integration.test.d.ts +16 -0
  210. package/dist/tests/sql-dump-integration.test.d.ts.map +1 -0
  211. package/dist/tests/sql-dump-integration.test.js +342 -0
  212. package/dist/tests/sql-dump-integration.test.js.map +1 -0
  213. package/dist/tests/sql-dump-table-ordering.test.d.ts +8 -0
  214. package/dist/tests/sql-dump-table-ordering.test.d.ts.map +1 -0
  215. package/dist/tests/sql-dump-table-ordering.test.js +253 -0
  216. package/dist/tests/sql-dump-table-ordering.test.js.map +1 -0
  217. package/dist/tests/tasks.link-file-backward-compat.test.js +11 -1
  218. package/dist/tests/tasks.link-file-backward-compat.test.js.map +1 -1
  219. package/dist/tests/tasks.watch-files-action.test.js +11 -1
  220. package/dist/tests/tasks.watch-files-action.test.js.map +1 -1
  221. package/dist/tests/type-conversion.test.d.ts +8 -0
  222. package/dist/tests/type-conversion.test.d.ts.map +1 -0
  223. package/dist/tests/type-conversion.test.js +312 -0
  224. package/dist/tests/type-conversion.test.js.map +1 -0
  225. package/dist/tests/utils/test-helpers.d.ts +93 -0
  226. package/dist/tests/utils/test-helpers.d.ts.map +1 -0
  227. package/dist/tests/utils/test-helpers.js +407 -0
  228. package/dist/tests/utils/test-helpers.js.map +1 -0
  229. package/dist/tools/config.d.ts +58 -0
  230. package/dist/tools/config.d.ts.map +1 -0
  231. package/dist/tools/config.js +281 -0
  232. package/dist/tools/config.js.map +1 -0
  233. package/dist/tools/constraints.d.ts.map +1 -1
  234. package/dist/tools/constraints.js +138 -122
  235. package/dist/tools/constraints.js.map +1 -1
  236. package/dist/tools/context.d.ts.map +1 -1
  237. package/dist/tools/context.js +216 -109
  238. package/dist/tools/context.js.map +1 -1
  239. package/dist/tools/files.d.ts.map +1 -1
  240. package/dist/tools/files.js +123 -102
  241. package/dist/tools/files.js.map +1 -1
  242. package/dist/tools/tasks.d.ts.map +1 -1
  243. package/dist/tools/tasks.js +593 -518
  244. package/dist/tools/tasks.js.map +1 -1
  245. package/dist/tools/utils.d.ts +5 -0
  246. package/dist/tools/utils.d.ts.map +1 -1
  247. package/dist/tools/utils.js +176 -122
  248. package/dist/tools/utils.js.map +1 -1
  249. package/dist/types.d.ts +9 -26
  250. package/dist/types.d.ts.map +1 -1
  251. package/dist/utils/cleanup.d.ts +3 -0
  252. package/dist/utils/cleanup.d.ts.map +1 -1
  253. package/dist/utils/cleanup.js +14 -2
  254. package/dist/utils/cleanup.js.map +1 -1
  255. package/dist/utils/connection-manager.d.ts +59 -0
  256. package/dist/utils/connection-manager.d.ts.map +1 -0
  257. package/dist/utils/connection-manager.js +178 -0
  258. package/dist/utils/connection-manager.js.map +1 -0
  259. package/dist/utils/debug-logger.d.ts +8 -4
  260. package/dist/utils/debug-logger.d.ts.map +1 -1
  261. package/dist/utils/debug-logger.js +27 -7
  262. package/dist/utils/debug-logger.js.map +1 -1
  263. package/dist/utils/error-handler.d.ts +6 -4
  264. package/dist/utils/error-handler.d.ts.map +1 -1
  265. package/dist/utils/error-handler.js +34 -9
  266. package/dist/utils/error-handler.js.map +1 -1
  267. package/dist/utils/parameter-validator.d.ts.map +1 -1
  268. package/dist/utils/parameter-validator.js +50 -16
  269. package/dist/utils/parameter-validator.js.map +1 -1
  270. package/dist/utils/project-context.d.ts +111 -0
  271. package/dist/utils/project-context.d.ts.map +1 -0
  272. package/dist/utils/project-context.js +187 -0
  273. package/dist/utils/project-context.js.map +1 -0
  274. package/dist/utils/sql-dump-converters.d.ts +188 -0
  275. package/dist/utils/sql-dump-converters.d.ts.map +1 -0
  276. package/dist/utils/sql-dump-converters.js +311 -0
  277. package/dist/utils/sql-dump-converters.js.map +1 -0
  278. package/dist/utils/sql-dump.d.ts +102 -0
  279. package/dist/utils/sql-dump.d.ts.map +1 -0
  280. package/dist/utils/sql-dump.js +1550 -0
  281. package/dist/utils/sql-dump.js.map +1 -0
  282. package/dist/utils/vcs-adapter.d.ts +42 -0
  283. package/dist/utils/vcs-adapter.d.ts.map +1 -1
  284. package/dist/utils/vcs-adapter.js +154 -0
  285. package/dist/utils/vcs-adapter.js.map +1 -1
  286. package/docs/BASEADAPTER_IMPLEMENTATION.md +399 -0
  287. package/docs/DATABASE_AUTH.md +445 -0
  288. package/docs/DATABASE_MIGRATION.md +247 -0
  289. package/docs/MULTI_PROJECT_ARCHITECTURE.md +497 -0
  290. package/package.json +12 -4
  291. package/dist/migrations/knex/bootstrap/20251025020452_create_master_tables.d.ts.map +0 -1
  292. package/dist/migrations/knex/bootstrap/20251025020452_create_master_tables.js.map +0 -1
  293. package/dist/migrations/knex/bootstrap/20251025021152_create_transaction_tables.d.ts.map +0 -1
  294. package/dist/migrations/knex/bootstrap/20251025021152_create_transaction_tables.js.map +0 -1
  295. package/dist/migrations/knex/bootstrap/20251025021351_create_indexes.d.ts.map +0 -1
  296. package/dist/migrations/knex/bootstrap/20251025021351_create_indexes.js.map +0 -1
  297. package/dist/migrations/knex/bootstrap/20251025021416_seed_master_data.d.ts.map +0 -1
  298. package/dist/migrations/knex/bootstrap/20251025021416_seed_master_data.js.map +0 -1
  299. package/dist/migrations/knex/bootstrap/20251025070349_create_views.d.ts.map +0 -1
  300. package/dist/migrations/knex/bootstrap/20251025070349_create_views.js.map +0 -1
  301. package/dist/migrations/knex/enhancements/20251025081221_add_link_type_to_task_decision_links.d.ts.map +0 -1
  302. package/dist/migrations/knex/enhancements/20251025081221_add_link_type_to_task_decision_links.js +0 -15
  303. package/dist/migrations/knex/enhancements/20251025081221_add_link_type_to_task_decision_links.js.map +0 -1
  304. package/dist/migrations/knex/enhancements/20251025082220_fix_task_dependencies_columns.d.ts.map +0 -1
  305. package/dist/migrations/knex/enhancements/20251025082220_fix_task_dependencies_columns.js.map +0 -1
  306. package/dist/migrations/knex/enhancements/20251025090000_create_help_system_tables.d.ts.map +0 -1
  307. package/dist/migrations/knex/enhancements/20251025090000_create_help_system_tables.js.map +0 -1
  308. package/dist/migrations/knex/enhancements/20251025090100_seed_help_categories_and_use_cases.d.ts.map +0 -1
  309. package/dist/migrations/knex/enhancements/20251025090100_seed_help_categories_and_use_cases.js.map +0 -1
  310. package/dist/migrations/knex/enhancements/20251025100000_seed_help_metadata.d.ts.map +0 -1
  311. package/dist/migrations/knex/enhancements/20251025100000_seed_help_metadata.js.map +0 -1
  312. package/dist/migrations/knex/enhancements/20251025100100_seed_remaining_use_cases.d.ts.map +0 -1
  313. package/dist/migrations/knex/enhancements/20251025100100_seed_remaining_use_cases.js.map +0 -1
  314. package/dist/migrations/knex/enhancements/20251025120000_add_cascade_to_task_dependencies.d.ts.map +0 -1
  315. package/dist/migrations/knex/enhancements/20251025120000_add_cascade_to_task_dependencies.js.map +0 -1
  316. package/dist/migrations/knex/enhancements/20251027000000_add_agent_reuse_system.d.ts.map +0 -1
  317. package/dist/migrations/knex/enhancements/20251027000000_add_agent_reuse_system.js +0 -34
  318. package/dist/migrations/knex/enhancements/20251027000000_add_agent_reuse_system.js.map +0 -1
  319. package/dist/migrations/knex/enhancements/20251027010000_add_task_constraint_to_decision_context.d.ts.map +0 -1
  320. package/dist/migrations/knex/enhancements/20251027010000_add_task_constraint_to_decision_context.js.map +0 -1
  321. package/dist/migrations/knex/enhancements/20251027020000_update_agent_reusability.d.ts.map +0 -1
  322. package/dist/migrations/knex/enhancements/20251027020000_update_agent_reusability.js.map +0 -1
  323. package/dist/migrations/knex/enhancements/20251028000000_simplify_agent_system.d.ts.map +0 -1
  324. package/dist/migrations/knex/enhancements/20251028000000_simplify_agent_system.js.map +0 -1
  325. package/dist/migrations/knex/upgrades/20251024010000_upgrade_v1_0_to_v1_1.d.ts.map +0 -1
  326. package/dist/migrations/knex/upgrades/20251024010000_upgrade_v1_0_to_v1_1.js.map +0 -1
  327. package/dist/migrations/knex/upgrades/20251024020000_upgrade_v2_0_to_v2_1.d.ts.map +0 -1
  328. package/dist/migrations/knex/upgrades/20251024020000_upgrade_v2_0_to_v2_1.js.map +0 -1
  329. package/dist/migrations/knex/upgrades/20251024030000_upgrade_v2_1_to_v3_0.d.ts.map +0 -1
  330. package/dist/migrations/knex/upgrades/20251024030000_upgrade_v2_1_to_v3_0.js.map +0 -1
  331. package/dist/migrations/knex/upgrades/20251024040000_upgrade_v3_0_to_v3_2.d.ts.map +0 -1
  332. package/dist/migrations/knex/upgrades/20251024040000_upgrade_v3_0_to_v3_2.js.map +0 -1
  333. package/dist/migrations/knex/upgrades/20251024050000_upgrade_v3_2_0_to_v3_2_2.d.ts.map +0 -1
  334. package/dist/migrations/knex/upgrades/20251024050000_upgrade_v3_2_0_to_v3_2_2.js.map +0 -1
  335. package/dist/migrations/knex/upgrades/20251024060000_upgrade_v3_4_to_v3_5.d.ts.map +0 -1
  336. package/dist/migrations/knex/upgrades/20251024060000_upgrade_v3_4_to_v3_5.js.map +0 -1
  337. package/dist/migrations/knex/upgrades/20251024070000_upgrade_v3_5_to_v3_6.d.ts.map +0 -1
  338. package/dist/migrations/knex/upgrades/20251024070000_upgrade_v3_5_to_v3_6.js.map +0 -1
  339. /package/dist/{migrations → config}/knex/bootstrap/20251025020452_create_master_tables.d.ts +0 -0
  340. /package/dist/{migrations → config}/knex/bootstrap/20251025021152_create_transaction_tables.d.ts +0 -0
  341. /package/dist/{migrations → config}/knex/bootstrap/20251025021351_create_indexes.d.ts +0 -0
  342. /package/dist/{migrations → config}/knex/bootstrap/20251025021351_create_indexes.js +0 -0
  343. /package/dist/{migrations → config}/knex/bootstrap/20251025021416_seed_master_data.d.ts +0 -0
  344. /package/dist/{migrations → config}/knex/bootstrap/20251025070349_create_views.d.ts +0 -0
  345. /package/dist/{migrations → config}/knex/enhancements/20251025081221_add_link_type_to_task_decision_links.d.ts +0 -0
  346. /package/dist/{migrations → config}/knex/enhancements/20251025082220_fix_task_dependencies_columns.d.ts +0 -0
  347. /package/dist/{migrations → config}/knex/enhancements/20251025082220_fix_task_dependencies_columns.js +0 -0
  348. /package/dist/{migrations → config}/knex/enhancements/20251025090000_create_help_system_tables.d.ts +0 -0
  349. /package/dist/{migrations → config}/knex/enhancements/20251025090100_seed_help_categories_and_use_cases.d.ts +0 -0
  350. /package/dist/{migrations → config}/knex/enhancements/20251025100000_seed_help_metadata.d.ts +0 -0
  351. /package/dist/{migrations → config}/knex/enhancements/20251025100100_seed_remaining_use_cases.d.ts +0 -0
  352. /package/dist/{migrations → config}/knex/enhancements/20251025100100_seed_remaining_use_cases.js +0 -0
  353. /package/dist/{migrations → config}/knex/enhancements/20251025120000_add_cascade_to_task_dependencies.d.ts +0 -0
  354. /package/dist/{migrations → config}/knex/enhancements/20251027000000_add_agent_reuse_system.d.ts +0 -0
  355. /package/dist/{migrations → config}/knex/enhancements/20251027010000_add_task_constraint_to_decision_context.d.ts +0 -0
  356. /package/dist/{migrations → config}/knex/enhancements/20251027010000_add_task_constraint_to_decision_context.js +0 -0
  357. /package/dist/{migrations → config}/knex/enhancements/20251027020000_update_agent_reusability.d.ts +0 -0
  358. /package/dist/{migrations → config}/knex/enhancements/20251028000000_simplify_agent_system.d.ts +0 -0
  359. /package/dist/{migrations → config}/knex/upgrades/20251024010000_upgrade_v1_0_to_v1_1.d.ts +0 -0
  360. /package/dist/{migrations → config}/knex/upgrades/20251024010000_upgrade_v1_0_to_v1_1.js +0 -0
  361. /package/dist/{migrations → config}/knex/upgrades/20251024020000_upgrade_v2_0_to_v2_1.d.ts +0 -0
  362. /package/dist/{migrations → config}/knex/upgrades/20251024020000_upgrade_v2_0_to_v2_1.js +0 -0
  363. /package/dist/{migrations → config}/knex/upgrades/20251024030000_upgrade_v2_1_to_v3_0.d.ts +0 -0
  364. /package/dist/{migrations → config}/knex/upgrades/20251024030000_upgrade_v2_1_to_v3_0.js +0 -0
  365. /package/dist/{migrations → config}/knex/upgrades/20251024040000_upgrade_v3_0_to_v3_2.d.ts +0 -0
  366. /package/dist/{migrations → config}/knex/upgrades/20251024040000_upgrade_v3_0_to_v3_2.js +0 -0
  367. /package/dist/{migrations → config}/knex/upgrades/20251024050000_upgrade_v3_2_0_to_v3_2_2.d.ts +0 -0
  368. /package/dist/{migrations → config}/knex/upgrades/20251024050000_upgrade_v3_2_0_to_v3_2_2.js +0 -0
  369. /package/dist/{migrations → config}/knex/upgrades/20251024060000_upgrade_v3_4_to_v3_5.d.ts +0 -0
  370. /package/dist/{migrations → config}/knex/upgrades/20251024060000_upgrade_v3_4_to_v3_5.js +0 -0
  371. /package/dist/{migrations → config}/knex/upgrades/20251024070000_upgrade_v3_5_to_v3_6.d.ts +0 -0
  372. /package/dist/{migrations → config}/knex/upgrades/20251024070000_upgrade_v3_5_to_v3_6.js +0 -0
@@ -1,63 +1,682 @@
1
- // src/adapters/mysql-adapter.ts
2
- import knexLib from 'knex';
3
- const { knex } = knexLib;
4
- export class MySQLAdapter {
5
- knexInstance = null;
1
+ import { BaseAdapter } from './base-adapter.js';
2
+ /**
3
+ * MySQL adapter implementation with authentication support.
4
+ *
5
+ * This adapter provides MySQL-specific implementations for database operations,
6
+ * integrating with the authentication layer for secure connections via SSH tunnels,
7
+ * direct connections, or cloud IAM (AWS RDS, GCP Cloud SQL).
8
+ *
9
+ * **MySQL-Specific Features:**
10
+ * - ON DUPLICATE KEY UPDATE for upserts
11
+ * - JSON_EXTRACT() and JSON_OBJECT() for JSON operations
12
+ * - GROUP_CONCAT() for string aggregation
13
+ * - LAST_INSERT_ID() for retrieving inserted IDs
14
+ * - UNIX_TIMESTAMP() and FROM_UNIXTIME() for epoch conversions
15
+ * - AUTO_INCREMENT with UNSIGNED for ID columns
16
+ * - UTF8MB4 character set support for full Unicode
17
+ *
18
+ * **Supported MySQL Versions:**
19
+ * - MySQL 8.0+ (full feature support)
20
+ * - MySQL 5.7+ (basic feature support)
21
+ *
22
+ * **Authentication Methods:**
23
+ * - Direct: Standard username/password authentication
24
+ * - SSH Tunnel: Connect via SSH bastion host
25
+ * - AWS RDS IAM: Token-based authentication for AWS RDS
26
+ * - GCP Cloud SQL IAM: Token-based authentication for Cloud SQL
27
+ *
28
+ * @extends BaseAdapter
29
+ *
30
+ * @example
31
+ * // Direct connection
32
+ * const adapter = new MySQLAdapter({
33
+ * type: 'mysql',
34
+ * connection: {
35
+ * host: 'localhost',
36
+ * port: 3306,
37
+ * database: 'mydb'
38
+ * },
39
+ * auth: {
40
+ * type: 'direct',
41
+ * user: 'root',
42
+ * password: 'password'
43
+ * }
44
+ * });
45
+ *
46
+ * @example
47
+ * // SSH tunnel connection
48
+ * const adapter = new MySQLAdapter({
49
+ * type: 'mysql',
50
+ * connection: {
51
+ * host: 'db.internal',
52
+ * port: 3306,
53
+ * database: 'production'
54
+ * },
55
+ * auth: {
56
+ * type: 'ssh',
57
+ * user: 'dbuser',
58
+ * password: 'dbpass',
59
+ * ssh: {
60
+ * host: 'bastion.example.com',
61
+ * username: 'deploy',
62
+ * privateKeyPath: '/path/to/key.pem'
63
+ * }
64
+ * }
65
+ * });
66
+ *
67
+ * @example
68
+ * // AWS RDS IAM authentication
69
+ * const adapter = new MySQLAdapter({
70
+ * type: 'mysql',
71
+ * connection: {
72
+ * host: 'mydb.cluster-xxx.us-east-1.rds.amazonaws.com',
73
+ * port: 3306,
74
+ * database: 'production'
75
+ * },
76
+ * auth: {
77
+ * type: 'aws-iam',
78
+ * region: 'us-east-1'
79
+ * }
80
+ * });
81
+ */
82
+ export class MySQLAdapter extends BaseAdapter {
6
83
  // Feature detection
7
- supportsReturning = false;
8
- supportsJSON = true;
9
- supportsUpsert = true;
10
- supportsCTE = true;
11
- supportsWindowFunctions = true;
12
- supportsSavepoints = true;
84
+ supportsReturning = false; // MySQL doesn't support RETURNING clause
85
+ supportsJSON = true; // MySQL 5.7+ has native JSON support
86
+ supportsUpsert = true; // ON DUPLICATE KEY UPDATE
87
+ supportsCTE = true; // MySQL 8.0+ supports WITH clause
88
+ supportsWindowFunctions = true; // MySQL 8.0+ supports window functions
89
+ supportsSavepoints = true; // Full savepoint support
13
90
  databaseName = 'mysql';
14
- async connect(config) {
15
- throw new Error('MySQL adapter not implemented yet. Planned for Phase 3.');
91
+ /**
92
+ * Creates a new MySQL adapter instance.
93
+ *
94
+ * @param {DatabaseConfig} config - Database configuration with auth settings
95
+ */
96
+ constructor(config) {
97
+ super(config);
16
98
  }
17
- async disconnect() {
18
- throw new Error('MySQL adapter not implemented yet. Planned for Phase 3.');
99
+ /**
100
+ * Returns the Knex dialect for MySQL.
101
+ *
102
+ * Uses 'mysql2' driver which supports:
103
+ * - Prepared statements
104
+ * - Binary protocol
105
+ * - Promise-based API
106
+ * - Full Unicode (UTF8MB4)
107
+ *
108
+ * @returns {string} 'mysql2' dialect identifier
109
+ */
110
+ getDialect() {
111
+ return 'mysql2';
19
112
  }
20
- getKnex() {
21
- throw new Error('MySQL adapter not implemented yet. Planned for Phase 3.');
113
+ /**
114
+ * Initializes MySQL-specific session settings.
115
+ *
116
+ * **Configuration Applied:**
117
+ * - Character set: UTF8MB4 for full Unicode support (including emojis)
118
+ * - Collation: utf8mb4_unicode_ci for proper sorting
119
+ * - SQL mode: TRADITIONAL for strict SQL compliance
120
+ * - Timezone: UTC for consistent timestamp handling
121
+ * - Transaction isolation: READ COMMITTED (default)
122
+ *
123
+ * **Important Notes:**
124
+ * - UTF8MB4 requires MySQL 5.5.3+
125
+ * - These settings apply to the current session only
126
+ * - Connection pool creates new sessions with these settings
127
+ *
128
+ * @returns {Promise<void>}
129
+ *
130
+ * @throws {Error} If MySQL server version is incompatible
131
+ *
132
+ * @example
133
+ * // Called automatically after connect()
134
+ * await adapter.connect();
135
+ * // Session is now configured with UTF8MB4 and UTC timezone
136
+ */
137
+ async initialize() {
138
+ const knex = this.getKnex();
139
+ // Validate database exists
140
+ const dbName = this.config.connection?.database;
141
+ if (!dbName) {
142
+ throw new Error('MySQL adapter requires database name in configuration');
143
+ }
144
+ try {
145
+ // Query to check if we can access the database
146
+ const result = await knex.raw('SELECT DATABASE() as db');
147
+ const currentDb = result[0]?.[0]?.db;
148
+ if (!currentDb || currentDb !== dbName) {
149
+ throw new Error(`Database '${dbName}' does not exist or cannot be accessed. ` +
150
+ `Please create it manually: CREATE DATABASE ${dbName} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;`);
151
+ }
152
+ }
153
+ catch (error) {
154
+ if (error.code === 'ER_BAD_DB_ERROR') {
155
+ throw new Error(`Database '${dbName}' does not exist. ` +
156
+ `Please create it manually before connecting. Required privileges: SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, DROP, REFERENCES`);
157
+ }
158
+ throw error;
159
+ }
160
+ // Configure character set and collation for full Unicode support
161
+ await knex.raw("SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'");
162
+ // Set timezone to UTC for consistent timestamp handling
163
+ await knex.raw("SET time_zone = '+00:00'");
164
+ // Set SQL mode for strict compliance and safety
165
+ await knex.raw("SET sql_mode = 'TRADITIONAL'");
22
166
  }
167
+ // ============================================================================
168
+ // Query Adaptations - MySQL-specific implementations
169
+ // ============================================================================
170
+ /**
171
+ * Inserts a row and returns the inserted record.
172
+ *
173
+ * MySQL doesn't support RETURNING clause, so this method:
174
+ * 1. Inserts the row
175
+ * 2. Retrieves LAST_INSERT_ID()
176
+ * 3. Queries the inserted row by ID
177
+ *
178
+ * **Important Notes:**
179
+ * - Assumes table has an auto-increment `id` column
180
+ * - LAST_INSERT_ID() is connection-specific (thread-safe)
181
+ * - For tables without auto-increment ID, use composite unique keys
182
+ *
183
+ * @template T - Record type
184
+ * @param {string} table - Table name
185
+ * @param {Partial<T>} data - Data to insert
186
+ * @returns {Promise<T>} Inserted record
187
+ *
188
+ * @throws {Error} If insert fails or record cannot be retrieved
189
+ *
190
+ * @example
191
+ * // Insert user and return full record
192
+ * const user = await adapter.insertReturning<User>('users', {
193
+ * name: 'Alice',
194
+ * email: 'alice@example.com'
195
+ * });
196
+ * console.log(user.id); // Auto-generated ID
197
+ *
198
+ * @example
199
+ * // With transaction
200
+ * await adapter.transaction(async (trx) => {
201
+ * const user = await adapter.insertReturning<User>('users', {
202
+ * name: 'Bob'
203
+ * });
204
+ * await trx('profiles').insert({ user_id: user.id });
205
+ * });
206
+ */
23
207
  async insertReturning(table, data) {
24
- throw new Error('MySQL adapter not implemented yet. Planned for Phase 3.');
208
+ const knex = this.getKnex();
209
+ // Insert and get the auto-increment ID
210
+ const [insertId] = await knex(table).insert(data);
211
+ // Retrieve the inserted row using LAST_INSERT_ID()
212
+ const result = await knex(table).where({ id: insertId }).first();
213
+ if (!result) {
214
+ throw new Error(`Failed to retrieve inserted row from ${table}`);
215
+ }
216
+ return result;
25
217
  }
218
+ /**
219
+ * Upserts a row using MySQL's ON DUPLICATE KEY UPDATE syntax.
220
+ *
221
+ * **Behavior:**
222
+ * - If row with conflicting key exists: UPDATE specified columns
223
+ * - If no conflict: INSERT new row
224
+ * - Returns number of affected rows (1 = insert, 2 = update)
225
+ *
226
+ * **Important Notes:**
227
+ * - Requires UNIQUE index or PRIMARY KEY on conflictColumns
228
+ * - MySQL counts updates as 2 affected rows (1 delete + 1 insert internally)
229
+ * - If updateColumns not specified, updates all columns except conflict columns
230
+ *
231
+ * @template T - Record type
232
+ * @param {string} table - Table name
233
+ * @param {Partial<T>} data - Data to insert/update
234
+ * @param {string[]} conflictColumns - Columns that define uniqueness (must have UNIQUE index)
235
+ * @param {string[]} [updateColumns] - Columns to update on conflict (default: all except conflict columns)
236
+ * @returns {Promise<number>} Affected rows (1 = insert, 2 = update)
237
+ *
238
+ * @throws {Error} If conflictColumns don't have UNIQUE index
239
+ *
240
+ * @example
241
+ * // Upsert user by email (UNIQUE index on email)
242
+ * await adapter.upsert('users',
243
+ * { email: 'alice@example.com', name: 'Alice Updated', age: 30 },
244
+ * ['email'], // Conflict column
245
+ * ['name', 'age'] // Update these on conflict
246
+ * );
247
+ *
248
+ * @example
249
+ * // Upsert with composite key
250
+ * await adapter.upsert('user_settings',
251
+ * { user_id: 1, setting_key: 'theme', value: 'dark' },
252
+ * ['user_id', 'setting_key'] // Composite UNIQUE key
253
+ * );
254
+ */
26
255
  async upsert(table, data, conflictColumns, updateColumns) {
27
- throw new Error('MySQL adapter not implemented yet. Planned for Phase 3.');
256
+ const knex = this.getKnex();
257
+ // Determine which columns to update on conflict
258
+ const columnsToUpdate = updateColumns || Object.keys(data).filter(key => !conflictColumns.includes(key));
259
+ // Build update data for ON DUPLICATE KEY UPDATE clause
260
+ const updateData = columnsToUpdate.reduce((acc, col) => {
261
+ acc[col] = data[col];
262
+ return acc;
263
+ }, {});
264
+ // Use Knex's onConflict() which generates ON DUPLICATE KEY UPDATE for MySQL
265
+ const result = await knex(table)
266
+ .insert(data)
267
+ .onConflict(conflictColumns)
268
+ .merge(updateData);
269
+ return result.length;
28
270
  }
271
+ /**
272
+ * Extracts a value from a JSON column using JSON_EXTRACT().
273
+ *
274
+ * **MySQL JSON Path Syntax:**
275
+ * - `$` - Root element
276
+ * - `$.key` - Object member
277
+ * - `$[n]` - Array element
278
+ * - `$.key[n]` - Nested access
279
+ * - `$.*.key` - Wildcard member
280
+ *
281
+ * **Important Notes:**
282
+ * - Returns JSON value (may need JSON_UNQUOTE() for strings)
283
+ * - Path must start with `$` (auto-prepended if missing)
284
+ * - Returns NULL if path doesn't exist
285
+ *
286
+ * @param {string} column - JSON column name
287
+ * @param {string} path - JSON path (e.g., '$.address.city' or 'address.city')
288
+ * @returns {Knex.Raw} Raw SQL expression for JSON extraction
289
+ *
290
+ * @example
291
+ * // Extract nested value
292
+ * const query = knex('users').select(
293
+ * adapter.jsonExtract('metadata', '$.address.city').as('city')
294
+ * );
295
+ * // SELECT JSON_EXTRACT(`metadata`, '$.address.city') AS `city` FROM `users`
296
+ *
297
+ * @example
298
+ * // Array element access
299
+ * const query = knex('orders').select(
300
+ * adapter.jsonExtract('items', '$[0].name').as('first_item')
301
+ * );
302
+ */
29
303
  jsonExtract(column, path) {
30
- throw new Error('MySQL adapter not implemented yet. Planned for Phase 3.');
304
+ const knex = this.getKnex();
305
+ // Ensure path starts with $ for MySQL JSON path syntax
306
+ const jsonPath = path.startsWith('$') ? path : `$.${path}`;
307
+ return knex.raw('JSON_EXTRACT(??, ?)', [column, jsonPath]);
31
308
  }
309
+ /**
310
+ * Builds a JSON object from field values using JSON_OBJECT().
311
+ *
312
+ * **Behavior:**
313
+ * - Takes key-value pairs and returns JSON object
314
+ * - Automatically handles NULL values
315
+ * - Returns NULL if all values are NULL
316
+ *
317
+ * @param {Record<string, any>} fields - Object with key-value pairs
318
+ * @returns {Knex.Raw} Raw SQL expression for JSON object construction
319
+ *
320
+ * @example
321
+ * // Build JSON object from columns
322
+ * const query = knex('users').select(
323
+ * adapter.jsonBuildObject({
324
+ * name: knex.ref('name'),
325
+ * email: knex.ref('email'),
326
+ * age: knex.ref('age')
327
+ * }).as('user_json')
328
+ * );
329
+ * // SELECT JSON_OBJECT('name', `name`, 'email', `email`, 'age', `age`) AS `user_json`
330
+ *
331
+ * @example
332
+ * // With literal values
333
+ * const query = knex('orders').insert({
334
+ * metadata: adapter.jsonBuildObject({
335
+ * source: 'web',
336
+ * campaign: 'summer-sale',
337
+ * discount: 10
338
+ * })
339
+ * });
340
+ */
32
341
  jsonBuildObject(fields) {
33
- throw new Error('MySQL adapter not implemented yet. Planned for Phase 3.');
342
+ const knex = this.getKnex();
343
+ const keys = Object.keys(fields);
344
+ const values = Object.values(fields);
345
+ // Build arguments array: [key1, value1, key2, value2, ...]
346
+ const args = [];
347
+ keys.forEach((key, i) => {
348
+ args.push(key);
349
+ args.push(values[i]);
350
+ });
351
+ // Create placeholders for JSON_OBJECT(?, ?, ?, ?, ...)
352
+ const placeholders = args.map(() => '?').join(', ');
353
+ return knex.raw(`JSON_OBJECT(${placeholders})`, args);
34
354
  }
355
+ /**
356
+ * Returns current Unix timestamp using UNIX_TIMESTAMP().
357
+ *
358
+ * **Behavior:**
359
+ * - Returns seconds since Unix epoch (1970-01-01 00:00:00 UTC)
360
+ * - Always returns UTC timestamp regardless of session timezone
361
+ * - Integer value (no fractional seconds)
362
+ *
363
+ * @returns {Knex.Raw} Raw SQL expression for current timestamp
364
+ *
365
+ * @example
366
+ * // Insert with current timestamp
367
+ * await knex('events').insert({
368
+ * name: 'user_login',
369
+ * created_at: adapter.currentTimestamp()
370
+ * });
371
+ * // INSERT INTO `events` (`name`, `created_at`) VALUES ('user_login', UNIX_TIMESTAMP())
372
+ *
373
+ * @example
374
+ * // Update with current timestamp
375
+ * await knex('users')
376
+ * .where({ id: userId })
377
+ * .update({ last_seen: adapter.currentTimestamp() });
378
+ */
35
379
  currentTimestamp() {
36
- throw new Error('MySQL adapter not implemented yet. Planned for Phase 3.');
380
+ return this.getKnex().raw('UNIX_TIMESTAMP()');
37
381
  }
382
+ /**
383
+ * Converts Unix epoch timestamp to MySQL datetime using FROM_UNIXTIME().
384
+ *
385
+ * **Behavior:**
386
+ * - Converts integer epoch to DATETIME
387
+ * - Returns UTC datetime (session timezone affects display)
388
+ * - Handles NULL values
389
+ *
390
+ * @param {string} epochColumn - Column containing Unix epoch timestamp
391
+ * @returns {Knex.Raw} Raw SQL expression for epoch conversion
392
+ *
393
+ * @example
394
+ * // Convert epoch to datetime for display
395
+ * const query = knex('events').select(
396
+ * 'name',
397
+ * adapter.fromUnixEpoch('created_at').as('created_datetime')
398
+ * );
399
+ * // SELECT `name`, FROM_UNIXTIME(`created_at`) AS `created_datetime` FROM `events`
400
+ *
401
+ * @example
402
+ * // Filter by datetime range using epoch column
403
+ * const query = knex('logs')
404
+ * .where(adapter.fromUnixEpoch('timestamp'), '>=', '2024-01-01')
405
+ * .andWhere(adapter.fromUnixEpoch('timestamp'), '<', '2024-02-01');
406
+ */
38
407
  fromUnixEpoch(epochColumn) {
39
- throw new Error('MySQL adapter not implemented yet. Planned for Phase 3.');
408
+ return this.getKnex().raw('FROM_UNIXTIME(??)', [epochColumn]);
40
409
  }
410
+ /**
411
+ * Converts MySQL datetime to Unix epoch using UNIX_TIMESTAMP().
412
+ *
413
+ * **Behavior:**
414
+ * - Converts DATETIME/TIMESTAMP to integer epoch
415
+ * - Assumes input is UTC
416
+ * - Handles NULL values
417
+ *
418
+ * @param {string} timestampColumn - Column containing datetime value
419
+ * @returns {Knex.Raw} Raw SQL expression for datetime conversion
420
+ *
421
+ * @example
422
+ * // Convert datetime to epoch for storage
423
+ * const query = knex('events').insert({
424
+ * name: 'signup',
425
+ * timestamp: adapter.toUnixEpoch('NOW()')
426
+ * });
427
+ *
428
+ * @example
429
+ * // Calculate time difference in seconds
430
+ * const query = knex('sessions').select(
431
+ * knex.raw('?? - ??', [
432
+ * adapter.toUnixEpoch('logout_time'),
433
+ * adapter.toUnixEpoch('login_time')
434
+ * ]).as('duration_seconds')
435
+ * );
436
+ */
41
437
  toUnixEpoch(timestampColumn) {
42
- throw new Error('MySQL adapter not implemented yet. Planned for Phase 3.');
438
+ return this.getKnex().raw('UNIX_TIMESTAMP(??)', [timestampColumn]);
43
439
  }
440
+ /**
441
+ * Concatenates string values using CONCAT().
442
+ *
443
+ * **Behavior:**
444
+ * - Returns NULL if any argument is NULL
445
+ * - Automatically converts non-string types to strings
446
+ * - Empty strings are preserved
447
+ *
448
+ * **Alternative:** Use CONCAT_WS() for separator-based concatenation
449
+ *
450
+ * @param {...(string | Knex.Raw)[]} values - Values to concatenate
451
+ * @returns {Knex.Raw} Raw SQL expression for concatenation
452
+ *
453
+ * @example
454
+ * // Concatenate columns
455
+ * const query = knex('users').select(
456
+ * adapter.concat(
457
+ * knex.ref('first_name'),
458
+ * ' ',
459
+ * knex.ref('last_name')
460
+ * ).as('full_name')
461
+ * );
462
+ * // SELECT CONCAT(`first_name`, ' ', `last_name`) AS `full_name` FROM `users`
463
+ *
464
+ * @example
465
+ * // Build URL from parts
466
+ * const query = knex('products').select(
467
+ * adapter.concat(
468
+ * 'https://example.com/products/',
469
+ * knex.ref('slug')
470
+ * ).as('url')
471
+ * );
472
+ */
44
473
  concat(...values) {
45
- throw new Error('MySQL adapter not implemented yet. Planned for Phase 3.');
474
+ const knex = this.getKnex();
475
+ const placeholders = values.map(() => '?').join(', ');
476
+ return knex.raw(`CONCAT(${placeholders})`, values);
46
477
  }
47
- stringAgg(column, separator) {
48
- throw new Error('MySQL adapter not implemented yet. Planned for Phase 3.');
478
+ /**
479
+ * Aggregates strings with separator using GROUP_CONCAT().
480
+ *
481
+ * **Behavior:**
482
+ * - Concatenates values from multiple rows into single string
483
+ * - Default separator: comma (,)
484
+ * - NULL values are skipped
485
+ * - Result may be truncated by group_concat_max_len setting
486
+ *
487
+ * **Important Notes:**
488
+ * - Default max length: 1024 bytes (can be increased with SET group_concat_max_len)
489
+ * - Use with GROUP BY for grouped aggregation
490
+ * - For large results, increase group_concat_max_len session variable
491
+ *
492
+ * @param {string} column - Column to aggregate
493
+ * @param {string} [separator=','] - Separator between values
494
+ * @returns {Knex.Raw} Raw SQL expression for string aggregation
495
+ *
496
+ * @example
497
+ * // Get comma-separated list of tags
498
+ * const query = knex('posts')
499
+ * .select('posts.id', 'posts.title')
500
+ * .select(adapter.stringAgg('tags.name').as('tags'))
501
+ * .leftJoin('post_tags', 'posts.id', 'post_tags.post_id')
502
+ * .leftJoin('tags', 'post_tags.tag_id', 'tags.id')
503
+ * .groupBy('posts.id');
504
+ * // Result: { id: 1, title: 'Post', tags: 'javascript,typescript,node' }
505
+ *
506
+ * @example
507
+ * // Custom separator
508
+ * const query = knex('users')
509
+ * .select('department')
510
+ * .select(adapter.stringAgg('name', '; ').as('members'))
511
+ * .groupBy('department');
512
+ */
513
+ stringAgg(column, separator = ',') {
514
+ return this.getKnex().raw('GROUP_CONCAT(?? SEPARATOR ?)', [column, separator]);
49
515
  }
516
+ // ============================================================================
517
+ // Transaction Support
518
+ // ============================================================================
519
+ /**
520
+ * Executes a callback within a database transaction.
521
+ *
522
+ * Delegates to BaseAdapter's transaction() method, which uses Knex's
523
+ * transaction management with automatic commit/rollback.
524
+ *
525
+ * **MySQL Transaction Characteristics:**
526
+ * - Default isolation level: REPEATABLE READ
527
+ * - Supports nested transactions via savepoints
528
+ * - Automatic rollback on error
529
+ * - Deadlock detection and retry recommended for production
530
+ *
531
+ * @template T - Return type
532
+ * @param {Function} callback - Transaction callback
533
+ * @param {Object} [options] - Transaction options
534
+ * @param {string} [options.isolationLevel] - Isolation level
535
+ * @returns {Promise<T>} Transaction result
536
+ *
537
+ * @example
538
+ * // Bank transfer with transaction
539
+ * await adapter.transaction(async (trx) => {
540
+ * await trx('accounts')
541
+ * .where({ id: fromAccount })
542
+ * .decrement('balance', amount);
543
+ *
544
+ * await trx('accounts')
545
+ * .where({ id: toAccount })
546
+ * .increment('balance', amount);
547
+ * });
548
+ *
549
+ * @example
550
+ * // With isolation level
551
+ * await adapter.transaction(async (trx) => {
552
+ * // ... transaction operations ...
553
+ * }, { isolationLevel: 'serializable' });
554
+ */
50
555
  async transaction(callback, options) {
51
- throw new Error('MySQL adapter not implemented yet. Planned for Phase 3.');
556
+ // Delegate to BaseAdapter's implementation
557
+ return super.transaction(callback, options);
52
558
  }
559
+ /**
560
+ * Creates a savepoint within a transaction.
561
+ *
562
+ * **MySQL Savepoint Behavior:**
563
+ * - Allows partial rollback within transaction
564
+ * - Savepoint names are case-insensitive
565
+ * - Automatically released on transaction commit
566
+ * - Rolled back on transaction rollback
567
+ *
568
+ * @template T - Return type
569
+ * @param {Knex.Transaction} trx - Parent transaction
570
+ * @param {Function} callback - Savepoint callback
571
+ * @returns {Promise<T>} Savepoint result
572
+ *
573
+ * @throws {Error} If savepoint operation fails
574
+ *
575
+ * @example
576
+ * // Use savepoint for partial rollback
577
+ * await adapter.transaction(async (trx) => {
578
+ * await trx('users').insert({ name: 'Alice' });
579
+ *
580
+ * try {
581
+ * await adapter.savepoint(trx, async (sp) => {
582
+ * await sp('users').insert({ name: 'Bob' });
583
+ * throw new Error('Bob insert failed');
584
+ * });
585
+ * } catch (error) {
586
+ * // Bob insert rolled back, Alice insert preserved
587
+ * }
588
+ *
589
+ * await trx('users').insert({ name: 'Charlie' });
590
+ * });
591
+ */
53
592
  async savepoint(trx, callback) {
54
- throw new Error('MySQL adapter not implemented yet. Planned for Phase 3.');
593
+ return trx.savepoint(callback);
55
594
  }
595
+ // ============================================================================
596
+ // Schema Management
597
+ // ============================================================================
598
+ /**
599
+ * Checks if a table exists in the database.
600
+ *
601
+ * Queries INFORMATION_SCHEMA.TABLES which is the standard MySQL approach
602
+ * for table existence checking.
603
+ *
604
+ * **Important Notes:**
605
+ * - Case sensitivity depends on operating system (Linux: case-sensitive, Windows: case-insensitive)
606
+ * - Uses current database (from connection config)
607
+ * - Checks both base tables and views
608
+ *
609
+ * @param {string} tableName - Table name to check
610
+ * @returns {Promise<boolean>} True if table exists, false otherwise
611
+ *
612
+ * @example
613
+ * // Check before creating table
614
+ * if (!(await adapter.tableExists('users'))) {
615
+ * await knex.schema.createTable('users', (table) => {
616
+ * adapter.autoIncrementColumn(table);
617
+ * table.string('name');
618
+ * });
619
+ * }
620
+ *
621
+ * @example
622
+ * // Conditional migration
623
+ * if (await adapter.tableExists('old_table')) {
624
+ * await knex.raw('RENAME TABLE old_table TO new_table');
625
+ * }
626
+ */
56
627
  async tableExists(tableName) {
57
- throw new Error('MySQL adapter not implemented yet. Planned for Phase 3.');
628
+ const knex = this.getKnex();
629
+ const database = this.config.connection.database;
630
+ const result = await knex.raw(`SELECT TABLE_NAME
631
+ FROM INFORMATION_SCHEMA.TABLES
632
+ WHERE TABLE_SCHEMA = ?
633
+ AND TABLE_NAME = ?`, [database, tableName]);
634
+ return result[0].length > 0;
58
635
  }
59
- autoIncrementColumn(table, columnName) {
60
- throw new Error('MySQL adapter not implemented yet. Planned for Phase 3.');
636
+ /**
637
+ * Adds an auto-increment primary key column to a table.
638
+ *
639
+ * **MySQL AUTO_INCREMENT Behavior:**
640
+ * - Generates sequential integer IDs starting from 1
641
+ * - Must be indexed (PRIMARY KEY or UNIQUE)
642
+ * - Only one AUTO_INCREMENT column per table
643
+ * - Uses UNSIGNED INT for larger range (0 to 4,294,967,295)
644
+ *
645
+ * **Column Characteristics:**
646
+ * - Type: INTEGER UNSIGNED
647
+ * - Primary Key: Yes
648
+ * - Auto Increment: Yes
649
+ * - Not Nullable: Yes
650
+ *
651
+ * @param {Knex.CreateTableBuilder} table - Knex table builder
652
+ * @param {string} [columnName='id'] - Column name (default: 'id')
653
+ *
654
+ * @example
655
+ * // Create table with auto-increment ID
656
+ * await knex.schema.createTable('users', (table) => {
657
+ * adapter.autoIncrementColumn(table);
658
+ * table.string('name').notNullable();
659
+ * table.string('email').unique();
660
+ * table.timestamps(true, true);
661
+ * });
662
+ * // CREATE TABLE `users` (
663
+ * // `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
664
+ * // `name` VARCHAR(255) NOT NULL,
665
+ * // `email` VARCHAR(255) UNIQUE,
666
+ * // `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
667
+ * // `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
668
+ * // )
669
+ *
670
+ * @example
671
+ * // Custom column name
672
+ * await knex.schema.createTable('orders', (table) => {
673
+ * adapter.autoIncrementColumn(table, 'order_id');
674
+ * table.integer('user_id').unsigned().notNullable();
675
+ * });
676
+ */
677
+ autoIncrementColumn(table, columnName = 'id') {
678
+ // Use increments() which creates UNSIGNED INT AUTO_INCREMENT PRIMARY KEY
679
+ table.increments(columnName).unsigned();
61
680
  }
62
681
  }
63
682
  //# sourceMappingURL=mysql-adapter.js.map