mongo.do 0.1.0 → 0.1.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 (706) hide show
  1. package/dist/cli/index.d.ts +1 -15
  2. package/dist/cli/index.js +4083 -196
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/index.d.ts +2740 -20
  5. package/dist/index.js +9375 -27
  6. package/dist/index.js.map +1 -1
  7. package/dist/worker-entrypoint-BEW23Gmp.d.ts +1331 -0
  8. package/dist/worker.d.ts +6 -5
  9. package/dist/worker.js +5477 -18
  10. package/dist/worker.js.map +1 -1
  11. package/package.json +3 -2
  12. package/dist/agentfs/adapters/anthropic.d.ts +0 -176
  13. package/dist/agentfs/adapters/anthropic.d.ts.map +0 -1
  14. package/dist/agentfs/adapters/anthropic.js +0 -629
  15. package/dist/agentfs/adapters/anthropic.js.map +0 -1
  16. package/dist/agentfs/adapters/index.d.ts +0 -21
  17. package/dist/agentfs/adapters/index.d.ts.map +0 -1
  18. package/dist/agentfs/adapters/index.js +0 -23
  19. package/dist/agentfs/adapters/index.js.map +0 -1
  20. package/dist/agentfs/adapters/vercel.d.ts +0 -260
  21. package/dist/agentfs/adapters/vercel.d.ts.map +0 -1
  22. package/dist/agentfs/adapters/vercel.js +0 -288
  23. package/dist/agentfs/adapters/vercel.js.map +0 -1
  24. package/dist/agentfs/glob.d.ts +0 -116
  25. package/dist/agentfs/glob.d.ts.map +0 -1
  26. package/dist/agentfs/glob.js +0 -270
  27. package/dist/agentfs/glob.js.map +0 -1
  28. package/dist/agentfs/grep.d.ts +0 -83
  29. package/dist/agentfs/grep.d.ts.map +0 -1
  30. package/dist/agentfs/grep.js +0 -193
  31. package/dist/agentfs/grep.js.map +0 -1
  32. package/dist/agentfs/index.d.ts +0 -22
  33. package/dist/agentfs/index.d.ts.map +0 -1
  34. package/dist/agentfs/index.js +0 -18
  35. package/dist/agentfs/index.js.map +0 -1
  36. package/dist/agentfs/kv-store.d.ts +0 -128
  37. package/dist/agentfs/kv-store.d.ts.map +0 -1
  38. package/dist/agentfs/kv-store.js +0 -227
  39. package/dist/agentfs/kv-store.js.map +0 -1
  40. package/dist/agentfs/mondo-agent.d.ts +0 -255
  41. package/dist/agentfs/mondo-agent.d.ts.map +0 -1
  42. package/dist/agentfs/mondo-agent.js +0 -879
  43. package/dist/agentfs/mondo-agent.js.map +0 -1
  44. package/dist/agentfs/toolcalls.d.ts +0 -130
  45. package/dist/agentfs/toolcalls.d.ts.map +0 -1
  46. package/dist/agentfs/toolcalls.js +0 -178
  47. package/dist/agentfs/toolcalls.js.map +0 -1
  48. package/dist/agentfs/types.d.ts +0 -171
  49. package/dist/agentfs/types.d.ts.map +0 -1
  50. package/dist/agentfs/types.js +0 -7
  51. package/dist/agentfs/types.js.map +0 -1
  52. package/dist/agentfs/vfs.d.ts +0 -249
  53. package/dist/agentfs/vfs.d.ts.map +0 -1
  54. package/dist/agentfs/vfs.js +0 -469
  55. package/dist/agentfs/vfs.js.map +0 -1
  56. package/dist/cli/index.d.ts.map +0 -1
  57. package/dist/cli/mcp.d.ts +0 -119
  58. package/dist/cli/mcp.d.ts.map +0 -1
  59. package/dist/cli/mcp.js +0 -418
  60. package/dist/cli/mcp.js.map +0 -1
  61. package/dist/cli/server.d.ts +0 -179
  62. package/dist/cli/server.d.ts.map +0 -1
  63. package/dist/cli/server.js +0 -441
  64. package/dist/cli/server.js.map +0 -1
  65. package/dist/client/Collection.d.ts +0 -199
  66. package/dist/client/Collection.d.ts.map +0 -1
  67. package/dist/client/Collection.js +0 -256
  68. package/dist/client/Collection.js.map +0 -1
  69. package/dist/client/Database.d.ts +0 -68
  70. package/dist/client/Database.d.ts.map +0 -1
  71. package/dist/client/Database.js +0 -105
  72. package/dist/client/Database.js.map +0 -1
  73. package/dist/client/MongoClient.d.ts +0 -165
  74. package/dist/client/MongoClient.d.ts.map +0 -1
  75. package/dist/client/MongoClient.js +0 -307
  76. package/dist/client/MongoClient.js.map +0 -1
  77. package/dist/client/aggregation-cursor.d.ts +0 -210
  78. package/dist/client/aggregation-cursor.d.ts.map +0 -1
  79. package/dist/client/aggregation-cursor.js +0 -509
  80. package/dist/client/aggregation-cursor.js.map +0 -1
  81. package/dist/client/bulk-write.d.ts +0 -216
  82. package/dist/client/bulk-write.d.ts.map +0 -1
  83. package/dist/client/bulk-write.js +0 -63
  84. package/dist/client/bulk-write.js.map +0 -1
  85. package/dist/client/change-stream.d.ts +0 -245
  86. package/dist/client/change-stream.d.ts.map +0 -1
  87. package/dist/client/change-stream.js +0 -429
  88. package/dist/client/change-stream.js.map +0 -1
  89. package/dist/client/cursor.d.ts +0 -85
  90. package/dist/client/cursor.d.ts.map +0 -1
  91. package/dist/client/cursor.js +0 -156
  92. package/dist/client/cursor.js.map +0 -1
  93. package/dist/client/http-cursor.d.ts +0 -233
  94. package/dist/client/http-cursor.d.ts.map +0 -1
  95. package/dist/client/http-cursor.js +0 -496
  96. package/dist/client/http-cursor.js.map +0 -1
  97. package/dist/client/index.d.ts +0 -18
  98. package/dist/client/index.d.ts.map +0 -1
  99. package/dist/client/index.js +0 -24
  100. package/dist/client/index.js.map +0 -1
  101. package/dist/client/mongo-client.d.ts +0 -60
  102. package/dist/client/mongo-client.d.ts.map +0 -1
  103. package/dist/client/mongo-client.js +0 -190
  104. package/dist/client/mongo-client.js.map +0 -1
  105. package/dist/client/mongo-collection.d.ts +0 -359
  106. package/dist/client/mongo-collection.d.ts.map +0 -1
  107. package/dist/client/mongo-collection.js +0 -1641
  108. package/dist/client/mongo-collection.js.map +0 -1
  109. package/dist/client/mongo-cursor.d.ts +0 -257
  110. package/dist/client/mongo-cursor.d.ts.map +0 -1
  111. package/dist/client/mongo-cursor.js +0 -621
  112. package/dist/client/mongo-cursor.js.map +0 -1
  113. package/dist/client/mongo-database.d.ts +0 -88
  114. package/dist/client/mongo-database.d.ts.map +0 -1
  115. package/dist/client/mongo-database.js +0 -139
  116. package/dist/client/mongo-database.js.map +0 -1
  117. package/dist/client/session.d.ts +0 -210
  118. package/dist/client/session.d.ts.map +0 -1
  119. package/dist/client/session.js +0 -326
  120. package/dist/client/session.js.map +0 -1
  121. package/dist/durable-object/index-manager.d.ts +0 -173
  122. package/dist/durable-object/index-manager.d.ts.map +0 -1
  123. package/dist/durable-object/index-manager.js +0 -764
  124. package/dist/durable-object/index-manager.js.map +0 -1
  125. package/dist/durable-object/index.d.ts +0 -12
  126. package/dist/durable-object/index.d.ts.map +0 -1
  127. package/dist/durable-object/index.js +0 -8
  128. package/dist/durable-object/index.js.map +0 -1
  129. package/dist/durable-object/mcp-handler.d.ts +0 -52
  130. package/dist/durable-object/mcp-handler.d.ts.map +0 -1
  131. package/dist/durable-object/mcp-handler.js +0 -186
  132. package/dist/durable-object/mcp-handler.js.map +0 -1
  133. package/dist/durable-object/migrations.d.ts +0 -40
  134. package/dist/durable-object/migrations.d.ts.map +0 -1
  135. package/dist/durable-object/migrations.js +0 -121
  136. package/dist/durable-object/migrations.js.map +0 -1
  137. package/dist/durable-object/mondo-database.d.ts +0 -148
  138. package/dist/durable-object/mondo-database.d.ts.map +0 -1
  139. package/dist/durable-object/mondo-database.js +0 -621
  140. package/dist/durable-object/mondo-database.js.map +0 -1
  141. package/dist/durable-object/schema.d.ts +0 -192
  142. package/dist/durable-object/schema.d.ts.map +0 -1
  143. package/dist/durable-object/schema.js +0 -186
  144. package/dist/durable-object/schema.js.map +0 -1
  145. package/dist/embedding/document-serializer.d.ts +0 -118
  146. package/dist/embedding/document-serializer.d.ts.map +0 -1
  147. package/dist/embedding/document-serializer.js +0 -339
  148. package/dist/embedding/document-serializer.js.map +0 -1
  149. package/dist/embedding/embedding-manager.d.ts +0 -136
  150. package/dist/embedding/embedding-manager.d.ts.map +0 -1
  151. package/dist/embedding/embedding-manager.js +0 -176
  152. package/dist/embedding/embedding-manager.js.map +0 -1
  153. package/dist/embedding/index.d.ts +0 -9
  154. package/dist/embedding/index.d.ts.map +0 -1
  155. package/dist/embedding/index.js +0 -9
  156. package/dist/embedding/index.js.map +0 -1
  157. package/dist/executor/aggregation-executor.d.ts +0 -93
  158. package/dist/executor/aggregation-executor.d.ts.map +0 -1
  159. package/dist/executor/aggregation-executor.js +0 -275
  160. package/dist/executor/aggregation-executor.js.map +0 -1
  161. package/dist/executor/function-executor.d.ts +0 -39
  162. package/dist/executor/function-executor.d.ts.map +0 -1
  163. package/dist/executor/function-executor.js +0 -168
  164. package/dist/executor/function-executor.js.map +0 -1
  165. package/dist/executor/index.d.ts +0 -4
  166. package/dist/executor/index.d.ts.map +0 -1
  167. package/dist/executor/index.js +0 -4
  168. package/dist/executor/index.js.map +0 -1
  169. package/dist/executor/vector-search-executor.d.ts +0 -71
  170. package/dist/executor/vector-search-executor.d.ts.map +0 -1
  171. package/dist/executor/vector-search-executor.js +0 -113
  172. package/dist/executor/vector-search-executor.js.map +0 -1
  173. package/dist/index.d.ts.map +0 -1
  174. package/dist/mcp/adapters/anthropic-adapter.d.ts +0 -256
  175. package/dist/mcp/adapters/anthropic-adapter.d.ts.map +0 -1
  176. package/dist/mcp/adapters/anthropic-adapter.js +0 -409
  177. package/dist/mcp/adapters/anthropic-adapter.js.map +0 -1
  178. package/dist/mcp/adapters/base-adapter.d.ts +0 -164
  179. package/dist/mcp/adapters/base-adapter.d.ts.map +0 -1
  180. package/dist/mcp/adapters/base-adapter.js +0 -277
  181. package/dist/mcp/adapters/base-adapter.js.map +0 -1
  182. package/dist/mcp/adapters/errors.d.ts +0 -173
  183. package/dist/mcp/adapters/errors.d.ts.map +0 -1
  184. package/dist/mcp/adapters/errors.js +0 -305
  185. package/dist/mcp/adapters/errors.js.map +0 -1
  186. package/dist/mcp/adapters/index.d.ts +0 -65
  187. package/dist/mcp/adapters/index.d.ts.map +0 -1
  188. package/dist/mcp/adapters/index.js +0 -92
  189. package/dist/mcp/adapters/index.js.map +0 -1
  190. package/dist/mcp/adapters/streaming.d.ts +0 -200
  191. package/dist/mcp/adapters/streaming.d.ts.map +0 -1
  192. package/dist/mcp/adapters/streaming.js +0 -381
  193. package/dist/mcp/adapters/streaming.js.map +0 -1
  194. package/dist/mcp/adapters/vercel-adapter.d.ts +0 -321
  195. package/dist/mcp/adapters/vercel-adapter.d.ts.map +0 -1
  196. package/dist/mcp/adapters/vercel-adapter.js +0 -487
  197. package/dist/mcp/adapters/vercel-adapter.js.map +0 -1
  198. package/dist/mcp/agent.d.ts +0 -192
  199. package/dist/mcp/agent.d.ts.map +0 -1
  200. package/dist/mcp/agent.js +0 -338
  201. package/dist/mcp/agent.js.map +0 -1
  202. package/dist/mcp/cli.d.ts +0 -71
  203. package/dist/mcp/cli.d.ts.map +0 -1
  204. package/dist/mcp/cli.js +0 -218
  205. package/dist/mcp/cli.js.map +0 -1
  206. package/dist/mcp/index.d.ts +0 -15
  207. package/dist/mcp/index.d.ts.map +0 -1
  208. package/dist/mcp/index.js +0 -20
  209. package/dist/mcp/index.js.map +0 -1
  210. package/dist/mcp/sandbox/database-proxy.d.ts +0 -118
  211. package/dist/mcp/sandbox/database-proxy.d.ts.map +0 -1
  212. package/dist/mcp/sandbox/database-proxy.js +0 -154
  213. package/dist/mcp/sandbox/database-proxy.js.map +0 -1
  214. package/dist/mcp/sandbox/index.d.ts +0 -8
  215. package/dist/mcp/sandbox/index.d.ts.map +0 -1
  216. package/dist/mcp/sandbox/index.js +0 -7
  217. package/dist/mcp/sandbox/index.js.map +0 -1
  218. package/dist/mcp/sandbox/miniflare-evaluator.d.ts +0 -72
  219. package/dist/mcp/sandbox/miniflare-evaluator.d.ts.map +0 -1
  220. package/dist/mcp/sandbox/miniflare-evaluator.js +0 -379
  221. package/dist/mcp/sandbox/miniflare-evaluator.js.map +0 -1
  222. package/dist/mcp/sandbox/template.d.ts +0 -48
  223. package/dist/mcp/sandbox/template.d.ts.map +0 -1
  224. package/dist/mcp/sandbox/template.js +0 -147
  225. package/dist/mcp/sandbox/template.js.map +0 -1
  226. package/dist/mcp/sandbox/worker-evaluator.d.ts +0 -160
  227. package/dist/mcp/sandbox/worker-evaluator.d.ts.map +0 -1
  228. package/dist/mcp/sandbox/worker-evaluator.js +0 -217
  229. package/dist/mcp/sandbox/worker-evaluator.js.map +0 -1
  230. package/dist/mcp/server.d.ts +0 -75
  231. package/dist/mcp/server.d.ts.map +0 -1
  232. package/dist/mcp/server.js +0 -278
  233. package/dist/mcp/server.js.map +0 -1
  234. package/dist/mcp/tool-call-auditor.d.ts +0 -188
  235. package/dist/mcp/tool-call-auditor.d.ts.map +0 -1
  236. package/dist/mcp/tool-call-auditor.js +0 -198
  237. package/dist/mcp/tool-call-auditor.js.map +0 -1
  238. package/dist/mcp/tools/do.d.ts +0 -51
  239. package/dist/mcp/tools/do.d.ts.map +0 -1
  240. package/dist/mcp/tools/do.js +0 -113
  241. package/dist/mcp/tools/do.js.map +0 -1
  242. package/dist/mcp/tools/fetch.d.ts +0 -43
  243. package/dist/mcp/tools/fetch.d.ts.map +0 -1
  244. package/dist/mcp/tools/fetch.js +0 -127
  245. package/dist/mcp/tools/fetch.js.map +0 -1
  246. package/dist/mcp/tools/index.d.ts +0 -9
  247. package/dist/mcp/tools/index.d.ts.map +0 -1
  248. package/dist/mcp/tools/index.js +0 -9
  249. package/dist/mcp/tools/index.js.map +0 -1
  250. package/dist/mcp/tools/search.d.ts +0 -60
  251. package/dist/mcp/tools/search.d.ts.map +0 -1
  252. package/dist/mcp/tools/search.js +0 -278
  253. package/dist/mcp/tools/search.js.map +0 -1
  254. package/dist/mcp/transport/http.d.ts +0 -144
  255. package/dist/mcp/transport/http.d.ts.map +0 -1
  256. package/dist/mcp/transport/http.js +0 -545
  257. package/dist/mcp/transport/http.js.map +0 -1
  258. package/dist/mcp/transport/index.d.ts +0 -10
  259. package/dist/mcp/transport/index.d.ts.map +0 -1
  260. package/dist/mcp/transport/index.js +0 -12
  261. package/dist/mcp/transport/index.js.map +0 -1
  262. package/dist/mcp/transport/stdio.d.ts +0 -132
  263. package/dist/mcp/transport/stdio.d.ts.map +0 -1
  264. package/dist/mcp/transport/stdio.js +0 -466
  265. package/dist/mcp/transport/stdio.js.map +0 -1
  266. package/dist/mcp/types.d.ts +0 -476
  267. package/dist/mcp/types.d.ts.map +0 -1
  268. package/dist/mcp/types.js +0 -178
  269. package/dist/mcp/types.js.map +0 -1
  270. package/dist/olap/cdc/cdc-buffer.d.ts +0 -92
  271. package/dist/olap/cdc/cdc-buffer.d.ts.map +0 -1
  272. package/dist/olap/cdc/cdc-buffer.js +0 -146
  273. package/dist/olap/cdc/cdc-buffer.js.map +0 -1
  274. package/dist/olap/cdc/cdc-emitter.d.ts +0 -118
  275. package/dist/olap/cdc/cdc-emitter.d.ts.map +0 -1
  276. package/dist/olap/cdc/cdc-emitter.js +0 -217
  277. package/dist/olap/cdc/cdc-emitter.js.map +0 -1
  278. package/dist/olap/cdc/cdc-schema.d.ts +0 -119
  279. package/dist/olap/cdc/cdc-schema.d.ts.map +0 -1
  280. package/dist/olap/cdc/cdc-schema.js +0 -253
  281. package/dist/olap/cdc/cdc-schema.js.map +0 -1
  282. package/dist/olap/cdc/index.d.ts +0 -10
  283. package/dist/olap/cdc/index.d.ts.map +0 -1
  284. package/dist/olap/cdc/index.js +0 -10
  285. package/dist/olap/cdc/index.js.map +0 -1
  286. package/dist/olap/clickhouse/iceberg.d.ts +0 -164
  287. package/dist/olap/clickhouse/iceberg.d.ts.map +0 -1
  288. package/dist/olap/clickhouse/iceberg.js +0 -138
  289. package/dist/olap/clickhouse/iceberg.js.map +0 -1
  290. package/dist/olap/clickhouse/index.d.ts +0 -14
  291. package/dist/olap/clickhouse/index.d.ts.map +0 -1
  292. package/dist/olap/clickhouse/index.js +0 -14
  293. package/dist/olap/clickhouse/index.js.map +0 -1
  294. package/dist/olap/clickhouse/mapper.d.ts +0 -170
  295. package/dist/olap/clickhouse/mapper.d.ts.map +0 -1
  296. package/dist/olap/clickhouse/mapper.js +0 -654
  297. package/dist/olap/clickhouse/mapper.js.map +0 -1
  298. package/dist/olap/clickhouse/olap-backend.d.ts +0 -181
  299. package/dist/olap/clickhouse/olap-backend.d.ts.map +0 -1
  300. package/dist/olap/clickhouse/olap-backend.js +0 -1083
  301. package/dist/olap/clickhouse/olap-backend.js.map +0 -1
  302. package/dist/olap/clickhouse/query-executor.d.ts +0 -163
  303. package/dist/olap/clickhouse/query-executor.d.ts.map +0 -1
  304. package/dist/olap/clickhouse/query-executor.js +0 -560
  305. package/dist/olap/clickhouse/query-executor.js.map +0 -1
  306. package/dist/olap/clickhouse/query.d.ts +0 -134
  307. package/dist/olap/clickhouse/query.d.ts.map +0 -1
  308. package/dist/olap/clickhouse/query.js +0 -512
  309. package/dist/olap/clickhouse/query.js.map +0 -1
  310. package/dist/olap/stage/index.d.ts +0 -6
  311. package/dist/olap/stage/index.d.ts.map +0 -1
  312. package/dist/olap/stage/index.js +0 -6
  313. package/dist/olap/stage/index.js.map +0 -1
  314. package/dist/olap/stage/parser.d.ts +0 -68
  315. package/dist/olap/stage/parser.d.ts.map +0 -1
  316. package/dist/olap/stage/parser.js +0 -293
  317. package/dist/olap/stage/parser.js.map +0 -1
  318. package/dist/olap/stage/router.d.ts +0 -94
  319. package/dist/olap/stage/router.d.ts.map +0 -1
  320. package/dist/olap/stage/router.js +0 -390
  321. package/dist/olap/stage/router.js.map +0 -1
  322. package/dist/rpc/endpoint.d.ts +0 -52
  323. package/dist/rpc/endpoint.d.ts.map +0 -1
  324. package/dist/rpc/endpoint.js +0 -734
  325. package/dist/rpc/endpoint.js.map +0 -1
  326. package/dist/rpc/index.d.ts +0 -34
  327. package/dist/rpc/index.d.ts.map +0 -1
  328. package/dist/rpc/index.js +0 -45
  329. package/dist/rpc/index.js.map +0 -1
  330. package/dist/rpc/rpc-client.d.ts +0 -275
  331. package/dist/rpc/rpc-client.d.ts.map +0 -1
  332. package/dist/rpc/rpc-client.js +0 -735
  333. package/dist/rpc/rpc-client.js.map +0 -1
  334. package/dist/rpc/rpc-target.d.ts +0 -220
  335. package/dist/rpc/rpc-target.d.ts.map +0 -1
  336. package/dist/rpc/rpc-target.js +0 -500
  337. package/dist/rpc/rpc-target.js.map +0 -1
  338. package/dist/rpc/worker-entrypoint.d.ts +0 -159
  339. package/dist/rpc/worker-entrypoint.d.ts.map +0 -1
  340. package/dist/rpc/worker-entrypoint.js +0 -212
  341. package/dist/rpc/worker-entrypoint.js.map +0 -1
  342. package/dist/server.d.ts +0 -18
  343. package/dist/server.d.ts.map +0 -1
  344. package/dist/server.js +0 -129
  345. package/dist/server.js.map +0 -1
  346. package/dist/studio/components/browser/CollectionItem.d.ts +0 -26
  347. package/dist/studio/components/browser/CollectionItem.d.ts.map +0 -1
  348. package/dist/studio/components/browser/CollectionItem.js +0 -143
  349. package/dist/studio/components/browser/CollectionItem.js.map +0 -1
  350. package/dist/studio/components/browser/CollectionTree.d.ts +0 -45
  351. package/dist/studio/components/browser/CollectionTree.d.ts.map +0 -1
  352. package/dist/studio/components/browser/CollectionTree.js +0 -207
  353. package/dist/studio/components/browser/CollectionTree.js.map +0 -1
  354. package/dist/studio/components/browser/ConnectedDatabaseBrowser.d.ts +0 -51
  355. package/dist/studio/components/browser/ConnectedDatabaseBrowser.d.ts.map +0 -1
  356. package/dist/studio/components/browser/ConnectedDatabaseBrowser.js +0 -185
  357. package/dist/studio/components/browser/ConnectedDatabaseBrowser.js.map +0 -1
  358. package/dist/studio/components/browser/DatabaseBrowser.d.ts +0 -46
  359. package/dist/studio/components/browser/DatabaseBrowser.d.ts.map +0 -1
  360. package/dist/studio/components/browser/DatabaseBrowser.js +0 -304
  361. package/dist/studio/components/browser/DatabaseBrowser.js.map +0 -1
  362. package/dist/studio/components/browser/__tests__/CollectionItem.test.d.ts +0 -5
  363. package/dist/studio/components/browser/__tests__/CollectionItem.test.d.ts.map +0 -1
  364. package/dist/studio/components/browser/__tests__/CollectionItem.test.js +0 -169
  365. package/dist/studio/components/browser/__tests__/CollectionItem.test.js.map +0 -1
  366. package/dist/studio/components/browser/__tests__/CollectionTree.test.d.ts +0 -5
  367. package/dist/studio/components/browser/__tests__/CollectionTree.test.d.ts.map +0 -1
  368. package/dist/studio/components/browser/__tests__/CollectionTree.test.js +0 -203
  369. package/dist/studio/components/browser/__tests__/CollectionTree.test.js.map +0 -1
  370. package/dist/studio/components/browser/__tests__/DatabaseBrowser.e2e.test.d.ts +0 -8
  371. package/dist/studio/components/browser/__tests__/DatabaseBrowser.e2e.test.d.ts.map +0 -1
  372. package/dist/studio/components/browser/__tests__/DatabaseBrowser.e2e.test.js +0 -522
  373. package/dist/studio/components/browser/__tests__/DatabaseBrowser.e2e.test.js.map +0 -1
  374. package/dist/studio/components/browser/__tests__/DatabaseBrowser.test.d.ts +0 -5
  375. package/dist/studio/components/browser/__tests__/DatabaseBrowser.test.d.ts.map +0 -1
  376. package/dist/studio/components/browser/__tests__/DatabaseBrowser.test.js +0 -518
  377. package/dist/studio/components/browser/__tests__/DatabaseBrowser.test.js.map +0 -1
  378. package/dist/studio/components/browser/__tests__/setup.d.ts +0 -5
  379. package/dist/studio/components/browser/__tests__/setup.d.ts.map +0 -1
  380. package/dist/studio/components/browser/__tests__/setup.js +0 -22
  381. package/dist/studio/components/browser/__tests__/setup.js.map +0 -1
  382. package/dist/studio/components/browser/index.d.ts +0 -15
  383. package/dist/studio/components/browser/index.d.ts.map +0 -1
  384. package/dist/studio/components/browser/index.js +0 -10
  385. package/dist/studio/components/browser/index.js.map +0 -1
  386. package/dist/studio/components/browser/types.d.ts +0 -33
  387. package/dist/studio/components/browser/types.d.ts.map +0 -1
  388. package/dist/studio/components/browser/types.js +0 -5
  389. package/dist/studio/components/browser/types.js.map +0 -1
  390. package/dist/studio/components/connection/ConnectionForm.d.ts +0 -59
  391. package/dist/studio/components/connection/ConnectionForm.d.ts.map +0 -1
  392. package/dist/studio/components/connection/ConnectionForm.js +0 -274
  393. package/dist/studio/components/connection/ConnectionForm.js.map +0 -1
  394. package/dist/studio/components/connection/ConnectionList.d.ts +0 -59
  395. package/dist/studio/components/connection/ConnectionList.d.ts.map +0 -1
  396. package/dist/studio/components/connection/ConnectionList.js +0 -286
  397. package/dist/studio/components/connection/ConnectionList.js.map +0 -1
  398. package/dist/studio/components/connection/ConnectionPanel.d.ts +0 -132
  399. package/dist/studio/components/connection/ConnectionPanel.d.ts.map +0 -1
  400. package/dist/studio/components/connection/ConnectionPanel.js +0 -293
  401. package/dist/studio/components/connection/ConnectionPanel.js.map +0 -1
  402. package/dist/studio/components/connection/__tests__/ConnectionPanel.test.d.ts +0 -8
  403. package/dist/studio/components/connection/__tests__/ConnectionPanel.test.d.ts.map +0 -1
  404. package/dist/studio/components/connection/__tests__/ConnectionPanel.test.js +0 -632
  405. package/dist/studio/components/connection/__tests__/ConnectionPanel.test.js.map +0 -1
  406. package/dist/studio/components/connection/__tests__/setup.d.ts +0 -5
  407. package/dist/studio/components/connection/__tests__/setup.d.ts.map +0 -1
  408. package/dist/studio/components/connection/__tests__/setup.js +0 -11
  409. package/dist/studio/components/connection/__tests__/setup.js.map +0 -1
  410. package/dist/studio/components/connection/index.d.ts +0 -10
  411. package/dist/studio/components/connection/index.d.ts.map +0 -1
  412. package/dist/studio/components/connection/index.js +0 -7
  413. package/dist/studio/components/connection/index.js.map +0 -1
  414. package/dist/studio/components/crud/DeleteDocumentDialog.d.ts +0 -91
  415. package/dist/studio/components/crud/DeleteDocumentDialog.d.ts.map +0 -1
  416. package/dist/studio/components/crud/DeleteDocumentDialog.js +0 -273
  417. package/dist/studio/components/crud/DeleteDocumentDialog.js.map +0 -1
  418. package/dist/studio/components/crud/DocumentEditor.d.ts +0 -32
  419. package/dist/studio/components/crud/DocumentEditor.d.ts.map +0 -1
  420. package/dist/studio/components/crud/DocumentEditor.js +0 -546
  421. package/dist/studio/components/crud/DocumentEditor.js.map +0 -1
  422. package/dist/studio/components/crud/InsertDocumentDialog.d.ts +0 -78
  423. package/dist/studio/components/crud/InsertDocumentDialog.d.ts.map +0 -1
  424. package/dist/studio/components/crud/InsertDocumentDialog.js +0 -323
  425. package/dist/studio/components/crud/InsertDocumentDialog.js.map +0 -1
  426. package/dist/studio/components/crud/__tests__/DeleteDocumentDialog.test.d.ts +0 -5
  427. package/dist/studio/components/crud/__tests__/DeleteDocumentDialog.test.d.ts.map +0 -1
  428. package/dist/studio/components/crud/__tests__/DeleteDocumentDialog.test.js +0 -298
  429. package/dist/studio/components/crud/__tests__/DeleteDocumentDialog.test.js.map +0 -1
  430. package/dist/studio/components/crud/__tests__/DocumentEditor.test.d.ts +0 -8
  431. package/dist/studio/components/crud/__tests__/DocumentEditor.test.d.ts.map +0 -1
  432. package/dist/studio/components/crud/__tests__/DocumentEditor.test.js +0 -368
  433. package/dist/studio/components/crud/__tests__/DocumentEditor.test.js.map +0 -1
  434. package/dist/studio/components/crud/__tests__/InsertDocumentDialog.test.d.ts +0 -2
  435. package/dist/studio/components/crud/__tests__/InsertDocumentDialog.test.d.ts.map +0 -1
  436. package/dist/studio/components/crud/__tests__/InsertDocumentDialog.test.js +0 -352
  437. package/dist/studio/components/crud/__tests__/InsertDocumentDialog.test.js.map +0 -1
  438. package/dist/studio/components/crud/__tests__/setup.d.ts +0 -5
  439. package/dist/studio/components/crud/__tests__/setup.d.ts.map +0 -1
  440. package/dist/studio/components/crud/__tests__/setup.js +0 -22
  441. package/dist/studio/components/crud/__tests__/setup.js.map +0 -1
  442. package/dist/studio/components/crud/index.d.ts +0 -12
  443. package/dist/studio/components/crud/index.d.ts.map +0 -1
  444. package/dist/studio/components/crud/index.js +0 -11
  445. package/dist/studio/components/crud/index.js.map +0 -1
  446. package/dist/studio/hooks/useConnection.d.ts +0 -127
  447. package/dist/studio/hooks/useConnection.d.ts.map +0 -1
  448. package/dist/studio/hooks/useConnection.js +0 -414
  449. package/dist/studio/hooks/useConnection.js.map +0 -1
  450. package/dist/studio/hooks/useDatabaseBrowser.d.ts +0 -107
  451. package/dist/studio/hooks/useDatabaseBrowser.d.ts.map +0 -1
  452. package/dist/studio/hooks/useDatabaseBrowser.js +0 -294
  453. package/dist/studio/hooks/useDatabaseBrowser.js.map +0 -1
  454. package/dist/studio/index.d.ts +0 -16
  455. package/dist/studio/index.d.ts.map +0 -1
  456. package/dist/studio/index.js +0 -14
  457. package/dist/studio/index.js.map +0 -1
  458. package/dist/studio/types/connection.d.ts +0 -266
  459. package/dist/studio/types/connection.d.ts.map +0 -1
  460. package/dist/studio/types/connection.js +0 -159
  461. package/dist/studio/types/connection.js.map +0 -1
  462. package/dist/studio/vitest.config.d.ts +0 -3
  463. package/dist/studio/vitest.config.d.ts.map +0 -1
  464. package/dist/studio/vitest.config.js +0 -33
  465. package/dist/studio/vitest.config.js.map +0 -1
  466. package/dist/translator/aggregation-translator.d.ts +0 -51
  467. package/dist/translator/aggregation-translator.d.ts.map +0 -1
  468. package/dist/translator/aggregation-translator.js +0 -324
  469. package/dist/translator/aggregation-translator.js.map +0 -1
  470. package/dist/translator/dialect.d.ts +0 -131
  471. package/dist/translator/dialect.d.ts.map +0 -1
  472. package/dist/translator/dialect.js +0 -276
  473. package/dist/translator/dialect.js.map +0 -1
  474. package/dist/translator/geo-translator.d.ts +0 -91
  475. package/dist/translator/geo-translator.d.ts.map +0 -1
  476. package/dist/translator/geo-translator.js +0 -587
  477. package/dist/translator/geo-translator.js.map +0 -1
  478. package/dist/translator/hybrid-translator.d.ts +0 -70
  479. package/dist/translator/hybrid-translator.d.ts.map +0 -1
  480. package/dist/translator/hybrid-translator.js +0 -193
  481. package/dist/translator/hybrid-translator.js.map +0 -1
  482. package/dist/translator/index.d.ts +0 -13
  483. package/dist/translator/index.d.ts.map +0 -1
  484. package/dist/translator/index.js +0 -11
  485. package/dist/translator/index.js.map +0 -1
  486. package/dist/translator/query-translator.d.ts +0 -211
  487. package/dist/translator/query-translator.d.ts.map +0 -1
  488. package/dist/translator/query-translator.js +0 -1276
  489. package/dist/translator/query-translator.js.map +0 -1
  490. package/dist/translator/search-highlight.d.ts +0 -83
  491. package/dist/translator/search-highlight.d.ts.map +0 -1
  492. package/dist/translator/search-highlight.js +0 -83
  493. package/dist/translator/search-highlight.js.map +0 -1
  494. package/dist/translator/search-translator.d.ts +0 -155
  495. package/dist/translator/search-translator.d.ts.map +0 -1
  496. package/dist/translator/search-translator.js +0 -241
  497. package/dist/translator/search-translator.js.map +0 -1
  498. package/dist/translator/stages/add-fields-stage.d.ts +0 -7
  499. package/dist/translator/stages/add-fields-stage.d.ts.map +0 -1
  500. package/dist/translator/stages/add-fields-stage.js +0 -72
  501. package/dist/translator/stages/add-fields-stage.js.map +0 -1
  502. package/dist/translator/stages/bucket-stage.d.ts +0 -7
  503. package/dist/translator/stages/bucket-stage.d.ts.map +0 -1
  504. package/dist/translator/stages/bucket-stage.js +0 -87
  505. package/dist/translator/stages/bucket-stage.js.map +0 -1
  506. package/dist/translator/stages/count-stage.d.ts +0 -7
  507. package/dist/translator/stages/count-stage.d.ts.map +0 -1
  508. package/dist/translator/stages/count-stage.js +0 -12
  509. package/dist/translator/stages/count-stage.js.map +0 -1
  510. package/dist/translator/stages/expression-translator.d.ts +0 -68
  511. package/dist/translator/stages/expression-translator.d.ts.map +0 -1
  512. package/dist/translator/stages/expression-translator.js +0 -467
  513. package/dist/translator/stages/expression-translator.js.map +0 -1
  514. package/dist/translator/stages/facet-stage.d.ts +0 -13
  515. package/dist/translator/stages/facet-stage.d.ts.map +0 -1
  516. package/dist/translator/stages/facet-stage.js +0 -26
  517. package/dist/translator/stages/facet-stage.js.map +0 -1
  518. package/dist/translator/stages/fusion-stages.d.ts +0 -118
  519. package/dist/translator/stages/fusion-stages.d.ts.map +0 -1
  520. package/dist/translator/stages/fusion-stages.js +0 -201
  521. package/dist/translator/stages/fusion-stages.js.map +0 -1
  522. package/dist/translator/stages/group-stage.d.ts +0 -8
  523. package/dist/translator/stages/group-stage.d.ts.map +0 -1
  524. package/dist/translator/stages/group-stage.js +0 -123
  525. package/dist/translator/stages/group-stage.js.map +0 -1
  526. package/dist/translator/stages/index.d.ts +0 -24
  527. package/dist/translator/stages/index.d.ts.map +0 -1
  528. package/dist/translator/stages/index.js +0 -24
  529. package/dist/translator/stages/index.js.map +0 -1
  530. package/dist/translator/stages/join-optimizer.d.ts +0 -37
  531. package/dist/translator/stages/join-optimizer.d.ts.map +0 -1
  532. package/dist/translator/stages/join-optimizer.js +0 -93
  533. package/dist/translator/stages/join-optimizer.js.map +0 -1
  534. package/dist/translator/stages/limit-stage.d.ts +0 -7
  535. package/dist/translator/stages/limit-stage.d.ts.map +0 -1
  536. package/dist/translator/stages/limit-stage.js +0 -11
  537. package/dist/translator/stages/limit-stage.js.map +0 -1
  538. package/dist/translator/stages/lookup-stage.d.ts +0 -7
  539. package/dist/translator/stages/lookup-stage.d.ts.map +0 -1
  540. package/dist/translator/stages/lookup-stage.js +0 -73
  541. package/dist/translator/stages/lookup-stage.js.map +0 -1
  542. package/dist/translator/stages/match-stage.d.ts +0 -7
  543. package/dist/translator/stages/match-stage.d.ts.map +0 -1
  544. package/dist/translator/stages/match-stage.js +0 -14
  545. package/dist/translator/stages/match-stage.js.map +0 -1
  546. package/dist/translator/stages/optimizer.d.ts +0 -15
  547. package/dist/translator/stages/optimizer.d.ts.map +0 -1
  548. package/dist/translator/stages/optimizer.js +0 -249
  549. package/dist/translator/stages/optimizer.js.map +0 -1
  550. package/dist/translator/stages/parallel-facet.d.ts +0 -47
  551. package/dist/translator/stages/parallel-facet.d.ts.map +0 -1
  552. package/dist/translator/stages/parallel-facet.js +0 -57
  553. package/dist/translator/stages/parallel-facet.js.map +0 -1
  554. package/dist/translator/stages/project-stage.d.ts +0 -8
  555. package/dist/translator/stages/project-stage.d.ts.map +0 -1
  556. package/dist/translator/stages/project-stage.js +0 -145
  557. package/dist/translator/stages/project-stage.js.map +0 -1
  558. package/dist/translator/stages/search-stage.d.ts +0 -60
  559. package/dist/translator/stages/search-stage.d.ts.map +0 -1
  560. package/dist/translator/stages/search-stage.js +0 -89
  561. package/dist/translator/stages/search-stage.js.map +0 -1
  562. package/dist/translator/stages/skip-stage.d.ts +0 -7
  563. package/dist/translator/stages/skip-stage.d.ts.map +0 -1
  564. package/dist/translator/stages/skip-stage.js +0 -11
  565. package/dist/translator/stages/skip-stage.js.map +0 -1
  566. package/dist/translator/stages/sort-stage.d.ts +0 -7
  567. package/dist/translator/stages/sort-stage.d.ts.map +0 -1
  568. package/dist/translator/stages/sort-stage.js +0 -21
  569. package/dist/translator/stages/sort-stage.js.map +0 -1
  570. package/dist/translator/stages/types.d.ts +0 -136
  571. package/dist/translator/stages/types.d.ts.map +0 -1
  572. package/dist/translator/stages/types.js +0 -5
  573. package/dist/translator/stages/types.js.map +0 -1
  574. package/dist/translator/stages/unwind-stage.d.ts +0 -7
  575. package/dist/translator/stages/unwind-stage.d.ts.map +0 -1
  576. package/dist/translator/stages/unwind-stage.js +0 -61
  577. package/dist/translator/stages/unwind-stage.js.map +0 -1
  578. package/dist/translator/stages/vector-search-stage.d.ts +0 -53
  579. package/dist/translator/stages/vector-search-stage.d.ts.map +0 -1
  580. package/dist/translator/stages/vector-search-stage.js +0 -62
  581. package/dist/translator/stages/vector-search-stage.js.map +0 -1
  582. package/dist/translator/update-translator.d.ts +0 -148
  583. package/dist/translator/update-translator.d.ts.map +0 -1
  584. package/dist/translator/update-translator.js +0 -819
  585. package/dist/translator/update-translator.js.map +0 -1
  586. package/dist/translator/vector-translator.d.ts +0 -89
  587. package/dist/translator/vector-translator.d.ts.map +0 -1
  588. package/dist/translator/vector-translator.js +0 -106
  589. package/dist/translator/vector-translator.js.map +0 -1
  590. package/dist/types/env.d.ts +0 -31
  591. package/dist/types/env.d.ts.map +0 -1
  592. package/dist/types/env.js +0 -5
  593. package/dist/types/env.js.map +0 -1
  594. package/dist/types/function.d.ts +0 -65
  595. package/dist/types/function.d.ts.map +0 -1
  596. package/dist/types/function.js +0 -5
  597. package/dist/types/function.js.map +0 -1
  598. package/dist/types/index.d.ts +0 -137
  599. package/dist/types/index.d.ts.map +0 -1
  600. package/dist/types/index.js +0 -13
  601. package/dist/types/index.js.map +0 -1
  602. package/dist/types/mongodb.d.ts +0 -258
  603. package/dist/types/mongodb.d.ts.map +0 -1
  604. package/dist/types/mongodb.js +0 -5
  605. package/dist/types/mongodb.js.map +0 -1
  606. package/dist/types/objectid.d.ts +0 -130
  607. package/dist/types/objectid.d.ts.map +0 -1
  608. package/dist/types/objectid.js +0 -314
  609. package/dist/types/objectid.js.map +0 -1
  610. package/dist/types/rpc.d.ts +0 -313
  611. package/dist/types/rpc.d.ts.map +0 -1
  612. package/dist/types/rpc.js +0 -136
  613. package/dist/types/rpc.js.map +0 -1
  614. package/dist/types/vectorize.d.ts +0 -136
  615. package/dist/types/vectorize.d.ts.map +0 -1
  616. package/dist/types/vectorize.js +0 -8
  617. package/dist/types/vectorize.js.map +0 -1
  618. package/dist/utils/sql-safety.d.ts +0 -64
  619. package/dist/utils/sql-safety.d.ts.map +0 -1
  620. package/dist/utils/sql-safety.js +0 -112
  621. package/dist/utils/sql-safety.js.map +0 -1
  622. package/dist/validation/document-validator.d.ts +0 -195
  623. package/dist/validation/document-validator.d.ts.map +0 -1
  624. package/dist/validation/document-validator.js +0 -529
  625. package/dist/validation/document-validator.js.map +0 -1
  626. package/dist/vectorize/document-serializer.d.ts +0 -119
  627. package/dist/vectorize/document-serializer.d.ts.map +0 -1
  628. package/dist/vectorize/document-serializer.js +0 -320
  629. package/dist/vectorize/document-serializer.js.map +0 -1
  630. package/dist/wire/auth/index.d.ts +0 -5
  631. package/dist/wire/auth/index.d.ts.map +0 -1
  632. package/dist/wire/auth/index.js +0 -5
  633. package/dist/wire/auth/index.js.map +0 -1
  634. package/dist/wire/auth/scram.d.ts +0 -160
  635. package/dist/wire/auth/scram.d.ts.map +0 -1
  636. package/dist/wire/auth/scram.js +0 -425
  637. package/dist/wire/auth/scram.js.map +0 -1
  638. package/dist/wire/backend/interface.d.ts +0 -168
  639. package/dist/wire/backend/interface.d.ts.map +0 -1
  640. package/dist/wire/backend/interface.js +0 -10
  641. package/dist/wire/backend/interface.js.map +0 -1
  642. package/dist/wire/backend/local-sqlite.d.ts +0 -89
  643. package/dist/wire/backend/local-sqlite.d.ts.map +0 -1
  644. package/dist/wire/backend/local-sqlite.js +0 -1002
  645. package/dist/wire/backend/local-sqlite.js.map +0 -1
  646. package/dist/wire/backend/query-router.d.ts +0 -197
  647. package/dist/wire/backend/query-router.d.ts.map +0 -1
  648. package/dist/wire/backend/query-router.js +0 -590
  649. package/dist/wire/backend/query-router.js.map +0 -1
  650. package/dist/wire/backend/validation.d.ts +0 -26
  651. package/dist/wire/backend/validation.d.ts.map +0 -1
  652. package/dist/wire/backend/validation.js +0 -79
  653. package/dist/wire/backend/validation.js.map +0 -1
  654. package/dist/wire/backend/workers-proxy.d.ts +0 -95
  655. package/dist/wire/backend/workers-proxy.d.ts.map +0 -1
  656. package/dist/wire/backend/workers-proxy.js +0 -429
  657. package/dist/wire/backend/workers-proxy.js.map +0 -1
  658. package/dist/wire/commands/admin.d.ts +0 -49
  659. package/dist/wire/commands/admin.d.ts.map +0 -1
  660. package/dist/wire/commands/admin.js +0 -272
  661. package/dist/wire/commands/admin.js.map +0 -1
  662. package/dist/wire/commands/aggregate.d.ts +0 -15
  663. package/dist/wire/commands/aggregate.d.ts.map +0 -1
  664. package/dist/wire/commands/aggregate.js +0 -98
  665. package/dist/wire/commands/aggregate.js.map +0 -1
  666. package/dist/wire/commands/auth.d.ts +0 -58
  667. package/dist/wire/commands/auth.d.ts.map +0 -1
  668. package/dist/wire/commands/auth.js +0 -158
  669. package/dist/wire/commands/auth.js.map +0 -1
  670. package/dist/wire/commands/crud.d.ts +0 -49
  671. package/dist/wire/commands/crud.d.ts.map +0 -1
  672. package/dist/wire/commands/crud.js +0 -336
  673. package/dist/wire/commands/crud.js.map +0 -1
  674. package/dist/wire/commands/hello.d.ts +0 -35
  675. package/dist/wire/commands/hello.d.ts.map +0 -1
  676. package/dist/wire/commands/hello.js +0 -204
  677. package/dist/wire/commands/hello.js.map +0 -1
  678. package/dist/wire/commands/index.d.ts +0 -24
  679. package/dist/wire/commands/index.d.ts.map +0 -1
  680. package/dist/wire/commands/index.js +0 -145
  681. package/dist/wire/commands/index.js.map +0 -1
  682. package/dist/wire/commands/router.d.ts +0 -46
  683. package/dist/wire/commands/router.d.ts.map +0 -1
  684. package/dist/wire/commands/router.js +0 -151
  685. package/dist/wire/commands/router.js.map +0 -1
  686. package/dist/wire/commands/types.d.ts +0 -51
  687. package/dist/wire/commands/types.d.ts.map +0 -1
  688. package/dist/wire/commands/types.js +0 -15
  689. package/dist/wire/commands/types.js.map +0 -1
  690. package/dist/wire/index.d.ts +0 -15
  691. package/dist/wire/index.d.ts.map +0 -1
  692. package/dist/wire/index.js +0 -19
  693. package/dist/wire/index.js.map +0 -1
  694. package/dist/wire/message.d.ts +0 -49
  695. package/dist/wire/message.d.ts.map +0 -1
  696. package/dist/wire/message.js +0 -299
  697. package/dist/wire/message.js.map +0 -1
  698. package/dist/wire/server.d.ts +0 -145
  699. package/dist/wire/server.d.ts.map +0 -1
  700. package/dist/wire/server.js +0 -284
  701. package/dist/wire/server.js.map +0 -1
  702. package/dist/wire/types.d.ts +0 -140
  703. package/dist/wire/types.d.ts.map +0 -1
  704. package/dist/wire/types.js +0 -64
  705. package/dist/wire/types.js.map +0 -1
  706. package/dist/worker.d.ts.map +0 -1
