@loopback/repository 4.0.0-alpha.8 → 4.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 (463) hide show
  1. package/LICENSE +25 -0
  2. package/README.md +93 -389
  3. package/dist/common-types.d.ts +96 -0
  4. package/dist/common-types.js +24 -0
  5. package/dist/common-types.js.map +1 -0
  6. package/dist/connectors/connector.d.ts +48 -0
  7. package/{lib → dist/connectors}/connector.js +1 -1
  8. package/dist/connectors/connector.js.map +1 -0
  9. package/{lib/crud-connector.d.ts → dist/connectors/crud.connector.d.ts} +51 -51
  10. package/{lib/common-types.js → dist/connectors/crud.connector.js} +2 -2
  11. package/dist/connectors/crud.connector.js.map +1 -0
  12. package/dist/connectors/index.d.ts +3 -0
  13. package/dist/connectors/index.js +11 -0
  14. package/dist/connectors/index.js.map +1 -0
  15. package/{lib6/kv-connector.d.ts → dist/connectors/kv.connector.d.ts} +28 -28
  16. package/{lib/datasource.js → dist/connectors/kv.connector.js} +2 -2
  17. package/dist/connectors/kv.connector.js.map +1 -0
  18. package/dist/datasource.d.ts +27 -0
  19. package/{lib6 → dist}/datasource.js +1 -1
  20. package/dist/datasource.js.map +1 -0
  21. package/dist/decorators/index.d.ts +3 -0
  22. package/dist/decorators/index.js +11 -0
  23. package/dist/decorators/index.js.map +1 -0
  24. package/dist/decorators/metadata.d.ts +12 -0
  25. package/dist/decorators/metadata.js +51 -0
  26. package/dist/decorators/metadata.js.map +1 -0
  27. package/dist/decorators/model.decorator.d.ts +40 -0
  28. package/dist/decorators/model.decorator.js +112 -0
  29. package/dist/decorators/model.decorator.js.map +1 -0
  30. package/dist/decorators/repository.decorator.d.ts +106 -0
  31. package/dist/decorators/repository.decorator.js +114 -0
  32. package/dist/decorators/repository.decorator.js.map +1 -0
  33. package/dist/define-model-class.d.ts +55 -0
  34. package/dist/define-model-class.js +57 -0
  35. package/dist/define-model-class.js.map +1 -0
  36. package/dist/define-repository-class.d.ts +119 -0
  37. package/dist/define-repository-class.js +98 -0
  38. package/dist/define-repository-class.js.map +1 -0
  39. package/dist/errors/entity-not-found.error.d.ts +8 -0
  40. package/dist/errors/entity-not-found.error.js +28 -0
  41. package/dist/errors/entity-not-found.error.js.map +1 -0
  42. package/dist/errors/index.d.ts +2 -0
  43. package/dist/errors/index.js +10 -0
  44. package/dist/errors/index.js.map +1 -0
  45. package/dist/errors/invalid-relation.error.d.ts +10 -0
  46. package/dist/errors/invalid-relation.error.js +28 -0
  47. package/dist/errors/invalid-relation.error.js.map +1 -0
  48. package/dist/index.d.ts +30 -0
  49. package/dist/index.js +39 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/keys.d.ts +34 -0
  52. package/dist/keys.js +44 -0
  53. package/dist/keys.js.map +1 -0
  54. package/dist/mixins/index.d.ts +1 -0
  55. package/dist/mixins/index.js +9 -0
  56. package/dist/mixins/index.js.map +1 -0
  57. package/dist/mixins/repository.mixin.d.ts +377 -0
  58. package/dist/mixins/repository.mixin.js +405 -0
  59. package/dist/mixins/repository.mixin.js.map +1 -0
  60. package/dist/model.d.ts +232 -0
  61. package/dist/model.js +367 -0
  62. package/dist/model.js.map +1 -0
  63. package/dist/relations/belongs-to/belongs-to.accessor.d.ts +17 -0
  64. package/dist/relations/belongs-to/belongs-to.accessor.js +40 -0
  65. package/dist/relations/belongs-to/belongs-to.accessor.js.map +1 -0
  66. package/dist/relations/belongs-to/belongs-to.decorator.d.ts +11 -0
  67. package/dist/relations/belongs-to/belongs-to.decorator.js +64 -0
  68. package/dist/relations/belongs-to/belongs-to.decorator.js.map +1 -0
  69. package/dist/relations/belongs-to/belongs-to.helpers.d.ts +17 -0
  70. package/dist/relations/belongs-to/belongs-to.helpers.js +63 -0
  71. package/dist/relations/belongs-to/belongs-to.helpers.js.map +1 -0
  72. package/dist/relations/belongs-to/belongs-to.inclusion-resolver.d.ts +14 -0
  73. package/dist/relations/belongs-to/belongs-to.inclusion-resolver.js +36 -0
  74. package/dist/relations/belongs-to/belongs-to.inclusion-resolver.js.map +1 -0
  75. package/dist/relations/belongs-to/belongs-to.repository.d.ts +28 -0
  76. package/dist/relations/belongs-to/belongs-to.repository.js +33 -0
  77. package/dist/relations/belongs-to/belongs-to.repository.js.map +1 -0
  78. package/dist/relations/belongs-to/index.d.ts +4 -0
  79. package/dist/relations/belongs-to/index.js +12 -0
  80. package/dist/relations/belongs-to/index.js.map +1 -0
  81. package/dist/relations/has-many/has-many-through.helpers.d.ts +182 -0
  82. package/dist/relations/has-many/has-many-through.helpers.js +282 -0
  83. package/dist/relations/has-many/has-many-through.helpers.js.map +1 -0
  84. package/dist/relations/has-many/has-many-through.inclusion-resolver.d.ts +16 -0
  85. package/dist/relations/has-many/has-many-through.inclusion-resolver.js +78 -0
  86. package/dist/relations/has-many/has-many-through.inclusion-resolver.js.map +1 -0
  87. package/dist/relations/has-many/has-many-through.repository-factory.d.ts +17 -0
  88. package/dist/relations/has-many/has-many-through.repository-factory.js +37 -0
  89. package/dist/relations/has-many/has-many-through.repository-factory.js.map +1 -0
  90. package/dist/relations/has-many/has-many-through.repository.d.ts +114 -0
  91. package/dist/relations/has-many/has-many-through.repository.js +103 -0
  92. package/dist/relations/has-many/has-many-through.repository.js.map +1 -0
  93. package/dist/relations/has-many/has-many.decorator.d.ts +11 -0
  94. package/dist/relations/has-many/has-many.decorator.js +36 -0
  95. package/dist/relations/has-many/has-many.decorator.js.map +1 -0
  96. package/dist/relations/has-many/has-many.helpers.d.ts +26 -0
  97. package/dist/relations/has-many/has-many.helpers.js +78 -0
  98. package/dist/relations/has-many/has-many.helpers.js.map +1 -0
  99. package/dist/relations/has-many/has-many.inclusion-resolver.d.ts +14 -0
  100. package/dist/relations/has-many/has-many.inclusion-resolver.js +45 -0
  101. package/dist/relations/has-many/has-many.inclusion-resolver.js.map +1 -0
  102. package/dist/relations/has-many/has-many.repository-factory.d.ts +28 -0
  103. package/dist/relations/has-many/has-many.repository-factory.js +39 -0
  104. package/dist/relations/has-many/has-many.repository-factory.js.map +1 -0
  105. package/dist/relations/has-many/has-many.repository.d.ts +54 -0
  106. package/dist/relations/has-many/has-many.repository.js +38 -0
  107. package/dist/relations/has-many/has-many.repository.js.map +1 -0
  108. package/dist/relations/has-many/index.d.ts +6 -0
  109. package/dist/relations/has-many/index.js +14 -0
  110. package/dist/relations/has-many/index.js.map +1 -0
  111. package/dist/relations/has-one/has-one.decorator.d.ts +3 -0
  112. package/dist/relations/has-one/has-one.decorator.js +37 -0
  113. package/dist/relations/has-one/has-one.decorator.js.map +1 -0
  114. package/dist/relations/has-one/has-one.helpers.d.ts +17 -0
  115. package/dist/relations/has-one/has-one.helpers.js +64 -0
  116. package/dist/relations/has-one/has-one.helpers.js.map +1 -0
  117. package/dist/relations/has-one/has-one.inclusion-resolver.d.ts +14 -0
  118. package/dist/relations/has-one/has-one.inclusion-resolver.js +35 -0
  119. package/dist/relations/has-one/has-one.inclusion-resolver.js.map +1 -0
  120. package/dist/relations/has-one/has-one.repository-factory.d.ts +28 -0
  121. package/dist/relations/has-one/has-one.repository-factory.js +39 -0
  122. package/dist/relations/has-one/has-one.repository-factory.js.map +1 -0
  123. package/dist/relations/has-one/has-one.repository.d.ts +53 -0
  124. package/dist/relations/has-one/has-one.repository.js +45 -0
  125. package/dist/relations/has-one/has-one.repository.js.map +1 -0
  126. package/dist/relations/has-one/index.d.ts +3 -0
  127. package/dist/relations/has-one/index.js +11 -0
  128. package/dist/relations/has-one/index.js.map +1 -0
  129. package/dist/relations/index.d.ts +6 -0
  130. package/dist/relations/index.js +14 -0
  131. package/dist/relations/index.js.map +1 -0
  132. package/dist/relations/relation.decorator.d.ts +39 -0
  133. package/dist/relations/relation.decorator.js +88 -0
  134. package/dist/relations/relation.decorator.js.map +1 -0
  135. package/dist/relations/relation.helpers.d.ts +105 -0
  136. package/dist/relations/relation.helpers.js +304 -0
  137. package/dist/relations/relation.helpers.js.map +1 -0
  138. package/dist/relations/relation.types.d.ts +142 -0
  139. package/dist/relations/relation.types.js +21 -0
  140. package/dist/relations/relation.types.js.map +1 -0
  141. package/dist/repositories/constraint-utils.d.ts +49 -0
  142. package/dist/repositories/constraint-utils.js +87 -0
  143. package/dist/repositories/constraint-utils.js.map +1 -0
  144. package/dist/repositories/index.d.ts +5 -0
  145. package/dist/repositories/index.js +13 -0
  146. package/dist/repositories/index.js.map +1 -0
  147. package/dist/repositories/kv.repository.bridge.d.ts +30 -0
  148. package/dist/repositories/kv.repository.bridge.js +76 -0
  149. package/dist/repositories/kv.repository.bridge.js.map +1 -0
  150. package/dist/repositories/kv.repository.d.ts +74 -0
  151. package/{lib/crud-connector.js → dist/repositories/kv.repository.js} +2 -2
  152. package/dist/repositories/kv.repository.js.map +1 -0
  153. package/dist/repositories/legacy-juggler-bridge.d.ts +305 -0
  154. package/dist/repositories/legacy-juggler-bridge.js +452 -0
  155. package/dist/repositories/legacy-juggler-bridge.js.map +1 -0
  156. package/dist/repositories/repository.d.ts +223 -0
  157. package/dist/repositories/repository.js +157 -0
  158. package/dist/repositories/repository.js.map +1 -0
  159. package/dist/transaction.d.ts +30 -0
  160. package/dist/transaction.js +18 -0
  161. package/dist/transaction.js.map +1 -0
  162. package/dist/type-resolver.d.ts +42 -0
  163. package/dist/type-resolver.js +61 -0
  164. package/dist/type-resolver.js.map +1 -0
  165. package/{lib → dist}/types/any.d.ts +1 -1
  166. package/{lib6 → dist}/types/any.js +3 -2
  167. package/dist/types/any.js.map +1 -0
  168. package/{lib6 → dist}/types/array.d.ts +4 -4
  169. package/{lib → dist}/types/array.js +6 -4
  170. package/dist/types/array.js.map +1 -0
  171. package/{lib → dist}/types/boolean.d.ts +1 -1
  172. package/{lib6 → dist}/types/boolean.js +3 -2
  173. package/dist/types/boolean.js.map +1 -0
  174. package/{lib6 → dist}/types/buffer.d.ts +2 -2
  175. package/{lib → dist}/types/buffer.js +8 -6
  176. package/dist/types/buffer.js.map +1 -0
  177. package/{lib → dist}/types/date.d.ts +1 -1
  178. package/{lib → dist}/types/date.js +6 -4
  179. package/dist/types/date.js.map +1 -0
  180. package/{lib → dist}/types/index.d.ts +11 -9
  181. package/dist/types/index.js +49 -0
  182. package/dist/types/index.js.map +1 -0
  183. package/{lib6 → dist}/types/model.d.ts +2 -1
  184. package/{lib6 → dist}/types/model.js +2 -2
  185. package/dist/types/model.js.map +1 -0
  186. package/dist/types/null.d.ts +12 -0
  187. package/{lib/types/boolean.js → dist/types/null.js} +12 -11
  188. package/dist/types/null.js.map +1 -0
  189. package/{lib6 → dist}/types/number.d.ts +1 -1
  190. package/{lib → dist}/types/number.js +6 -4
  191. package/dist/types/number.js.map +1 -0
  192. package/{lib → dist}/types/object.d.ts +1 -1
  193. package/{lib → dist}/types/object.js +7 -6
  194. package/dist/types/object.js.map +1 -0
  195. package/{lib → dist}/types/string.d.ts +1 -1
  196. package/{lib → dist}/types/string.js +3 -2
  197. package/dist/types/string.js.map +1 -0
  198. package/{lib6 → dist}/types/type.d.ts +7 -7
  199. package/{lib6 → dist}/types/type.js +1 -1
  200. package/dist/types/type.js.map +1 -0
  201. package/{lib → dist}/types/union.d.ts +1 -1
  202. package/{lib → dist}/types/union.js +6 -4
  203. package/dist/types/union.js.map +1 -0
  204. package/package.json +49 -33
  205. package/src/common-types.ts +123 -0
  206. package/src/connectors/connector.ts +70 -0
  207. package/src/connectors/crud.connector.ts +208 -0
  208. package/src/connectors/index.ts +8 -0
  209. package/src/connectors/kv.connector.ts +113 -0
  210. package/src/datasource.ts +37 -0
  211. package/src/decorators/index.ts +8 -0
  212. package/src/decorators/metadata.ts +84 -0
  213. package/src/decorators/model.decorator.ts +166 -0
  214. package/src/decorators/repository.decorator.ts +223 -0
  215. package/src/define-model-class.ts +90 -0
  216. package/src/define-repository-class.ts +170 -0
  217. package/src/errors/entity-not-found.error.ts +40 -0
  218. package/src/errors/index.ts +7 -0
  219. package/src/errors/invalid-relation.error.ts +39 -0
  220. package/src/index.ts +36 -0
  221. package/src/keys.ts +40 -0
  222. package/{index.d.ts → src/mixins/index.ts} +2 -2
  223. package/src/mixins/repository.mixin.ts +499 -0
  224. package/src/model.ts +539 -0
  225. package/src/relations/belongs-to/belongs-to.accessor.ts +74 -0
  226. package/src/relations/belongs-to/belongs-to.decorator.ts +81 -0
  227. package/src/relations/belongs-to/belongs-to.helpers.ts +78 -0
  228. package/src/relations/belongs-to/belongs-to.inclusion-resolver.ts +71 -0
  229. package/src/relations/belongs-to/belongs-to.repository.ts +55 -0
  230. package/src/relations/belongs-to/index.ts +9 -0
  231. package/src/relations/has-many/has-many-through.helpers.ts +361 -0
  232. package/src/relations/has-many/has-many-through.inclusion-resolver.ts +135 -0
  233. package/src/relations/has-many/has-many-through.repository-factory.ts +121 -0
  234. package/src/relations/has-many/has-many-through.repository.ts +318 -0
  235. package/src/relations/has-many/has-many.decorator.ts +38 -0
  236. package/src/relations/has-many/has-many.helpers.ts +100 -0
  237. package/src/relations/has-many/has-many.inclusion-resolver.ts +88 -0
  238. package/src/relations/has-many/has-many.repository-factory.ts +76 -0
  239. package/src/relations/has-many/has-many.repository.ts +118 -0
  240. package/src/relations/has-many/index.ts +11 -0
  241. package/src/relations/has-one/has-one.decorator.ts +40 -0
  242. package/src/relations/has-one/has-one.helpers.ts +84 -0
  243. package/src/relations/has-one/has-one.inclusion-resolver.ts +65 -0
  244. package/src/relations/has-one/has-one.repository-factory.ts +72 -0
  245. package/src/relations/has-one/has-one.repository.ts +127 -0
  246. package/src/relations/has-one/index.ts +8 -0
  247. package/src/relations/index.ts +11 -0
  248. package/src/relations/relation.decorator.ts +90 -0
  249. package/src/relations/relation.helpers.ts +373 -0
  250. package/src/relations/relation.types.ts +180 -0
  251. package/src/repositories/constraint-utils.ts +98 -0
  252. package/src/repositories/index.ts +10 -0
  253. package/src/repositories/kv.repository.bridge.ts +97 -0
  254. package/src/repositories/kv.repository.ts +87 -0
  255. package/src/repositories/legacy-juggler-bridge.ts +788 -0
  256. package/src/repositories/repository.ts +441 -0
  257. package/src/transaction.ts +39 -0
  258. package/src/type-resolver.ts +98 -0
  259. package/src/types/any.ts +38 -0
  260. package/src/types/array.ts +53 -0
  261. package/src/types/boolean.ts +35 -0
  262. package/src/types/buffer.ts +53 -0
  263. package/src/types/date.ts +61 -0
  264. package/src/types/index.ts +52 -0
  265. package/src/types/model.ts +24 -0
  266. package/src/types/null.ts +35 -0
  267. package/src/types/number.ts +42 -0
  268. package/src/types/object.ts +53 -0
  269. package/src/types/string.ts +42 -0
  270. package/src/types/type.ts +51 -0
  271. package/src/types/union.ts +55 -0
  272. package/api-docs/apple-touch-icon-114x114-precomposed.png +0 -0
  273. package/api-docs/apple-touch-icon-144x144-precomposed.png +0 -0
  274. package/api-docs/apple-touch-icon-57x57-precomposed.png +0 -0
  275. package/api-docs/apple-touch-icon-72x72-precomposed.png +0 -0
  276. package/api-docs/apple-touch-icon-precomposed.png +0 -0
  277. package/api-docs/apple-touch-icon.png +0 -0
  278. package/api-docs/css/bootstrap.min.css +0 -9
  279. package/api-docs/css/code-themes/arta.css +0 -158
  280. package/api-docs/css/code-themes/ascetic.css +0 -50
  281. package/api-docs/css/code-themes/brown_paper.css +0 -104
  282. package/api-docs/css/code-themes/brown_papersq.png +0 -0
  283. package/api-docs/css/code-themes/dark.css +0 -103
  284. package/api-docs/css/code-themes/default.css +0 -135
  285. package/api-docs/css/code-themes/far.css +0 -111
  286. package/api-docs/css/code-themes/github.css +0 -127
  287. package/api-docs/css/code-themes/googlecode.css +0 -144
  288. package/api-docs/css/code-themes/idea.css +0 -121
  289. package/api-docs/css/code-themes/ir_black.css +0 -104
  290. package/api-docs/css/code-themes/magula.css +0 -121
  291. package/api-docs/css/code-themes/monokai.css +0 -114
  292. package/api-docs/css/code-themes/pojoaque.css +0 -104
  293. package/api-docs/css/code-themes/pojoaque.jpg +0 -0
  294. package/api-docs/css/code-themes/rainbow.css +0 -114
  295. package/api-docs/css/code-themes/school_book.css +0 -111
  296. package/api-docs/css/code-themes/school_book.png +0 -0
  297. package/api-docs/css/code-themes/sl-theme.css +0 -45
  298. package/api-docs/css/code-themes/solarized_dark.css +0 -88
  299. package/api-docs/css/code-themes/solarized_light.css +0 -88
  300. package/api-docs/css/code-themes/sunburst.css +0 -158
  301. package/api-docs/css/code-themes/tomorrow-night-blue.css +0 -52
  302. package/api-docs/css/code-themes/tomorrow-night-bright.css +0 -51
  303. package/api-docs/css/code-themes/tomorrow-night-eighties.css +0 -51
  304. package/api-docs/css/code-themes/tomorrow-night.css +0 -52
  305. package/api-docs/css/code-themes/tomorrow.css +0 -49
  306. package/api-docs/css/code-themes/vs.css +0 -86
  307. package/api-docs/css/code-themes/xcode.css +0 -154
  308. package/api-docs/css/code-themes/zenburn.css +0 -115
  309. package/api-docs/css/main.css +0 -139
  310. package/api-docs/favicon.ico +0 -0
  311. package/api-docs/fonts/0ihfXUL2emPh0ROJezvraLO3LdcAZYWl9Si6vvxL-qU.woff +0 -0
  312. package/api-docs/fonts/OsJ2DjdpjqFRVUSto6IffLO3LdcAZYWl9Si6vvxL-qU.woff +0 -0
  313. package/api-docs/fonts/_aijTyevf54tkVDLy-dlnLO3LdcAZYWl9Si6vvxL-qU.woff +0 -0
  314. package/api-docs/index.html +0 -18017
  315. package/api-docs/js/main.js +0 -19
  316. package/api-docs/js/vendor/bootstrap.min.js +0 -6
  317. package/api-docs/js/vendor/jquery-1.10.1.min.js +0 -6
  318. package/api-docs/js/vendor/jquery.scrollTo-1.4.3.1.js +0 -218
  319. package/api-docs/js/vendor/modernizr-2.6.2-respond-1.1.0.min.js +0 -11
  320. package/index.js +0 -9
  321. package/lib/common-types.d.ts +0 -44
  322. package/lib/common-types.js.map +0 -1
  323. package/lib/connector.d.ts +0 -12
  324. package/lib/connector.js.map +0 -1
  325. package/lib/crud-connector.js.map +0 -1
  326. package/lib/datasource.d.ts +0 -11
  327. package/lib/datasource.js.map +0 -1
  328. package/lib/decorators/model.d.ts +0 -17
  329. package/lib/decorators/model.js +0 -55
  330. package/lib/decorators/model.js.map +0 -1
  331. package/lib/decorators/relation.d.ts +0 -65
  332. package/lib/decorators/relation.js +0 -126
  333. package/lib/decorators/relation.js.map +0 -1
  334. package/lib/decorators/repository.d.ts +0 -61
  335. package/lib/decorators/repository.js +0 -107
  336. package/lib/decorators/repository.js.map +0 -1
  337. package/lib/index.d.ts +0 -17
  338. package/lib/index.js +0 -21
  339. package/lib/index.js.map +0 -1
  340. package/lib/kv-connector.d.ts +0 -77
  341. package/lib/kv-connector.js +0 -7
  342. package/lib/kv-connector.js.map +0 -1
  343. package/lib/kv-repository.d.ts +0 -78
  344. package/lib/kv-repository.js +0 -7
  345. package/lib/kv-repository.js.map +0 -1
  346. package/lib/legacy-juggler-bridge.d.ts +0 -53
  347. package/lib/legacy-juggler-bridge.js +0 -142
  348. package/lib/legacy-juggler-bridge.js.map +0 -1
  349. package/lib/loopback-datasource-juggler.d.ts +0 -666
  350. package/lib/loopback-datasource-juggler.js +0 -8
  351. package/lib/loopback-datasource-juggler.js.map +0 -1
  352. package/lib/mixin.d.ts +0 -43
  353. package/lib/mixin.js +0 -34
  354. package/lib/mixin.js.map +0 -1
  355. package/lib/model.d.ts +0 -137
  356. package/lib/model.js +0 -182
  357. package/lib/model.js.map +0 -1
  358. package/lib/query.d.ts +0 -112
  359. package/lib/query.js +0 -25
  360. package/lib/query.js.map +0 -1
  361. package/lib/repository-mixin.d.ts +0 -20
  362. package/lib/repository-mixin.js +0 -111
  363. package/lib/repository-mixin.js.map +0 -1
  364. package/lib/repository.d.ts +0 -172
  365. package/lib/repository.js +0 -127
  366. package/lib/repository.js.map +0 -1
  367. package/lib/types/any.js +0 -35
  368. package/lib/types/any.js.map +0 -1
  369. package/lib/types/array.d.ts +0 -14
  370. package/lib/types/array.js.map +0 -1
  371. package/lib/types/boolean.js.map +0 -1
  372. package/lib/types/buffer.d.ts +0 -14
  373. package/lib/types/buffer.js.map +0 -1
  374. package/lib/types/date.js.map +0 -1
  375. package/lib/types/index.js +0 -33
  376. package/lib/types/index.js.map +0 -1
  377. package/lib/types/model.d.ts +0 -11
  378. package/lib/types/model.js +0 -25
  379. package/lib/types/model.js.map +0 -1
  380. package/lib/types/number.d.ts +0 -12
  381. package/lib/types/number.js.map +0 -1
  382. package/lib/types/object.js.map +0 -1
  383. package/lib/types/string.js.map +0 -1
  384. package/lib/types/type.d.ts +0 -38
  385. package/lib/types/type.js +0 -7
  386. package/lib/types/type.js.map +0 -1
  387. package/lib/types/union.js.map +0 -1
  388. package/lib6/common-types.d.ts +0 -44
  389. package/lib6/common-types.js +0 -7
  390. package/lib6/common-types.js.map +0 -1
  391. package/lib6/connector.d.ts +0 -12
  392. package/lib6/connector.js +0 -7
  393. package/lib6/connector.js.map +0 -1
  394. package/lib6/crud-connector.d.ts +0 -130
  395. package/lib6/crud-connector.js +0 -7
  396. package/lib6/crud-connector.js.map +0 -1
  397. package/lib6/datasource.d.ts +0 -11
  398. package/lib6/datasource.js.map +0 -1
  399. package/lib6/decorators/model.d.ts +0 -17
  400. package/lib6/decorators/model.js +0 -55
  401. package/lib6/decorators/model.js.map +0 -1
  402. package/lib6/decorators/relation.d.ts +0 -65
  403. package/lib6/decorators/relation.js +0 -126
  404. package/lib6/decorators/relation.js.map +0 -1
  405. package/lib6/decorators/repository.d.ts +0 -61
  406. package/lib6/decorators/repository.js +0 -117
  407. package/lib6/decorators/repository.js.map +0 -1
  408. package/lib6/index.d.ts +0 -17
  409. package/lib6/index.js +0 -21
  410. package/lib6/index.js.map +0 -1
  411. package/lib6/kv-connector.js +0 -7
  412. package/lib6/kv-connector.js.map +0 -1
  413. package/lib6/kv-repository.d.ts +0 -78
  414. package/lib6/kv-repository.js +0 -7
  415. package/lib6/kv-repository.js.map +0 -1
  416. package/lib6/legacy-juggler-bridge.d.ts +0 -53
  417. package/lib6/legacy-juggler-bridge.js +0 -158
  418. package/lib6/legacy-juggler-bridge.js.map +0 -1
  419. package/lib6/loopback-datasource-juggler.d.ts +0 -666
  420. package/lib6/loopback-datasource-juggler.js +0 -8
  421. package/lib6/loopback-datasource-juggler.js.map +0 -1
  422. package/lib6/mixin.d.ts +0 -43
  423. package/lib6/mixin.js +0 -34
  424. package/lib6/mixin.js.map +0 -1
  425. package/lib6/model.d.ts +0 -137
  426. package/lib6/model.js +0 -182
  427. package/lib6/model.js.map +0 -1
  428. package/lib6/query.d.ts +0 -112
  429. package/lib6/query.js +0 -25
  430. package/lib6/query.js.map +0 -1
  431. package/lib6/repository-mixin.d.ts +0 -20
  432. package/lib6/repository-mixin.js +0 -111
  433. package/lib6/repository-mixin.js.map +0 -1
  434. package/lib6/repository.d.ts +0 -172
  435. package/lib6/repository.js +0 -127
  436. package/lib6/repository.js.map +0 -1
  437. package/lib6/types/any.d.ts +0 -12
  438. package/lib6/types/any.js.map +0 -1
  439. package/lib6/types/array.js +0 -53
  440. package/lib6/types/array.js.map +0 -1
  441. package/lib6/types/boolean.d.ts +0 -12
  442. package/lib6/types/boolean.js.map +0 -1
  443. package/lib6/types/buffer.js +0 -57
  444. package/lib6/types/buffer.js.map +0 -1
  445. package/lib6/types/date.d.ts +0 -12
  446. package/lib6/types/date.js +0 -60
  447. package/lib6/types/date.js.map +0 -1
  448. package/lib6/types/index.d.ts +0 -30
  449. package/lib6/types/index.js +0 -33
  450. package/lib6/types/index.js.map +0 -1
  451. package/lib6/types/model.js.map +0 -1
  452. package/lib6/types/number.js +0 -40
  453. package/lib6/types/number.js.map +0 -1
  454. package/lib6/types/object.d.ts +0 -15
  455. package/lib6/types/object.js +0 -49
  456. package/lib6/types/object.js.map +0 -1
  457. package/lib6/types/string.d.ts +0 -12
  458. package/lib6/types/string.js +0 -40
  459. package/lib6/types/string.js.map +0 -1
  460. package/lib6/types/type.js.map +0 -1
  461. package/lib6/types/union.d.ts +0 -14
  462. package/lib6/types/union.js +0 -51
  463. package/lib6/types/union.js.map +0 -1
