@nocobase/database 0.5.0-alpha.38 → 0.7.0-alpha.10

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 (458) hide show
  1. package/LICENSE +201 -21
  2. package/esm/collection-importer.d.ts +7 -0
  3. package/esm/collection-importer.js +49 -0
  4. package/esm/collection-importer.js.map +1 -0
  5. package/esm/collection.d.ts +73 -0
  6. package/esm/collection.js +224 -0
  7. package/esm/collection.js.map +1 -0
  8. package/esm/database.d.ts +101 -0
  9. package/esm/database.js +275 -0
  10. package/esm/database.js.map +1 -0
  11. package/esm/fields/array-field.d.ts +11 -0
  12. package/esm/fields/array-field.js +26 -0
  13. package/esm/fields/array-field.js.map +1 -0
  14. package/esm/fields/belongs-to-field.d.ts +12 -0
  15. package/esm/fields/belongs-to-field.js +57 -0
  16. package/esm/fields/belongs-to-field.js.map +1 -0
  17. package/esm/fields/belongs-to-many-field.d.ts +11 -0
  18. package/esm/fields/belongs-to-many-field.js +55 -0
  19. package/esm/fields/belongs-to-many-field.js.map +1 -0
  20. package/esm/fields/boolean-field.d.ts +8 -0
  21. package/esm/fields/boolean-field.js +8 -0
  22. package/esm/fields/boolean-field.js.map +1 -0
  23. package/esm/fields/context-field.d.ts +13 -0
  24. package/esm/fields/context-field.js +43 -0
  25. package/esm/fields/context-field.js.map +1 -0
  26. package/esm/fields/date-field.d.ts +8 -0
  27. package/esm/fields/date-field.js +8 -0
  28. package/esm/fields/date-field.js.map +1 -0
  29. package/esm/fields/field.d.ts +37 -0
  30. package/esm/fields/field.js +74 -0
  31. package/esm/fields/field.js.map +1 -0
  32. package/esm/fields/has-inverse-field.d.ts +4 -0
  33. package/esm/fields/has-inverse-field.js +2 -0
  34. package/esm/fields/has-inverse-field.js.map +1 -0
  35. package/esm/fields/has-many-field.d.ts +64 -0
  36. package/esm/fields/has-many-field.js +58 -0
  37. package/esm/fields/has-many-field.js.map +1 -0
  38. package/esm/fields/has-one-field.d.ts +64 -0
  39. package/esm/fields/has-one-field.js +57 -0
  40. package/esm/fields/has-one-field.js.map +1 -0
  41. package/esm/fields/index.d.ts +40 -0
  42. package/esm/fields/index.js +21 -0
  43. package/esm/fields/index.js.map +1 -0
  44. package/esm/fields/json-field.d.ts +14 -0
  45. package/esm/fields/json-field.js +17 -0
  46. package/esm/fields/json-field.js.map +1 -0
  47. package/esm/fields/number-field.d.ts +32 -0
  48. package/esm/fields/number-field.js +28 -0
  49. package/esm/fields/number-field.js.map +1 -0
  50. package/esm/fields/password-field.d.ts +21 -0
  51. package/esm/fields/password-field.js +71 -0
  52. package/esm/fields/password-field.js.map +1 -0
  53. package/esm/fields/radio-field.d.ts +14 -0
  54. package/esm/fields/radio-field.js +49 -0
  55. package/esm/fields/radio-field.js.map +1 -0
  56. package/esm/fields/relation-field.d.ts +20 -0
  57. package/esm/fields/relation-field.js +27 -0
  58. package/esm/fields/relation-field.js.map +1 -0
  59. package/esm/fields/sort-field.d.ts +16 -0
  60. package/esm/fields/sort-field.js +90 -0
  61. package/esm/fields/sort-field.js.map +1 -0
  62. package/esm/fields/string-field.d.ts +8 -0
  63. package/esm/fields/string-field.js +8 -0
  64. package/esm/fields/string-field.js.map +1 -0
  65. package/esm/fields/text-field.d.ts +8 -0
  66. package/esm/fields/text-field.js +8 -0
  67. package/esm/fields/text-field.js.map +1 -0
  68. package/esm/fields/time-field.d.ts +8 -0
  69. package/esm/fields/time-field.js +8 -0
  70. package/esm/fields/time-field.js.map +1 -0
  71. package/esm/fields/uid-field.d.ts +10 -0
  72. package/esm/fields/uid-field.js +27 -0
  73. package/esm/fields/uid-field.js.map +1 -0
  74. package/esm/fields/virtual-field.d.ts +8 -0
  75. package/esm/fields/virtual-field.js +8 -0
  76. package/esm/fields/virtual-field.js.map +1 -0
  77. package/esm/filter-parser.d.ts +27 -0
  78. package/esm/filter-parser.js +185 -0
  79. package/esm/filter-parser.js.map +1 -0
  80. package/esm/index.d.ts +15 -0
  81. package/esm/index.js +16 -0
  82. package/esm/index.js.map +1 -0
  83. package/esm/magic-attribute-model.d.ts +7 -0
  84. package/esm/magic-attribute-model.js +70 -0
  85. package/esm/magic-attribute-model.js.map +1 -0
  86. package/esm/mock-database.d.ts +22 -0
  87. package/esm/mock-database.js +34 -0
  88. package/esm/mock-database.js.map +1 -0
  89. package/esm/model-hook.d.ts +12 -0
  90. package/esm/model-hook.js +61 -0
  91. package/esm/model-hook.js.map +1 -0
  92. package/esm/model.d.ts +15 -0
  93. package/esm/model.js +80 -0
  94. package/esm/model.js.map +1 -0
  95. package/esm/operators/array.d.ts +26 -0
  96. package/esm/operators/array.js +105 -0
  97. package/esm/operators/array.js.map +1 -0
  98. package/esm/operators/association.d.ts +10 -0
  99. package/esm/operators/association.js +14 -0
  100. package/esm/operators/association.js.map +1 -0
  101. package/esm/operators/date.d.ts +34 -0
  102. package/esm/operators/date.js +35 -0
  103. package/esm/operators/date.js.map +1 -0
  104. package/esm/operators/empty.d.ts +28 -0
  105. package/esm/operators/empty.js +58 -0
  106. package/esm/operators/empty.js.map +1 -0
  107. package/esm/operators/index.d.ts +2 -0
  108. package/esm/operators/index.js +2 -0
  109. package/esm/operators/index.js.map +1 -0
  110. package/esm/operators/ne.d.ts +10 -0
  111. package/esm/operators/ne.js +12 -0
  112. package/esm/operators/ne.js.map +1 -0
  113. package/esm/operators/string.d.ts +21 -0
  114. package/esm/operators/string.js +35 -0
  115. package/esm/operators/string.js.map +1 -0
  116. package/esm/operators/utils.d.ts +4 -0
  117. package/esm/operators/utils.js +11 -0
  118. package/esm/operators/utils.js.map +1 -0
  119. package/esm/options-parser.d.ts +31 -0
  120. package/esm/options-parser.js +225 -0
  121. package/esm/options-parser.js.map +1 -0
  122. package/esm/playground.d.ts +1 -0
  123. package/esm/playground.js +53 -0
  124. package/esm/playground.js.map +1 -0
  125. package/esm/relation-repository/belongs-to-many-repository.d.ts +36 -0
  126. package/esm/relation-repository/belongs-to-many-repository.js +199 -0
  127. package/esm/relation-repository/belongs-to-many-repository.js.map +1 -0
  128. package/esm/relation-repository/belongs-to-repository.d.ts +17 -0
  129. package/esm/relation-repository/belongs-to-repository.js +4 -0
  130. package/esm/relation-repository/belongs-to-repository.js.map +1 -0
  131. package/esm/relation-repository/hasmany-repository.d.ts +23 -0
  132. package/esm/relation-repository/hasmany-repository.js +125 -0
  133. package/esm/relation-repository/hasmany-repository.js.map +1 -0
  134. package/esm/relation-repository/hasone-repository.d.ts +17 -0
  135. package/esm/relation-repository/hasone-repository.js +4 -0
  136. package/esm/relation-repository/hasone-repository.js.map +1 -0
  137. package/esm/relation-repository/multiple-relation-repository.d.ts +23 -0
  138. package/esm/relation-repository/multiple-relation-repository.js +149 -0
  139. package/esm/relation-repository/multiple-relation-repository.js.map +1 -0
  140. package/esm/relation-repository/relation-repository.d.ts +32 -0
  141. package/esm/relation-repository/relation-repository.js +93 -0
  142. package/esm/relation-repository/relation-repository.js.map +1 -0
  143. package/esm/relation-repository/single-relation-repository.d.ts +23 -0
  144. package/esm/relation-repository/single-relation-repository.js +96 -0
  145. package/esm/relation-repository/single-relation-repository.js.map +1 -0
  146. package/esm/relation-repository/types.d.ts +7 -0
  147. package/esm/relation-repository/types.js +2 -0
  148. package/esm/relation-repository/types.js.map +1 -0
  149. package/esm/repository.d.ts +165 -0
  150. package/esm/repository.js +276 -0
  151. package/esm/repository.js.map +1 -0
  152. package/esm/transaction-decorator.d.ts +1 -0
  153. package/esm/transaction-decorator.js +63 -0
  154. package/esm/transaction-decorator.js.map +1 -0
  155. package/esm/update-associations.d.ts +60 -0
  156. package/esm/update-associations.js +362 -0
  157. package/esm/update-associations.js.map +1 -0
  158. package/esm/update-guard.d.ts +26 -0
  159. package/esm/update-guard.js +122 -0
  160. package/esm/update-guard.js.map +1 -0
  161. package/lib/collection-importer.d.ts +7 -0
  162. package/lib/collection-importer.js +75 -0
  163. package/lib/collection-importer.js.map +1 -0
  164. package/lib/collection.d.ts +73 -0
  165. package/lib/collection.js +231 -0
  166. package/lib/collection.js.map +1 -0
  167. package/lib/database.d.ts +93 -43
  168. package/lib/database.js +277 -471
  169. package/lib/database.js.map +1 -1
  170. package/lib/fields/array-field.d.ts +11 -0
  171. package/lib/fields/array-field.js +30 -0
  172. package/lib/fields/array-field.js.map +1 -0
  173. package/lib/fields/belongs-to-field.d.ts +12 -0
  174. package/lib/fields/belongs-to-field.js +61 -0
  175. package/lib/fields/belongs-to-field.js.map +1 -0
  176. package/lib/fields/belongs-to-many-field.d.ts +11 -0
  177. package/lib/fields/belongs-to-many-field.js +59 -0
  178. package/lib/fields/belongs-to-many-field.js.map +1 -0
  179. package/lib/fields/boolean-field.d.ts +8 -0
  180. package/lib/fields/boolean-field.js +12 -0
  181. package/lib/fields/boolean-field.js.map +1 -0
  182. package/lib/fields/context-field.d.ts +13 -0
  183. package/lib/fields/context-field.js +50 -0
  184. package/lib/fields/context-field.js.map +1 -0
  185. package/lib/fields/date-field.d.ts +8 -0
  186. package/lib/fields/date-field.js +12 -0
  187. package/lib/fields/date-field.js.map +1 -0
  188. package/lib/fields/field.d.ts +37 -0
  189. package/lib/fields/field.js +81 -0
  190. package/lib/fields/field.js.map +1 -0
  191. package/lib/fields/has-inverse-field.d.ts +4 -0
  192. package/lib/fields/has-inverse-field.js +3 -0
  193. package/lib/fields/has-inverse-field.js.map +1 -0
  194. package/lib/fields/has-many-field.d.ts +64 -0
  195. package/lib/fields/has-many-field.js +62 -0
  196. package/lib/fields/has-many-field.js.map +1 -0
  197. package/lib/fields/has-one-field.d.ts +64 -0
  198. package/lib/fields/has-one-field.js +61 -0
  199. package/lib/fields/has-one-field.js.map +1 -0
  200. package/lib/fields/index.d.ts +40 -10
  201. package/lib/fields/index.js +31 -138
  202. package/lib/fields/index.js.map +1 -1
  203. package/lib/fields/json-field.d.ts +14 -0
  204. package/lib/fields/json-field.js +22 -0
  205. package/lib/fields/json-field.js.map +1 -0
  206. package/lib/fields/number-field.d.ts +32 -0
  207. package/lib/fields/number-field.js +36 -0
  208. package/lib/fields/number-field.js.map +1 -0
  209. package/lib/fields/password-field.d.ts +21 -0
  210. package/lib/fields/password-field.js +78 -0
  211. package/lib/fields/password-field.js.map +1 -0
  212. package/lib/fields/radio-field.d.ts +14 -0
  213. package/lib/fields/radio-field.js +53 -0
  214. package/lib/fields/radio-field.js.map +1 -0
  215. package/lib/fields/relation-field.d.ts +20 -0
  216. package/lib/fields/relation-field.js +31 -0
  217. package/lib/fields/relation-field.js.map +1 -0
  218. package/lib/fields/sort-field.d.ts +16 -0
  219. package/lib/fields/sort-field.js +94 -0
  220. package/lib/fields/sort-field.js.map +1 -0
  221. package/lib/fields/string-field.d.ts +8 -0
  222. package/lib/fields/string-field.js +12 -0
  223. package/lib/fields/string-field.js.map +1 -0
  224. package/lib/fields/text-field.d.ts +8 -0
  225. package/lib/fields/text-field.js +12 -0
  226. package/lib/fields/text-field.js.map +1 -0
  227. package/lib/fields/time-field.d.ts +8 -0
  228. package/lib/fields/time-field.js +12 -0
  229. package/lib/fields/time-field.js.map +1 -0
  230. package/lib/fields/uid-field.d.ts +10 -0
  231. package/lib/fields/uid-field.js +31 -0
  232. package/lib/fields/uid-field.js.map +1 -0
  233. package/lib/fields/virtual-field.d.ts +8 -0
  234. package/lib/fields/virtual-field.js +12 -0
  235. package/lib/fields/virtual-field.js.map +1 -0
  236. package/lib/filter-parser.d.ts +27 -0
  237. package/lib/filter-parser.js +191 -0
  238. package/lib/filter-parser.js.map +1 -0
  239. package/lib/index.d.ts +13 -6
  240. package/lib/index.js +27 -60
  241. package/lib/index.js.map +1 -1
  242. package/lib/magic-attribute-model.d.ts +7 -0
  243. package/lib/magic-attribute-model.js +77 -0
  244. package/lib/magic-attribute-model.js.map +1 -0
  245. package/lib/mock-database.d.ts +22 -0
  246. package/lib/mock-database.js +40 -0
  247. package/lib/mock-database.js.map +1 -0
  248. package/lib/model-hook.d.ts +12 -0
  249. package/lib/model-hook.js +68 -0
  250. package/lib/model-hook.js.map +1 -0
  251. package/lib/model.d.ts +11 -45
  252. package/lib/model.js +76 -452
  253. package/lib/model.js.map +1 -1
  254. package/lib/operators/array.d.ts +26 -0
  255. package/lib/operators/array.js +107 -0
  256. package/lib/operators/array.js.map +1 -0
  257. package/lib/operators/association.d.ts +10 -0
  258. package/lib/operators/association.js +16 -0
  259. package/lib/operators/association.js.map +1 -0
  260. package/lib/operators/date.d.ts +34 -0
  261. package/lib/operators/date.js +40 -0
  262. package/lib/operators/date.js.map +1 -0
  263. package/lib/operators/empty.d.ts +28 -0
  264. package/lib/operators/empty.js +82 -0
  265. package/lib/operators/empty.js.map +1 -0
  266. package/lib/operators/index.d.ts +2 -0
  267. package/lib/operators/index.js +4 -0
  268. package/lib/operators/index.js.map +1 -0
  269. package/lib/operators/ne.d.ts +10 -0
  270. package/lib/operators/ne.js +14 -0
  271. package/lib/operators/ne.js.map +1 -0
  272. package/lib/operators/string.d.ts +21 -0
  273. package/lib/operators/string.js +37 -0
  274. package/lib/operators/string.js.map +1 -0
  275. package/lib/operators/utils.d.ts +4 -0
  276. package/lib/operators/utils.js +16 -0
  277. package/lib/operators/utils.js.map +1 -0
  278. package/lib/options-parser.d.ts +31 -0
  279. package/lib/options-parser.js +232 -0
  280. package/lib/options-parser.js.map +1 -0
  281. package/lib/playground.d.ts +1 -0
  282. package/lib/playground.js +55 -0
  283. package/lib/playground.js.map +1 -0
  284. package/lib/relation-repository/belongs-to-many-repository.d.ts +36 -0
  285. package/lib/relation-repository/belongs-to-many-repository.js +206 -0
  286. package/lib/relation-repository/belongs-to-many-repository.js.map +1 -0
  287. package/lib/relation-repository/belongs-to-repository.d.ts +17 -0
  288. package/lib/relation-repository/belongs-to-repository.js +8 -0
  289. package/lib/relation-repository/belongs-to-repository.js.map +1 -0
  290. package/lib/relation-repository/hasmany-repository.d.ts +23 -0
  291. package/lib/relation-repository/hasmany-repository.js +129 -0
  292. package/lib/relation-repository/hasmany-repository.js.map +1 -0
  293. package/lib/relation-repository/hasone-repository.d.ts +17 -0
  294. package/lib/relation-repository/hasone-repository.js +8 -0
  295. package/lib/relation-repository/hasone-repository.js.map +1 -0
  296. package/lib/relation-repository/multiple-relation-repository.d.ts +23 -0
  297. package/lib/relation-repository/multiple-relation-repository.js +153 -0
  298. package/lib/relation-repository/multiple-relation-repository.js.map +1 -0
  299. package/lib/relation-repository/relation-repository.d.ts +32 -0
  300. package/lib/relation-repository/relation-repository.js +100 -0
  301. package/lib/relation-repository/relation-repository.js.map +1 -0
  302. package/lib/relation-repository/single-relation-repository.d.ts +23 -0
  303. package/lib/relation-repository/single-relation-repository.js +103 -0
  304. package/lib/relation-repository/single-relation-repository.js.map +1 -0
  305. package/lib/relation-repository/types.d.ts +7 -0
  306. package/lib/relation-repository/types.js +3 -0
  307. package/lib/relation-repository/types.js.map +1 -0
  308. package/lib/repository.d.ts +165 -0
  309. package/lib/repository.js +302 -0
  310. package/lib/repository.js.map +1 -0
  311. package/lib/transaction-decorator.d.ts +1 -0
  312. package/lib/transaction-decorator.js +70 -0
  313. package/lib/transaction-decorator.js.map +1 -0
  314. package/lib/update-associations.d.ts +60 -0
  315. package/lib/update-associations.js +374 -0
  316. package/lib/update-associations.js.map +1 -0
  317. package/lib/update-guard.d.ts +26 -0
  318. package/lib/update-guard.js +129 -0
  319. package/lib/update-guard.js.map +1 -0
  320. package/package.json +17 -5
  321. package/src/__tests__/collection-importer.test.ts +21 -0
  322. package/src/__tests__/collection.sortable.test.ts +65 -0
  323. package/src/__tests__/collection.test.ts +218 -0
  324. package/src/__tests__/database.import.test.ts +33 -0
  325. package/src/__tests__/database.test.ts +229 -0
  326. package/src/__tests__/field-options/hidden.test.ts +302 -0
  327. package/src/__tests__/field-options/sort-by.test.ts +220 -0
  328. package/src/__tests__/fields/belongs-to-field.test.ts +162 -0
  329. package/src/__tests__/fields/belongs-to-many-field.test.ts +61 -0
  330. package/src/__tests__/fields/context-field.test.ts +140 -0
  331. package/src/__tests__/fields/has-many-field.test.ts +152 -0
  332. package/src/__tests__/fields/has-one-field.test.ts +67 -0
  333. package/src/__tests__/fields/password-field.test.ts +30 -0
  334. package/src/__tests__/fields/sort-field.test.ts +133 -0
  335. package/src/__tests__/fields/string-field.test.ts +77 -0
  336. package/src/__tests__/filter-parser.test.ts +104 -0
  337. package/src/__tests__/fixtures/c0/a.ts +6 -0
  338. package/src/__tests__/fixtures/c1/b.ts +6 -0
  339. package/src/__tests__/fixtures/c2/a.ts +6 -0
  340. package/src/__tests__/fixtures/collections/delay-extend.ts +6 -0
  341. package/src/__tests__/fixtures/collections/delay-extend2.ts +6 -0
  342. package/src/__tests__/fixtures/collections/extend.ts +6 -0
  343. package/src/__tests__/fixtures/collections/extend2.ts +6 -0
  344. package/src/__tests__/fixtures/collections/posts.ts +4 -0
  345. package/src/__tests__/fixtures/collections/tags.js +4 -0
  346. package/src/__tests__/fixtures/collections/test.jpg +0 -0
  347. package/src/__tests__/fixtures/collections/user.json +9 -0
  348. package/src/__tests__/index.ts +1 -0
  349. package/src/__tests__/magic-attribute-model.test.ts +103 -0
  350. package/src/__tests__/model.test.ts +60 -0
  351. package/src/__tests__/operator/array-operator.test.ts +268 -0
  352. package/src/__tests__/operator/association-operator.test.ts +263 -0
  353. package/src/__tests__/operator/date-operator.test.ts +165 -0
  354. package/src/__tests__/operator/empty-operator.test.ts +77 -0
  355. package/src/__tests__/operator/ne.test.ts +33 -0
  356. package/src/__tests__/operator/string-operator.test.ts +62 -0
  357. package/src/__tests__/option-parser.test.ts +185 -0
  358. package/src/__tests__/relation-repository/belongs-to-many-repository.test.ts +697 -0
  359. package/src/__tests__/relation-repository/has-many-repository.test.ts +414 -0
  360. package/src/__tests__/relation-repository/hasone-repository.test.ts +77 -0
  361. package/src/__tests__/repository/count.test.ts +180 -0
  362. package/src/__tests__/repository/create.test.ts +163 -0
  363. package/src/__tests__/repository/destroy.test.ts +196 -0
  364. package/src/__tests__/repository/find.test.ts +247 -0
  365. package/src/__tests__/repository/update.test.ts +60 -0
  366. package/src/__tests__/repository.test.ts +438 -0
  367. package/src/__tests__/update-associations.test.ts +412 -0
  368. package/src/__tests__/update-guard.test.ts +376 -0
  369. package/src/collection-importer.ts +49 -0
  370. package/src/collection.ts +282 -0
  371. package/src/database.ts +340 -0
  372. package/src/fields/array-field.ts +35 -0
  373. package/src/fields/belongs-to-field.ts +76 -0
  374. package/src/fields/belongs-to-many-field.ts +77 -0
  375. package/src/fields/boolean-field.ts +12 -0
  376. package/src/fields/context-field.ts +45 -0
  377. package/src/fields/date-field.ts +12 -0
  378. package/src/fields/field.ts +105 -0
  379. package/src/fields/has-inverse-field.ts +5 -0
  380. package/src/fields/has-many-field.ts +143 -0
  381. package/src/fields/has-one-field.ts +136 -0
  382. package/src/fields/index.ts +72 -0
  383. package/src/fields/json-field.ts +25 -0
  384. package/src/fields/number-field.ts +52 -0
  385. package/src/fields/password-field.ts +72 -0
  386. package/src/fields/radio-field.ts +50 -0
  387. package/src/fields/relation-field.ts +37 -0
  388. package/src/fields/sort-field.ts +96 -0
  389. package/src/fields/string-field.ts +12 -0
  390. package/src/fields/text-field.ts +12 -0
  391. package/src/fields/time-field.ts +12 -0
  392. package/src/fields/uid-field.ts +24 -0
  393. package/src/fields/virtual-field.ts +12 -0
  394. package/src/filter-parser.ts +243 -0
  395. package/src/index.ts +16 -0
  396. package/src/magic-attribute-model.ts +62 -0
  397. package/src/mock-database.ts +42 -0
  398. package/src/model-hook.ts +69 -0
  399. package/src/model.ts +114 -0
  400. package/src/operators/array.ts +145 -0
  401. package/src/operators/association.ts +14 -0
  402. package/src/operators/date.ts +41 -0
  403. package/src/operators/empty.ts +75 -0
  404. package/src/operators/index.ts +8 -0
  405. package/src/operators/ne.ts +12 -0
  406. package/src/operators/string.ts +40 -0
  407. package/src/operators/utils.ts +13 -0
  408. package/src/options-parser.ts +285 -0
  409. package/src/playground.ts +52 -0
  410. package/src/relation-repository/belongs-to-many-repository.ts +240 -0
  411. package/src/relation-repository/belongs-to-repository.ts +23 -0
  412. package/src/relation-repository/hasmany-repository.ts +145 -0
  413. package/src/relation-repository/hasone-repository.ts +23 -0
  414. package/src/relation-repository/multiple-relation-repository.ts +198 -0
  415. package/src/relation-repository/relation-repository.ts +114 -0
  416. package/src/relation-repository/single-relation-repository.ts +99 -0
  417. package/src/relation-repository/types.ts +15 -0
  418. package/src/repository.ts +478 -0
  419. package/src/transaction-decorator.ts +58 -0
  420. package/src/update-associations.ts +478 -0
  421. package/src/update-guard.ts +167 -0
  422. package/tsconfig.build.json +9 -0
  423. package/tsconfig.json +5 -0
  424. package/examples/index.ts +0 -125
  425. package/examples/plugins/db-driven/index.ts +0 -25
  426. package/examples/plugins/db-driven/tables/fields.ts +0 -78
  427. package/examples/plugins/db-driven/tables/tables.ts +0 -53
  428. package/examples/tables/bar.js +0 -26
  429. package/examples/tables/comments.ts +0 -19
  430. package/examples/tables/foo.json +0 -3
  431. package/examples/tables/posts.ts +0 -28
  432. package/examples/tables/profiles.ts +0 -23
  433. package/examples/tables/tags.ts +0 -15
  434. package/examples/tables/users.ts +0 -34
  435. package/lib/database.d.ts.map +0 -1
  436. package/lib/fields/field-types.d.ts +0 -419
  437. package/lib/fields/field-types.d.ts.map +0 -1
  438. package/lib/fields/field-types.js +0 -1222
  439. package/lib/fields/field-types.js.map +0 -1
  440. package/lib/fields/index.d.ts.map +0 -1
  441. package/lib/fields/option-types.d.ts +0 -105
  442. package/lib/fields/option-types.d.ts.map +0 -1
  443. package/lib/fields/option-types.js +0 -18
  444. package/lib/fields/option-types.js.map +0 -1
  445. package/lib/index.d.ts.map +0 -1
  446. package/lib/model.d.ts.map +0 -1
  447. package/lib/op.d.ts +0 -45
  448. package/lib/op.d.ts.map +0 -1
  449. package/lib/op.js +0 -225
  450. package/lib/op.js.map +0 -1
  451. package/lib/table.d.ts +0 -56
  452. package/lib/table.d.ts.map +0 -1
  453. package/lib/table.js +0 -456
  454. package/lib/table.js.map +0 -1
  455. package/lib/utils.d.ts +0 -26
  456. package/lib/utils.d.ts.map +0 -1
  457. package/lib/utils.js +0 -438
  458. package/lib/utils.js.map +0 -1