@@ -1,1276 +0,0 @@
1
- /**
2
- * QueryTranslator - Translates MongoDB-style queries to SQL
3
- * using json_extract for field access on JSON documents.
4
- *
5
- * Features:
6
- * - Operator registry pattern for extensibility
7
- * - Automatic flattening of nested $and/$or for SQL optimization
8
- * - CTE-based optimization for multiple array operations
9
- * - Parameterized queries for SQL injection prevention
10
- * - $text operator for full-text search with FTS5
11
- * - Multi-dialect support (SQLite, ClickHouse)
12
- */
13
- import { validateFieldPath } from '../utils/sql-safety.js';
14
- import { validateDialect, jsonExtract as dialectJsonExtract, jsonType as dialectJsonType, jsonTypeWithPath as dialectJsonTypeWithPath, jsonArrayLength as dialectJsonArrayLength, regexMatch as dialectRegexMatch, } from './dialect.js';
15
- import { translateExpression } from './stages/expression-translator.js';
16
- /**
17
- * MongoDB type to SQLite json_type mapping
18
- */
19
- const MONGO_TYPE_TO_SQLITE = {
20
- string: 'text',
21
- number: ['integer', 'real'],
22
- bool: ['true', 'false'],
23
- boolean: ['true', 'false'],
24
- array: 'array',
25
- object: 'object',
26
- null: 'null',
27
- };
28
- const DEFAULT_OPTIONS = {
29
- useCTE: true,
30
- flattenLogical: true,
31
- dialect: 'sqlite',
32
- };
33
- /**
34
- * QueryTranslator - Converts MongoDB query syntax to SQL with json_extract
35
- */
36
- export class QueryTranslator {
37
- options;
38
- dialect;
39
- constructor(options = {}) {
40
- // Validate dialect before merging options
41
- const dialect = validateDialect(options.dialect);
42
- this.options = { ...DEFAULT_OPTIONS, ...options, dialect };
43
- this.dialect = dialect;
44
- }
45
- /**
46
- * Registry of comparison operators and their SQL translations
47
- */
48
- comparisonOperators = {
49
- $eq: (path, value, params) => {
50
- if (value === null) {
51
- return `${this.jsonExtract(path)} IS NULL`;
52
- }
53
- // SQLite's json_extract returns 1/0 for booleans, so convert JS booleans
54
- const sqlValue = typeof value === 'boolean' ? (value ? 1 : 0) : value;
55
- params.push(sqlValue);
56
- return `${this.jsonExtract(path)} = ?`;
57
- },
58
- $ne: (path, value, params) => {
59
- if (value === null) {
60
- return `${this.jsonExtract(path)} IS NOT NULL`;
61
- }
62
- // SQLite's json_extract returns 1/0 for booleans, so convert JS booleans
63
- const sqlValue = typeof value === 'boolean' ? (value ? 1 : 0) : value;
64
- params.push(sqlValue);
65
- return `${this.jsonExtract(path)} != ?`;
66
- },
67
- $gt: (path, value, params) => {
68
- params.push(value);
69
- return `${this.jsonExtract(path)} > ?`;
70
- },
71
- $gte: (path, value, params) => {
72
- params.push(value);
73
- return `${this.jsonExtract(path)} >= ?`;
74
- },
75
- $lt: (path, value, params) => {
76
- params.push(value);
77
- return `${this.jsonExtract(path)} < ?`;
78
- },
79
- $lte: (path, value, params) => {
80
- params.push(value);
81
- return `${this.jsonExtract(path)} <= ?`;
82
- },
83
- $in: (path, value, params) => {
84
- const arr = value;
85
- if (arr.length === 0) {
86
- return '0 = 1';
87
- }
88
- params.push(...arr);
89
- const placeholders = arr.map(() => '?').join(', ');
90
- return `${this.jsonExtract(path)} IN (${placeholders})`;
91
- },
92
- $nin: (path, value, params) => {
93
- const arr = value;
94
- if (arr.length === 0) {
95
- return '1 = 1';
96
- }
97
- params.push(...arr);
98
- const placeholders = arr.map(() => '?').join(', ');
99
- return `${this.jsonExtract(path)} NOT IN (${placeholders})`;
100
- },
101
- $regex: (path, value, params) => {
102
- // Handle both { $regex: "pattern" } and { $regex: "pattern", $options: "i" }
103
- // Also handle direct { field: { $regex: /pattern/i } } form
104
- // Also support $regexType: 'glob' for SQLite GLOB syntax
105
- let pattern;
106
- let options = '';
107
- let regexType = 'like'; // default to LIKE pattern matching
108
- if (typeof value === 'string') {
109
- pattern = value;
110
- }
111
- else if (value instanceof RegExp) {
112
- pattern = value.source;
113
- options = value.flags;
114
- }
115
- else if (value && typeof value === 'object') {
116
- const regexObj = value;
117
- pattern = regexObj.$regex || '';
118
- options = regexObj.$options || '';
119
- regexType = regexObj.$regexType || 'like';
120
- }
121
- else {
122
- pattern = String(value);
123
- }
124
- const fieldExpr = this.jsonExtract(path);
125
- const caseInsensitive = options.includes('i');
126
- // Handle GLOB type for SQLite
127
- if (regexType === 'glob' && this.dialect === 'sqlite') {
128
- params.push(pattern);
129
- const typeCheck = `json_type(${fieldExpr}) = 'text'`;
130
- return `(${typeCheck} AND ${fieldExpr} GLOB ?)`;
131
- }
132
- // Convert regex pattern to LIKE pattern
133
- // This is a simplified conversion that handles common cases
134
- const likePattern = this.regexToLike(pattern, options);
135
- params.push(likePattern);
136
- // First ensure the field is a string type (regex only works on strings)
137
- if (this.dialect === 'clickhouse') {
138
- const typeCheck = `JSONType(data, ${path.replace(/^\$\.?/, '').split('.').map(p => `'${p}'`).join(', ')}) = 'String'`;
139
- const matchExpr = dialectRegexMatch(this.dialect, fieldExpr, '?', caseInsensitive);
140
- return `(${typeCheck} AND ${matchExpr})`;
141
- }
142
- const typeCheck = `json_type(${fieldExpr}) = 'text'`;
143
- const matchExpr = dialectRegexMatch(this.dialect, fieldExpr, '?', caseInsensitive);
144
- return `(${typeCheck} AND ${matchExpr})`;
145
- },
146
- $mod: (path, value, params) => {
147
- // $mod: [divisor, remainder] - matches if field % divisor == remainder
148
- const [divisor, remainder] = value;
149
- params.push(divisor, remainder);
150
- // Check that the field is numeric and apply modulo
151
- // Use CAST to handle float truncation like MongoDB
152
- return `(json_type(${this.jsonExtract(path)}) IN ('integer', 'real') AND CAST(${this.jsonExtract(path)} AS INTEGER) % ? = ?)`;
153
- },
154
- // Bitwise operators
155
- $bitsAllSet: (path, value, params) => {
156
- // $bitsAllSet: [bit positions] or bitmask number
157
- // Matches if all specified bits are set (1)
158
- const mask = this.resolveBitmask(value);
159
- params.push(mask, mask);
160
- // (field & mask) == mask means all bits in mask are set
161
- return `(json_type(${this.jsonExtract(path)}) IN ('integer', 'real') AND (CAST(${this.jsonExtract(path)} AS INTEGER) & ?) = ?)`;
162
- },
163
- $bitsAnyClear: (path, value, params) => {
164
- // $bitsAnyClear: [bit positions] or bitmask number
165
- // Matches if any of the specified bits are clear (0)
166
- const mask = this.resolveBitmask(value);
167
- params.push(mask, mask);
168
- // (field & mask) != mask means at least one bit in mask is clear
169
- return `(json_type(${this.jsonExtract(path)}) IN ('integer', 'real') AND (CAST(${this.jsonExtract(path)} AS INTEGER) & ?) != ?)`;
170
- },
171
- $bitsAllClear: (path, value, params) => {
172
- // $bitsAllClear: [bit positions] or bitmask number
173
- // Matches if all specified bits are clear (0)
174
- const mask = this.resolveBitmask(value);
175
- params.push(mask);
176
- // (field & mask) == 0 means all bits in mask are clear
177
- return `(json_type(${this.jsonExtract(path)}) IN ('integer', 'real') AND (CAST(${this.jsonExtract(path)} AS INTEGER) & ?) = 0)`;
178
- },
179
- $bitsAnySet: (path, value, params) => {
180
- // $bitsAnySet: [bit positions] or bitmask number
181
- // Matches if any of the specified bits are set (1)
182
- const mask = this.resolveBitmask(value);
183
- params.push(mask);
184
- // (field & mask) != 0 means at least one bit in mask is set
185
- return `(json_type(${this.jsonExtract(path)}) IN ('integer', 'real') AND (CAST(${this.jsonExtract(path)} AS INTEGER) & ?) != 0)`;
186
- },
187
- };
188
- /**
189
- * Registry of element operators
190
- */
191
- elementOperators = {
192
- $exists: (path, value, _params) => {
193
- // MongoDB $exists distinguishes between missing fields and null values:
194
- // - $exists: true -> field exists (including explicit null values)
195
- // - $exists: false -> field is completely missing from the document
196
- //
197
- // SQLite's json_extract returns NULL for both missing fields AND null values,
198
- // but json_type returns 'null' for explicit nulls and NULL for missing fields.
199
- // So we use json_type with path directly to properly detect field existence.
200
- if (path.startsWith('$')) {
201
- // JSON path - use json_type(data, path) directly for existence checks
202
- const typeExpr = dialectJsonTypeWithPath(this.dialect, 'data', path);
203
- if (value) {
204
- return `${typeExpr} IS NOT NULL`;
205
- }
206
- return `${typeExpr} IS NULL`;
207
- }
208
- // Direct reference (for elemMatch context) - use json_type
209
- if (this.dialect === 'clickhouse') {
210
- if (value) {
211
- return `JSONType(${path}) IS NOT NULL`;
212
- }
213
- return `JSONType(${path}) IS NULL`;
214
- }
215
- if (value) {
216
- return `json_type(${path}) IS NOT NULL`;
217
- }
218
- return `json_type(${path}) IS NULL`;
219
- },
220
- $type: (path, value, _params) => {
221
- const mongoType = value;
222
- const sqliteType = MONGO_TYPE_TO_SQLITE[mongoType];
223
- const typeExpr = dialectJsonType(this.dialect, 'data', path);
224
- if (Array.isArray(sqliteType)) {
225
- if (mongoType === 'number') {
226
- if (this.dialect === 'clickhouse') {
227
- return `${typeExpr} IN ('Int64', 'Float64', 'UInt64')`;
228
- }
229
- return `${typeExpr} IN ('integer', 'real')`;
230
- }
231
- // bool type checks for true/false values
232
- if (this.dialect === 'clickhouse') {
233
- return `${typeExpr} = 'Bool'`;
234
- }
235
- return `${typeExpr} IN ('true', 'false')`;
236
- }
237
- if (this.dialect === 'clickhouse') {
238
- const chType = mongoType === 'string' ? 'String' : mongoType === 'array' ? 'Array' : mongoType === 'object' ? 'Object' : sqliteType;
239
- return `${typeExpr} = '${chType}'`;
240
- }
241
- return `${typeExpr} = '${sqliteType}'`;
242
- },
243
- };
244
- /**
245
- * Registry of array operators
246
- */
247
- arrayOperators = {
248
- $size: (path, value, params) => {
249
- params.push(value);
250
- const lenExpr = dialectJsonArrayLength(this.dialect, 'data', path);
251
- return `${lenExpr} = ?`;
252
- },
253
- $all: (path, value, params) => {
254
- const arr = value;
255
- if (arr.length === 0) {
256
- return '1 = 1';
257
- }
258
- // Each value must exist in the array using EXISTS with json_each
259
- const conditions = arr.map((v) => {
260
- params.push(v);
261
- return `EXISTS (SELECT 1 FROM json_each(${this.jsonExtract(path)}) WHERE value = ?)`;
262
- });
263
- return conditions.length === 1
264
- ? conditions[0]
265
- : `(${conditions.join(' AND ')})`;
266
- },
267
- $elemMatch: (path, value, params) => {
268
- const conditions = value;
269
- // Generate subquery for array element matching
270
- const innerConditions = this.translateElemMatchConditions(conditions, params);
271
- return `EXISTS (SELECT 1 FROM json_each(${this.jsonExtract(path)}) WHERE ${innerConditions})`;
272
- },
273
- };
274
- /**
275
- * Main entry point - translate a MongoDB query to SQL
276
- */
277
- translate(query) {
278
- const params = [];
279
- if (Object.keys(query).length === 0) {
280
- return { sql: '1 = 1', params: [] };
281
- }
282
- // Pre-process to flatten nested logical operators if enabled
283
- const processedQuery = this.options.flattenLogical
284
- ? this.flattenLogicalOperators(query)
285
- : query;
286
- const sql = this.translateDocument(processedQuery, params);
287
- return { sql, params };
288
- }
289
- /**
290
- * Flatten nested logical operators of the same type
291
- * E.g., $and: [{ $and: [a, b] }, c] -> $and: [a, b, c]
292
- */
293
- flattenLogicalOperators(query) {
294
- const result = {};
295
- for (const [key, value] of Object.entries(query)) {
296
- if (key === '$and' || key === '$or') {
297
- const conditions = value;
298
- const flattened = [];
299
- for (const condition of conditions) {
300
- // Recursively flatten nested conditions
301
- const flatCondition = this.flattenLogicalOperators(condition);
302
- // If the nested condition is the same logical operator, merge it
303
- if (Object.keys(flatCondition).length === 1 && flatCondition[key]) {
304
- const nestedConditions = flatCondition[key];
305
- flattened.push(...nestedConditions);
306
- }
307
- else {
308
- flattened.push(flatCondition);
309
- }
310
- }
311
- result[key] = flattened;
312
- }
313
- else if (key === '$nor') {
314
- // $nor cannot be flattened the same way, but we still process nested conditions
315
- const conditions = value;
316
- result[key] = conditions.map(c => this.flattenLogicalOperators(c));
317
- }
318
- else if (key.startsWith('$')) {
319
- // Other operators, just copy
320
- result[key] = value;
321
- }
322
- else {
323
- // Field condition - recursively process if it's an object
324
- if (value && typeof value === 'object' && !Array.isArray(value)) {
325
- const operators = value;
326
- const processedOps = {};
327
- for (const [op, opValue] of Object.entries(operators)) {
328
- if (op === '$not' && opValue && typeof opValue === 'object') {
329
- processedOps[op] = this.flattenLogicalOperators(opValue);
330
- }
331
- else if (op === '$elemMatch' && opValue && typeof opValue === 'object') {
332
- processedOps[op] = this.flattenLogicalOperators(opValue);
333
- }
334
- else {
335
- processedOps[op] = opValue;
336
- }
337
- }
338
- result[key] = processedOps;
339
- }
340
- else {
341
- result[key] = value;
342
- }
343
- }
344
- }
345
- return result;
346
- }
347
- /**
348
- * Translate a query document (top-level or nested)
349
- */
350
- translateDocument(query, params) {
351
- const conditions = [];
352
- for (const [key, value] of Object.entries(query)) {
353
- if (key.startsWith('$')) {
354
- // Logical operator at top level
355
- const sql = this.translateLogicalOperator(key, value, params);
356
- conditions.push(sql);
357
- }
358
- else {
359
- // Field condition
360
- const sql = this.translateField(key, value, params);
361
- conditions.push(sql);
362
- }
363
- }
364
- if (conditions.length === 0) {
365
- return '1 = 1';
366
- }
367
- if (conditions.length === 1) {
368
- return conditions[0];
369
- }
370
- return `(${conditions.join(' AND ')})`;
371
- }
372
- /**
373
- * Translate a field condition
374
- */
375
- translateField(field, value, params) {
376
- const path = this.fieldToJsonPath(field);
377
- // Direct value comparison (implicit $eq)
378
- if (value === null || typeof value !== 'object' || Array.isArray(value)) {
379
- return this.comparisonOperators.$eq(path, value, params);
380
- }
381
- // Object with operators
382
- const operators = value;
383
- const operatorKeys = Object.keys(operators);
384
- // Check if it's an object with operators
385
- if (operatorKeys.length > 0 && operatorKeys.every(k => k.startsWith('$'))) {
386
- return this.translateFieldConditions(path, operators, params, false);
387
- }
388
- // Plain object equality (implicit $eq)
389
- return this.comparisonOperators.$eq(path, value, params);
390
- }
391
- /**
392
- * Translate conditions on a single field
393
- */
394
- translateFieldConditions(path, conditions, params, isElemMatch) {
395
- const sqlParts = [];
396
- // Check for $regex with sibling $options or $regexType
397
- const hasRegexWithOptions = '$regex' in conditions && ('$options' in conditions || '$regexType' in conditions);
398
- for (const [op, value] of Object.entries(conditions)) {
399
- // Skip $options and $regexType when they're siblings of $regex (handled together with $regex)
400
- if ((op === '$options' || op === '$regexType') && hasRegexWithOptions) {
401
- continue;
402
- }
403
- let sql;
404
- if (op === '$not') {
405
- // $not wraps another operator
406
- const innerConditions = value;
407
- const innerSql = this.translateFieldConditions(path, innerConditions, params, isElemMatch);
408
- sql = `NOT (${innerSql})`;
409
- }
410
- else if (op === '$regex' && hasRegexWithOptions) {
411
- // Handle $regex with sibling $options or $regexType
412
- const actualPath = isElemMatch ? this.elemMatchFieldPath(path, '') : path;
413
- const regexValue = {
414
- $regex: value,
415
- $options: conditions.$options,
416
- $regexType: conditions.$regexType
417
- };
418
- sql = this.comparisonOperators[op](actualPath, regexValue, params);
419
- }
420
- else if (this.comparisonOperators[op]) {
421
- const actualPath = isElemMatch ? this.elemMatchFieldPath(path, '') : path;
422
- sql = this.comparisonOperators[op](actualPath, value, params);
423
- }
424
- else if (this.elementOperators[op]) {
425
- const actualPath = isElemMatch ? this.elemMatchFieldPath(path, '') : path;
426
- sql = this.elementOperators[op](actualPath, value, params);
427
- }
428
- else if (this.arrayOperators[op]) {
429
- const actualPath = isElemMatch ? this.elemMatchFieldPath(path, '') : path;
430
- sql = this.arrayOperators[op](actualPath, value, params);
431
- }
432
- else {
433
- // Unknown operator - treat as nested field in elemMatch context
434
- if (isElemMatch) {
435
- const nestedPath = this.elemMatchFieldPath(path, op.replace('$', ''));
436
- sql = this.translateFieldConditions(nestedPath, { $eq: value }, params, true);
437
- }
438
- else {
439
- throw new Error(`Unknown operator: ${op}`);
440
- }
441
- }
442
- sqlParts.push(sql);
443
- }
444
- if (sqlParts.length === 0) {
445
- return '1 = 1';
446
- }
447
- if (sqlParts.length === 1) {
448
- return sqlParts[0];
449
- }
450
- return `(${sqlParts.join(' AND ')})`;
451
- }
452
- /**
453
- * Translate logical operators ($and, $or, $not, $nor, $text)
454
- */
455
- translateLogicalOperator(op, value, params) {
456
- switch (op) {
457
- case '$and': {
458
- const conditions = value;
459
- if (conditions.length === 0) {
460
- return '1 = 1';
461
- }
462
- const parts = conditions.map(c => this.translateDocument(c, params));
463
- if (parts.length === 1) {
464
- return parts[0];
465
- }
466
- return `(${parts.join(' AND ')})`;
467
- }
468
- case '$or': {
469
- const conditions = value;
470
- if (conditions.length === 0) {
471
- return '0 = 1';
472
- }
473
- const parts = conditions.map(c => this.translateDocument(c, params));
474
- if (parts.length === 1) {
475
- return parts[0];
476
- }
477
- return `(${parts.join(' OR ')})`;
478
- }
479
- case '$nor': {
480
- const conditions = value;
481
- if (conditions.length === 0) {
482
- return '1 = 1';
483
- }
484
- const parts = conditions.map(c => this.translateDocument(c, params));
485
- return `NOT (${parts.join(' OR ')})`;
486
- }
487
- case '$not': {
488
- // $not at top level wraps a condition
489
- const innerSql = this.translateDocument(value, params);
490
- return `NOT (${innerSql})`;
491
- }
492
- case '$text': {
493
- // $text operator for full-text search
494
- const textOp = value;
495
- const { sql } = this.translateTextOperator(textOp, params);
496
- return sql;
497
- }
498
- case '$expr': {
499
- // $expr allows use of aggregation expressions in the query language
500
- // It enables comparing fields within the same document
501
- const exprResult = translateExpression(value, params, this.dialect);
502
- return exprResult;
503
- }
504
- case '$jsonSchema': {
505
- // $jsonSchema validates documents against a JSON Schema
506
- const schema = value;
507
- return this.translateJsonSchema(schema, '$', params);
508
- }
509
- case '$where': {
510
- // $where executes JavaScript expressions - NOT SUPPORTED due to security risks
511
- // MongoDB's $where allows arbitrary JavaScript execution which is a security risk
512
- // In a SQL context, we cannot safely execute JavaScript
513
- throw new Error('$where operator is not supported due to security risks. ' +
514
- 'Use $expr with aggregation expressions instead for field comparisons.');
515
- }
516
- default:
517
- throw new Error(`Unknown logical operator: ${op}`);
518
- }
519
- }
520
- /**
521
- * Convert a field name to a JSON path
522
- * e.g., "a.b.c" -> "$.a.b.c"
523
- * e.g., "items.0.name" -> "$.items[0].name"
524
- *
525
- * SECURITY: Validates field name to prevent SQL injection attacks.
526
- * @throws Error if field contains invalid characters
527
- */
528
- fieldToJsonPath(field) {
529
- // Validate the entire field path to prevent SQL injection
530
- validateFieldPath(field);
531
- const parts = field.split('.');
532
- let path = '$';
533
- for (const part of parts) {
534
- // Check if part is a numeric index
535
- if (/^\d+$/.test(part)) {
536
- path += `[${part}]`;
537
- }
538
- else {
539
- path += `.${part}`;
540
- }
541
- }
542
- return path;
543
- }
544
- /**
545
- * Generate json_extract SQL for a path
546
- */
547
- jsonExtract(path) {
548
- // If path starts with $, it's a JSON path
549
- if (path.startsWith('$')) {
550
- return dialectJsonExtract(this.dialect, 'data', path);
551
- }
552
- // Otherwise, it's a direct reference (for elemMatch context)
553
- return path;
554
- }
555
- /**
556
- * Convert a bitwise operator value to a bitmask
557
- * Accepts either:
558
- * - A number (used directly as bitmask)
559
- * - An array of bit positions (converted to bitmask)
560
- */
561
- resolveBitmask(value) {
562
- if (typeof value === 'number') {
563
- return value;
564
- }
565
- if (Array.isArray(value)) {
566
- // Convert array of bit positions to bitmask
567
- // e.g., [0, 2, 4] -> 0b10101 = 21
568
- return value.reduce((mask, pos) => mask | (1 << pos), 0);
569
- }
570
- throw new Error('Bitwise operator value must be a number or array of bit positions');
571
- }
572
- /**
573
- * Generate path for elemMatch field access
574
- * SECURITY: Validates field name to prevent SQL injection attacks.
575
- */
576
- elemMatchFieldPath(basePath, field) {
577
- if (basePath === 'value') {
578
- // Inside json_each, value is the current element
579
- if (field === '') {
580
- return 'value';
581
- }
582
- // Validate field name to prevent SQL injection
583
- validateFieldPath(field);
584
- return `json_extract(value, '$.${field}')`;
585
- }
586
- if (field === '') {
587
- return basePath;
588
- }
589
- // Validate field name to prevent SQL injection
590
- validateFieldPath(field);
591
- return `${basePath}.${field}`;
592
- }
593
- /**
594
- * Convert a regex pattern to SQLite LIKE/GLOB pattern
595
- * This handles common regex patterns:
596
- * - ^pattern -> pattern% (starts with)
597
- * - pattern$ -> %pattern (ends with)
598
- * - ^pattern$ -> pattern (exact match)
599
- * - .* or .+ -> % (any characters)
600
- * - . -> _ (single character)
601
- * - [0-9] -> character class (converted to GLOB syntax)
602
- * - [a-z] -> character class (converted to GLOB syntax)
603
- * - Literal text -> %text% (contains, default behavior)
604
- *
605
- * @param pattern The regex pattern to convert
606
- * @param options Regex options (i=case-insensitive, m=multiline)
607
- */
608
- regexToLike(pattern, options = '') {
609
- // For multiline mode, we need special handling of ^ and $
610
- // In multiline mode, ^ matches start of line (after \n) and $ matches before \n
611
- const isMultiline = options.includes('m');
612
- // Handle anchors
613
- let startsWithAnchor = pattern.startsWith('^');
614
- let endsWithAnchor = pattern.endsWith('$') && !pattern.endsWith('\\$');
615
- // In multiline mode, anchors match line boundaries, not string boundaries
616
- // Since LIKE can't match line boundaries, we convert to contains match
617
- if (isMultiline && (startsWithAnchor || endsWithAnchor)) {
618
- // For multiline, we treat ^ and $ as matching within the string
619
- // This is an approximation - LIKE can't truly match line boundaries
620
- // But we can check for patterns after newline or before newline
621
- startsWithAnchor = false;
622
- endsWithAnchor = false;
623
- }
624
- // Remove anchors for processing
625
- let processed = pattern;
626
- if (pattern.startsWith('^')) {
627
- processed = processed.slice(1);
628
- }
629
- if (processed.endsWith('$') && !processed.endsWith('\\$')) {
630
- processed = processed.slice(0, -1);
631
- }
632
- // Process character by character to handle escaping properly
633
- let result = '';
634
- let i = 0;
635
- while (i < processed.length) {
636
- const char = processed[i];
637
- const nextChar = processed[i + 1];
638
- if (char === '\\' && nextChar !== undefined) {
639
- // Escaped character in regex - keep literal character
640
- // But we need to escape it for LIKE if it's a special LIKE character
641
- if (nextChar === '%' || nextChar === '_') {
642
- result += '\\' + nextChar;
643
- }
644
- else {
645
- result += nextChar;
646
- }
647
- i += 2;
648
- }
649
- else if (char === '[') {
650
- // Character class - find the closing bracket
651
- const endBracket = processed.indexOf(']', i + 1);
652
- if (endBracket !== -1) {
653
- const charClass = processed.slice(i + 1, endBracket);
654
- // Convert common character classes to approximate LIKE patterns
655
- // [0-9] -> _ (single digit) or % for multiple
656
- // [a-zA-Z] -> _ (single letter)
657
- // For now, use _ as a single character match (approximation)
658
- if (charClass.includes('+') || processed[endBracket + 1] === '+') {
659
- result += '%';
660
- i = endBracket + (processed[endBracket + 1] === '+' ? 2 : 1);
661
- }
662
- else if (processed[endBracket + 1] === '*') {
663
- result += '%';
664
- i = endBracket + 2;
665
- }
666
- else {
667
- result += '_';
668
- i = endBracket + 1;
669
- }
670
- }
671
- else {
672
- // No closing bracket, treat [ as literal
673
- result += char;
674
- i += 1;
675
- }
676
- }
677
- else if (char === '.' && nextChar === '*') {
678
- // .* -> % (any characters)
679
- result += '%';
680
- i += 2;
681
- }
682
- else if (char === '.' && nextChar === '+') {
683
- // .+ -> % (one or more characters, approximate with %)
684
- result += '%';
685
- i += 2;
686
- }
687
- else if (char === '.') {
688
- // . -> _ (single character)
689
- result += '_';
690
- i += 1;
691
- }
692
- else if (char === '%') {
693
- // Escape literal % for LIKE
694
- result += '\\%';
695
- i += 1;
696
- }
697
- else if (char === '_') {
698
- // Escape literal _ for LIKE
699
- result += '\\_';
700
- i += 1;
701
- }
702
- else if (char === '+' || char === '*' || char === '?' || char === '|' || char === '(' || char === ')') {
703
- // Skip regex quantifiers and grouping - not directly translatable to LIKE
704
- // These would need more sophisticated handling
705
- i += 1;
706
- }
707
- else {
708
- // Regular character
709
- result += char;
710
- i += 1;
711
- }
712
- }
713
- // Apply wildcards based on anchors
714
- if (!startsWithAnchor && !endsWithAnchor) {
715
- // No anchors: match anywhere (contains)
716
- return `%${result}%`;
717
- }
718
- else if (startsWithAnchor && !endsWithAnchor) {
719
- // Starts with anchor only
720
- return `${result}%`;
721
- }
722
- else if (!startsWithAnchor && endsWithAnchor) {
723
- // Ends with anchor only
724
- return `%${result}`;
725
- }
726
- else {
727
- // Both anchors: exact match
728
- return result;
729
- }
730
- }
731
- /**
732
- * Translate conditions inside $elemMatch
733
- * This handles document conditions like { field: value, field: { $op: value } }
734
- * SECURITY: Validates field names to prevent SQL injection attacks.
735
- */
736
- translateElemMatchConditions(conditions, params) {
737
- const sqlParts = [];
738
- for (const [field, value] of Object.entries(conditions)) {
739
- // Validate field name to prevent SQL injection
740
- validateFieldPath(field);
741
- // In elemMatch, 'value' refers to the current array element from json_each
742
- // For nested fields, we use json_extract(value, '$.field')
743
- const extractPath = `json_extract(value, '$.${field}')`;
744
- if (value === null || typeof value !== 'object' || Array.isArray(value)) {
745
- // Direct value comparison
746
- if (value === null) {
747
- sqlParts.push(`${extractPath} IS NULL`);
748
- }
749
- else {
750
- params.push(value);
751
- sqlParts.push(`${extractPath} = ?`);
752
- }
753
- }
754
- else {
755
- // Object with operators
756
- const operators = value;
757
- const opKeys = Object.keys(operators);
758
- if (opKeys.length > 0 && opKeys.every(k => k.startsWith('$'))) {
759
- // It's operators like { $gte: 90 }
760
- for (const [op, opValue] of Object.entries(operators)) {
761
- const opSql = this.translateElemMatchOperator(extractPath, op, opValue, params);
762
- sqlParts.push(opSql);
763
- }
764
- }
765
- else {
766
- // Plain object equality
767
- params.push(JSON.stringify(value));
768
- sqlParts.push(`${extractPath} = json(?)`);
769
- }
770
- }
771
- }
772
- if (sqlParts.length === 0) {
773
- return '1 = 1';
774
- }
775
- return sqlParts.length === 1 ? sqlParts[0] : `(${sqlParts.join(' AND ')})`;
776
- }
777
- /**
778
- * Translate a single operator for elemMatch context
779
- */
780
- translateElemMatchOperator(path, op, value, params) {
781
- switch (op) {
782
- case '$eq': {
783
- if (value === null) {
784
- return `${path} IS NULL`;
785
- }
786
- // SQLite's json_extract returns 1/0 for booleans, so convert JS booleans
787
- const eqValue = typeof value === 'boolean' ? (value ? 1 : 0) : value;
788
- params.push(eqValue);
789
- return `${path} = ?`;
790
- }
791
- case '$ne': {
792
- if (value === null) {
793
- return `${path} IS NOT NULL`;
794
- }
795
- // SQLite's json_extract returns 1/0 for booleans, so convert JS booleans
796
- const neValue = typeof value === 'boolean' ? (value ? 1 : 0) : value;
797
- params.push(neValue);
798
- return `${path} != ?`;
799
- }
800
- case '$gt':
801
- params.push(value);
802
- return `${path} > ?`;
803
- case '$gte':
804
- params.push(value);
805
- return `${path} >= ?`;
806
- case '$lt':
807
- params.push(value);
808
- return `${path} < ?`;
809
- case '$lte':
810
- params.push(value);
811
- return `${path} <= ?`;
812
- case '$in': {
813
- const arr = value;
814
- if (arr.length === 0)
815
- return '0 = 1';
816
- params.push(...arr);
817
- return `${path} IN (${arr.map(() => '?').join(', ')})`;
818
- }
819
- case '$nin': {
820
- const arr = value;
821
- if (arr.length === 0)
822
- return '1 = 1';
823
- params.push(...arr);
824
- return `${path} NOT IN (${arr.map(() => '?').join(', ')})`;
825
- }
826
- case '$exists':
827
- // Use json_type to distinguish between null values and missing fields
828
- return value ? `json_type(${path}) IS NOT NULL` : `json_type(${path}) IS NULL`;
829
- case '$regex': {
830
- // Handle $regex in elemMatch context
831
- let pattern;
832
- let options = '';
833
- if (typeof value === 'string') {
834
- pattern = value;
835
- }
836
- else if (value instanceof RegExp) {
837
- pattern = value.source;
838
- options = value.flags;
839
- }
840
- else if (value && typeof value === 'object') {
841
- const regexObj = value;
842
- pattern = regexObj.$regex || '';
843
- options = regexObj.$options || '';
844
- }
845
- else {
846
- pattern = String(value);
847
- }
848
- const likePattern = this.regexToLike(pattern, options);
849
- params.push(likePattern);
850
- // Add type check to ensure we only match string values
851
- const typeCheck = `json_type(${path}) = 'text'`;
852
- if (options.includes('i')) {
853
- return `(${typeCheck} AND LOWER(${path}) LIKE LOWER(?))`;
854
- }
855
- return `(${typeCheck} AND ${path} LIKE ?)`;
856
- }
857
- case '$mod': {
858
- // Handle $mod in elemMatch context
859
- const [divisor, remainder] = value;
860
- params.push(divisor, remainder);
861
- return `(json_type(${path}) IN ('integer', 'real') AND CAST(${path} AS INTEGER) % ? = ?)`;
862
- }
863
- default:
864
- throw new Error(`Unsupported operator in $elemMatch: ${op}`);
865
- }
866
- }
867
- /**
868
- * Generate optimized SQL with CTE for multiple array operations on the same field
869
- * This is useful when you have multiple $all checks or $elemMatch on the same array
870
- *
871
- * Example output:
872
- * WITH array_cte AS (
873
- * SELECT value FROM json_each(json_extract(data, '$.tags'))
874
- * )
875
- * SELECT * FROM documents WHERE
876
- * EXISTS (SELECT 1 FROM array_cte WHERE value = ?) AND
877
- * EXISTS (SELECT 1 FROM array_cte WHERE value = ?)
878
- */
879
- translateWithCTE(query, tableName = 'documents') {
880
- const params = [];
881
- if (Object.keys(query).length === 0) {
882
- return { sql: `SELECT * FROM ${tableName}`, params: [] };
883
- }
884
- // Collect all array fields that have multiple operations
885
- const arrayFieldOps = this.collectArrayOperations(query);
886
- const cteDefinitions = [];
887
- const cteAliases = new Map();
888
- let cteIndex = 0;
889
- // Create CTEs for fields with multiple array operations
890
- for (const [field, count] of arrayFieldOps.entries()) {
891
- if (count > 1) {
892
- const alias = `arr_cte_${cteIndex++}`;
893
- const path = this.fieldToJsonPath(field);
894
- cteDefinitions.push(`${alias} AS (SELECT value FROM json_each(json_extract(data, '${path}')))`);
895
- cteAliases.set(field, alias);
896
- }
897
- }
898
- // Translate the query, replacing repeated json_each with CTE references
899
- const whereClause = this.translateDocumentWithCTE(query, params, cteAliases);
900
- let sql;
901
- if (cteDefinitions.length > 0) {
902
- sql = `WITH ${cteDefinitions.join(', ')} SELECT * FROM ${tableName} WHERE ${whereClause}`;
903
- }
904
- else {
905
- sql = `SELECT * FROM ${tableName} WHERE ${whereClause}`;
906
- }
907
- return { sql, params };
908
- }
909
- /**
910
- * Collect array operations for CTE optimization analysis
911
- */
912
- collectArrayOperations(query, counts = new Map()) {
913
- for (const [key, value] of Object.entries(query)) {
914
- if (key === '$and' || key === '$or' || key === '$nor') {
915
- const conditions = value;
916
- for (const condition of conditions) {
917
- this.collectArrayOperations(condition, counts);
918
- }
919
- }
920
- else if (!key.startsWith('$') && value && typeof value === 'object') {
921
- const operators = value;
922
- for (const op of Object.keys(operators)) {
923
- if (op === '$all' || op === '$elemMatch') {
924
- counts.set(key, (counts.get(key) || 0) + 1);
925
- }
926
- }
927
- }
928
- }
929
- return counts;
930
- }
931
- /**
932
- * Translate document using CTE aliases where applicable
933
- */
934
- translateDocumentWithCTE(query, params, _cteAliases) {
935
- // For now, fall back to standard translation
936
- // CTE optimization would replace json_each references with CTE aliases
937
- // This is a placeholder for full CTE implementation
938
- return this.translateDocument(query, params);
939
- }
940
- /**
941
- * Register a custom comparison operator
942
- * Allows extending the translator with custom operators
943
- */
944
- registerOperator(name, handler) {
945
- if (!name.startsWith('$')) {
946
- throw new Error('Operator name must start with $');
947
- }
948
- this.comparisonOperators[name] = handler;
949
- }
950
- /**
951
- * Register a custom element operator
952
- */
953
- registerElementOperator(name, handler) {
954
- if (!name.startsWith('$')) {
955
- throw new Error('Operator name must start with $');
956
- }
957
- this.elementOperators[name] = handler;
958
- }
959
- /**
960
- * Register a custom array operator
961
- */
962
- registerArrayOperator(name, handler) {
963
- if (!name.startsWith('$')) {
964
- throw new Error('Operator name must start with $');
965
- }
966
- this.arrayOperators[name] = handler;
967
- }
968
- /**
969
- * Translate a MongoDB $text query to FTS5 MATCH SQL
970
- */
971
- translateTextOperator(textOp, params) {
972
- const search = textOp.$search;
973
- const caseSensitive = textOp.$caseSensitive;
974
- const diacriticSensitive = textOp.$diacriticSensitive;
975
- // Handle empty search string
976
- if (!search || search.trim() === '') {
977
- return { sql: '0 = 1', ftsMatch: '' };
978
- }
979
- // Convert MongoDB text search syntax to FTS5 syntax
980
- const ftsQuery = this.convertToFTS5Query(search, caseSensitive, diacriticSensitive);
981
- params.push(ftsQuery);
982
- // Generate the FTS5 MATCH condition
983
- // This will be joined with the main documents table using rowid
984
- const sql = `id IN (SELECT rowid FROM {{FTS_TABLE}} WHERE {{FTS_TABLE}} MATCH ?)`;
985
- return { sql, ftsMatch: ftsQuery };
986
- }
987
- /**
988
- * Convert MongoDB text search syntax to FTS5 query syntax
989
- *
990
- * MongoDB syntax:
991
- * - "word" -> matches word
992
- * - "word1 word2" -> matches word1 OR word2
993
- * - "\"phrase\"" -> matches exact phrase
994
- * - "-word" -> excludes word (negation)
995
- *
996
- * FTS5 syntax:
997
- * - "word" -> matches word
998
- * - "word1 OR word2" -> matches word1 or word2
999
- * - "word1 word2" -> matches word1 AND word2
1000
- * - "\"phrase\"" -> matches exact phrase
1001
- * - "NOT word" -> excludes word
1002
- */
1003
- convertToFTS5Query(search, _caseSensitive, _diacriticSensitive) {
1004
- // Escape special FTS5 characters except quotes and minus
1005
- const escaped = search.replace(/[&|()^~*:]/g, (char) => {
1006
- return '\\' + char;
1007
- });
1008
- const tokens = [];
1009
- let remaining = escaped.trim();
1010
- // Parse the search string for phrases and terms
1011
- while (remaining.length > 0) {
1012
- remaining = remaining.trim();
1013
- // Check for quoted phrase
1014
- if (remaining.startsWith('"')) {
1015
- const endQuote = remaining.indexOf('"', 1);
1016
- if (endQuote > 1) {
1017
- const phrase = remaining.slice(1, endQuote);
1018
- tokens.push(`"${phrase}"`);
1019
- remaining = remaining.slice(endQuote + 1);
1020
- continue;
1021
- }
1022
- }
1023
- // Check for negation
1024
- if (remaining.startsWith('-')) {
1025
- const spaceIdx = remaining.indexOf(' ');
1026
- const term = spaceIdx > 0 ? remaining.slice(1, spaceIdx) : remaining.slice(1);
1027
- if (term) {
1028
- tokens.push(`NOT ${term}`);
1029
- }
1030
- remaining = spaceIdx > 0 ? remaining.slice(spaceIdx + 1) : '';
1031
- continue;
1032
- }
1033
- // Regular term
1034
- const spaceIdx = remaining.indexOf(' ');
1035
- const term = spaceIdx > 0 ? remaining.slice(0, spaceIdx) : remaining;
1036
- if (term) {
1037
- tokens.push(term);
1038
- }
1039
- remaining = spaceIdx > 0 ? remaining.slice(spaceIdx + 1) : '';
1040
- }
1041
- // Join tokens - MongoDB uses OR by default for multiple terms
1042
- // FTS5 uses AND by default, so we explicitly use OR
1043
- if (tokens.length === 0) {
1044
- return '*'; // Match all if no valid tokens
1045
- }
1046
- // Separate NOT terms from regular terms
1047
- const notTerms = tokens.filter(t => t.startsWith('NOT '));
1048
- const regularTerms = tokens.filter(t => !t.startsWith('NOT '));
1049
- let query = '';
1050
- if (regularTerms.length > 0) {
1051
- // Use OR for regular terms (MongoDB default behavior)
1052
- query = regularTerms.join(' OR ');
1053
- }
1054
- // Add NOT terms with AND
1055
- if (notTerms.length > 0) {
1056
- if (query) {
1057
- query = `(${query}) AND ${notTerms.join(' AND ')}`;
1058
- }
1059
- else {
1060
- // Only negations - need a base to negate from
1061
- query = `* AND ${notTerms.join(' AND ')}`;
1062
- }
1063
- }
1064
- return query;
1065
- }
1066
- /**
1067
- * Translate a query with $meta projection support for textScore
1068
- *
1069
- * @param query The MongoDB query (must contain $text for textScore)
1070
- * @param projection The projection with potential {$meta: "textScore"} fields
1071
- * @param sort Optional sort with potential {$meta: "textScore"} fields
1072
- */
1073
- translateWithMeta(query, projection, sort) {
1074
- const params = [];
1075
- // Check if query has $text
1076
- const hasText = '$text' in query;
1077
- if (!hasText) {
1078
- // No text search, fall back to regular translation
1079
- const baseResult = this.translate(query);
1080
- return baseResult;
1081
- }
1082
- // Extract $text operator
1083
- const textOp = query.$text;
1084
- const { sql: textSql, ftsMatch } = this.translateTextOperator(textOp, params);
1085
- // Process remaining query conditions
1086
- const remainingQuery = {};
1087
- for (const [key, value] of Object.entries(query)) {
1088
- if (key !== '$text') {
1089
- remainingQuery[key] = value;
1090
- }
1091
- }
1092
- let whereClause = textSql;
1093
- if (Object.keys(remainingQuery).length > 0) {
1094
- const remainingResult = this.translateDocument(remainingQuery, params);
1095
- whereClause = `(${textSql}) AND (${remainingResult})`;
1096
- }
1097
- // Build SELECT clause with textScore if projected
1098
- let selectClause = '*';
1099
- const hasTextScoreProjection = projection && Object.values(projection).some(v => v && typeof v === 'object' && v.$meta === 'textScore');
1100
- if (hasTextScoreProjection) {
1101
- // FTS5 uses bm25() for relevance ranking
1102
- // bm25() returns negative values (more negative = more relevant)
1103
- // We negate it to get positive scores where higher = more relevant
1104
- selectClause = '*, -bm25({{FTS_TABLE}}) as rank';
1105
- }
1106
- // Build ORDER BY clause
1107
- let orderByClause = '';
1108
- if (sort) {
1109
- const hasTextScoreSort = Object.values(sort).some(v => v && typeof v === 'object' && v.$meta === 'textScore');
1110
- if (hasTextScoreSort) {
1111
- // Sort by rank (descending by default for textScore)
1112
- orderByClause = ' ORDER BY rank DESC';
1113
- }
1114
- }
1115
- return {
1116
- sql: `SELECT ${selectClause} WHERE ${whereClause}${orderByClause}`,
1117
- params,
1118
- requiresFTS: true,
1119
- ftsMatch,
1120
- };
1121
- }
1122
- /**
1123
- * Translate a JSON Schema to SQL conditions
1124
- * Supports common JSON Schema validation keywords
1125
- *
1126
- * @param schema The JSON Schema to validate against
1127
- * @param path The current JSON path (e.g., "$.field.nested")
1128
- * @param params The parameters array to push values to
1129
- */
1130
- translateJsonSchema(schema, path, params) {
1131
- const conditions = [];
1132
- const jsonPath = path === '$' ? 'data' : `json_extract(data, '${path}')`;
1133
- const typeExpr = path === '$'
1134
- ? 'json_type(data)'
1135
- : dialectJsonType(this.dialect, 'data', path);
1136
- // Handle type/bsonType constraint
1137
- const schemaType = schema.type || schema.bsonType;
1138
- if (schemaType) {
1139
- const types = Array.isArray(schemaType) ? schemaType : [schemaType];
1140
- const typeConditions = types.map(t => {
1141
- const sqlType = MONGO_TYPE_TO_SQLITE[t];
1142
- if (Array.isArray(sqlType)) {
1143
- return `${typeExpr} IN (${sqlType.map(st => `'${st}'`).join(', ')})`;
1144
- }
1145
- return `${typeExpr} = '${sqlType || t}'`;
1146
- });
1147
- if (typeConditions.length === 1) {
1148
- conditions.push(typeConditions[0]);
1149
- }
1150
- else {
1151
- conditions.push(`(${typeConditions.join(' OR ')})`);
1152
- }
1153
- }
1154
- // Handle required fields
1155
- if (schema.required && schema.required.length > 0) {
1156
- for (const field of schema.required) {
1157
- validateFieldPath(field);
1158
- const fieldPath = path === '$' ? `$.${field}` : `${path}.${field}`;
1159
- const existsExpr = dialectJsonTypeWithPath(this.dialect, 'data', fieldPath);
1160
- conditions.push(`${existsExpr} IS NOT NULL`);
1161
- }
1162
- }
1163
- // Handle properties
1164
- if (schema.properties) {
1165
- for (const [field, propSchema] of Object.entries(schema.properties)) {
1166
- validateFieldPath(field);
1167
- const fieldPath = path === '$' ? `$.${field}` : `${path}.${field}`;
1168
- const existsExpr = dialectJsonTypeWithPath(this.dialect, 'data', fieldPath);
1169
- // Property validation only applies if the field exists
1170
- const propCondition = this.translateJsonSchema(propSchema, fieldPath, params);
1171
- if (propCondition !== '1 = 1') {
1172
- conditions.push(`(${existsExpr} IS NULL OR ${propCondition})`);
1173
- }
1174
- }
1175
- }
1176
- // Handle enum constraint
1177
- if (schema.enum && schema.enum.length > 0) {
1178
- const enumValues = schema.enum.map(v => {
1179
- if (v === null)
1180
- return 'NULL';
1181
- params.push(typeof v === 'object' ? JSON.stringify(v) : v);
1182
- return '?';
1183
- });
1184
- const nullIncluded = schema.enum.includes(null);
1185
- const nonNullValues = enumValues.filter(v => v !== 'NULL');
1186
- if (nullIncluded && nonNullValues.length > 0) {
1187
- conditions.push(`(${jsonPath} IS NULL OR ${jsonPath} IN (${nonNullValues.join(', ')}))`);
1188
- }
1189
- else if (nullIncluded) {
1190
- conditions.push(`${jsonPath} IS NULL`);
1191
- }
1192
- else {
1193
- conditions.push(`${jsonPath} IN (${enumValues.join(', ')})`);
1194
- }
1195
- }
1196
- // Handle minimum/maximum for numbers
1197
- if (schema.minimum !== undefined) {
1198
- params.push(schema.minimum);
1199
- conditions.push(`${jsonPath} >= ?`);
1200
- }
1201
- if (schema.maximum !== undefined) {
1202
- params.push(schema.maximum);
1203
- conditions.push(`${jsonPath} <= ?`);
1204
- }
1205
- if (schema.exclusiveMinimum !== undefined) {
1206
- const val = typeof schema.exclusiveMinimum === 'boolean' ? schema.minimum : schema.exclusiveMinimum;
1207
- if (val !== undefined) {
1208
- params.push(val);
1209
- conditions.push(`${jsonPath} > ?`);
1210
- }
1211
- }
1212
- if (schema.exclusiveMaximum !== undefined) {
1213
- const val = typeof schema.exclusiveMaximum === 'boolean' ? schema.maximum : schema.exclusiveMaximum;
1214
- if (val !== undefined) {
1215
- params.push(val);
1216
- conditions.push(`${jsonPath} < ?`);
1217
- }
1218
- }
1219
- // Handle minLength/maxLength for strings
1220
- if (schema.minLength !== undefined) {
1221
- params.push(schema.minLength);
1222
- conditions.push(`LENGTH(${jsonPath}) >= ?`);
1223
- }
1224
- if (schema.maxLength !== undefined) {
1225
- params.push(schema.maxLength);
1226
- conditions.push(`LENGTH(${jsonPath}) <= ?`);
1227
- }
1228
- // Handle pattern for strings
1229
- if (schema.pattern) {
1230
- const likePattern = this.regexToLike(schema.pattern);
1231
- params.push(likePattern);
1232
- conditions.push(`${jsonPath} LIKE ?`);
1233
- }
1234
- // Handle minItems/maxItems for arrays
1235
- if (schema.minItems !== undefined) {
1236
- params.push(schema.minItems);
1237
- const lenExpr = dialectJsonArrayLength(this.dialect, 'data', path);
1238
- conditions.push(`${lenExpr} >= ?`);
1239
- }
1240
- if (schema.maxItems !== undefined) {
1241
- params.push(schema.maxItems);
1242
- const lenExpr = dialectJsonArrayLength(this.dialect, 'data', path);
1243
- conditions.push(`${lenExpr} <= ?`);
1244
- }
1245
- // Handle allOf - all schemas must match
1246
- if (schema.allOf && schema.allOf.length > 0) {
1247
- const allOfConditions = schema.allOf.map(s => this.translateJsonSchema(s, path, params));
1248
- conditions.push(`(${allOfConditions.join(' AND ')})`);
1249
- }
1250
- // Handle anyOf - at least one schema must match
1251
- if (schema.anyOf && schema.anyOf.length > 0) {
1252
- const anyOfConditions = schema.anyOf.map(s => this.translateJsonSchema(s, path, params));
1253
- conditions.push(`(${anyOfConditions.join(' OR ')})`);
1254
- }
1255
- // Handle oneOf - exactly one schema must match (approximated with OR for SQL)
1256
- if (schema.oneOf && schema.oneOf.length > 0) {
1257
- // Note: True oneOf validation (exactly one match) is complex in SQL
1258
- // We approximate with anyOf behavior since exact oneOf requires counting matches
1259
- const oneOfConditions = schema.oneOf.map(s => this.translateJsonSchema(s, path, params));
1260
- conditions.push(`(${oneOfConditions.join(' OR ')})`);
1261
- }
1262
- // Handle not - schema must not match
1263
- if (schema.not) {
1264
- const notCondition = this.translateJsonSchema(schema.not, path, params);
1265
- conditions.push(`NOT (${notCondition})`);
1266
- }
1267
- if (conditions.length === 0) {
1268
- return '1 = 1';
1269
- }
1270
- if (conditions.length === 1) {
1271
- return conditions[0];
1272
- }
1273
- return `(${conditions.join(' AND ')})`;
1274
- }
1275
- }
1276
- //# sourceMappingURL=query-translator.js.map