@uql/core 1.0.12 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (464) hide show
  1. package/CHANGELOG.md +254 -0
  2. package/LICENSE.md +2 -2
  3. package/dist/browser/http/bus.d.ts +3 -0
  4. package/dist/browser/http/bus.js +14 -0
  5. package/dist/browser/http/http.d.ts +6 -0
  6. package/dist/browser/http/http.js +45 -0
  7. package/dist/browser/http/index.d.ts +2 -0
  8. package/dist/browser/http/index.js +3 -0
  9. package/dist/browser/index.d.ts +4 -0
  10. package/dist/browser/index.js +5 -0
  11. package/dist/browser/options.d.ts +4 -0
  12. package/dist/browser/options.js +14 -0
  13. package/dist/browser/querier/genericClientRepository.d.ts +17 -0
  14. package/dist/browser/querier/genericClientRepository.js +39 -0
  15. package/dist/browser/querier/httpQuerier.d.ts +20 -0
  16. package/dist/browser/querier/httpQuerier.js +71 -0
  17. package/dist/browser/querier/index.d.ts +3 -0
  18. package/dist/browser/querier/index.js +4 -0
  19. package/dist/browser/querier/querier.util.d.ts +2 -0
  20. package/dist/browser/querier/querier.util.js +17 -0
  21. package/dist/browser/type/clientQuerier.d.ts +16 -0
  22. package/dist/browser/type/clientQuerier.js +2 -0
  23. package/dist/browser/type/clientQuerierPool.d.ts +4 -0
  24. package/dist/browser/type/clientQuerierPool.js +2 -0
  25. package/dist/browser/type/clientRepository.d.ts +13 -0
  26. package/dist/browser/type/clientRepository.js +2 -0
  27. package/dist/browser/type/index.d.ts +4 -0
  28. package/dist/browser/type/index.js +5 -0
  29. package/dist/browser/type/request.d.ts +28 -0
  30. package/dist/browser/type/request.js +2 -0
  31. package/dist/browser/uql-browser.min.js +2150 -0
  32. package/dist/browser/uql-browser.min.js.map +1 -0
  33. package/dist/dialect/abstractDialect.d.ts +16 -0
  34. package/dist/dialect/abstractDialect.js +28 -0
  35. package/dist/dialect/abstractSqlDialect.d.ts +47 -0
  36. package/dist/dialect/abstractSqlDialect.js +650 -0
  37. package/dist/dialect/index.d.ts +3 -0
  38. package/dist/dialect/index.js +4 -0
  39. package/dist/dialect/queryContext.d.ts +48 -0
  40. package/dist/dialect/queryContext.js +65 -0
  41. package/{entity → dist/entity}/decorator/definition.d.ts +3 -3
  42. package/dist/entity/decorator/definition.js +214 -0
  43. package/{entity → dist/entity}/decorator/entity.d.ts +1 -1
  44. package/dist/entity/decorator/entity.js +7 -0
  45. package/{entity → dist/entity}/decorator/field.d.ts +1 -1
  46. package/dist/entity/decorator/field.js +8 -0
  47. package/{entity → dist/entity}/decorator/id.d.ts +1 -1
  48. package/dist/entity/decorator/id.js +8 -0
  49. package/dist/entity/decorator/index.d.ts +5 -0
  50. package/dist/entity/decorator/index.js +6 -0
  51. package/{entity → dist/entity}/decorator/relation.d.ts +1 -1
  52. package/dist/entity/decorator/relation.js +20 -0
  53. package/dist/entity/index.d.ts +1 -0
  54. package/dist/entity/index.js +2 -0
  55. package/dist/express/index.d.ts +2 -0
  56. package/dist/express/index.js +3 -0
  57. package/dist/express/querierMiddleware.d.ts +26 -0
  58. package/dist/express/querierMiddleware.js +190 -0
  59. package/dist/express/query.util.d.ts +2 -0
  60. package/dist/express/query.util.js +19 -0
  61. package/dist/index.d.ts +9 -0
  62. package/dist/index.js +10 -0
  63. package/dist/maria/index.d.ts +3 -0
  64. package/dist/maria/index.js +4 -0
  65. package/dist/maria/mariaDialect.d.ts +8 -0
  66. package/dist/maria/mariaDialect.js +38 -0
  67. package/dist/maria/mariaQuerierPool.test.d.ts +5 -0
  68. package/dist/maria/mariaQuerierPool.test.js +19 -0
  69. package/dist/maria/mariadbQuerier.d.ts +17 -0
  70. package/dist/maria/mariadbQuerier.js +39 -0
  71. package/dist/maria/mariadbQuerier.test.d.ts +4 -0
  72. package/dist/maria/mariadbQuerier.test.js +19 -0
  73. package/dist/maria/mariadbQuerierPool.d.ts +10 -0
  74. package/dist/maria/mariadbQuerierPool.js +17 -0
  75. package/dist/migrate/cli.d.ts +2 -0
  76. package/dist/migrate/cli.js +254 -0
  77. package/dist/migrate/generator/index.d.ts +4 -0
  78. package/dist/migrate/generator/index.js +5 -0
  79. package/dist/migrate/generator/mongoSchemaGenerator.d.ts +12 -0
  80. package/dist/migrate/generator/mongoSchemaGenerator.js +100 -0
  81. package/dist/migrate/generator/mysqlSchemaGenerator.d.ts +14 -0
  82. package/dist/migrate/generator/mysqlSchemaGenerator.js +81 -0
  83. package/dist/migrate/generator/postgresSchemaGenerator.d.ts +18 -0
  84. package/dist/migrate/generator/postgresSchemaGenerator.js +111 -0
  85. package/dist/migrate/generator/sqliteSchemaGenerator.d.ts +14 -0
  86. package/dist/migrate/generator/sqliteSchemaGenerator.js +68 -0
  87. package/dist/migrate/index.d.ts +12 -0
  88. package/dist/migrate/index.js +17 -0
  89. package/dist/migrate/introspection/index.d.ts +4 -0
  90. package/dist/migrate/introspection/index.js +5 -0
  91. package/dist/migrate/introspection/mongoIntrospector.d.ts +8 -0
  92. package/dist/migrate/introspection/mongoIntrospector.js +46 -0
  93. package/dist/migrate/introspection/mysqlIntrospector.d.ts +25 -0
  94. package/dist/migrate/introspection/mysqlIntrospector.js +220 -0
  95. package/dist/migrate/introspection/postgresIntrospector.d.ts +21 -0
  96. package/dist/migrate/introspection/postgresIntrospector.js +269 -0
  97. package/dist/migrate/introspection/sqliteIntrospector.d.ts +23 -0
  98. package/dist/migrate/introspection/sqliteIntrospector.js +212 -0
  99. package/dist/migrate/migrator-mongo.test.d.ts +1 -0
  100. package/dist/migrate/migrator-mongo.test.js +54 -0
  101. package/dist/migrate/migrator.d.ts +133 -0
  102. package/dist/migrate/migrator.js +600 -0
  103. package/dist/migrate/migrator.test.d.ts +1 -0
  104. package/dist/migrate/migrator.test.js +106 -0
  105. package/dist/migrate/schemaGenerator.d.ts +78 -0
  106. package/dist/migrate/schemaGenerator.js +363 -0
  107. package/dist/migrate/storage/databaseStorage.d.ts +24 -0
  108. package/dist/migrate/storage/databaseStorage.js +77 -0
  109. package/dist/migrate/storage/index.d.ts +2 -0
  110. package/dist/migrate/storage/index.js +3 -0
  111. package/dist/migrate/storage/jsonStorage.d.ts +15 -0
  112. package/dist/migrate/storage/jsonStorage.js +51 -0
  113. package/dist/migrate/type.d.ts +1 -0
  114. package/dist/migrate/type.js +2 -0
  115. package/dist/mongo/index.d.ts +3 -0
  116. package/dist/mongo/index.js +4 -0
  117. package/dist/mongo/mongoDialect.d.ts +34 -0
  118. package/dist/mongo/mongoDialect.js +163 -0
  119. package/dist/mongo/mongodbQuerier.d.ts +28 -0
  120. package/dist/mongo/mongodbQuerier.js +204 -0
  121. package/dist/mongo/mongodbQuerier.test.d.ts +1 -0
  122. package/dist/mongo/mongodbQuerier.test.js +36 -0
  123. package/dist/mongo/mongodbQuerierPool.d.ts +10 -0
  124. package/dist/mongo/mongodbQuerierPool.js +20 -0
  125. package/dist/mongo/mongodbQuerierPool.test.d.ts +1 -0
  126. package/dist/mongo/mongodbQuerierPool.test.js +21 -0
  127. package/dist/mysql/index.d.ts +3 -0
  128. package/dist/mysql/index.js +4 -0
  129. package/dist/mysql/mysql2Querier.d.ts +17 -0
  130. package/dist/mysql/mysql2Querier.js +43 -0
  131. package/dist/mysql/mysql2Querier.test.d.ts +4 -0
  132. package/dist/mysql/mysql2Querier.test.js +16 -0
  133. package/dist/mysql/mysql2QuerierPool.d.ts +10 -0
  134. package/dist/mysql/mysql2QuerierPool.js +17 -0
  135. package/dist/mysql/mysql2QuerierPool.test.d.ts +5 -0
  136. package/dist/mysql/mysql2QuerierPool.test.js +16 -0
  137. package/dist/mysql/mysqlDialect.d.ts +5 -0
  138. package/dist/mysql/mysqlDialect.js +15 -0
  139. package/dist/namingStrategy/defaultNamingStrategy.d.ts +9 -0
  140. package/dist/namingStrategy/defaultNamingStrategy.js +15 -0
  141. package/dist/namingStrategy/index.d.ts +2 -0
  142. package/dist/namingStrategy/index.js +3 -0
  143. package/dist/namingStrategy/snakeCaseNamingStrategy.d.ts +8 -0
  144. package/dist/namingStrategy/snakeCaseNamingStrategy.js +14 -0
  145. package/{options.d.ts → dist/options.d.ts} +1 -1
  146. package/dist/options.js +14 -0
  147. package/dist/package.json +131 -0
  148. package/dist/postgres/index.d.ts +3 -0
  149. package/dist/postgres/index.js +4 -0
  150. package/dist/postgres/pgQuerier.d.ts +17 -0
  151. package/dist/postgres/pgQuerier.js +39 -0
  152. package/dist/postgres/pgQuerier.test.d.ts +4 -0
  153. package/dist/postgres/pgQuerier.test.js +20 -0
  154. package/dist/postgres/pgQuerierPool.d.ts +10 -0
  155. package/dist/postgres/pgQuerierPool.js +17 -0
  156. package/dist/postgres/pgQuerierPool.test.d.ts +5 -0
  157. package/dist/postgres/pgQuerierPool.test.js +23 -0
  158. package/dist/postgres/postgresDialect.d.ts +13 -0
  159. package/dist/postgres/postgresDialect.js +110 -0
  160. package/dist/querier/abstractQuerier-test.d.ts +45 -0
  161. package/dist/querier/abstractQuerier-test.js +461 -0
  162. package/dist/querier/abstractQuerier.d.ts +50 -0
  163. package/dist/querier/abstractQuerier.js +278 -0
  164. package/dist/querier/abstractQuerierPool-test.d.ts +9 -0
  165. package/dist/querier/abstractQuerierPool-test.js +18 -0
  166. package/dist/querier/abstractQuerierPool.d.ts +14 -0
  167. package/dist/querier/abstractQuerierPool.js +9 -0
  168. package/dist/querier/abstractSqlQuerier-test.d.ts +9 -0
  169. package/dist/querier/abstractSqlQuerier-test.js +16 -0
  170. package/dist/querier/abstractSqlQuerier.d.ts +28 -0
  171. package/dist/querier/abstractSqlQuerier.js +133 -0
  172. package/dist/querier/decorator/index.d.ts +3 -0
  173. package/dist/querier/decorator/index.js +4 -0
  174. package/dist/querier/decorator/injectQuerier.d.ts +3 -0
  175. package/dist/querier/decorator/injectQuerier.js +33 -0
  176. package/dist/querier/decorator/serialized.d.ts +6 -0
  177. package/dist/querier/decorator/serialized.js +14 -0
  178. package/{querier → dist/querier}/decorator/transactional.d.ts +1 -1
  179. package/dist/querier/decorator/transactional.js +48 -0
  180. package/dist/querier/index.d.ts +4 -0
  181. package/dist/querier/index.js +5 -0
  182. package/dist/repository/genericRepository.d.ts +20 -0
  183. package/dist/repository/genericRepository.js +51 -0
  184. package/dist/repository/index.d.ts +1 -0
  185. package/dist/repository/index.js +2 -0
  186. package/dist/sqlite/index.d.ts +3 -0
  187. package/dist/sqlite/index.js +4 -0
  188. package/dist/sqlite/sqliteDialect.d.ts +10 -0
  189. package/dist/sqlite/sqliteDialect.js +48 -0
  190. package/dist/sqlite/sqliteQuerier.d.ts +15 -0
  191. package/dist/sqlite/sqliteQuerier.js +33 -0
  192. package/dist/sqlite/sqliteQuerier.test.d.ts +5 -0
  193. package/dist/sqlite/sqliteQuerier.test.js +19 -0
  194. package/dist/sqlite/sqliteQuerierPool.d.ts +14 -0
  195. package/dist/sqlite/sqliteQuerierPool.js +34 -0
  196. package/dist/sqlite/sqliteQuerierPool.test.d.ts +5 -0
  197. package/dist/sqlite/sqliteQuerierPool.test.js +10 -0
  198. package/dist/test/entityMock.d.ts +164 -0
  199. package/dist/test/entityMock.js +554 -0
  200. package/dist/test/index.d.ts +3 -0
  201. package/dist/test/index.js +4 -0
  202. package/dist/test/it.util.d.ts +4 -0
  203. package/dist/test/it.util.js +55 -0
  204. package/dist/test/spec.util.d.ts +14 -0
  205. package/dist/test/spec.util.js +50 -0
  206. package/{type → dist/type}/entity.d.ts +97 -4
  207. package/dist/type/entity.js +5 -0
  208. package/dist/type/index.d.ts +9 -0
  209. package/dist/type/index.js +10 -0
  210. package/dist/type/migration.d.ts +213 -0
  211. package/dist/type/migration.js +2 -0
  212. package/dist/type/namingStrategy.d.ts +17 -0
  213. package/dist/type/namingStrategy.js +2 -0
  214. package/dist/type/querier.d.ts +96 -0
  215. package/dist/type/querier.js +11 -0
  216. package/{type → dist/type}/querierPool.d.ts +7 -3
  217. package/dist/type/querierPool.js +2 -0
  218. package/{type → dist/type}/query.d.ts +170 -108
  219. package/dist/type/query.js +9 -0
  220. package/{type → dist/type}/repository.d.ts +42 -35
  221. package/dist/type/repository.js +2 -0
  222. package/{type → dist/type}/universalQuerier.d.ts +50 -28
  223. package/dist/type/universalQuerier.js +2 -0
  224. package/dist/type/utility.d.ts +13 -0
  225. package/dist/type/utility.js +2 -0
  226. package/dist/util/dialect.util.d.ts +12 -0
  227. package/dist/util/dialect.util.js +93 -0
  228. package/dist/util/index.d.ts +5 -0
  229. package/dist/util/index.js +6 -0
  230. package/dist/util/object.util.d.ts +7 -0
  231. package/dist/util/object.util.js +19 -0
  232. package/dist/util/raw.d.ts +8 -0
  233. package/dist/util/raw.js +11 -0
  234. package/dist/util/sql.util.d.ts +13 -0
  235. package/dist/util/sql.util.js +78 -0
  236. package/{util → dist/util}/string.util.d.ts +1 -0
  237. package/dist/util/string.util.js +34 -0
  238. package/package.json +85 -17
  239. package/src/@types/index.d.ts +1 -0
  240. package/src/@types/jest.d.ts +6 -0
  241. package/src/browser/http/bus.spec.ts +22 -0
  242. package/src/browser/http/bus.ts +17 -0
  243. package/src/browser/http/http.spec.ts +70 -0
  244. package/src/browser/http/http.ts +55 -0
  245. package/src/browser/http/index.ts +2 -0
  246. package/src/browser/index.ts +4 -0
  247. package/src/browser/options.spec.ts +37 -0
  248. package/src/browser/options.ts +18 -0
  249. package/src/browser/querier/genericClientRepository.spec.ts +105 -0
  250. package/src/browser/querier/genericClientRepository.ts +49 -0
  251. package/src/browser/querier/httpQuerier.ts +82 -0
  252. package/src/browser/querier/index.ts +3 -0
  253. package/src/browser/querier/querier.util.spec.ts +35 -0
  254. package/src/browser/querier/querier.util.ts +18 -0
  255. package/src/browser/type/clientQuerier.ts +45 -0
  256. package/src/browser/type/clientQuerierPool.ts +5 -0
  257. package/src/browser/type/clientRepository.ts +22 -0
  258. package/src/browser/type/index.ts +4 -0
  259. package/src/browser/type/request.ts +25 -0
  260. package/src/dialect/abstractDialect.ts +28 -0
  261. package/src/dialect/abstractSqlDialect-spec.ts +1309 -0
  262. package/src/dialect/abstractSqlDialect.ts +805 -0
  263. package/src/dialect/index.ts +3 -0
  264. package/src/dialect/namingStrategy.spec.ts +52 -0
  265. package/src/dialect/queryContext.ts +69 -0
  266. package/src/entity/decorator/definition.spec.ts +736 -0
  267. package/src/entity/decorator/definition.ts +265 -0
  268. package/src/entity/decorator/entity.ts +8 -0
  269. package/src/entity/decorator/field.ts +9 -0
  270. package/src/entity/decorator/id.ts +9 -0
  271. package/src/entity/decorator/index.ts +5 -0
  272. package/src/entity/decorator/relation.spec.ts +41 -0
  273. package/src/entity/decorator/relation.ts +34 -0
  274. package/src/entity/index.ts +1 -0
  275. package/src/express/@types/express.d.ts +8 -0
  276. package/src/express/@types/index.d.ts +1 -0
  277. package/src/express/index.ts +2 -0
  278. package/src/express/querierMiddleware.ts +217 -0
  279. package/src/express/query.util.spec.ts +40 -0
  280. package/src/express/query.util.ts +21 -0
  281. package/src/index.ts +9 -0
  282. package/src/maria/index.ts +3 -0
  283. package/src/maria/mariaDialect.spec.ts +207 -0
  284. package/src/maria/mariaDialect.ts +42 -0
  285. package/src/maria/mariaQuerierPool.test.ts +23 -0
  286. package/src/maria/mariadbQuerier.test.ts +23 -0
  287. package/src/maria/mariadbQuerier.ts +45 -0
  288. package/src/maria/mariadbQuerierPool.ts +21 -0
  289. package/src/migrate/cli.ts +301 -0
  290. package/src/migrate/generator/index.ts +4 -0
  291. package/src/migrate/generator/mongoSchemaGenerator.spec.ts +112 -0
  292. package/src/migrate/generator/mongoSchemaGenerator.ts +115 -0
  293. package/src/migrate/generator/mysqlSchemaGenerator.spec.ts +34 -0
  294. package/src/migrate/generator/mysqlSchemaGenerator.ts +92 -0
  295. package/src/migrate/generator/postgresSchemaGenerator.spec.ts +44 -0
  296. package/src/migrate/generator/postgresSchemaGenerator.ts +127 -0
  297. package/src/migrate/generator/sqliteSchemaGenerator.spec.ts +33 -0
  298. package/src/migrate/generator/sqliteSchemaGenerator.ts +81 -0
  299. package/src/migrate/index.ts +41 -0
  300. package/src/migrate/introspection/index.ts +4 -0
  301. package/src/migrate/introspection/mongoIntrospector.spec.ts +75 -0
  302. package/src/migrate/introspection/mongoIntrospector.ts +47 -0
  303. package/src/migrate/introspection/mysqlIntrospector.spec.ts +113 -0
  304. package/src/migrate/introspection/mysqlIntrospector.ts +278 -0
  305. package/src/migrate/introspection/postgresIntrospector.spec.ts +112 -0
  306. package/src/migrate/introspection/postgresIntrospector.ts +329 -0
  307. package/src/migrate/introspection/sqliteIntrospector.spec.ts +112 -0
  308. package/src/migrate/introspection/sqliteIntrospector.ts +296 -0
  309. package/src/migrate/migrator-mongo.test.ts +54 -0
  310. package/src/migrate/migrator.spec.ts +255 -0
  311. package/src/migrate/migrator.test.ts +94 -0
  312. package/src/migrate/migrator.ts +719 -0
  313. package/src/migrate/namingStrategy.spec.ts +22 -0
  314. package/src/migrate/schemaGenerator-advanced.spec.ts +138 -0
  315. package/src/migrate/schemaGenerator.spec.ts +190 -0
  316. package/src/migrate/schemaGenerator.ts +478 -0
  317. package/src/migrate/storage/databaseStorage.spec.ts +69 -0
  318. package/src/migrate/storage/databaseStorage.ts +100 -0
  319. package/src/migrate/storage/index.ts +2 -0
  320. package/src/migrate/storage/jsonStorage.ts +58 -0
  321. package/src/migrate/type.ts +1 -0
  322. package/src/mongo/index.ts +3 -0
  323. package/src/mongo/mongoDialect.spec.ts +251 -0
  324. package/src/mongo/mongoDialect.ts +238 -0
  325. package/src/mongo/mongodbQuerier.test.ts +45 -0
  326. package/src/mongo/mongodbQuerier.ts +256 -0
  327. package/src/mongo/mongodbQuerierPool.test.ts +25 -0
  328. package/src/mongo/mongodbQuerierPool.ts +24 -0
  329. package/src/mysql/index.ts +3 -0
  330. package/src/mysql/mysql2Querier.test.ts +20 -0
  331. package/src/mysql/mysql2Querier.ts +49 -0
  332. package/src/mysql/mysql2QuerierPool.test.ts +20 -0
  333. package/src/mysql/mysql2QuerierPool.ts +21 -0
  334. package/src/mysql/mysqlDialect.spec.ts +20 -0
  335. package/src/mysql/mysqlDialect.ts +16 -0
  336. package/src/namingStrategy/defaultNamingStrategy.ts +18 -0
  337. package/src/namingStrategy/index.spec.ts +36 -0
  338. package/src/namingStrategy/index.ts +2 -0
  339. package/src/namingStrategy/snakeCaseNamingStrategy.ts +15 -0
  340. package/src/options.spec.ts +41 -0
  341. package/src/options.ts +18 -0
  342. package/src/postgres/index.ts +3 -0
  343. package/src/postgres/manual-types.d.ts +4 -0
  344. package/src/postgres/pgQuerier.test.ts +25 -0
  345. package/src/postgres/pgQuerier.ts +45 -0
  346. package/src/postgres/pgQuerierPool.test.ts +28 -0
  347. package/src/postgres/pgQuerierPool.ts +21 -0
  348. package/src/postgres/postgresDialect.spec.ts +428 -0
  349. package/src/postgres/postgresDialect.ts +144 -0
  350. package/src/querier/abstractQuerier-test.ts +584 -0
  351. package/src/querier/abstractQuerier.ts +353 -0
  352. package/src/querier/abstractQuerierPool-test.ts +20 -0
  353. package/src/querier/abstractQuerierPool.ts +18 -0
  354. package/src/querier/abstractSqlQuerier-spec.ts +979 -0
  355. package/src/querier/abstractSqlQuerier-test.ts +21 -0
  356. package/src/querier/abstractSqlQuerier.ts +138 -0
  357. package/src/querier/decorator/index.ts +3 -0
  358. package/src/querier/decorator/injectQuerier.spec.ts +74 -0
  359. package/src/querier/decorator/injectQuerier.ts +45 -0
  360. package/src/querier/decorator/serialized.spec.ts +98 -0
  361. package/src/querier/decorator/serialized.ts +13 -0
  362. package/src/querier/decorator/transactional.spec.ts +240 -0
  363. package/src/querier/decorator/transactional.ts +56 -0
  364. package/src/querier/index.ts +4 -0
  365. package/src/repository/genericRepository.spec.ts +111 -0
  366. package/src/repository/genericRepository.ts +74 -0
  367. package/src/repository/index.ts +1 -0
  368. package/src/sqlite/index.ts +3 -0
  369. package/src/sqlite/manual-types.d.ts +4 -0
  370. package/src/sqlite/sqliteDialect.spec.ts +155 -0
  371. package/src/sqlite/sqliteDialect.ts +76 -0
  372. package/src/sqlite/sqliteQuerier.spec.ts +36 -0
  373. package/src/sqlite/sqliteQuerier.test.ts +21 -0
  374. package/src/sqlite/sqliteQuerier.ts +37 -0
  375. package/src/sqlite/sqliteQuerierPool.test.ts +12 -0
  376. package/src/sqlite/sqliteQuerierPool.ts +38 -0
  377. package/src/test/entityMock.ts +375 -0
  378. package/src/test/index.ts +3 -0
  379. package/src/test/it.util.ts +69 -0
  380. package/src/test/spec.util.ts +57 -0
  381. package/src/type/entity.ts +218 -0
  382. package/src/type/index.ts +9 -0
  383. package/src/type/migration.ts +241 -0
  384. package/src/type/namingStrategy.ts +17 -0
  385. package/src/type/querier.ts +143 -0
  386. package/src/type/querierPool.ts +26 -0
  387. package/src/type/query.ts +506 -0
  388. package/src/type/repository.ts +142 -0
  389. package/src/type/universalQuerier.ts +133 -0
  390. package/src/type/utility.ts +21 -0
  391. package/src/util/dialect.util-extra.spec.ts +96 -0
  392. package/src/util/dialect.util.spec.ts +23 -0
  393. package/src/util/dialect.util.ts +134 -0
  394. package/src/util/index.ts +5 -0
  395. package/src/util/object.util.spec.ts +29 -0
  396. package/src/util/object.util.ts +27 -0
  397. package/src/util/raw.ts +11 -0
  398. package/src/util/sql.util-extra.spec.ts +17 -0
  399. package/src/util/sql.util.spec.ts +208 -0
  400. package/src/util/sql.util.ts +104 -0
  401. package/src/util/string.util.spec.ts +46 -0
  402. package/src/util/string.util.ts +35 -0
  403. package/tsconfig.build.json +5 -0
  404. package/tsconfig.json +8 -0
  405. package/README.md +0 -177
  406. package/dialect/abstractSqlDialect.d.ts +0 -30
  407. package/dialect/abstractSqlDialect.js +0 -365
  408. package/dialect/index.d.ts +0 -4
  409. package/dialect/index.js +0 -8
  410. package/dialect/mysqlDialect.d.ts +0 -6
  411. package/dialect/mysqlDialect.js +0 -21
  412. package/dialect/postgresDialect.d.ts +0 -8
  413. package/dialect/postgresDialect.js +0 -44
  414. package/dialect/sqliteDialect.d.ts +0 -4
  415. package/dialect/sqliteDialect.js +0 -11
  416. package/entity/decorator/definition.js +0 -223
  417. package/entity/decorator/entity.js +0 -11
  418. package/entity/decorator/field.js +0 -12
  419. package/entity/decorator/id.js +0 -12
  420. package/entity/decorator/index.d.ts +0 -5
  421. package/entity/decorator/index.js +0 -12
  422. package/entity/decorator/relation.js +0 -27
  423. package/entity/index.d.ts +0 -1
  424. package/entity/index.js +0 -5
  425. package/index.d.ts +0 -1
  426. package/index.js +0 -5
  427. package/options.js +0 -20
  428. package/querier/abstractQuerier.d.ts +0 -30
  429. package/querier/abstractQuerier.js +0 -230
  430. package/querier/abstractSqlQuerier.d.ts +0 -27
  431. package/querier/abstractSqlQuerier.js +0 -88
  432. package/querier/decorator/index.d.ts +0 -2
  433. package/querier/decorator/index.js +0 -6
  434. package/querier/decorator/injectQuerier.d.ts +0 -3
  435. package/querier/decorator/injectQuerier.js +0 -39
  436. package/querier/decorator/transactional.js +0 -52
  437. package/querier/index.d.ts +0 -3
  438. package/querier/index.js +0 -7
  439. package/repository/genericRepository.d.ts +0 -19
  440. package/repository/genericRepository.js +0 -52
  441. package/repository/index.d.ts +0 -1
  442. package/repository/index.js +0 -5
  443. package/type/entity.js +0 -5
  444. package/type/index.d.ts +0 -7
  445. package/type/index.js +0 -11
  446. package/type/querier.d.ts +0 -53
  447. package/type/querier.js +0 -3
  448. package/type/querierPool.js +0 -3
  449. package/type/query.js +0 -13
  450. package/type/repository.js +0 -3
  451. package/type/universalQuerier.js +0 -3
  452. package/type/utility.d.ts +0 -12
  453. package/type/utility.js +0 -3
  454. package/util/dialect.util.d.ts +0 -17
  455. package/util/dialect.util.js +0 -114
  456. package/util/index.d.ts +0 -5
  457. package/util/index.js +0 -9
  458. package/util/object.util.d.ts +0 -3
  459. package/util/object.util.js +0 -22
  460. package/util/raw.d.ts +0 -2
  461. package/util/raw.js +0 -9
  462. package/util/sql.util.d.ts +0 -2
  463. package/util/sql.util.js +0 -55
  464. package/util/string.util.js +0 -20