@@ -0,0 +1,78 @@
1
+ // Copyright IBM Corp. 2019. All Rights Reserved.
2
+ // Node module: @loopback/repository
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ import debugFactory from 'debug';
7
+ import {camelCase} from 'lodash';
8
+ import {InvalidRelationError} from '../../errors';
9
+ import {isTypeResolver} from '../../type-resolver';
10
+ import {BelongsToDefinition, RelationType} from '../relation.types';
11
+
12
+ const debug = debugFactory('loopback:repository:relations:belongs-to:helpers');
13
+
14
+ /**
15
+ * Relation definition with optional metadata (e.g. `keyTo`) filled in.
16
+ * @internal
17
+ */
18
+ export type BelongsToResolvedDefinition = BelongsToDefinition & {
19
+ keyFrom: string;
20
+ keyTo: string;
21
+ };
22
+
23
+ /**
24
+ * Resolves given belongsTo metadata if target is specified to be a resolver.
25
+ * Mainly used to infer what the `keyTo` property should be from the target's
26
+ * property id metadata
27
+ * @param relationMeta - belongsTo metadata to resolve
28
+ * @internal
29
+ */
30
+ export function resolveBelongsToMetadata(relationMeta: BelongsToDefinition) {
31
+ if ((relationMeta.type as RelationType) !== RelationType.belongsTo) {
32
+ const reason = 'relation type must be BelongsTo';
33
+ throw new InvalidRelationError(reason, relationMeta);
34
+ }
35
+
36
+ if (!isTypeResolver(relationMeta.target)) {
37
+ const reason = 'target must be a type resolver';
38
+ throw new InvalidRelationError(reason, relationMeta);
39
+ }
40
+
41
+ const sourceModel = relationMeta.source;
42
+ if (!sourceModel || !sourceModel.modelName) {
43
+ const reason = 'source model must be defined';
44
+ throw new InvalidRelationError(reason, relationMeta);
45
+ }
46
+
47
+ const targetModel = relationMeta.target();
48
+ const targetName = targetModel.modelName;
49
+ debug('Resolved model %s from given metadata: %o', targetName, targetModel);
50
+
51
+ let keyFrom;
52
+ if (
53
+ relationMeta.keyFrom &&
54
+ relationMeta.source.definition.properties[relationMeta.keyFrom]
55
+ ) {
56
+ keyFrom = relationMeta.keyFrom;
57
+ } else {
58
+ keyFrom = camelCase(targetName + '_id');
59
+ }
60
+
61
+ const targetProperties = targetModel.definition.properties;
62
+ debug('relation metadata from %o: %o', targetName, targetProperties);
63
+
64
+ if (relationMeta.keyTo && targetProperties[relationMeta.keyTo]) {
65
+ // The explicit cast is needed because of a limitation of type inference
66
+ return Object.assign(relationMeta, {
67
+ keyFrom,
68
+ }) as BelongsToResolvedDefinition;
69
+ }
70
+
71
+ const targetPrimaryKey = targetModel.definition.idProperties()[0];
72
+ if (!targetPrimaryKey) {
73
+ const reason = `${targetName} does not have any primary key (id property)`;
74
+ throw new InvalidRelationError(reason, relationMeta);
75
+ }
76
+
77
+ return Object.assign(relationMeta, {keyFrom, keyTo: targetPrimaryKey});
78
+ }
@@ -0,0 +1,71 @@
1
+ // Copyright IBM Corp. 2019,2020. All Rights Reserved.
2
+ // Node module: @loopback/repository
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ import {Filter, InclusionFilter} from '@loopback/filter';
7
+ import {AnyObject, Options} from '../../common-types';
8
+ import {Entity} from '../../model';
9
+ import {EntityCrudRepository} from '../../repositories';
10
+ import {
11
+ deduplicate,
12
+ findByForeignKeys,
13
+ flattenTargetsOfOneToOneRelation,
14
+ StringKeyOf,
15
+ } from '../relation.helpers';
16
+ import {
17
+ BelongsToDefinition,
18
+ Getter,
19
+ InclusionResolver,
20
+ } from '../relation.types';
21
+ import {resolveBelongsToMetadata} from './belongs-to.helpers';
22
+
23
+ /**
24
+ * Creates InclusionResolver for BelongsTo relation.
25
+ * Notice that this function only generates the inclusionResolver.
26
+ * It doesn't register it for the source repository.
27
+ *
28
+ * Notice: scope field for inclusion is not supported yet
29
+ *
30
+ * @param meta - resolved BelongsToMetadata
31
+ * @param getTargetRepo - target repository i.e where related instances are
32
+ */
33
+ export function createBelongsToInclusionResolver<
34
+ Target extends Entity,
35
+ TargetID,
36
+ TargetRelations extends object,
37
+ >(
38
+ meta: BelongsToDefinition,
39
+ getTargetRepo: Getter<
40
+ EntityCrudRepository<Target, TargetID, TargetRelations>
41
+ >,
42
+ ): InclusionResolver<Entity, Target> {
43
+ const relationMeta = resolveBelongsToMetadata(meta);
44
+
45
+ return async function fetchIncludedModels(
46
+ entities: Entity[],
47
+ inclusion: InclusionFilter,
48
+ options?: Options,
49
+ ): Promise<((Target & TargetRelations) | undefined)[]> {
50
+ if (!entities.length) return [];
51
+
52
+ const sourceKey = relationMeta.keyFrom;
53
+ const sourceIds = entities.map(e => (e as AnyObject)[sourceKey]);
54
+ const targetKey = relationMeta.keyTo as StringKeyOf<Target>;
55
+ const dedupedSourceIds = deduplicate(sourceIds);
56
+
57
+ const scope =
58
+ typeof inclusion === 'string' ? {} : (inclusion.scope as Filter<Target>);
59
+
60
+ const targetRepo = await getTargetRepo();
61
+ const targetsFound = await findByForeignKeys(
62
+ targetRepo,
63
+ targetKey,
64
+ dedupedSourceIds.filter(e => e),
65
+ scope,
66
+ options,
67
+ );
68
+
69
+ return flattenTargetsOfOneToOneRelation(sourceIds, targetsFound, targetKey);
70
+ };
71
+ }
@@ -0,0 +1,55 @@
1
+ // Copyright IBM Corp. 2018,2020. All Rights Reserved.
2
+ // Node module: @loopback/repository
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ import {Getter} from '@loopback/core';
7
+ import {DataObject, Options} from '../../common-types';
8
+ import {EntityNotFoundError} from '../../errors';
9
+ import {Entity} from '../../model';
10
+ import {constrainFilter, EntityCrudRepository} from '../../repositories';
11
+
12
+ /**
13
+ * CRUD operations for a target repository of a BelongsTo relation
14
+ */
15
+ export interface BelongsToRepository<Target extends Entity> {
16
+ /**
17
+ * Gets the target model instance
18
+ * @param options
19
+ * @returns A promise resolved with the target object or rejected
20
+ * with an EntityNotFoundError when target model instance was not found.
21
+ */
22
+ get(options?: Options): Promise<Target>;
23
+ }
24
+
25
+ export class DefaultBelongsToRepository<
26
+ TargetEntity extends Entity,
27
+ TargetId,
28
+ TargetRepository extends EntityCrudRepository<TargetEntity, TargetId>,
29
+ > implements BelongsToRepository<TargetEntity>
30
+ {
31
+ /**
32
+ * Constructor of DefaultBelongsToEntityCrudRepository
33
+ * @param getTargetRepository - the getter of the related target model repository instance
34
+ * @param constraint - the key value pair representing foreign key name to constrain
35
+ * the target repository instance
36
+ */
37
+ constructor(
38
+ public getTargetRepository: Getter<TargetRepository>,
39
+ public constraint: DataObject<TargetEntity>,
40
+ ) {}
41
+
42
+ async get(options?: Options): Promise<TargetEntity> {
43
+ const targetRepo = await this.getTargetRepository();
44
+ const result = await targetRepo.find(
45
+ constrainFilter(undefined, this.constraint),
46
+ options,
47
+ );
48
+ if (!result.length) {
49
+ // We don't have a direct access to the foreign key value here :(
50
+ const id = 'constraint ' + JSON.stringify(this.constraint);
51
+ throw new EntityNotFoundError(targetRepo.entityClass, id);
52
+ }
53
+ return result[0];
54
+ }
55
+ }
@@ -0,0 +1,9 @@
1
+ // Copyright IBM Corp. 2018,2020. All Rights Reserved.
2
+ // Node module: @loopback/repository
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ export * from './belongs-to.decorator';
7
+ export * from './belongs-to.repository';
8
+ export * from './belongs-to.accessor';
9
+ export * from './belongs-to.inclusion-resolver';
@@ -0,0 +1,361 @@
1
+ // Copyright IBM Corp. 2020. All Rights Reserved.
2
+ // Node module: @loopback/repository
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ import debugFactory from 'debug';
7
+ import {camelCase} from 'lodash';
8
+ import {
9
+ DataObject,
10
+ deduplicate,
11
+ Entity,
12
+ HasManyDefinition,
13
+ InvalidRelationError,
14
+ isTypeResolver,
15
+ } from '../..';
16
+ import {resolveHasManyMetaHelper} from './has-many.helpers';
17
+
18
+ const debug = debugFactory(
19
+ 'loopback:repository:relations:has-many-through:helpers',
20
+ );
21
+
22
+ export type HasManyThroughResolvedDefinition = HasManyDefinition & {
23
+ keyTo: string;
24
+ keyFrom: string;
25
+ through: {
26
+ keyTo: string;
27
+ keyFrom: string;
28
+ };
29
+ };
30
+
31
+ /**
32
+ * Creates target constraint based on through models
33
+ * @param relationMeta - resolved hasManyThrough metadata
34
+ * @param throughInstances - an array of through instances
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * const resolvedMetadata = {
39
+ * // .. other props
40
+ * keyFrom: 'id',
41
+ * keyTo: 'id',
42
+ * through: {
43
+ * model: () => CategoryProductLink,
44
+ * keyFrom: 'categoryId',
45
+ * keyTo: 'productId',
46
+ * },
47
+ * };
48
+ * createTargetConstraintFromThrough(resolvedMetadata,[{
49
+ id: 2,
50
+ categoryId: 2,
51
+ productId: 8,
52
+ }]);
53
+ * >>> {id: 8}
54
+ * createTargetConstraintFromThrough(resolvedMetadata, [
55
+ {
56
+ id: 2,
57
+ categoryId: 2,
58
+ productId: 8,
59
+ }, {
60
+ id: 1,
61
+ categoryId: 2,
62
+ productId: 9,
63
+ }
64
+ ]);
65
+
66
+ >>> {id: {inq: [9, 8]}}
67
+ * ```
68
+ */
69
+ export function createTargetConstraintFromThrough<
70
+ Target extends Entity,
71
+ Through extends Entity,
72
+ >(
73
+ relationMeta: HasManyThroughResolvedDefinition,
74
+ throughInstances: Through[],
75
+ ): DataObject<Target> {
76
+ const fkValues = getTargetKeysFromThroughModels(
77
+ relationMeta,
78
+ throughInstances,
79
+ );
80
+ const targetPrimaryKey = relationMeta.keyTo;
81
+
82
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
83
+ const constraint: any = {
84
+ [targetPrimaryKey]: fkValues.length === 1 ? fkValues[0] : {inq: fkValues},
85
+ };
86
+ return constraint;
87
+ }
88
+
89
+ /**
90
+ * Returns an array of target fks of the given throughInstances.
91
+ *
92
+ * @param relationMeta - resolved hasManyThrough metadata
93
+ * @param throughInstances - an array of through instances
94
+ *
95
+ * @example
96
+ * ```ts
97
+ * const resolvedMetadata = {
98
+ * // .. other props
99
+ * keyFrom: 'id',
100
+ * keyTo: 'id',
101
+ * through: {
102
+ * model: () => CategoryProductLink,
103
+ * keyFrom: 'categoryId',
104
+ * keyTo: 'productId',
105
+ * },
106
+ * };
107
+ * getTargetKeysFromThroughModels(resolvedMetadata,[{
108
+ id: 2,
109
+ categoryId: 2,
110
+ productId: 8,
111
+ }]);
112
+ * >>> [8]
113
+ * getTargetKeysFromThroughModels(resolvedMetadata, [
114
+ {
115
+ id: 2,
116
+ categoryId: 2,
117
+ productId: 8,
118
+ }, {
119
+ id: 1,
120
+ categoryId: 2,
121
+ productId: 9,
122
+ }
123
+ ]);
124
+ >>> [8, 9]
125
+ */
126
+ export function getTargetKeysFromThroughModels<
127
+ Through extends Entity,
128
+ TargetID,
129
+ >(
130
+ relationMeta: HasManyThroughResolvedDefinition,
131
+ throughInstances: Through[],
132
+ ): TargetID[] {
133
+ const targetFkName = relationMeta.through.keyTo;
134
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
135
+ let fkValues: any = throughInstances.map(
136
+ (throughInstance: Through) =>
137
+ throughInstance[targetFkName as keyof Through],
138
+ );
139
+ fkValues = deduplicate(fkValues);
140
+ return fkValues as TargetID[];
141
+ }
142
+
143
+ /**
144
+ * Creates through constraint based on the source key
145
+ *
146
+ * @param relationMeta - resolved hasManyThrough metadata
147
+ * @param fkValue - foreign key of the source instance
148
+ * @internal
149
+ *
150
+ * @example
151
+ * ```ts
152
+ * const resolvedMetadata = {
153
+ * // .. other props
154
+ * keyFrom: 'id',
155
+ * keyTo: 'id',
156
+ * through: {
157
+ * model: () => CategoryProductLink,
158
+ * keyFrom: 'categoryId',
159
+ * keyTo: 'productId',
160
+ * },
161
+ * };
162
+ * createThroughConstraintFromSource(resolvedMetadata, 1);
163
+ *
164
+ * >>> {categoryId: 1}
165
+ * ```
166
+ */
167
+ export function createThroughConstraintFromSource<
168
+ Through extends Entity,
169
+ SourceID,
170
+ >(
171
+ relationMeta: HasManyThroughResolvedDefinition,
172
+ fkValue: SourceID,
173
+ ): DataObject<Through> {
174
+ const sourceFkName = relationMeta.through.keyFrom;
175
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
176
+ const constraint: any = {[sourceFkName]: fkValue};
177
+ return constraint;
178
+ }
179
+
180
+ /**
181
+ * Returns an array of target ids of the given target instances.
182
+ *
183
+ * @param relationMeta - resolved hasManyThrough metadata
184
+ * @param targetInstances - an array of target instances
185
+ *
186
+ * @example
187
+ * ```ts
188
+ * const resolvedMetadata = {
189
+ * // .. other props
190
+ * keyFrom: 'id',
191
+ * keyTo: 'id',
192
+ * through: {
193
+ * model: () => CategoryProductLink,
194
+ * keyFrom: 'categoryId',
195
+ * keyTo: 'productId',
196
+ * },
197
+ * };
198
+ * getTargetKeysFromTargetModels(resolvedMetadata,[{
199
+ id: 2,
200
+ des: 'a target',
201
+ }]);
202
+ * >>> [2]
203
+ * getTargetKeysFromTargetModels(resolvedMetadata, [
204
+ {
205
+ id: 2,
206
+ des: 'a target',
207
+ }, {
208
+ id: 1,
209
+ des: 'a target',
210
+ }
211
+ ]);
212
+ >>> [2, 1]
213
+ */
214
+ export function getTargetIdsFromTargetModels<Target extends Entity, TargetID>(
215
+ relationMeta: HasManyThroughResolvedDefinition,
216
+ targetInstances: Target[],
217
+ ): TargetID[] {
218
+ const targetId = relationMeta.keyTo;
219
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
220
+ let ids = [] as any;
221
+ ids = targetInstances.map(
222
+ (targetInstance: Target) => targetInstance[targetId as keyof Target],
223
+ );
224
+ ids = deduplicate(ids);
225
+ return ids as TargetID[];
226
+ }
227
+
228
+ /**
229
+ * Creates through constraint based on the target foreign key
230
+ *
231
+ * @param relationMeta - resolved hasManyThrough metadata
232
+ * @param fkValue an array of the target instance foreign keys
233
+ * @internal
234
+ *
235
+ * @example
236
+ * ```ts
237
+ * const resolvedMetadata = {
238
+ * // .. other props
239
+ * keyFrom: 'id',
240
+ * keyTo: 'id',
241
+ * through: {
242
+ * model: () => CategoryProductLink,
243
+ * keyFrom: 'categoryId',
244
+ * keyTo: 'productId',
245
+ * },
246
+ * };
247
+ * createThroughConstraintFromTarget(resolvedMetadata, [3]);
248
+ *
249
+ * >>> {productId: 3}
250
+ *
251
+ * createThroughConstraintFromTarget(resolvedMetadata, [3,4]);
252
+ *
253
+ * >>> {productId: {inq:[3,4]}}
254
+ */
255
+ export function createThroughConstraintFromTarget<
256
+ Through extends Entity,
257
+ TargetID,
258
+ >(
259
+ relationMeta: HasManyThroughResolvedDefinition,
260
+ fkValues: TargetID[],
261
+ ): DataObject<Through> {
262
+ if (fkValues === undefined || fkValues.length === 0) {
263
+ throw new Error('"fkValue" must be provided');
264
+ }
265
+ const targetFkName = relationMeta.through.keyTo;
266
+
267
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
268
+ const constraint: any =
269
+ fkValues.length === 1
270
+ ? {[targetFkName]: fkValues[0]}
271
+ : {[targetFkName]: {inq: fkValues}};
272
+
273
+ return constraint as DataObject<Through>;
274
+ }
275
+
276
+ /**
277
+ * Resolves given hasMany metadata if target is specified to be a resolver.
278
+ * Mainly used to infer what the `keyTo` property should be from the target's
279
+ * belongsTo metadata
280
+ * @param relationMeta - hasManyThrough metadata to resolve
281
+ * @internal
282
+ */
283
+ export function resolveHasManyThroughMetadata(
284
+ relationMeta: HasManyDefinition,
285
+ ): HasManyThroughResolvedDefinition {
286
+ // some checks and relationMeta.keyFrom are handled in here
287
+ relationMeta = resolveHasManyMetaHelper(relationMeta);
288
+
289
+ if (!relationMeta.through) {
290
+ const reason = 'through must be specified';
291
+ throw new InvalidRelationError(reason, relationMeta);
292
+ }
293
+ if (!isTypeResolver(relationMeta.through?.model)) {
294
+ const reason = 'through.model must be a type resolver';
295
+ throw new InvalidRelationError(reason, relationMeta);
296
+ }
297
+
298
+ const throughModel = relationMeta.through.model();
299
+ const throughModelProperties = throughModel.definition?.properties;
300
+
301
+ const targetModel = relationMeta.target();
302
+ const targetModelProperties = targetModel.definition?.properties;
303
+
304
+ // check if metadata is already complete
305
+ if (
306
+ relationMeta.through.keyTo &&
307
+ throughModelProperties[relationMeta.through.keyTo] &&
308
+ relationMeta.through.keyFrom &&
309
+ throughModelProperties[relationMeta.through.keyFrom] &&
310
+ relationMeta.keyTo &&
311
+ targetModelProperties[relationMeta.keyTo]
312
+ ) {
313
+ // The explicit cast is needed because of a limitation of type inference
314
+ return relationMeta as HasManyThroughResolvedDefinition;
315
+ }
316
+
317
+ const sourceModel = relationMeta.source;
318
+
319
+ debug(
320
+ 'Resolved model %s from given metadata: %o',
321
+ targetModel.modelName,
322
+ targetModel,
323
+ );
324
+
325
+ debug(
326
+ 'Resolved model %s from given metadata: %o',
327
+ throughModel.modelName,
328
+ throughModel,
329
+ );
330
+
331
+ const sourceFkName =
332
+ relationMeta.through.keyFrom ?? camelCase(sourceModel.modelName + '_id');
333
+ if (!throughModelProperties[sourceFkName]) {
334
+ const reason = `through model ${throughModel.name} is missing definition of source foreign key`;
335
+ throw new InvalidRelationError(reason, relationMeta);
336
+ }
337
+
338
+ const targetFkName =
339
+ relationMeta.through.keyTo ?? camelCase(targetModel.modelName + '_id');
340
+ if (!throughModelProperties[targetFkName]) {
341
+ const reason = `through model ${throughModel.name} is missing definition of target foreign key`;
342
+ throw new InvalidRelationError(reason, relationMeta);
343
+ }
344
+
345
+ const targetPrimaryKey =
346
+ relationMeta.keyTo ?? targetModel.definition.idProperties()[0];
347
+ if (!targetPrimaryKey || !targetModelProperties[targetPrimaryKey]) {
348
+ const reason = `target model ${targetModel.modelName} does not have any primary key (id property)`;
349
+ throw new InvalidRelationError(reason, relationMeta);
350
+ }
351
+
352
+ return Object.assign(relationMeta, {
353
+ keyTo: targetPrimaryKey,
354
+ keyFrom: relationMeta.keyFrom!,
355
+ through: {
356
+ ...relationMeta.through,
357
+ keyTo: targetFkName,
358
+ keyFrom: sourceFkName,
359
+ },
360
+ });
361
+ }
@@ -0,0 +1,135 @@
1
+ // Copyright IBM Corp. 2020. All Rights Reserved.
2
+ // Node module: @loopback/repository
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ import {Filter, InclusionFilter} from '@loopback/filter';
7
+ import debugFactory from 'debug';
8
+ import {AnyObject, Options} from '../../common-types';
9
+ import {Entity} from '../../model';
10
+ import {EntityCrudRepository} from '../../repositories';
11
+ import {
12
+ findByForeignKeys,
13
+ flattenTargetsOfOneToManyRelation,
14
+ StringKeyOf,
15
+ } from '../relation.helpers';
16
+ import {Getter, HasManyDefinition, InclusionResolver} from '../relation.types';
17
+ import {resolveHasManyMetadata} from './has-many.helpers';
18
+
19
+ const debug = debugFactory(
20
+ 'loopback:repository:relations:has-many-through:inclusion-resolver',
21
+ );
22
+
23
+ /**
24
+ * Creates InclusionResolver for HasManyThrough relation.
25
+ * Notice that this function only generates the inclusionResolver.
26
+ * It doesn't register it for the source repository.
27
+ *
28
+ *
29
+ * @param meta - metadata of the hasMany relation (including through)
30
+ * @param getThroughRepo - through repository getter i.e. where through
31
+ * instances are
32
+ * @param getTargetRepo - target repository getter i.e where target instances
33
+ * are
34
+ */
35
+ export function createHasManyThroughInclusionResolver<
36
+ Through extends Entity,
37
+ ThroughID,
38
+ ThroughRelations extends object,
39
+ Target extends Entity,
40
+ TargetID,
41
+ TargetRelations extends object,
42
+ >(
43
+ meta: HasManyDefinition,
44
+ getThroughRepo: Getter<
45
+ EntityCrudRepository<Through, ThroughID, ThroughRelations>
46
+ >,
47
+ getTargetRepo: Getter<
48
+ EntityCrudRepository<Target, TargetID, TargetRelations>
49
+ >,
50
+ ): InclusionResolver<Entity, Target> {
51
+ const relationMeta = resolveHasManyMetadata(meta);
52
+
53
+ return async function fetchHasManyThroughModels(
54
+ entities: Entity[],
55
+ inclusion: InclusionFilter,
56
+ options?: Options,
57
+ ): Promise<((Target & TargetRelations)[] | undefined)[]> {
58
+ if (!entities.length) return [];
59
+
60
+ debug('Fetching target models for entities:', entities);
61
+ debug('Relation metadata:', relationMeta);
62
+
63
+ const sourceKey = relationMeta.keyFrom;
64
+ const sourceIds = entities.map(e => (e as AnyObject)[sourceKey]);
65
+ const targetKey = relationMeta.keyTo as StringKeyOf<Target>;
66
+ if (!relationMeta.through) {
67
+ throw new Error(
68
+ `relationMeta.through must be defined on ${relationMeta}`,
69
+ );
70
+ }
71
+ const throughKeyTo = relationMeta.through.keyTo as StringKeyOf<Through>;
72
+ const throughKeyFrom = relationMeta.through.keyFrom as StringKeyOf<Through>;
73
+
74
+ debug('Parameters:', {
75
+ sourceKey,
76
+ sourceIds,
77
+ targetKey,
78
+ throughKeyTo,
79
+ throughKeyFrom,
80
+ });
81
+
82
+ debug(
83
+ 'sourceId types',
84
+ sourceIds.map(i => typeof i),
85
+ );
86
+
87
+ const throughRepo = await getThroughRepo();
88
+ const targetRepo = await getTargetRepo();
89
+
90
+ // find through models
91
+ const throughFound = await findByForeignKeys(
92
+ throughRepo,
93
+ throughKeyFrom,
94
+ sourceIds,
95
+ {}, // scope will be applied at the target level
96
+ options,
97
+ );
98
+
99
+ const throughResult = flattenTargetsOfOneToManyRelation(
100
+ sourceIds,
101
+ throughFound,
102
+ throughKeyFrom,
103
+ );
104
+
105
+ const result = [];
106
+
107
+ const scope =
108
+ typeof inclusion === 'string' ? {} : (inclusion.scope as Filter<Target>);
109
+
110
+ // convert from through entities to the target entities
111
+ for (const entityList of throughResult) {
112
+ if (entityList) {
113
+ // get target ids from the through entities by foreign key
114
+ const targetIds = entityList.map(entity => entity[throughKeyTo]);
115
+
116
+ // the explicit types and casts are needed
117
+ const targetEntityList = await findByForeignKeys<
118
+ Target,
119
+ TargetRelations,
120
+ StringKeyOf<Target>
121
+ >(targetRepo, targetKey, targetIds as unknown as [], scope, {
122
+ ...options,
123
+ isThroughModelInclude: true,
124
+ });
125
+ result.push(targetEntityList);
126
+ } else {
127
+ // no entities found, add undefined to results
128
+ result.push(entityList);
129
+ }
130
+ }
131
+
132
+ debug('fetchHasManyThroughModels result', result);
133
+ return result;
134
+ };
135
+ }