@@ -0,0 +1,145 @@
1
+ import { Op, Sequelize } from 'sequelize';
2
+ import { isPg, isMySQL } from './utils';
3
+
4
+ const getFieldName = (ctx) => {
5
+ const fieldName = ctx.fieldName;
6
+ return fieldName;
7
+ };
8
+
9
+ const escape = (value, ctx) => {
10
+ const sequelize: Sequelize = ctx.db.sequelize;
11
+ return sequelize.escape(value);
12
+ };
13
+
14
+ const sqliteExistQuery = (value, ctx) => {
15
+ const fieldName = getFieldName(ctx);
16
+
17
+ const sqlArray = `(${value.map((v) => `'${v}'`).join(', ')})`;
18
+
19
+ const subQuery = `exists (select * from json_each(${fieldName}) where json_each.value in ${sqlArray})`;
20
+
21
+ return subQuery;
22
+ };
23
+
24
+ const emptyQuery = (ctx, operator: '=' | '>') => {
25
+ const fieldName = getFieldName(ctx);
26
+
27
+ let funcName = 'json_array_length';
28
+ let ifNull = 'IFNULL';
29
+
30
+ if (isPg(ctx)) {
31
+ funcName = 'jsonb_array_length';
32
+ ifNull = 'coalesce';
33
+ }
34
+
35
+ if (isMySQL(ctx)) {
36
+ funcName = 'json_length';
37
+ }
38
+
39
+ return `(select ${ifNull}(${funcName}(${fieldName}), 0) ${operator} 0)`;
40
+ };
41
+
42
+ export default {
43
+ $match(value, ctx) {
44
+ const fieldName = getFieldName(ctx);
45
+
46
+ if (isPg(ctx)) {
47
+ return {
48
+ [Op.contained]: value,
49
+ [Op.contains]: value,
50
+ };
51
+ }
52
+
53
+ value = escape(JSON.stringify(value.sort()), ctx);
54
+
55
+ if (isMySQL(ctx)) {
56
+ return Sequelize.literal(`JSON_CONTAINS(${fieldName}, ${value}) AND JSON_CONTAINS(${value}, ${fieldName})`);
57
+ }
58
+
59
+ return {
60
+ [Op.eq]: Sequelize.literal(`json(${value})`),
61
+ };
62
+ },
63
+
64
+ $notMatch(value, ctx) {
65
+ const fieldName = getFieldName(ctx);
66
+ value = escape(JSON.stringify(value), ctx);
67
+
68
+ if (isPg(ctx)) {
69
+ return Sequelize.literal(`not (${fieldName} <@ ${value}::JSONB and ${fieldName} @> ${value}::JSONB)`);
70
+ }
71
+
72
+ if (isMySQL(ctx)) {
73
+ return Sequelize.literal(`not (JSON_CONTAINS(${fieldName}, ${value}) AND JSON_CONTAINS(${value}, ${fieldName}))`);
74
+ }
75
+ return {
76
+ [Op.ne]: Sequelize.literal(`json(${value})`),
77
+ };
78
+ },
79
+
80
+ $anyOf(value, ctx) {
81
+ const fieldName = getFieldName(ctx);
82
+
83
+ if (isPg(ctx)) {
84
+ return Sequelize.literal(
85
+ `${fieldName} ?| ${escape(
86
+ value.map((i) => `${i}`),
87
+ ctx,
88
+ )}`,
89
+ );
90
+ }
91
+
92
+ if (isMySQL(ctx)) {
93
+ value = escape(JSON.stringify(value), ctx);
94
+
95
+ return Sequelize.literal(`JSON_OVERLAPS(${fieldName}, ${value})`);
96
+ }
97
+
98
+ const subQuery = sqliteExistQuery(value, ctx);
99
+
100
+ return Sequelize.literal(subQuery);
101
+ },
102
+
103
+ $noneOf(value, ctx) {
104
+ let where;
105
+
106
+ if (isPg(ctx)) {
107
+ const fieldName = getFieldName(ctx);
108
+ // pg single quote
109
+ where = Sequelize.literal(
110
+ `not (${fieldName} ?| ${escape(
111
+ value.map((i) => `${i}`),
112
+ ctx,
113
+ )})`,
114
+ );
115
+ } else if (isMySQL(ctx)) {
116
+ const fieldName = getFieldName(ctx);
117
+ value = escape(JSON.stringify(value), ctx);
118
+ where = Sequelize.literal(`NOT JSON_OVERLAPS(${fieldName}, ${value})`);
119
+ } else {
120
+ const subQuery = sqliteExistQuery(value, ctx);
121
+
122
+ where = Sequelize.literal(`not ${subQuery}`);
123
+ }
124
+
125
+ return {
126
+ [Op.or]: [where, { [Op.is]: null }],
127
+ };
128
+ },
129
+
130
+ $arrayEmpty(value, ctx) {
131
+ const subQuery = emptyQuery(ctx, '=');
132
+
133
+ return {
134
+ [Op.and]: [Sequelize.literal(`${subQuery}`)],
135
+ };
136
+ },
137
+
138
+ $arrayNotEmpty(value, ctx) {
139
+ const subQuery = emptyQuery(ctx, '>');
140
+
141
+ return {
142
+ [Op.and]: [Sequelize.literal(`${subQuery}`)],
143
+ };
144
+ },
145
+ };
@@ -0,0 +1,14 @@
1
+ import { Op, Sequelize } from 'sequelize';
2
+
3
+ export default {
4
+ $exists(value, ctx) {
5
+ return {
6
+ [Op.not]: null,
7
+ };
8
+ },
9
+ $notExists(value, ctx) {
10
+ return {
11
+ [Op.is]: null,
12
+ };
13
+ },
14
+ };
@@ -0,0 +1,41 @@
1
+ import { Op } from 'sequelize';
2
+ import moment, { MomentInput } from 'moment';
3
+ function stringToDate(value: string): Date {
4
+ return moment(value).toDate();
5
+ }
6
+
7
+ function getNextDay(value: MomentInput): Date {
8
+ return moment(value).add(1, 'd').toDate();
9
+ }
10
+
11
+ export default {
12
+ $dateOn(value) {
13
+ return {
14
+ [Op.and]: [{ [Op.gte]: stringToDate(value) }, { [Op.lt]: getNextDay(value) }],
15
+ };
16
+ },
17
+
18
+ $dateNotOn(value) {
19
+ return {
20
+ [Op.or]: [{ [Op.lt]: stringToDate(value) }, { [Op.gte]: getNextDay(value) }],
21
+ };
22
+ },
23
+
24
+ $dateBefore(value) {
25
+ return { [Op.lt]: stringToDate(value) };
26
+ },
27
+
28
+ $dateNotBefore(value) {
29
+ return {
30
+ [Op.gte]: stringToDate(value),
31
+ };
32
+ },
33
+
34
+ $dateAfter(value) {
35
+ return { [Op.gte]: getNextDay(value) };
36
+ },
37
+
38
+ $dateNotAfter(value) {
39
+ return { [Op.lt]: getNextDay(value) };
40
+ },
41
+ };
@@ -0,0 +1,75 @@
1
+ import { DataTypes, Op } from 'sequelize';
2
+ import { ArrayField, StringField } from '../fields';
3
+ import arrayOperators from './array';
4
+ import lodash, { parseInt } from 'lodash';
5
+
6
+ const findFilterFieldType = (ctx) => {
7
+ const db = ctx.db;
8
+
9
+ let path = ctx.path.split('.');
10
+
11
+ // remove operators
12
+ path.pop();
13
+
14
+ const fieldName = path.pop();
15
+
16
+ let model = ctx.model;
17
+
18
+ const associationPath = path;
19
+
20
+ for (const association of associationPath) {
21
+ if (lodash.isNumber(parseInt(association)) || association.startsWith('$')) {
22
+ continue;
23
+ }
24
+
25
+ model = model.associations[association].target;
26
+ }
27
+
28
+ const collection = db.modelCollection.get(model);
29
+
30
+ return collection.getField(fieldName);
31
+ };
32
+
33
+ export default {
34
+ $empty(_, ctx) {
35
+ const field = findFilterFieldType(ctx);
36
+
37
+ if (field instanceof StringField) {
38
+ return {
39
+ [Op.or]: {
40
+ [Op.is]: null,
41
+ [Op.eq]: '',
42
+ },
43
+ };
44
+ }
45
+
46
+ if (field instanceof ArrayField) {
47
+ return arrayOperators.$arrayEmpty(_, ctx);
48
+ }
49
+
50
+ return {
51
+ [Op.is]: null,
52
+ };
53
+ },
54
+
55
+ $notEmpty(_, ctx) {
56
+ const field = findFilterFieldType(ctx);
57
+
58
+ if (field instanceof StringField) {
59
+ return {
60
+ [Op.and]: {
61
+ [Op.not]: null,
62
+ [Op.ne]: '',
63
+ },
64
+ };
65
+ }
66
+
67
+ if (field instanceof ArrayField) {
68
+ return arrayOperators.$arrayNotEmpty(_, ctx);
69
+ }
70
+
71
+ return {
72
+ [Op.not]: null,
73
+ };
74
+ },
75
+ };
@@ -0,0 +1,8 @@
1
+ export default {
2
+ ...require('./association').default,
3
+ ...require('./date').default,
4
+ ...require('./array').default,
5
+ ...require('./empty').default,
6
+ ...require('./string').default,
7
+ ...require('./ne').default,
8
+ };
@@ -0,0 +1,12 @@
1
+ import { Op } from 'sequelize';
2
+
3
+ export default {
4
+ $ne(val, ctx) {
5
+ return {
6
+ [Op.or]: {
7
+ [Op.ne]: val,
8
+ [Op.is]: null,
9
+ },
10
+ };
11
+ },
12
+ };
@@ -0,0 +1,40 @@
1
+ import { isPg } from './utils';
2
+ import { Op } from 'sequelize';
3
+
4
+ export default {
5
+ $includes(value, ctx) {
6
+ return {
7
+ [isPg(ctx) ? Op.iLike : Op.like]: `%${value}%`,
8
+ };
9
+ },
10
+
11
+ $notIncludes(value, ctx) {
12
+ return {
13
+ [isPg(ctx) ? Op.notILike : Op.notLike]: `%${value}%`,
14
+ };
15
+ },
16
+
17
+ $startsWith(value, ctx) {
18
+ return {
19
+ [isPg(ctx) ? Op.iLike : Op.like]: `${value}%`,
20
+ };
21
+ },
22
+
23
+ $notStartsWith(value, ctx) {
24
+ return {
25
+ [isPg(ctx) ? Op.notILike : Op.notLike]: `${value}%`,
26
+ };
27
+ },
28
+
29
+ $endWith(value, ctx) {
30
+ return {
31
+ [isPg(ctx) ? Op.iLike : Op.like]: `%${value}`,
32
+ };
33
+ },
34
+
35
+ $notEndWith(value, ctx) {
36
+ return {
37
+ [isPg(ctx) ? Op.notILike : Op.notLike]: `%${value}`,
38
+ };
39
+ },
40
+ };
@@ -0,0 +1,13 @@
1
+ const getDialect = (ctx) => {
2
+ return ctx.db.sequelize.getDialect();
3
+ };
4
+
5
+ const isPg = (ctx) => {
6
+ return getDialect(ctx) === 'postgres';
7
+ };
8
+
9
+ const isMySQL = (ctx) => {
10
+ return getDialect(ctx) === 'mysql';
11
+ };
12
+
13
+ export { getDialect, isPg, isMySQL };
@@ -0,0 +1,285 @@
1
+ import { FindAttributeOptions, ModelCtor, Op } from 'sequelize';
2
+ import { Collection } from './collection';
3
+ import { Database } from './database';
4
+ import FilterParser from './filter-parser';
5
+ import { Appends, Except, FindOptions } from './repository';
6
+
7
+ const debug = require('debug')('noco-database');
8
+
9
+ interface OptionsParserContext {
10
+ collection: Collection;
11
+ targetKey?: string;
12
+ }
13
+
14
+ export class OptionsParser {
15
+ options: FindOptions;
16
+ database: Database;
17
+ collection: Collection;
18
+ model: ModelCtor<any>;
19
+ filterParser: FilterParser;
20
+ context: OptionsParserContext;
21
+
22
+ constructor(options: FindOptions, context: OptionsParserContext) {
23
+ const { collection } = context;
24
+
25
+ this.collection = collection;
26
+ this.model = collection.model;
27
+ this.options = options;
28
+ this.database = collection.context.database;
29
+ this.filterParser = new FilterParser(options?.filter, {
30
+ collection,
31
+ app: {
32
+ ctx: options?.context,
33
+ },
34
+ });
35
+ this.context = context;
36
+ }
37
+
38
+ isAssociation(key: string) {
39
+ return this.model.associations[key] !== undefined;
40
+ }
41
+
42
+ isAssociationPath(path: string) {
43
+ return this.isAssociation(path.split('.')[0]);
44
+ }
45
+
46
+ toSequelizeParams() {
47
+ const queryParams = this.filterParser.toSequelizeParams();
48
+
49
+ if (this.options?.filterByTk) {
50
+ queryParams.where = {
51
+ [Op.and]: [
52
+ queryParams.where,
53
+ {
54
+ [this.context.targetKey || this.collection.filterTargetKey]: this.options.filterByTk,
55
+ },
56
+ ],
57
+ };
58
+ }
59
+
60
+ return this.parseSort(this.parseFields(queryParams));
61
+ }
62
+
63
+ /**
64
+ * parser sort options
65
+ * @param filterParams
66
+ * @protected
67
+ */
68
+ protected parseSort(filterParams) {
69
+ let sort = this.options?.sort || [];
70
+ if (typeof sort === 'string') {
71
+ sort = sort.split(',');
72
+ }
73
+ const orderParams = sort.map((sortKey: string) => {
74
+ const direction = sortKey.startsWith('-') ? 'DESC' : 'ASC';
75
+ const sortField: Array<any> = sortKey.replace('-', '').split('.');
76
+
77
+ // handle sort by association
78
+ if (sortField.length > 1) {
79
+ let associationModel = this.model;
80
+
81
+ for (let i = 0; i < sortField.length - 1; i++) {
82
+ const associationKey = sortField[i];
83
+ sortField[i] = associationModel.associations[associationKey].target;
84
+ associationModel = sortField[i];
85
+ }
86
+ }
87
+
88
+ sortField.push(direction);
89
+ return sortField;
90
+ });
91
+
92
+ if (orderParams.length > 0) {
93
+ return {
94
+ order: orderParams,
95
+ ...filterParams,
96
+ };
97
+ }
98
+
99
+ return filterParams;
100
+ }
101
+
102
+ protected parseFields(filterParams: any) {
103
+ const appends = this.options?.appends || [];
104
+ const except = [];
105
+
106
+ let attributes: FindAttributeOptions = {
107
+ include: [],
108
+ exclude: [],
109
+ }; // out put all fields by default
110
+
111
+ if (this.options?.fields) {
112
+ // 将fields拆分为 attributes 和 appends
113
+ for (const field of this.options.fields) {
114
+ if (this.isAssociationPath(field)) {
115
+ // field is association field
116
+ appends.push(field);
117
+ } else {
118
+ // field is model attribute, change attributes to array type
119
+ if (!Array.isArray(attributes)) attributes = [];
120
+
121
+ attributes.push(field);
122
+ }
123
+ }
124
+ }
125
+
126
+ if (this.options?.except) {
127
+ for (const exceptKey of this.options.except) {
128
+ if (this.isAssociationPath(exceptKey)) {
129
+ // except association field
130
+ except.push(exceptKey);
131
+ } else {
132
+ // if attributes is array form, ignore except
133
+ if (Array.isArray(attributes)) continue;
134
+ attributes.exclude.push(exceptKey);
135
+ }
136
+ }
137
+ }
138
+
139
+ return {
140
+ attributes,
141
+ ...this.parseExcept(except, this.parseAppends(appends, filterParams)),
142
+ };
143
+ }
144
+
145
+ protected parseExcept(except: Except, filterParams: any) {
146
+ if (!except) return filterParams;
147
+ const setExcept = (queryParams: any, except: string) => {
148
+ // split exceptKey to path form
149
+ // posts.comments.content => ['posts', 'comments', 'content']
150
+ // then set except on include attributes
151
+ const exceptPath = except.split('.');
152
+ const association = exceptPath[0];
153
+ const lastLevel = exceptPath.length <= 2;
154
+
155
+ let existIncludeIndex = queryParams['include'].findIndex((include) => include['association'] == association);
156
+
157
+ if (existIncludeIndex == -1) {
158
+ // if include not exists, ignore this except
159
+ return;
160
+ }
161
+
162
+ if (lastLevel) {
163
+ // if it not have exclude form
164
+ if (Array.isArray(queryParams['include'][existIncludeIndex]['attributes'])) {
165
+ return;
166
+ } else {
167
+ if (!queryParams['include'][existIncludeIndex]['attributes']['exclude']) {
168
+ queryParams['include'][existIncludeIndex]['attributes']['exclude'] = [];
169
+ }
170
+
171
+ queryParams['include'][existIncludeIndex]['attributes']['exclude'].push(exceptPath[1]);
172
+ }
173
+ } else {
174
+ setExcept(queryParams['include'][existIncludeIndex], exceptPath.filter((_, index) => index !== 0).join('.'));
175
+ }
176
+ };
177
+
178
+ for (const exceptKey of except) {
179
+ setExcept(filterParams, exceptKey);
180
+ }
181
+
182
+ return filterParams;
183
+ }
184
+
185
+ protected parseAppends(appends: Appends, filterParams: any) {
186
+ if (!appends) return filterParams;
187
+
188
+ /**
189
+ * set include params
190
+ * @param includeRoot
191
+ * @param appends
192
+ */
193
+ const setInclude = (model: ModelCtor<any>, queryParams: any, append: string) => {
194
+ const appendFields = append.split('.');
195
+ const appendAssociation = appendFields[0];
196
+
197
+ const associations = model.associations;
198
+
199
+ // if append length less or equal 2
200
+ // example:
201
+ // appends: ['posts']
202
+ // appends: ['posts.title']
203
+ // All of these can be seen as last level
204
+ let lastLevel: boolean = false;
205
+
206
+ if (appendFields.length == 1) {
207
+ lastLevel = true;
208
+ }
209
+
210
+ if (appendFields.length == 2) {
211
+ const associationModel = associations[appendFields[0]].target;
212
+ if (associationModel.rawAttributes[appendFields[1]]) {
213
+ lastLevel = true;
214
+ }
215
+ }
216
+
217
+ // find association index
218
+ if (queryParams['include'] == undefined) {
219
+ queryParams['include'] = [];
220
+ }
221
+
222
+ let existIncludeIndex = queryParams['include'].findIndex(
223
+ (include) => include['association'] == appendAssociation,
224
+ );
225
+
226
+ // if association not exist, create it
227
+ if (existIncludeIndex == -1) {
228
+ // association not exists
229
+ queryParams['include'].push({
230
+ association: appendAssociation,
231
+ });
232
+
233
+ existIncludeIndex = 0;
234
+ }
235
+
236
+ // end appends
237
+ // without nests association
238
+ if (lastLevel) {
239
+ // get exist association attributes
240
+ let attributes = queryParams['include'][existIncludeIndex]['attributes'] || {
241
+ include: [], // all fields are output by default
242
+ };
243
+
244
+ // if need set attribute
245
+ if (appendFields.length == 2) {
246
+ if (!Array.isArray(attributes)) {
247
+ attributes = [];
248
+ }
249
+
250
+ const attributeName = appendFields[1];
251
+
252
+ // push field to it
253
+ attributes.push(attributeName);
254
+ } else {
255
+ // if attributes is empty array, change it to object
256
+ if (Array.isArray(attributes) && attributes.length == 0) {
257
+ attributes = {
258
+ include: [],
259
+ };
260
+ }
261
+ }
262
+
263
+ // set new attributes
264
+ queryParams['include'][existIncludeIndex] = {
265
+ ...queryParams['include'][existIncludeIndex],
266
+ attributes,
267
+ };
268
+ } else {
269
+ setInclude(
270
+ model.associations[queryParams['include'][existIncludeIndex].association].target,
271
+ queryParams['include'][existIncludeIndex],
272
+ appendFields.filter((_, index) => index !== 0).join('.'),
273
+ );
274
+ }
275
+ };
276
+
277
+ // handle every appends
278
+ for (const append of appends) {
279
+ setInclude(this.model, filterParams, append);
280
+ }
281
+
282
+ debug('filter params: %o', filterParams);
283
+ return filterParams;
284
+ }
285
+ }
@@ -0,0 +1,52 @@
1
+ import { Database } from './database';
2
+ import FilterParser from './filter-parser';
3
+
4
+ const db = new Database({
5
+ dialect: 'sqlite',
6
+ dialectModule: require('sqlite3'),
7
+ storage: ':memory:',
8
+ });
9
+
10
+ (async () => {
11
+ const User = db.collection({
12
+ name: 'users',
13
+ fields: [{ type: 'string', name: 'name' }],
14
+ });
15
+
16
+ const Post = db.collection({
17
+ name: 'posts',
18
+ fields: [
19
+ { type: 'string', name: 'title' },
20
+ {
21
+ type: 'belongsTo',
22
+ name: 'user',
23
+ },
24
+ ],
25
+ });
26
+
27
+ await db.sync();
28
+
29
+ const repository = User.repository;
30
+
31
+ await repository.createMany({
32
+ records: [
33
+ { name: 'u1', posts: [{ title: 'u1t1' }] },
34
+ { name: 'u2', posts: [{ title: 'u2t1' }] },
35
+ { name: 'u3', posts: [{ title: 'u3t1' }] },
36
+ ],
37
+ });
38
+
39
+ const Model = User.model;
40
+ const user = await Model.findOne({
41
+ subQuery: false,
42
+ where: {
43
+ '$posts.title$': 'u1t1',
44
+ },
45
+ include: { association: 'posts', attributes: [] },
46
+ attributes: {
47
+ include: [],
48
+ },
49
+ });
50
+
51
+ console.log(user.toJSON());
52
+ })();