@@ -0,0 +1,1309 @@
1
+ import { expect } from 'bun:test';
2
+ import {
3
+ Company,
4
+ InventoryAdjustment,
5
+ Item,
6
+ ItemAdjustment,
7
+ MeasureUnit,
8
+ Profile,
9
+ type Spec,
10
+ Tax,
11
+ TaxCategory,
12
+ User,
13
+ } from '../test/index.js';
14
+ import type { FieldKey, QueryContext } from '../type/index.js';
15
+ import { raw } from '../util/index.js';
16
+ import type { AbstractSqlDialect } from './abstractSqlDialect.js';
17
+
18
+ export abstract class AbstractSqlDialectSpec implements Spec {
19
+ constructor(readonly dialect: AbstractSqlDialect) {}
20
+
21
+ protected exec(fn: (ctx: QueryContext) => void): { sql: string; values: unknown[] } {
22
+ const ctx = this.dialect.createContext();
23
+ fn(ctx);
24
+ return { sql: ctx.sql, values: ctx.values };
25
+ }
26
+
27
+ shouldBeValidEscapeCharacter() {
28
+ expect(this.dialect.escapeIdChar).toBe('`');
29
+ }
30
+
31
+ shouldBeginTransaction() {
32
+ expect(this.dialect.beginTransactionCommand).toBe('START TRANSACTION');
33
+ }
34
+
35
+ shouldInsertMany() {
36
+ const { sql, values } = this.exec((ctx) =>
37
+ this.dialect.insert(ctx, User, [
38
+ {
39
+ name: 'Some name 1',
40
+ email: 'someemail1@example.com',
41
+ createdAt: 123,
42
+ },
43
+ {
44
+ name: 'Some name 2',
45
+ email: 'someemail2@example.com',
46
+ createdAt: 456,
47
+ },
48
+ {
49
+ name: 'Some name 3',
50
+ email: 'someemail3@example.com',
51
+ createdAt: 789,
52
+ },
53
+ ]),
54
+ );
55
+ expect(sql).toBe('INSERT INTO `User` (`name`, `email`, `createdAt`) VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?)');
56
+ expect(values).toEqual([
57
+ 'Some name 1',
58
+ 'someemail1@example.com',
59
+ 123,
60
+ 'Some name 2',
61
+ 'someemail2@example.com',
62
+ 456,
63
+ 'Some name 3',
64
+ 'someemail3@example.com',
65
+ 789,
66
+ ]);
67
+ }
68
+
69
+ shouldInsertOne() {
70
+ let res = this.exec((ctx) =>
71
+ this.dialect.insert(ctx, User, {
72
+ name: 'Some Name',
73
+ email: 'someemail@example.com',
74
+ createdAt: 123,
75
+ }),
76
+ );
77
+ expect(res.sql).toBe('INSERT INTO `User` (`name`, `email`, `createdAt`) VALUES (?, ?, ?)');
78
+ expect(res.values).toEqual(['Some Name', 'someemail@example.com', 123]);
79
+
80
+ res = this.exec((ctx) =>
81
+ this.dialect.insert(ctx, InventoryAdjustment, {
82
+ date: new Date(2021, 11, 31, 23, 59, 59, 999),
83
+ createdAt: 123,
84
+ }),
85
+ );
86
+ expect(res.sql).toBe('INSERT INTO `InventoryAdjustment` (`date`, `createdAt`) VALUES (?, ?)');
87
+ expect(res.values[0]).toBeInstanceOf(Date);
88
+ expect(res.values[1]).toBe(123);
89
+ }
90
+
91
+ shouldInsertWithOnInsertId() {
92
+ const { sql, values } = this.exec((ctx) =>
93
+ this.dialect.insert(ctx, TaxCategory, {
94
+ name: 'Some Name',
95
+ createdAt: 123,
96
+ }),
97
+ );
98
+ expect(sql).toMatch(/^INSERT INTO `TaxCategory` \(`name`, `createdAt`, `pk`\) VALUES \(\?, \?, \?\)$/);
99
+ expect(values[0]).toBe('Some Name');
100
+ expect(values[1]).toBe(123);
101
+ expect(values[2]).toMatch(/.+/);
102
+ }
103
+
104
+ shouldUpdateWithRawString() {
105
+ const { sql, values } = this.exec((ctx) =>
106
+ this.dialect.update(
107
+ ctx,
108
+ Company,
109
+ { $where: { id: 1 } },
110
+ {
111
+ kind: raw("'value'"),
112
+ updatedAt: 123,
113
+ },
114
+ ),
115
+ );
116
+ expect(sql).toBe("UPDATE `Company` SET `kind` = 'value', `updatedAt` = ? WHERE `id` = ?");
117
+ expect(values).toEqual([123, 1]);
118
+ }
119
+
120
+ shouldUpdateWithJsonbField() {
121
+ const { sql, values } = this.exec((ctx) =>
122
+ this.dialect.update(
123
+ ctx,
124
+ Company,
125
+ { $where: { id: 1 } },
126
+ {
127
+ kind: { private: 1 },
128
+ updatedAt: 123,
129
+ },
130
+ ),
131
+ );
132
+ expect(sql).toBe('UPDATE `Company` SET `kind` = ?, `updatedAt` = ? WHERE `id` = ?');
133
+ expect(values).toEqual(['{"private":1}', 123, 1]);
134
+ }
135
+
136
+ shouldInsertManyWithSpecifiedIdsAndOnInsertIdAsDefault() {
137
+ const { sql, values } = this.exec((ctx) =>
138
+ this.dialect.insert(ctx, TaxCategory, [
139
+ {
140
+ name: 'Some Name A',
141
+ },
142
+ {
143
+ pk: '50',
144
+ name: 'Some Name B',
145
+ },
146
+ {
147
+ name: 'Some Name C',
148
+ },
149
+ {
150
+ pk: '70',
151
+ name: 'Some Name D',
152
+ },
153
+ ]),
154
+ );
155
+ expect(sql).toMatch(
156
+ /^INSERT INTO `TaxCategory` \(`name`, `createdAt`, `pk`\) VALUES \(\?, \?, \?\), \(\?, \?, \?\), \(\?, \?, \?\), \(\?, \?, \?\)$/,
157
+ );
158
+ expect(values[0]).toBe('Some Name A');
159
+ expect(values[2]).toMatch(/.+/);
160
+ expect(values[3]).toBe('Some Name B');
161
+ expect(values[5]).toBe('50');
162
+ }
163
+
164
+ shouldUpsert() {
165
+ const { sql, values } = this.exec((ctx) =>
166
+ this.dialect.upsert(
167
+ ctx,
168
+ User,
169
+ { email: true },
170
+ {
171
+ name: 'Some Name',
172
+ email: 'someemail@example.com',
173
+ createdAt: 123,
174
+ },
175
+ ),
176
+ );
177
+ expect(sql).toMatch(
178
+ /^INSERT INTO `User` \(.*`name`.*`email`.*`createdAt`.*\) VALUES \(\?, \?, \?, \?\).+ON DUPLICATE KEY UPDATE .*`name` = VALUES\(`name`\).*`createdAt` = VALUES\(`createdAt`\).*`updatedAt` = VALUES\(`updatedAt`\).*$/,
179
+ );
180
+ expect(values).toEqual(['Some Name', 'someemail@example.com', 123, expect.any(Number)]);
181
+ }
182
+
183
+ shouldUpdate() {
184
+ const { sql, values } = this.exec((ctx) =>
185
+ this.dialect.update(
186
+ ctx,
187
+ User,
188
+ { $where: { name: 'some', creatorId: 123 } },
189
+ {
190
+ name: 'Some Text',
191
+ email: 'this field should not be updated',
192
+ updatedAt: 321,
193
+ },
194
+ ),
195
+ );
196
+ expect(sql).toBe('UPDATE `User` SET `name` = ?, `updatedAt` = ? WHERE `name` = ? AND `creatorId` = ?');
197
+ expect(values).toEqual(['Some Text', 321, 'some', 123]);
198
+ }
199
+
200
+ shouldUpdateWithAlias() {
201
+ const { sql, values } = this.exec((ctx) =>
202
+ this.dialect.update(
203
+ ctx,
204
+ Profile,
205
+ { $where: { pk: 123 } },
206
+ {
207
+ picture: 'a base64 image',
208
+ updatedAt: 321,
209
+ },
210
+ ),
211
+ );
212
+ expect(sql).toBe('UPDATE `user_profile` SET `image` = ?, `updatedAt` = ? WHERE `pk` = ?');
213
+ expect(values).toEqual(['a base64 image', 321, 123]);
214
+ }
215
+
216
+ shouldFind() {
217
+ let res = this.exec((ctx) =>
218
+ this.dialect.find(ctx, User, {
219
+ $select: ['id'],
220
+ $where: { id: 123, name: { $ne: 'abc' } },
221
+ }),
222
+ );
223
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `id` = ? AND `name` <> ?');
224
+ expect(res.values).toEqual([123, 'abc']);
225
+
226
+ res = this.exec((ctx) =>
227
+ this.dialect.find(ctx, Profile, {
228
+ $select: ['pk', 'picture', 'companyId'],
229
+ $where: { pk: 123, picture: 'abc' },
230
+ }),
231
+ );
232
+ expect(res.sql).toBe(
233
+ 'SELECT `pk`, `image` `picture`, `companyId` FROM `user_profile` WHERE `pk` = ? AND `image` = ?',
234
+ );
235
+ expect(res.values).toEqual([123, 'abc']);
236
+
237
+ res = this.exec((ctx) =>
238
+ this.dialect.find(ctx, MeasureUnit, {
239
+ $select: ['id'],
240
+ $where: { id: 123, name: 'abc' },
241
+ }),
242
+ );
243
+ expect(res.sql).toBe('SELECT `id` FROM `MeasureUnit` WHERE `id` = ? AND `name` = ? AND `deletedAt` IS NULL');
244
+ expect(res.values).toEqual([123, 'abc']);
245
+ }
246
+
247
+ shouldBeSecure() {
248
+ let res = this.exec((ctx) =>
249
+ this.dialect.find(ctx, User, {
250
+ $select: ['id', 'something' as FieldKey<User>],
251
+ $where: {
252
+ id: 1,
253
+ something: 1,
254
+ } as any,
255
+ $sort: {
256
+ id: 1,
257
+ something: 1,
258
+ } as any,
259
+ }),
260
+ );
261
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `id` = ? AND `something` = ? ORDER BY `id`, `something`');
262
+ expect(res.values).toEqual([1, 1]);
263
+
264
+ res = this.exec((ctx) =>
265
+ this.dialect.insert(ctx, User, {
266
+ name: 'Some Name',
267
+ something: 'anything',
268
+ createdAt: 1,
269
+ } as any),
270
+ );
271
+ expect(res.sql).toBe('INSERT INTO `User` (`name`, `createdAt`) VALUES (?, ?)');
272
+ expect(res.values).toEqual(['Some Name', 1]);
273
+
274
+ res = this.exec((ctx) =>
275
+ this.dialect.update(
276
+ ctx,
277
+ User,
278
+ {
279
+ $where: { something: 'anything' },
280
+ },
281
+ {
282
+ name: 'Some Name',
283
+ something: 'anything',
284
+ updatedAt: 1,
285
+ } as any,
286
+ ),
287
+ );
288
+ expect(res.sql).toBe('UPDATE `User` SET `name` = ?, `updatedAt` = ? WHERE `something` = ?');
289
+ expect(res.values).toEqual(['Some Name', 1, 'anything']);
290
+
291
+ res = this.exec((ctx) =>
292
+ this.dialect.delete(ctx, User, {
293
+ $where: { something: 'anything' } as any,
294
+ }),
295
+ );
296
+ expect(res.sql).toBe('DELETE FROM `User` WHERE `something` = ?');
297
+ expect(res.values).toEqual(['anything']);
298
+ }
299
+
300
+ shouldFind$and() {
301
+ let res = this.exec((ctx) =>
302
+ this.dialect.find(ctx, User, {
303
+ $select: ['id'],
304
+ $where: { $and: [{ id: 123, name: 'abc' }] },
305
+ }),
306
+ );
307
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `id` = ? AND `name` = ?');
308
+ expect(res.values).toEqual([123, 'abc']);
309
+
310
+ res = this.exec((ctx) =>
311
+ this.dialect.find(ctx, User, {
312
+ $select: { id: 1 },
313
+ $where: { $and: [{ id: 123 }], name: 'abc' },
314
+ }),
315
+ );
316
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `id` = ? AND `name` = ?');
317
+ expect(res.values).toEqual([123, 'abc']);
318
+ }
319
+
320
+ shouldFind$or() {
321
+ let res = this.exec((ctx) =>
322
+ this.dialect.find(ctx, User, {
323
+ $select: ['id'],
324
+ $where: { $or: [{ id: 123 }, { name: 'abc' }] },
325
+ }),
326
+ );
327
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `id` = ? OR `name` = ?');
328
+ expect(res.values).toEqual([123, 'abc']);
329
+
330
+ res = this.exec((ctx) =>
331
+ this.dialect.find(ctx, User, {
332
+ $select: ['id'],
333
+ $where: { $or: [{ id: 123 }] },
334
+ }),
335
+ );
336
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `id` = ?');
337
+ expect(res.values).toEqual([123]);
338
+
339
+ res = this.exec((ctx) =>
340
+ this.dialect.find(ctx, User, {
341
+ $select: { id: 1 },
342
+ $where: { $or: [{ id: 123, name: 'abc' }] },
343
+ }),
344
+ );
345
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `id` = ? AND `name` = ?');
346
+ expect(res.values).toEqual([123, 'abc']);
347
+
348
+ res = this.exec((ctx) =>
349
+ this.dialect.find(ctx, User, {
350
+ $select: ['id'],
351
+ $where: { $or: [{ id: 123 }], name: 'abc' },
352
+ }),
353
+ );
354
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `id` = ? AND `name` = ?');
355
+ expect(res.values).toEqual([123, 'abc']);
356
+ }
357
+
358
+ shouldFind$not() {
359
+ let res = this.exec((ctx) =>
360
+ this.dialect.find(ctx, User, {
361
+ $select: ['id'],
362
+ $where: { $not: [{ name: 'Some' }] },
363
+ }),
364
+ );
365
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE NOT `name` = ?');
366
+ expect(res.values).toEqual(['Some']);
367
+
368
+ res = this.exec((ctx) =>
369
+ this.dialect.find(ctx, Company, {
370
+ $select: ['id'],
371
+ $where: { id: { $not: 123 } },
372
+ }),
373
+ );
374
+ expect(res.sql).toBe('SELECT `id` FROM `Company` WHERE NOT (`id` = ?)');
375
+ expect(res.values).toEqual([123]);
376
+
377
+ res = this.exec((ctx) =>
378
+ this.dialect.find(ctx, Company, {
379
+ $select: ['id'],
380
+ $where: { id: { $not: [123, 456] } },
381
+ }),
382
+ );
383
+ expect(res.sql).toBe('SELECT `id` FROM `Company` WHERE NOT (`id` IN (?, ?))');
384
+ expect(res.values).toEqual([123, 456]);
385
+
386
+ res = this.exec((ctx) =>
387
+ this.dialect.find(ctx, Company, {
388
+ $select: ['id'],
389
+ $where: { id: 123, name: { $not: { $startsWith: 'a' } } },
390
+ }),
391
+ );
392
+ expect(res.sql).toBe('SELECT `id` FROM `Company` WHERE `id` = ? AND NOT (`name` LIKE ?)');
393
+ expect(res.values).toEqual([123, 'a%']);
394
+
395
+ res = this.exec((ctx) =>
396
+ this.dialect.find(ctx, Company, {
397
+ $select: ['id'],
398
+ $where: { name: { $not: { $startsWith: 'a', $endsWith: 'z' } } },
399
+ }),
400
+ );
401
+ expect(res.sql).toBe('SELECT `id` FROM `Company` WHERE NOT ((`name` LIKE ? AND `name` LIKE ?))');
402
+ expect(res.values).toEqual(['a%', '%z']);
403
+
404
+ res = this.exec((ctx) =>
405
+ this.dialect.find(ctx, User, {
406
+ $select: { id: true },
407
+ $where: { $not: [{ name: { $like: 'Some', $ne: 'Something' } }] },
408
+ }),
409
+ );
410
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE NOT (`name` LIKE ? AND `name` <> ?)');
411
+ expect(res.values).toEqual(['Some', 'Something']);
412
+
413
+ res = this.exec((ctx) =>
414
+ this.dialect.find(ctx, User, {
415
+ $select: { id: true },
416
+ $where: { $not: [{ name: 'abc' }, { creatorId: 1 }] },
417
+ }),
418
+ );
419
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE NOT (`name` = ? AND `creatorId` = ?)');
420
+ expect(res.values).toEqual(['abc', 1]);
421
+
422
+ res = this.exec((ctx) =>
423
+ this.dialect.find(ctx, Tax, {
424
+ $select: ['id'],
425
+ $where: { companyId: 1, name: { $not: { $startsWith: 'a' } } },
426
+ }),
427
+ );
428
+ expect(res.sql).toBe('SELECT `id` FROM `Tax` WHERE `companyId` = ? AND NOT (`name` LIKE ?)');
429
+ expect(res.values).toEqual([1, 'a%']);
430
+ }
431
+
432
+ shouldFind$nor() {
433
+ let res = this.exec((ctx) =>
434
+ this.dialect.find(ctx, User, {
435
+ $select: ['id'],
436
+ $where: { $nor: [{ name: 'Some' }] },
437
+ }),
438
+ );
439
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE NOT `name` = ?');
440
+ expect(res.values).toEqual(['Some']);
441
+
442
+ res = this.exec((ctx) =>
443
+ this.dialect.find(ctx, User, {
444
+ $select: { id: true },
445
+ $where: { $nor: [{ name: { $like: 'Some', $ne: 'Something' } }] },
446
+ }),
447
+ );
448
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE NOT (`name` LIKE ? AND `name` <> ?)');
449
+ expect(res.values).toEqual(['Some', 'Something']);
450
+
451
+ res = this.exec((ctx) =>
452
+ this.dialect.find(ctx, User, {
453
+ $select: { id: true },
454
+ $where: { $nor: [{ name: 'abc' }, { creatorId: 1 }] },
455
+ }),
456
+ );
457
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE NOT (`name` = ? OR `creatorId` = ?)');
458
+ expect(res.values).toEqual(['abc', 1]);
459
+ }
460
+
461
+ shouldFind$orAnd$and() {
462
+ const res = this.exec((ctx) =>
463
+ this.dialect.find(ctx, User, {
464
+ $select: ['id'],
465
+ $where: { creatorId: 1, $or: [{ name: ['a', 'b', 'c'] }, { email: 'abc@example.com' }], id: 1 },
466
+ }),
467
+ );
468
+ expect(res.sql).toBe(
469
+ 'SELECT `id` FROM `User` WHERE `creatorId` = ? AND (`name` IN (?, ?, ?) OR `email` = ?) AND `id` = ?',
470
+ );
471
+ expect(res.values).toEqual([1, 'a', 'b', 'c', 'abc@example.com', 1]);
472
+
473
+ const res2 = this.exec((ctx) =>
474
+ this.dialect.find(ctx, User, {
475
+ $select: ['id'],
476
+ $where: {
477
+ creatorId: 1,
478
+ $or: [{ name: ['a', 'b', 'c'] }, { email: 'abc@example.com' }],
479
+ id: 1,
480
+ email: 'e',
481
+ },
482
+ }),
483
+ );
484
+ expect(res2.sql).toBe(
485
+ 'SELECT `id` FROM `User` WHERE `creatorId` = ?' +
486
+ ' AND (`name` IN (?, ?, ?) OR `email` = ?) AND `id` = ? AND `email` = ?',
487
+ );
488
+ expect(res2.values).toEqual([1, 'a', 'b', 'c', 'abc@example.com', 1, 'e']);
489
+
490
+ const res3 = this.exec((ctx) =>
491
+ this.dialect.find(ctx, User, {
492
+ $select: ['id'],
493
+ $where: {
494
+ creatorId: 1,
495
+ $or: [{ name: ['a', 'b', 'c'] }, { email: 'abc@example.com' }],
496
+ id: 1,
497
+ email: 'e',
498
+ },
499
+ $sort: { name: 1, createdAt: -1 },
500
+ $skip: 50,
501
+ $limit: 10,
502
+ }),
503
+ );
504
+ expect(res3.sql).toBe(
505
+ 'SELECT `id` FROM `User` WHERE `creatorId` = ?' +
506
+ ' AND (`name` IN (?, ?, ?) OR `email` = ?)' +
507
+ ' AND `id` = ? AND `email` = ?' +
508
+ ' ORDER BY `name`, `createdAt` DESC LIMIT 10 OFFSET 50',
509
+ );
510
+ expect(res3.values).toEqual([1, 'a', 'b', 'c', 'abc@example.com', 1, 'e']);
511
+
512
+ const res4 = this.exec((ctx) =>
513
+ this.dialect.find(ctx, User, {
514
+ $select: ['id'],
515
+ $where: {
516
+ $or: [
517
+ {
518
+ creatorId: 1,
519
+ id: 1,
520
+ email: 'e',
521
+ },
522
+ { name: ['a', 'b', 'c'], email: 'abc@example.com' },
523
+ ],
524
+ },
525
+ $sort: [
526
+ { field: 'name', sort: 'asc' },
527
+ { field: 'createdAt', sort: 'desc' },
528
+ ],
529
+ $skip: 50,
530
+ $limit: 10,
531
+ }),
532
+ );
533
+ expect(res4.sql).toBe(
534
+ 'SELECT `id` FROM `User` WHERE (`creatorId` = ? AND `id` = ? AND `email` = ?)' +
535
+ ' OR (`name` IN (?, ?, ?) AND `email` = ?)' +
536
+ ' ORDER BY `name`, `createdAt` DESC LIMIT 10 OFFSET 50',
537
+ );
538
+ expect(res4.values).toEqual([1, 1, 'e', 'a', 'b', 'c', 'abc@example.com']);
539
+ }
540
+
541
+ shouldFindSingle$where() {
542
+ const { sql, values } = this.exec((ctx) =>
543
+ this.dialect.find(ctx, User, {
544
+ $select: ['id'],
545
+ $where: { name: 'some' },
546
+ $limit: 3,
547
+ }),
548
+ );
549
+ expect(sql).toBe('SELECT `id` FROM `User` WHERE `name` = ? LIMIT 3');
550
+ expect(values).toEqual(['some']);
551
+ }
552
+
553
+ shouldFindMultipleComparisonOperators() {
554
+ let res = this.exec((ctx) =>
555
+ this.dialect.find(ctx, User, {
556
+ $select: ['id'],
557
+ $where: { $or: [{ name: { $eq: 'other', $ne: 'other unwanted' } }, { companyId: 1 }] },
558
+ }),
559
+ );
560
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE (`name` = ? AND `name` <> ?) OR `companyId` = ?');
561
+ expect(res.values).toEqual(['other', 'other unwanted', 1]);
562
+
563
+ res = this.exec((ctx) =>
564
+ this.dialect.find(ctx, User, {
565
+ $select: ['id'],
566
+ $where: { createdAt: { $gte: 123, $lte: 999 } },
567
+ $limit: 10,
568
+ }),
569
+ );
570
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE (`createdAt` >= ? AND `createdAt` <= ?) LIMIT 10');
571
+ expect(res.values).toEqual([123, 999]);
572
+
573
+ res = this.exec((ctx) =>
574
+ this.dialect.find(ctx, User, {
575
+ $select: ['id'],
576
+ $where: { createdAt: { $gt: 123, $lt: 999 } },
577
+ $limit: 10,
578
+ }),
579
+ );
580
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE (`createdAt` > ? AND `createdAt` < ?) LIMIT 10');
581
+ expect(res.values).toEqual([123, 999]);
582
+ }
583
+
584
+ shouldFind$ne() {
585
+ const { sql, values } = this.exec((ctx) =>
586
+ this.dialect.find(ctx, User, {
587
+ $select: ['id'],
588
+ $where: { name: 'some', companyId: { $ne: 5 } },
589
+ $limit: 20,
590
+ }),
591
+ );
592
+ expect(sql).toBe('SELECT `id` FROM `User` WHERE `name` = ? AND `companyId` <> ? LIMIT 20');
593
+ expect(values).toEqual(['some', 5]);
594
+ }
595
+
596
+ shouldFindIsNull() {
597
+ let res = this.exec((ctx) =>
598
+ this.dialect.find(ctx, User, {
599
+ $select: ['id'],
600
+ $where: { creatorId: 123, companyId: null },
601
+ $limit: 5,
602
+ }),
603
+ );
604
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `creatorId` = ? AND `companyId` IS NULL LIMIT 5');
605
+ expect(res.values).toEqual([123]);
606
+
607
+ res = this.exec((ctx) =>
608
+ this.dialect.find(ctx, User, {
609
+ $select: ['id'],
610
+ $where: { creatorId: 123, companyId: { $ne: null } },
611
+ $limit: 5,
612
+ }),
613
+ );
614
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `creatorId` = ? AND `companyId` IS NOT NULL LIMIT 5');
615
+ expect(res.values).toEqual([123]);
616
+ }
617
+
618
+ shouldFind$in() {
619
+ let res = this.exec((ctx) =>
620
+ this.dialect.find(ctx, User, {
621
+ $select: ['id'],
622
+ $where: { name: 'some', companyId: [1, 2, 3] },
623
+ $limit: 10,
624
+ }),
625
+ );
626
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `name` = ? AND `companyId` IN (?, ?, ?) LIMIT 10');
627
+ expect(res.values).toEqual(['some', 1, 2, 3]);
628
+
629
+ res = this.exec((ctx) =>
630
+ this.dialect.find(ctx, User, {
631
+ $select: ['id'],
632
+ $where: { name: 'some', companyId: { $in: [1, 2, 3] } },
633
+ $limit: 10,
634
+ }),
635
+ );
636
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `name` = ? AND `companyId` IN (?, ?, ?) LIMIT 10');
637
+ expect(res.values).toEqual(['some', 1, 2, 3]);
638
+ }
639
+
640
+ shouldFind$nin() {
641
+ const { sql, values } = this.exec((ctx) =>
642
+ this.dialect.find(ctx, User, {
643
+ $select: ['id'],
644
+ $where: { name: 'some', companyId: { $nin: [1, 2, 3] } },
645
+ $limit: 10,
646
+ }),
647
+ );
648
+ expect(sql).toBe('SELECT `id` FROM `User` WHERE `name` = ? AND `companyId` NOT IN (?, ?, ?) LIMIT 10');
649
+ expect(values).toEqual(['some', 1, 2, 3]);
650
+ }
651
+
652
+ shouldFind$selectFields() {
653
+ const { sql } = this.exec((ctx) => this.dialect.find(ctx, User, { $select: { id: true, company: true } }));
654
+ expect(sql).toBe(
655
+ 'SELECT `User`.`id`, `company`.`id` `company_id`, `company`.`companyId` `company_companyId`, `company`.`creatorId` `company_creatorId`' +
656
+ ', `company`.`createdAt` `company_createdAt`, `company`.`updatedAt` `company_updatedAt`' +
657
+ ', `company`.`name` `company_name`, `company`.`description` `company_description`, `company`.`kind` `company_kind`' +
658
+ ' FROM `User` LEFT JOIN `Company` `company` ON `company`.`id` = `User`.`companyId`',
659
+ );
660
+ }
661
+
662
+ shouldFind$selectOneToOne() {
663
+ let res = this.exec((ctx) =>
664
+ this.dialect.find(ctx, User, { $select: { id: true, name: true, profile: ['id', 'picture'] } }),
665
+ );
666
+ expect(res.sql).toBe(
667
+ 'SELECT `User`.`id`, `User`.`name`, `profile`.`pk` `profile_pk`, `profile`.`image` `profile_picture` FROM `User`' +
668
+ ' LEFT JOIN `user_profile` `profile` ON `profile`.`creatorId` = `User`.`id`',
669
+ );
670
+
671
+ res = this.exec((ctx) => this.dialect.find(ctx, User, { $select: { profile: true } }));
672
+ expect(res.sql).toBe(
673
+ 'SELECT `User`.`id`, `profile`.`companyId` `profile_companyId`' +
674
+ ', `profile`.`creatorId` `profile_creatorId`, `profile`.`createdAt` `profile_createdAt`' +
675
+ ', `profile`.`updatedAt` `profile_updatedAt`' +
676
+ ', `profile`.`pk` `profile_pk`, `profile`.`image` `profile_picture`' +
677
+ ' FROM `User` LEFT JOIN `user_profile` `profile` ON `profile`.`creatorId` = `User`.`id`',
678
+ );
679
+ }
680
+
681
+ shouldFind$selectManyToOne() {
682
+ const { sql } = this.exec((ctx) =>
683
+ this.dialect.find(ctx, Item, {
684
+ $select: {
685
+ id: true,
686
+ name: true,
687
+ code: true,
688
+ tax: { $select: ['id', 'name'], $required: true },
689
+ measureUnit: { $select: ['id', 'name', 'categoryId'] },
690
+ },
691
+ $limit: 100,
692
+ }),
693
+ );
694
+ expect(sql).toBe(
695
+ 'SELECT `Item`.`id`, `Item`.`name`, `Item`.`code`' +
696
+ ', `tax`.`id` `tax_id`, `tax`.`name` `tax_name`' +
697
+ ', `measureUnit`.`id` `measureUnit_id`, `measureUnit`.`name` `measureUnit_name`, `measureUnit`.`categoryId` `measureUnit_categoryId`' +
698
+ ' FROM `Item`' +
699
+ ' INNER JOIN `Tax` `tax` ON `tax`.`id` = `Item`.`taxId`' +
700
+ ' LEFT JOIN `MeasureUnit` `measureUnit` ON `measureUnit`.`id` = `Item`.`measureUnitId`' +
701
+ ' LIMIT 100',
702
+ );
703
+ }
704
+
705
+ shouldFind$selectWithAllFieldsAndSpecificFieldsAndWhere() {
706
+ const { sql, values } = this.exec((ctx) =>
707
+ this.dialect.find(ctx, Item, {
708
+ $select: {
709
+ id: true,
710
+ name: true,
711
+ measureUnit: { $select: ['id', 'name'], $where: { name: { $ne: 'unidad' } }, $required: true },
712
+ tax: ['id', 'name'],
713
+ },
714
+ $where: { salePrice: { $gte: 1000 }, name: { $istartsWith: 'A' } },
715
+ $sort: { tax: { name: 1 }, measureUnit: { name: 1 }, createdAt: -1 },
716
+ $limit: 100,
717
+ }),
718
+ );
719
+ expect(sql).toBe(
720
+ 'SELECT `Item`.`id`, `Item`.`name`' +
721
+ ', `measureUnit`.`id` `measureUnit_id`, `measureUnit`.`name` `measureUnit_name`' +
722
+ ', `tax`.`id` `tax_id`, `tax`.`name` `tax_name`' +
723
+ ' FROM `Item`' +
724
+ ' INNER JOIN `MeasureUnit` `measureUnit` ON `measureUnit`.`id` = `Item`.`measureUnitId` AND `measureUnit`.`name` <> ? AND `measureUnit`.`deletedAt` IS NULL' +
725
+ ' LEFT JOIN `Tax` `tax` ON `tax`.`id` = `Item`.`taxId`' +
726
+ ' WHERE `Item`.`salePrice` >= ? AND `Item`.`name` LIKE ?' +
727
+ ' ORDER BY `tax`.`name`, `measureUnit`.`name`, `Item`.`createdAt` DESC LIMIT 100',
728
+ );
729
+ expect(values).toEqual(['unidad', 1000, 'a%']);
730
+ }
731
+
732
+ shouldVirtualField() {
733
+ let res = this.exec((ctx) =>
734
+ this.dialect.find(ctx, Item, {
735
+ $select: {
736
+ id: 1,
737
+ },
738
+ $where: {
739
+ tagsCount: { $gte: 10 },
740
+ },
741
+ }),
742
+ );
743
+ expect(res.sql).toBe(
744
+ 'SELECT `id` FROM `Item` WHERE (SELECT COUNT(*) `count` FROM `ItemTag` WHERE `ItemTag`.`itemId` = `id`) >= ?',
745
+ );
746
+ expect(res.values).toEqual([10]);
747
+
748
+ res = this.exec((ctx) =>
749
+ this.dialect.find(ctx, Item, {
750
+ $select: {
751
+ id: 1,
752
+ name: 1,
753
+ code: 1,
754
+ tagsCount: 1,
755
+ measureUnit: {
756
+ $select: { id: 1, name: 1, categoryId: 1, category: ['name'] },
757
+ },
758
+ },
759
+ $limit: 100,
760
+ }),
761
+ );
762
+ expect(res.sql).toBe(
763
+ 'SELECT `Item`.`id`, `Item`.`name`, `Item`.`code`' +
764
+ ', (SELECT COUNT(*) `count` FROM `ItemTag` WHERE `ItemTag`.`itemId` = `Item`.`id`) `tagsCount`' +
765
+ ', `measureUnit`.`id` `measureUnit_id`, `measureUnit`.`name` `measureUnit_name`, `measureUnit`.`categoryId` `measureUnit_categoryId`' +
766
+ ', `measureUnit.category`.`id` `measureUnit_category_id`, `measureUnit.category`.`name` `measureUnit_category_name`' +
767
+ ' FROM `Item` LEFT JOIN `MeasureUnit` `measureUnit` ON `measureUnit`.`id` = `Item`.`measureUnitId`' +
768
+ ' LEFT JOIN `MeasureUnitCategory` `measureUnit.category` ON `measureUnit.category`.`id` = `measureUnit`.`categoryId`' +
769
+ ' LIMIT 100',
770
+ );
771
+ }
772
+
773
+ shouldFind$selectDeep() {
774
+ let res = this.exec((ctx) =>
775
+ this.dialect.find(ctx, Item, {
776
+ $select: {
777
+ id: 1,
778
+ name: 1,
779
+ code: 1,
780
+ measureUnit: {
781
+ $select: { id: 1, name: 1, categoryId: 1, category: ['name'] },
782
+ },
783
+ },
784
+ $limit: 100,
785
+ }),
786
+ );
787
+ expect(res.sql).toBe(
788
+ 'SELECT `Item`.`id`, `Item`.`name`, `Item`.`code`' +
789
+ ', `measureUnit`.`id` `measureUnit_id`' +
790
+ ', `measureUnit`.`name` `measureUnit_name`, `measureUnit`.`categoryId` `measureUnit_categoryId`' +
791
+ ', `measureUnit.category`.`id` `measureUnit_category_id`, `measureUnit.category`.`name` `measureUnit_category_name`' +
792
+ ' FROM `Item` LEFT JOIN `MeasureUnit` `measureUnit` ON `measureUnit`.`id` = `Item`.`measureUnitId`' +
793
+ ' LEFT JOIN `MeasureUnitCategory` `measureUnit.category` ON `measureUnit.category`.`id` = `measureUnit`.`categoryId`' +
794
+ ' LIMIT 100',
795
+ );
796
+
797
+ res = this.exec((ctx) =>
798
+ this.dialect.find(ctx, Item, {
799
+ $select: {
800
+ id: true,
801
+ name: true,
802
+ code: true,
803
+ measureUnit: {
804
+ $select: { id: true, name: true, category: { $select: { id: true, name: true } } },
805
+ },
806
+ },
807
+ $limit: 100,
808
+ }),
809
+ );
810
+ expect(res.sql).toBe(
811
+ 'SELECT `Item`.`id`, `Item`.`name`, `Item`.`code`, `measureUnit`.`id` `measureUnit_id`' +
812
+ ', `measureUnit`.`name` `measureUnit_name`, `measureUnit.category`.`id` `measureUnit_category_id`' +
813
+ ', `measureUnit.category`.`name` `measureUnit_category_name`' +
814
+ ' FROM `Item` LEFT JOIN `MeasureUnit` `measureUnit` ON `measureUnit`.`id` = `Item`.`measureUnitId`' +
815
+ ' LEFT JOIN `MeasureUnitCategory` `measureUnit.category` ON `measureUnit.category`.`id` = `measureUnit`.`categoryId`' +
816
+ ' LIMIT 100',
817
+ );
818
+
819
+ res = this.exec((ctx) =>
820
+ this.dialect.find(ctx, ItemAdjustment, {
821
+ $select: {
822
+ id: true,
823
+ buyPrice: true,
824
+ number: true,
825
+ item: {
826
+ $select: {
827
+ id: true,
828
+ name: true,
829
+ measureUnit: {
830
+ $select: { id: true, name: true, category: ['id', 'name'] },
831
+ },
832
+ },
833
+ $required: true,
834
+ },
835
+ },
836
+ $limit: 100,
837
+ }),
838
+ );
839
+ expect(res.sql).toBe(
840
+ 'SELECT `ItemAdjustment`.`id`, `ItemAdjustment`.`buyPrice`, `ItemAdjustment`.`number`' +
841
+ ', `item`.`id` `item_id`, `item`.`name` `item_name`' +
842
+ ', `item.measureUnit`.`id` `item_measureUnit_id`, `item.measureUnit`.`name` `item_measureUnit_name`' +
843
+ ', `item.measureUnit.category`.`id` `item_measureUnit_category_id`, `item.measureUnit.category`.`name` `item_measureUnit_category_name`' +
844
+ ' FROM `ItemAdjustment`' +
845
+ ' INNER JOIN `Item` `item` ON `item`.`id` = `ItemAdjustment`.`itemId`' +
846
+ ' LEFT JOIN `MeasureUnit` `item.measureUnit` ON `item.measureUnit`.`id` = `item`.`measureUnitId`' +
847
+ ' LEFT JOIN `MeasureUnitCategory` `item.measureUnit.category` ON `item.measureUnit.category`.`id` = `item.measureUnit`.`categoryId`' +
848
+ ' LIMIT 100',
849
+ );
850
+ }
851
+
852
+ shouldFind$limit() {
853
+ let res = this.exec((ctx) =>
854
+ this.dialect.find(ctx, User, {
855
+ $select: ['id'],
856
+ $where: 9,
857
+ $limit: 1,
858
+ }),
859
+ );
860
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `id` = ? LIMIT 1');
861
+ expect(res.values).toEqual([9]);
862
+
863
+ res = this.exec((ctx) =>
864
+ this.dialect.find(ctx, User, {
865
+ $select: { id: 1, name: 1, creatorId: 1 },
866
+ $where: 9,
867
+ $limit: 1,
868
+ }),
869
+ );
870
+ expect(res.sql).toBe('SELECT `id`, `name`, `creatorId` FROM `User` WHERE `id` = ? LIMIT 1');
871
+ expect(res.values).toEqual([9]);
872
+
873
+ res = this.exec((ctx) =>
874
+ this.dialect.find(ctx, User, {
875
+ $select: ['id'],
876
+ $where: { name: 'something', creatorId: 123 },
877
+ $limit: 1,
878
+ }),
879
+ );
880
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `name` = ? AND `creatorId` = ? LIMIT 1');
881
+ expect(res.values).toEqual(['something', 123]);
882
+
883
+ res = this.exec((ctx) =>
884
+ this.dialect.find(ctx, User, {
885
+ $select: ['id', 'name', 'creatorId'],
886
+ $limit: 25,
887
+ }),
888
+ );
889
+ expect(res.sql).toBe('SELECT `id`, `name`, `creatorId` FROM `User` LIMIT 25');
890
+ }
891
+
892
+ shouldFind$skip() {
893
+ const res = this.exec((ctx) =>
894
+ this.dialect.find(ctx, User, {
895
+ $select: { id: 1, name: 1, creatorId: 1 },
896
+ $skip: 30,
897
+ }),
898
+ );
899
+ expect(res.sql).toBe('SELECT `id`, `name`, `creatorId` FROM `User` OFFSET 30');
900
+ }
901
+
902
+ shouldFind$select() {
903
+ let res = this.exec((ctx) => this.dialect.find(ctx, User, { $select: { password: false } }));
904
+ expect(res.sql).toBe(
905
+ 'SELECT `id`, `companyId`, `creatorId`, `createdAt`, `updatedAt`, `name`, `email` FROM `User`',
906
+ );
907
+
908
+ res = this.exec((ctx) => this.dialect.find(ctx, User, { $select: { name: 0, password: 0 } }));
909
+ expect(res.sql).toBe('SELECT `id`, `companyId`, `creatorId`, `createdAt`, `updatedAt`, `email` FROM `User`');
910
+
911
+ res = this.exec((ctx) => this.dialect.find(ctx, User, { $select: { id: 1, name: 1, password: 0 } }));
912
+ expect(res.sql).toBe('SELECT `id`, `name` FROM `User`');
913
+
914
+ res = this.exec((ctx) => this.dialect.find(ctx, User, { $select: { id: 1, name: 0, password: 0 } }));
915
+ expect(res.sql).toBe('SELECT `id` FROM `User`');
916
+
917
+ res = this.exec((ctx) =>
918
+ this.dialect.find(ctx, User, {
919
+ $select: [raw('*'), raw('LOG10(numberOfVotes + 1) * 287014.5873982681 + createdAt', 'hotness')],
920
+ $where: { name: 'something' },
921
+ }),
922
+ );
923
+ expect(res.sql).toBe(
924
+ 'SELECT *, LOG10(numberOfVotes + 1) * 287014.5873982681 + createdAt `hotness` FROM `User` WHERE `name` = ?',
925
+ );
926
+ expect(res.values).toEqual(['something']);
927
+ }
928
+
929
+ shouldDelete() {
930
+ let res = this.exec((ctx) => this.dialect.delete(ctx, User, { $where: 123 }));
931
+ expect(res.sql).toBe('DELETE FROM `User` WHERE `id` = ?');
932
+ expect(res.values).toEqual([123]);
933
+
934
+ expect(() => this.exec((ctx) => this.dialect.delete(ctx, User, { $where: 123 }, { softDelete: true }))).toThrow(
935
+ "'User' has not enabled 'softDelete'",
936
+ );
937
+
938
+ res = this.exec((ctx) => this.dialect.delete(ctx, User, { $where: 123 }, { softDelete: false }));
939
+ expect(res.sql).toBe('DELETE FROM `User` WHERE `id` = ?');
940
+ expect(res.values).toEqual([123]);
941
+
942
+ res = this.exec((ctx) => this.dialect.delete(ctx, MeasureUnit, { $where: 123 }));
943
+ expect(res.sql).toMatch(/^UPDATE `MeasureUnit` SET `deletedAt` = \? WHERE `id` = \? AND `deletedAt` IS NULL$/);
944
+ expect(res.values).toEqual([expect.any(Number), 123]);
945
+
946
+ res = this.exec((ctx) => this.dialect.delete(ctx, MeasureUnit, { $where: 123 }, { softDelete: true }));
947
+ expect(res.sql).toMatch(/^UPDATE `MeasureUnit` SET `deletedAt` = \? WHERE `id` = \? AND `deletedAt` IS NULL$/);
948
+ expect(res.values).toEqual([expect.any(Number), 123]);
949
+
950
+ res = this.exec((ctx) => this.dialect.delete(ctx, MeasureUnit, { $where: 123 }, { softDelete: false }));
951
+ expect(res.sql).toBe('DELETE FROM `MeasureUnit` WHERE `id` = ?');
952
+ expect(res.values).toEqual([123]);
953
+ }
954
+
955
+ shouldFind$selectRaw() {
956
+ let res = this.exec((ctx) =>
957
+ this.dialect.find(ctx, User, {
958
+ $select: [raw(() => 'createdAt', 'hotness')],
959
+ $where: { name: 'something' },
960
+ }),
961
+ );
962
+ expect(res.sql).toBe('SELECT createdAt `hotness` FROM `User` WHERE `name` = ?');
963
+ expect(res.values).toEqual(['something']);
964
+
965
+ res = this.exec((ctx) =>
966
+ this.dialect.find(ctx, User, {
967
+ $select: [raw('*'), raw('LOG10(numberOfVotes + 1) * 287014.5873982681 + createdAt', 'hotness')],
968
+ $where: { name: 'something' },
969
+ }),
970
+ );
971
+ expect(res.sql).toBe(
972
+ 'SELECT *, LOG10(numberOfVotes + 1) * 287014.5873982681 + createdAt `hotness` FROM `User` WHERE `name` = ?',
973
+ );
974
+ expect(res.values).toEqual(['something']);
975
+ }
976
+
977
+ shouldFind$whereRaw() {
978
+ let res = this.exec((ctx) =>
979
+ this.dialect.find(ctx, Item, {
980
+ $select: ['creatorId'],
981
+ $where: { $and: [{ companyId: 1 }, raw('SUM(salePrice) > 500')] },
982
+ }),
983
+ );
984
+ expect(res.sql).toBe('SELECT `creatorId` FROM `Item` WHERE `companyId` = ? AND SUM(salePrice) > 500');
985
+ expect(res.values).toEqual([1]);
986
+
987
+ res = this.exec((ctx) =>
988
+ this.dialect.find(ctx, Item, {
989
+ $select: ['id'],
990
+ $where: { $or: [{ companyId: 1 }, 5, raw('SUM(salePrice) > 500')] },
991
+ }),
992
+ );
993
+ expect(res.sql).toBe('SELECT `id` FROM `Item` WHERE `companyId` = ? OR `id` = ? OR SUM(salePrice) > 500');
994
+ expect(res.values).toEqual([1, 5]);
995
+
996
+ res = this.exec((ctx) =>
997
+ this.dialect.find(ctx, Item, {
998
+ $select: ['id'],
999
+ $where: { $or: [1, raw('SUM(salePrice) > 500')] },
1000
+ }),
1001
+ );
1002
+ expect(res.sql).toBe('SELECT `id` FROM `Item` WHERE `id` = ? OR SUM(salePrice) > 500');
1003
+ expect(res.values).toEqual([1]);
1004
+
1005
+ res = this.exec((ctx) =>
1006
+ this.dialect.find(ctx, Item, {
1007
+ $select: ['id'],
1008
+ $where: { $or: [raw('SUM(salePrice) > 500'), 1, { companyId: 1 }] },
1009
+ }),
1010
+ );
1011
+ expect(res.sql).toBe('SELECT `id` FROM `Item` WHERE SUM(salePrice) > 500 OR `id` = ? OR `companyId` = ?');
1012
+ expect(res.values).toEqual([1, 1]);
1013
+
1014
+ res = this.exec((ctx) =>
1015
+ this.dialect.find(ctx, Item, {
1016
+ $select: ['id'],
1017
+ $where: { $and: [raw('SUM(salePrice) > 500')] },
1018
+ }),
1019
+ );
1020
+ expect(res.sql).toBe('SELECT `id` FROM `Item` WHERE SUM(salePrice) > 500');
1021
+
1022
+ res = this.exec((ctx) =>
1023
+ this.dialect.find(ctx, Item, {
1024
+ $select: ['id'],
1025
+ $where: raw('SUM(salePrice) > 500'),
1026
+ }),
1027
+ );
1028
+ expect(res.sql).toBe('SELECT `id` FROM `Item` WHERE SUM(salePrice) > 500');
1029
+
1030
+ res = this.exec((ctx) =>
1031
+ this.dialect.find(ctx, Item, {
1032
+ $select: ['creatorId'],
1033
+ $where: { $or: [[1, 2], { code: 'abc' }] },
1034
+ }),
1035
+ );
1036
+ expect(res.sql).toBe('SELECT `creatorId` FROM `Item` WHERE `id` IN (?, ?) OR `code` = ?');
1037
+ expect(res.values).toEqual([1, 2, 'abc']);
1038
+ }
1039
+
1040
+ shouldFind$startsWith() {
1041
+ let res = this.exec((ctx) =>
1042
+ this.dialect.find(ctx, User, {
1043
+ $select: ['id'],
1044
+ $where: { name: { $startsWith: 'Some' } },
1045
+ $sort: [
1046
+ { field: 'name', sort: 'asc' },
1047
+ { field: 'createdAt', sort: 'desc' },
1048
+ ],
1049
+ $skip: 0,
1050
+ $limit: 50,
1051
+ }),
1052
+ );
1053
+ expect(res.sql).toBe(
1054
+ 'SELECT `id` FROM `User` WHERE `name` LIKE ? ORDER BY `name`, `createdAt` DESC LIMIT 50 OFFSET 0',
1055
+ );
1056
+ expect(res.values).toEqual(['Some%']);
1057
+
1058
+ res = this.exec((ctx) =>
1059
+ this.dialect.find(ctx, User, {
1060
+ $select: { id: true },
1061
+ $where: { name: { $startsWith: 'Some', $ne: 'Something' } },
1062
+ $sort: { name: 1, id: -1 },
1063
+ $skip: 0,
1064
+ $limit: 50,
1065
+ }),
1066
+ );
1067
+ expect(res.sql).toBe(
1068
+ 'SELECT `id` FROM `User` WHERE (`name` LIKE ? AND `name` <> ?) ORDER BY `name`, `id` DESC LIMIT 50 OFFSET 0',
1069
+ );
1070
+ expect(res.values).toEqual(['Some%', 'Something']);
1071
+ }
1072
+
1073
+ shouldFind$istartsWith() {
1074
+ let res = this.exec((ctx) =>
1075
+ this.dialect.find(ctx, User, {
1076
+ $select: ['id'],
1077
+ $where: { name: { $istartsWith: 'Some' } },
1078
+ $sort: { name: 1, id: -1 },
1079
+ $skip: 0,
1080
+ $limit: 50,
1081
+ }),
1082
+ );
1083
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `name` LIKE ? ORDER BY `name`, `id` DESC LIMIT 50 OFFSET 0');
1084
+ expect(res.values).toEqual(['some%']);
1085
+
1086
+ res = this.exec((ctx) =>
1087
+ this.dialect.find(ctx, User, {
1088
+ $select: { id: true },
1089
+ $where: { name: { $istartsWith: 'Some', $ne: 'Something' } },
1090
+ $sort: { name: 1, id: -1 },
1091
+ $skip: 0,
1092
+ $limit: 50,
1093
+ }),
1094
+ );
1095
+ expect(res.sql).toBe(
1096
+ 'SELECT `id` FROM `User` WHERE (`name` LIKE ? AND `name` <> ?) ORDER BY `name`, `id` DESC LIMIT 50 OFFSET 0',
1097
+ );
1098
+ expect(res.values).toEqual(['some%', 'Something']);
1099
+ }
1100
+
1101
+ shouldFind$endsWith() {
1102
+ let res = this.exec((ctx) =>
1103
+ this.dialect.find(ctx, User, {
1104
+ $select: ['id'],
1105
+ $where: { name: { $endsWith: 'Some' } },
1106
+ $sort: { name: 1, id: -1 },
1107
+ $skip: 0,
1108
+ $limit: 50,
1109
+ }),
1110
+ );
1111
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `name` LIKE ? ORDER BY `name`, `id` DESC LIMIT 50 OFFSET 0');
1112
+ expect(res.values).toEqual(['%Some']);
1113
+
1114
+ res = this.exec((ctx) =>
1115
+ this.dialect.find(ctx, User, {
1116
+ $select: ['id'],
1117
+ $where: { name: { $endsWith: 'Some', $ne: 'Something' } },
1118
+ $sort: { name: 1, id: -1 },
1119
+ $skip: 0,
1120
+ $limit: 50,
1121
+ }),
1122
+ );
1123
+ expect(res.sql).toBe(
1124
+ 'SELECT `id` FROM `User` WHERE (`name` LIKE ? AND `name` <> ?) ORDER BY `name`, `id` DESC LIMIT 50 OFFSET 0',
1125
+ );
1126
+ expect(res.values).toEqual(['%Some', 'Something']);
1127
+ }
1128
+
1129
+ shouldFind$iendsWith() {
1130
+ let res = this.exec((ctx) =>
1131
+ this.dialect.find(ctx, User, {
1132
+ $select: ['id'],
1133
+ $where: { name: { $iendsWith: 'Some' } },
1134
+ $sort: { name: 1, id: -1 },
1135
+ $skip: 0,
1136
+ $limit: 50,
1137
+ }),
1138
+ );
1139
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `name` LIKE ? ORDER BY `name`, `id` DESC LIMIT 50 OFFSET 0');
1140
+ expect(res.values).toEqual(['%some']);
1141
+
1142
+ res = this.exec((ctx) =>
1143
+ this.dialect.find(ctx, User, {
1144
+ $select: ['id'],
1145
+ $where: { name: { $iendsWith: 'Some', $ne: 'Something' } },
1146
+ $sort: { name: 1, id: -1 },
1147
+ $skip: 0,
1148
+ $limit: 50,
1149
+ }),
1150
+ );
1151
+ expect(res.sql).toBe(
1152
+ 'SELECT `id` FROM `User` WHERE (`name` LIKE ? AND `name` <> ?) ORDER BY `name`, `id` DESC LIMIT 50 OFFSET 0',
1153
+ );
1154
+ expect(res.values).toEqual(['%some', 'Something']);
1155
+ }
1156
+
1157
+ shouldFind$includes() {
1158
+ let res = this.exec((ctx) =>
1159
+ this.dialect.find(ctx, User, {
1160
+ $select: ['id'],
1161
+ $where: { name: { $includes: 'Some' } },
1162
+ $sort: { name: 1, id: -1 },
1163
+ $skip: 0,
1164
+ $limit: 50,
1165
+ }),
1166
+ );
1167
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `name` LIKE ? ORDER BY `name`, `id` DESC LIMIT 50 OFFSET 0');
1168
+ expect(res.values).toEqual(['%Some%']);
1169
+
1170
+ res = this.exec((ctx) =>
1171
+ this.dialect.find(ctx, User, {
1172
+ $select: ['id'],
1173
+ $where: { name: { $includes: 'Some', $ne: 'Something' } },
1174
+ $sort: { name: 1, id: -1 },
1175
+ $skip: 0,
1176
+ $limit: 50,
1177
+ }),
1178
+ );
1179
+ expect(res.sql).toBe(
1180
+ 'SELECT `id` FROM `User` WHERE (`name` LIKE ? AND `name` <> ?) ORDER BY `name`, `id` DESC LIMIT 50 OFFSET 0',
1181
+ );
1182
+ expect(res.values).toEqual(['%Some%', 'Something']);
1183
+ }
1184
+
1185
+ shouldFind$iincludes() {
1186
+ let res = this.exec((ctx) =>
1187
+ this.dialect.find(ctx, User, {
1188
+ $select: ['id'],
1189
+ $where: { name: { $iincludes: 'Some' } },
1190
+ $sort: { name: 1, id: -1 },
1191
+ $skip: 0,
1192
+ $limit: 50,
1193
+ }),
1194
+ );
1195
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `name` LIKE ? ORDER BY `name`, `id` DESC LIMIT 50 OFFSET 0');
1196
+ expect(res.values).toEqual(['%some%']);
1197
+
1198
+ res = this.exec((ctx) =>
1199
+ this.dialect.find(ctx, User, {
1200
+ $select: ['id'],
1201
+ $where: { name: { $iincludes: 'Some', $ne: 'Something' } },
1202
+ $sort: { name: 1, id: -1 },
1203
+ $skip: 0,
1204
+ $limit: 50,
1205
+ }),
1206
+ );
1207
+ expect(res.sql).toBe(
1208
+ 'SELECT `id` FROM `User` WHERE (`name` LIKE ? AND `name` <> ?) ORDER BY `name`, `id` DESC LIMIT 50 OFFSET 0',
1209
+ );
1210
+ expect(res.values).toEqual(['%some%', 'Something']);
1211
+ }
1212
+
1213
+ shouldFind$like() {
1214
+ let res = this.exec((ctx) =>
1215
+ this.dialect.find(ctx, User, {
1216
+ $select: ['id'],
1217
+ $where: { name: { $like: 'Some' } },
1218
+ $sort: { name: 1, id: -1 },
1219
+ $skip: 0,
1220
+ $limit: 50,
1221
+ }),
1222
+ );
1223
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `name` LIKE ? ORDER BY `name`, `id` DESC LIMIT 50 OFFSET 0');
1224
+ expect(res.values).toEqual(['Some']);
1225
+
1226
+ res = this.exec((ctx) =>
1227
+ this.dialect.find(ctx, User, {
1228
+ $select: { id: true },
1229
+ $where: { name: { $like: 'Some', $ne: 'Something' } },
1230
+ $sort: { name: 1, id: -1 },
1231
+ $skip: 0,
1232
+ $limit: 50,
1233
+ }),
1234
+ );
1235
+ expect(res.sql).toBe(
1236
+ 'SELECT `id` FROM `User` WHERE (`name` LIKE ? AND `name` <> ?) ORDER BY `name`, `id` DESC LIMIT 50 OFFSET 0',
1237
+ );
1238
+ expect(res.values).toEqual(['Some', 'Something']);
1239
+ }
1240
+
1241
+ shouldFind$ilike() {
1242
+ let res = this.exec((ctx) =>
1243
+ this.dialect.find(ctx, User, {
1244
+ $select: ['id'],
1245
+ $where: { name: { $ilike: 'Some' } },
1246
+ $sort: { name: 1, id: -1 },
1247
+ $skip: 0,
1248
+ $limit: 50,
1249
+ }),
1250
+ );
1251
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `name` LIKE ? ORDER BY `name`, `id` DESC LIMIT 50 OFFSET 0');
1252
+ expect(res.values).toEqual(['some']);
1253
+
1254
+ res = this.exec((ctx) =>
1255
+ this.dialect.find(ctx, User, {
1256
+ $select: { id: 1 },
1257
+ $where: { name: { $ilike: 'Some', $ne: 'Something' } },
1258
+ $sort: { name: 1, id: -1 },
1259
+ $skip: 0,
1260
+ $limit: 50,
1261
+ }),
1262
+ );
1263
+ expect(res.sql).toBe(
1264
+ 'SELECT `id` FROM `User` WHERE (`name` LIKE ? AND `name` <> ?) ORDER BY `name`, `id` DESC LIMIT 50 OFFSET 0',
1265
+ );
1266
+ expect(res.values).toEqual(['some', 'Something']);
1267
+ }
1268
+
1269
+ shouldFind$regex() {
1270
+ const res = this.exec((ctx) =>
1271
+ this.dialect.find(ctx, User, {
1272
+ $select: ['id'],
1273
+ $where: { name: { $regex: '^some' } },
1274
+ }),
1275
+ );
1276
+ expect(res.sql).toBe('SELECT `id` FROM `User` WHERE `name` REGEXP ?');
1277
+ expect(res.values).toEqual(['^some']);
1278
+ }
1279
+
1280
+ shouldFind$text() {
1281
+ let res = this.exec((ctx) =>
1282
+ this.dialect.find(ctx, Item, {
1283
+ $select: { id: true },
1284
+ $where: { $text: { $fields: ['name', 'description'], $value: 'some text' }, companyId: 1 },
1285
+ $limit: 30,
1286
+ }),
1287
+ );
1288
+ expect(res.sql).toBe(
1289
+ 'SELECT `id` FROM `Item` WHERE MATCH(`name`, `description`) AGAINST(?) AND `companyId` = ? LIMIT 30',
1290
+ );
1291
+ expect(res.values).toEqual(['some text', 1]);
1292
+
1293
+ res = this.exec((ctx) =>
1294
+ this.dialect.find(ctx, User, {
1295
+ $select: { id: 1 },
1296
+ $where: {
1297
+ $text: { $fields: ['name'], $value: 'something' },
1298
+ name: { $ne: 'other unwanted' },
1299
+ companyId: 1,
1300
+ },
1301
+ $limit: 10,
1302
+ }),
1303
+ );
1304
+ expect(res.sql).toBe(
1305
+ 'SELECT `id` FROM `User` WHERE MATCH(`name`) AGAINST(?) AND `name` <> ? AND `companyId` = ? LIMIT 10',
1306
+ );
1307
+ expect(res.values).toEqual(['something', 'other unwanted', 1]);
1308
+ }
1309
+ }