json-fs-query 0.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 (336) hide show
  1. package/.browserslistrc +1 -0
  2. package/.nvmrc +1 -0
  3. package/LICENSE +674 -0
  4. package/MAIN.md +15 -0
  5. package/README.md +63 -0
  6. package/babel.config.js +3 -0
  7. package/build-tools.config.json +30 -0
  8. package/dist/data/introspect/create.d.ts +11 -0
  9. package/dist/data/introspect/create.js +45 -0
  10. package/dist/data/introspect/create.min.js +1 -0
  11. package/dist/data/introspect/definitions/field.d.ts +28 -0
  12. package/dist/data/introspect/definitions/field.js +36 -0
  13. package/dist/data/introspect/definitions/field.min.js +1 -0
  14. package/dist/data/introspect/definitions/key.d.ts +26 -0
  15. package/dist/data/introspect/definitions/key.js +53 -0
  16. package/dist/data/introspect/definitions/key.min.js +1 -0
  17. package/dist/data/introspect/definitions/keyReference.d.ts +18 -0
  18. package/dist/data/introspect/definitions/keyReference.js +20 -0
  19. package/dist/data/introspect/definitions/keyReference.min.js +1 -0
  20. package/dist/data/introspect/definitions/record.d.ts +26 -0
  21. package/dist/data/introspect/definitions/record.js +32 -0
  22. package/dist/data/introspect/definitions/record.min.js +1 -0
  23. package/dist/data/introspect/describe.d.ts +2 -0
  24. package/dist/data/introspect/describe.js +15 -0
  25. package/dist/data/introspect/describe.min.js +1 -0
  26. package/dist/data/introspect/drop.d.ts +2 -0
  27. package/dist/data/introspect/drop.js +37 -0
  28. package/dist/data/introspect/drop.min.js +1 -0
  29. package/dist/data/introspect/index.d.ts +8 -0
  30. package/dist/data/introspect/index.js +30 -0
  31. package/dist/data/introspect/index.min.js +1 -0
  32. package/dist/data/introspect/policies/foreignKeyExists.d.ts +9 -0
  33. package/dist/data/introspect/policies/foreignKeyExists.js +25 -0
  34. package/dist/data/introspect/policies/foreignKeyExists.min.js +1 -0
  35. package/dist/data/introspect/policies/keyGenerate.d.ts +2 -0
  36. package/dist/data/introspect/policies/keyGenerate.js +17 -0
  37. package/dist/data/introspect/policies/keyGenerate.min.js +1 -0
  38. package/dist/data/introspect/policies/keyUnique.d.ts +2 -0
  39. package/dist/data/introspect/policies/keyUnique.js +21 -0
  40. package/dist/data/introspect/policies/keyUnique.min.js +1 -0
  41. package/dist/data/introspect/policies/typeCheck.d.ts +12 -0
  42. package/dist/data/introspect/policies/typeCheck.js +57 -0
  43. package/dist/data/introspect/policies/typeCheck.min.js +1 -0
  44. package/dist/data/introspect/policies/typeEnum.d.ts +2 -0
  45. package/dist/data/introspect/policies/typeEnum.js +14 -0
  46. package/dist/data/introspect/policies/typeEnum.min.js +1 -0
  47. package/dist/data/introspect/policies/useDefault.d.ts +2 -0
  48. package/dist/data/introspect/policies/useDefault.js +13 -0
  49. package/dist/data/introspect/policies/useDefault.min.js +1 -0
  50. package/dist/data/queries/deleteEntity.d.ts +2 -0
  51. package/dist/data/queries/deleteEntity.js +79 -0
  52. package/dist/data/queries/deleteEntity.min.js +1 -0
  53. package/dist/data/queries/groupBy.d.ts +2 -0
  54. package/dist/data/queries/groupBy.js +22 -0
  55. package/dist/data/queries/groupBy.min.js +1 -0
  56. package/dist/data/queries/insertEntity.d.ts +2 -0
  57. package/dist/data/queries/insertEntity.js +115 -0
  58. package/dist/data/queries/insertEntity.min.js +1 -0
  59. package/dist/data/queries/joinEntity.d.ts +2 -0
  60. package/dist/data/queries/joinEntity.js +27 -0
  61. package/dist/data/queries/joinEntity.min.js +1 -0
  62. package/dist/data/queries/mergeJoins.d.ts +2 -0
  63. package/dist/data/queries/mergeJoins.js +19 -0
  64. package/dist/data/queries/mergeJoins.min.js +1 -0
  65. package/dist/data/queries/parser.d.ts +2 -0
  66. package/dist/data/queries/parser.js +30 -0
  67. package/dist/data/queries/parser.min.js +1 -0
  68. package/dist/data/queries/query.d.ts +2 -0
  69. package/dist/data/queries/query.js +18 -0
  70. package/dist/data/queries/query.min.js +1 -0
  71. package/dist/data/queries/readEntity.d.ts +2 -0
  72. package/dist/data/queries/readEntity.js +14 -0
  73. package/dist/data/queries/readEntity.min.js +1 -0
  74. package/dist/data/queries/sortBy.d.ts +2 -0
  75. package/dist/data/queries/sortBy.js +25 -0
  76. package/dist/data/queries/sortBy.min.js +1 -0
  77. package/dist/data/queries/updateEntity.d.ts +2 -0
  78. package/dist/data/queries/updateEntity.js +164 -0
  79. package/dist/data/queries/updateEntity.min.js +1 -0
  80. package/dist/data/queries/where.d.ts +7 -0
  81. package/dist/data/queries/where.js +56 -0
  82. package/dist/data/queries/where.min.js +1 -0
  83. package/dist/data/utilities/deregisterRecord.d.ts +8 -0
  84. package/dist/data/utilities/deregisterRecord.js +34 -0
  85. package/dist/data/utilities/deregisterRecord.min.js +1 -0
  86. package/dist/data/utilities/getConditionIndexedList.d.ts +3 -0
  87. package/dist/data/utilities/getConditionIndexedList.js +47 -0
  88. package/dist/data/utilities/getConditionIndexedList.min.js +1 -0
  89. package/dist/data/utilities/getJoinIndexedList.d.ts +3 -0
  90. package/dist/data/utilities/getJoinIndexedList.js +59 -0
  91. package/dist/data/utilities/getJoinIndexedList.min.js +1 -0
  92. package/dist/data/utilities/getMatchingIndexes.d.ts +2 -0
  93. package/dist/data/utilities/getMatchingIndexes.js +28 -0
  94. package/dist/data/utilities/getMatchingIndexes.min.js +1 -0
  95. package/dist/data/utilities/matchIndexedJoins.d.ts +2 -0
  96. package/dist/data/utilities/matchIndexedJoins.js +61 -0
  97. package/dist/data/utilities/matchIndexedJoins.min.js +1 -0
  98. package/dist/data/utilities/mergeJoin.d.ts +2 -0
  99. package/dist/data/utilities/mergeJoin.js +44 -0
  100. package/dist/data/utilities/mergeJoin.min.js +1 -0
  101. package/dist/data/utilities/parsers/findCommand.d.ts +10 -0
  102. package/dist/data/utilities/parsers/findCommand.js +25 -0
  103. package/dist/data/utilities/parsers/findCommand.min.js +1 -0
  104. package/dist/data/utilities/parsers/findConditions.d.ts +15 -0
  105. package/dist/data/utilities/parsers/findConditions.js +28 -0
  106. package/dist/data/utilities/parsers/findConditions.min.js +1 -0
  107. package/dist/data/utilities/parsers/findGroupBy.d.ts +9 -0
  108. package/dist/data/utilities/parsers/findGroupBy.js +22 -0
  109. package/dist/data/utilities/parsers/findGroupBy.min.js +1 -0
  110. package/dist/data/utilities/parsers/findInsertValues.d.ts +13 -0
  111. package/dist/data/utilities/parsers/findInsertValues.js +34 -0
  112. package/dist/data/utilities/parsers/findInsertValues.min.js +1 -0
  113. package/dist/data/utilities/parsers/findJoinClauses.d.ts +13 -0
  114. package/dist/data/utilities/parsers/findJoinClauses.js +27 -0
  115. package/dist/data/utilities/parsers/findJoinClauses.min.js +1 -0
  116. package/dist/data/utilities/parsers/findJoinEntity.d.ts +9 -0
  117. package/dist/data/utilities/parsers/findJoinEntity.js +22 -0
  118. package/dist/data/utilities/parsers/findJoinEntity.min.js +1 -0
  119. package/dist/data/utilities/parsers/findLimit.d.ts +9 -0
  120. package/dist/data/utilities/parsers/findLimit.js +22 -0
  121. package/dist/data/utilities/parsers/findLimit.min.js +1 -0
  122. package/dist/data/utilities/parsers/findMergeJoins.d.ts +12 -0
  123. package/dist/data/utilities/parsers/findMergeJoins.js +26 -0
  124. package/dist/data/utilities/parsers/findMergeJoins.min.js +1 -0
  125. package/dist/data/utilities/parsers/findOffset.d.ts +9 -0
  126. package/dist/data/utilities/parsers/findOffset.js +22 -0
  127. package/dist/data/utilities/parsers/findOffset.min.js +1 -0
  128. package/dist/data/utilities/parsers/findSelects.d.ts +12 -0
  129. package/dist/data/utilities/parsers/findSelects.js +30 -0
  130. package/dist/data/utilities/parsers/findSelects.min.js +1 -0
  131. package/dist/data/utilities/parsers/findSortClauses.d.ts +12 -0
  132. package/dist/data/utilities/parsers/findSortClauses.js +30 -0
  133. package/dist/data/utilities/parsers/findSortClauses.min.js +1 -0
  134. package/dist/data/utilities/parsers/findUpdateValues.d.ts +15 -0
  135. package/dist/data/utilities/parsers/findUpdateValues.js +34 -0
  136. package/dist/data/utilities/parsers/findUpdateValues.min.js +1 -0
  137. package/dist/data/utilities/parsers/isEntityProperty.d.ts +2 -0
  138. package/dist/data/utilities/parsers/isEntityProperty.js +8 -0
  139. package/dist/data/utilities/parsers/isEntityProperty.min.js +1 -0
  140. package/dist/data/utilities/parsers/parseLiteralValue.d.ts +12 -0
  141. package/dist/data/utilities/parsers/parseLiteralValue.js +34 -0
  142. package/dist/data/utilities/parsers/parseLiteralValue.min.js +1 -0
  143. package/dist/data/utilities/parsers/parseQuery.d.ts +33 -0
  144. package/dist/data/utilities/parsers/parseQuery.js +51 -0
  145. package/dist/data/utilities/parsers/parseQuery.min.js +1 -0
  146. package/dist/data/utilities/parsers/removeFromQuery.d.ts +2 -0
  147. package/dist/data/utilities/parsers/removeFromQuery.js +8 -0
  148. package/dist/data/utilities/parsers/removeFromQuery.min.js +1 -0
  149. package/dist/data/utilities/parsers/splitEntityProperty.d.ts +5 -0
  150. package/dist/data/utilities/parsers/splitEntityProperty.js +23 -0
  151. package/dist/data/utilities/parsers/splitEntityProperty.min.js +1 -0
  152. package/dist/data/utilities/parsers/splitQueries.d.ts +2 -0
  153. package/dist/data/utilities/parsers/splitQueries.js +11 -0
  154. package/dist/data/utilities/parsers/splitQueries.min.js +1 -0
  155. package/dist/data/utilities/reconcileJoin.d.ts +2 -0
  156. package/dist/data/utilities/reconcileJoin.js +26 -0
  157. package/dist/data/utilities/reconcileJoin.min.js +1 -0
  158. package/dist/data/utilities/reconcileJoins.d.ts +2 -0
  159. package/dist/data/utilities/reconcileJoins.js +27 -0
  160. package/dist/data/utilities/reconcileJoins.min.js +1 -0
  161. package/dist/data/utilities/registerRecord.d.ts +8 -0
  162. package/dist/data/utilities/registerRecord.js +67 -0
  163. package/dist/data/utilities/registerRecord.min.js +1 -0
  164. package/dist/data/utilities/removeFromIndex.d.ts +14 -0
  165. package/dist/data/utilities/removeFromIndex.js +46 -0
  166. package/dist/data/utilities/removeFromIndex.min.js +1 -0
  167. package/dist/data/utilities/restrictIndexedList.d.ts +2 -0
  168. package/dist/data/utilities/restrictIndexedList.js +45 -0
  169. package/dist/data/utilities/restrictIndexedList.min.js +1 -0
  170. package/dist/data/utilities/retrieveFile.d.ts +2 -0
  171. package/dist/data/utilities/retrieveFile.js +28 -0
  172. package/dist/data/utilities/retrieveFile.min.js +1 -0
  173. package/dist/data/utilities/retrieveIndexes.d.ts +2 -0
  174. package/dist/data/utilities/retrieveIndexes.js +24 -0
  175. package/dist/data/utilities/retrieveIndexes.min.js +1 -0
  176. package/dist/data/utilities/retrieveRecord.d.ts +2 -0
  177. package/dist/data/utilities/retrieveRecord.js +9 -0
  178. package/dist/data/utilities/retrieveRecord.min.js +1 -0
  179. package/dist/data/utilities/retrieveRecords.d.ts +2 -0
  180. package/dist/data/utilities/retrieveRecords.js +21 -0
  181. package/dist/data/utilities/retrieveRecords.min.js +1 -0
  182. package/dist/data/utilities/runQuery.d.ts +2 -0
  183. package/dist/data/utilities/runQuery.js +72 -0
  184. package/dist/data/utilities/runQuery.min.js +1 -0
  185. package/dist/data/utilities/updateIndex.d.ts +17 -0
  186. package/dist/data/utilities/updateIndex.js +56 -0
  187. package/dist/data/utilities/updateIndex.min.js +1 -0
  188. package/dist/data/utilities/useJoinClause.d.ts +6 -0
  189. package/dist/data/utilities/useJoinClause.js +51 -0
  190. package/dist/data/utilities/useJoinClause.min.js +1 -0
  191. package/dist/index.d.ts +4 -0
  192. package/dist/index.js +35 -0
  193. package/dist/index.min.js +1 -0
  194. package/gulpfile.mjs +15 -0
  195. package/package.json +44 -0
  196. package/src/data/introspect/create.test.js +67 -0
  197. package/src/data/introspect/create.ts +29 -0
  198. package/src/data/introspect/definitions/field.test.js +23 -0
  199. package/src/data/introspect/definitions/field.ts +48 -0
  200. package/src/data/introspect/definitions/key.test.js +100 -0
  201. package/src/data/introspect/definitions/key.ts +64 -0
  202. package/src/data/introspect/definitions/keyReference.test.js +8 -0
  203. package/src/data/introspect/definitions/keyReference.ts +23 -0
  204. package/src/data/introspect/definitions/record.ts +42 -0
  205. package/src/data/introspect/describe.test.js +36 -0
  206. package/src/data/introspect/describe.ts +9 -0
  207. package/src/data/introspect/drop.test.js +77 -0
  208. package/src/data/introspect/drop.ts +20 -0
  209. package/src/data/introspect/index.ts +8 -0
  210. package/src/data/introspect/policies/foreignKeyExists.test.js +44 -0
  211. package/src/data/introspect/policies/foreignKeyExists.ts +15 -0
  212. package/src/data/introspect/policies/keyGenerate.ts +11 -0
  213. package/src/data/introspect/policies/keyUnique.ts +11 -0
  214. package/src/data/introspect/policies/typeCheck.test.js +84 -0
  215. package/src/data/introspect/policies/typeCheck.ts +49 -0
  216. package/src/data/introspect/policies/typeEnum.ts +6 -0
  217. package/src/data/introspect/policies/useDefault.ts +6 -0
  218. package/src/data/queries/deleteEntity.test.js +86 -0
  219. package/src/data/queries/deleteEntity.ts +56 -0
  220. package/src/data/queries/groupBy.test.js +135 -0
  221. package/src/data/queries/groupBy.ts +16 -0
  222. package/src/data/queries/insertEntity.test.js +156 -0
  223. package/src/data/queries/insertEntity.ts +113 -0
  224. package/src/data/queries/joinEntity.test.js +109 -0
  225. package/src/data/queries/joinEntity.ts +20 -0
  226. package/src/data/queries/mergeJoins.test.js +174 -0
  227. package/src/data/queries/mergeJoins.ts +13 -0
  228. package/src/data/queries/parser.test.js +343 -0
  229. package/src/data/queries/parser.ts +24 -0
  230. package/src/data/queries/query.test.js +233 -0
  231. package/src/data/queries/query.ts +12 -0
  232. package/src/data/queries/readEntity.test.js +85 -0
  233. package/src/data/queries/readEntity.ts +8 -0
  234. package/src/data/queries/sortBy.test.js +131 -0
  235. package/src/data/queries/sortBy.ts +18 -0
  236. package/src/data/queries/updateEntity.test.js +228 -0
  237. package/src/data/queries/updateEntity.ts +162 -0
  238. package/src/data/queries/where.test.js +129 -0
  239. package/src/data/queries/where.ts +54 -0
  240. package/src/data/utilities/deregisterRecord.test.js +26 -0
  241. package/src/data/utilities/deregisterRecord.ts +24 -0
  242. package/src/data/utilities/getConditionIndexedList.ts +43 -0
  243. package/src/data/utilities/getJoinIndexedList.ts +53 -0
  244. package/src/data/utilities/getMatchingIndexes.ts +21 -0
  245. package/src/data/utilities/matchIndexedJoins.ts +45 -0
  246. package/src/data/utilities/mergeJoin.test.js +102 -0
  247. package/src/data/utilities/mergeJoin.ts +28 -0
  248. package/src/data/utilities/parsers/findCommand.ts +25 -0
  249. package/src/data/utilities/parsers/findConditions.test.js +38 -0
  250. package/src/data/utilities/parsers/findConditions.ts +32 -0
  251. package/src/data/utilities/parsers/findGroupBy.ts +20 -0
  252. package/src/data/utilities/parsers/findInsertValues.test.js +26 -0
  253. package/src/data/utilities/parsers/findInsertValues.ts +32 -0
  254. package/src/data/utilities/parsers/findJoinClauses.ts +29 -0
  255. package/src/data/utilities/parsers/findJoinEntity.ts +20 -0
  256. package/src/data/utilities/parsers/findLimit.ts +20 -0
  257. package/src/data/utilities/parsers/findMergeJoins.ts +27 -0
  258. package/src/data/utilities/parsers/findOffset.ts +20 -0
  259. package/src/data/utilities/parsers/findSelects.ts +31 -0
  260. package/src/data/utilities/parsers/findSortClauses.ts +31 -0
  261. package/src/data/utilities/parsers/findUpdateValues.test.js +37 -0
  262. package/src/data/utilities/parsers/findUpdateValues.ts +32 -0
  263. package/src/data/utilities/parsers/isEntityProperty.ts +1 -0
  264. package/src/data/utilities/parsers/parseLiteralValue.test.js +41 -0
  265. package/src/data/utilities/parsers/parseLiteralValue.ts +29 -0
  266. package/src/data/utilities/parsers/parseQuery.ts +73 -0
  267. package/src/data/utilities/parsers/removeFromQuery.ts +1 -0
  268. package/src/data/utilities/parsers/splitEntityProperty.test.js +8 -0
  269. package/src/data/utilities/parsers/splitEntityProperty.ts +17 -0
  270. package/src/data/utilities/parsers/splitQueries.test.js +33 -0
  271. package/src/data/utilities/parsers/splitQueries.ts +4 -0
  272. package/src/data/utilities/reconcileJoin.test.js +38 -0
  273. package/src/data/utilities/reconcileJoin.ts +23 -0
  274. package/src/data/utilities/reconcileJoins.test.js +160 -0
  275. package/src/data/utilities/reconcileJoins.ts +15 -0
  276. package/src/data/utilities/registerRecord.test.js +44 -0
  277. package/src/data/utilities/registerRecord.ts +44 -0
  278. package/src/data/utilities/removeFromIndex.test.js +44 -0
  279. package/src/data/utilities/removeFromIndex.ts +34 -0
  280. package/src/data/utilities/restrictIndexedList.ts +38 -0
  281. package/src/data/utilities/retrieveFile.test.js +49 -0
  282. package/src/data/utilities/retrieveFile.ts +19 -0
  283. package/src/data/utilities/retrieveIndexes.ts +17 -0
  284. package/src/data/utilities/retrieveRecord.ts +3 -0
  285. package/src/data/utilities/retrieveRecords.test.js +223 -0
  286. package/src/data/utilities/retrieveRecords.ts +16 -0
  287. package/src/data/utilities/runQuery.test.js +88 -0
  288. package/src/data/utilities/runQuery.ts +75 -0
  289. package/src/data/utilities/updateIndex.test.js +44 -0
  290. package/src/data/utilities/updateIndex.ts +45 -0
  291. package/src/data/utilities/useJoinClause.test.js +94 -0
  292. package/src/data/utilities/useJoinClause.ts +44 -0
  293. package/src/global.d.ts +1 -0
  294. package/src/index.test.js +52 -0
  295. package/src/index.ts +17 -0
  296. package/test-data/__RECORDS.json +32 -0
  297. package/test-data/__indexes/exercise_muscle/fk_exercise_id.json +14 -0
  298. package/test-data/__indexes/exercise_muscle/fk_muscle_id.json +14 -0
  299. package/test-data/__indexes/exercise_muscle/pk__id.json +14 -0
  300. package/test-data/__indexes/exercises/pk__id.json +14 -0
  301. package/test-data/__indexes/muscles/pk__id.json +58 -0
  302. package/test-data/__indexes/workouts/fk_exercise_id.json +23 -0
  303. package/test-data/__indexes/workouts/index_date.json +18 -0
  304. package/test-data/__indexes/workouts/pk__id.json +26 -0
  305. package/test-data/copyDatabase.ts +64 -0
  306. package/test-data/exercise_muscle/bench_press_pectorals.json +6 -0
  307. package/test-data/exercise_muscle/deadlift_hamstrings.json +6 -0
  308. package/test-data/exercise_muscle/squat_quadriceps.json +6 -0
  309. package/test-data/exercise_muscle.json +69 -0
  310. package/test-data/exercises/bench_press.json +5 -0
  311. package/test-data/exercises/deadlift.json +5 -0
  312. package/test-data/exercises/squat.json +5 -0
  313. package/test-data/exercises.json +34 -0
  314. package/test-data/muscles/abdominal.json +6 -0
  315. package/test-data/muscles/biceps.json +6 -0
  316. package/test-data/muscles/calves.json +6 -0
  317. package/test-data/muscles/deltoids.json +6 -0
  318. package/test-data/muscles/erector_spinae.json +6 -0
  319. package/test-data/muscles/forearms.json +6 -0
  320. package/test-data/muscles/gluteus_maximus.json +6 -0
  321. package/test-data/muscles/hamstrings.json +6 -0
  322. package/test-data/muscles/latissimus_dorsi.json +6 -0
  323. package/test-data/muscles/obliques.json +6 -0
  324. package/test-data/muscles/pectorals.json +6 -0
  325. package/test-data/muscles/quadriceps.json +6 -0
  326. package/test-data/muscles/trapezius.json +6 -0
  327. package/test-data/muscles/triceps.json +6 -0
  328. package/test-data/muscles.json +50 -0
  329. package/test-data/workouts/2024-06-02-001.json +10 -0
  330. package/test-data/workouts/2024-06-02-002.json +10 -0
  331. package/test-data/workouts/2024-06-02-003.json +10 -0
  332. package/test-data/workouts/2024-06-05-001.json +10 -0
  333. package/test-data/workouts/2024-06-05-002.json +10 -0
  334. package/test-data/workouts/2024-06-05-003.json +10 -0
  335. package/test-data/workouts.json +84 -0
  336. package/tsconfig.json +15 -0
@@ -0,0 +1,27 @@
1
+ import { removeFromQuery } from './removeFromQuery'
2
+ import { ParsedQuery } from './parseQuery'
3
+
4
+ const mergeJoinMatch: RegExp = /(and)?\s*merge\s+([a-z0-9_-]+\.[a-z0-9_-]+)\s+with\s+([a-z0-9_-]+\.[a-z0-9_-]+)/ig
5
+
6
+ export type ParsedMergeJoin = {
7
+ propertyA: string
8
+ propertyB: string
9
+ }
10
+
11
+ /**
12
+ * Extract merge-join clauses from the query.
13
+ * @param parsed
14
+ * @param query
15
+ */
16
+ export const findMergeJoins = (parsed: ParsedQuery, query: string): string => {
17
+ const mergeJoinsFound: IterableIterator<RegExpMatchArray> = query.matchAll(mergeJoinMatch)
18
+ // @ts-ignore
19
+ for (let mergeJoin of mergeJoinsFound) {
20
+ parsed['mergeJoins'].push({
21
+ propertyA: mergeJoin[2],
22
+ propertyB: mergeJoin[3]
23
+ })
24
+ query = removeFromQuery(mergeJoin[0].trim(), query)
25
+ }
26
+ return query
27
+ }
@@ -0,0 +1,20 @@
1
+ import { removeFromQuery } from './removeFromQuery'
2
+ import { ParsedQuery } from './parseQuery'
3
+
4
+ const offsetMatch: RegExp = /offset\s*(\d+)/i
5
+
6
+ export type ParsedOffset = number
7
+
8
+ /**
9
+ * Extract the offset clauses from the query.
10
+ * @param parsed
11
+ * @param query
12
+ */
13
+ export const findOffset = (parsed: ParsedQuery, query: string): string => {
14
+ const offsetFound: RegExpMatchArray = query.match(offsetMatch)
15
+ if (offsetFound) {
16
+ parsed['offset'] = offsetFound ? parseInt(offsetFound[1]) : undefined
17
+ return removeFromQuery(offsetFound[0], query)
18
+ }
19
+ return query
20
+ }
@@ -0,0 +1,31 @@
1
+ import { removeFromQuery } from './removeFromQuery'
2
+ import { ParsedQuery } from './parseQuery'
3
+
4
+ const selectClausesMatch: RegExp = /select\s+([a-z0-9=._-]+\s*(as\s+)?([a-z0-9_-]+)?)+\s*(,\s*[a-z0-9=._-]+\s*(as\s*[a-z0-9_-]+)?)*/i
5
+ const selectClauseMatch: RegExp = /(select)?\s*,?\s*([a-z0-9=._-]+)\s*(as\s+)?([a-z0-9_-]+)?/ig
6
+
7
+ export type ParsedSelect = {
8
+ property: string
9
+ alias: string | undefined
10
+ }
11
+
12
+ /**
13
+ * Extract select clauses from the query.
14
+ * @param parsed
15
+ * @param query
16
+ */
17
+ export const findSelects = (parsed: ParsedQuery, query: string): string => {
18
+ const selectsFound: RegExpMatchArray = query.match(selectClausesMatch)
19
+ if (selectsFound) {
20
+ const selectClausesFound: IterableIterator<RegExpMatchArray> = selectsFound[0].matchAll(selectClauseMatch)
21
+ // @ts-ignore
22
+ for (let selectClause of selectClausesFound) {
23
+ parsed['selectClauses'].push({
24
+ property: selectClause[2],
25
+ alias: selectClause[4],
26
+ })
27
+ }
28
+ return removeFromQuery(selectsFound[0], query)
29
+ }
30
+ return query
31
+ }
@@ -0,0 +1,31 @@
1
+ import { removeFromQuery } from './removeFromQuery'
2
+ import { ParsedQuery } from './parseQuery'
3
+
4
+ const sortMatch: RegExp = /sort\s+([a-z0-9._-]+\s*(asc|desc)?)+\s*(,\s*[a-z0-9._-]+\s*(asc|desc)?)*/i
5
+ const sortRuleMatch: RegExp = /(sort)?\s*,?\s*([a-z0-9._-]+)\s*(asc|desc)?/ig
6
+
7
+ export type ParsedSortClause = {
8
+ property: string
9
+ direction: string | 'asc' | 'desc'
10
+ }
11
+
12
+ /**
13
+ * Extract sort clauses from the query.
14
+ * @param parsed
15
+ * @param query
16
+ */
17
+ export const findSortClauses = (parsed: ParsedQuery, query: string): string => {
18
+ const sortFound: RegExpMatchArray = query.match(sortMatch)
19
+ if (sortFound) {
20
+ const sortRulesFound: IterableIterator<RegExpMatchArray> = sortFound[0].matchAll(sortRuleMatch)
21
+ // @ts-ignore
22
+ for (let sortClause of sortRulesFound) {
23
+ parsed['sortClauses'].push({
24
+ property: sortClause[2],
25
+ direction: sortClause[3] || 'asc',
26
+ })
27
+ }
28
+ return removeFromQuery(sortFound[0], query)
29
+ }
30
+ return query
31
+ }
@@ -0,0 +1,37 @@
1
+ import { findUpdateValues } from './findUpdateValues'
2
+
3
+ const parse = (query) => {
4
+ const parsed = {}
5
+ const remaining = findUpdateValues(parsed, query)
6
+ return { parsed, remaining }
7
+ }
8
+
9
+ describe('findUpdateValues', () => {
10
+ test('extracts a single assignment', () => {
11
+ const { parsed, remaining } = parse("update workouts set reps = 12")
12
+ expect(parsed.updateValues).toEqual({ reps: 12 })
13
+ expect(remaining).toBe('update workouts')
14
+ })
15
+
16
+ test('extracts multiple comma-separated assignments', () => {
17
+ const { parsed } = parse("set reps = 12, note = 'done'")
18
+ expect(parsed.updateValues).toEqual({ reps: 12, note: 'done' })
19
+ })
20
+
21
+ test('stops before a following where clause', () => {
22
+ const { parsed, remaining } = parse("set reps = 12 where date = '2024-06-02'")
23
+ expect(parsed.updateValues).toEqual({ reps: 12 })
24
+ expect(remaining).toBe("where date = '2024-06-02'")
25
+ })
26
+
27
+ test('extracts every literal shape', () => {
28
+ const { parsed } = parse('set active = true, archived = false, note = null, tags = [1,2,3]')
29
+ expect(parsed.updateValues).toEqual({ active: true, archived: false, note: null, tags: [1, 2, 3] })
30
+ })
31
+
32
+ test('leaves the query untouched, with an empty updateValues, when there is no set clause', () => {
33
+ const { parsed, remaining } = parse("read workouts where date = '2024-06-02'")
34
+ expect(parsed.updateValues).toEqual({})
35
+ expect(remaining).toBe("read workouts where date = '2024-06-02'")
36
+ })
37
+ })
@@ -0,0 +1,32 @@
1
+ import { removeFromQuery } from './removeFromQuery'
2
+ import { parseLiteralValue } from './parseLiteralValue'
3
+ import { ParsedQuery } from './parseQuery'
4
+
5
+ const literal = '(?:["\'][^"\']*[\'"]|[0-9]+|\\[.*?]|null|true|false)'
6
+ const setClauseMatch: RegExp = new RegExp(`(set)\\s+([a-z0-9_-]+\\s*=\\s*${literal}(?:\\s*,\\s*[a-z0-9_-]+\\s*=\\s*${literal})*)`, 'i')
7
+ const assignmentMatch: RegExp = /([a-z0-9_-]+)\s*=\s*(["'](.*?)['"]|([0-9]+)|(\[.*?])|(null)|(true)|(false))/ig
8
+
9
+ export type ParsedUpdateValues = { [field: string]: any }
10
+
11
+ /**
12
+ * Extract an update's "set field = value, field2 = value2" clause from the query. Uses a two-pass
13
+ * match, unlike the other parsers here: the set clause's own boundary is found first (so it can
14
+ * be removed from the query as a whole, and so the comma-separated list doesn't get confused with
15
+ * anything that follows, like a where clause), then each individual assignment is parsed out of
16
+ * that captured substring.
17
+ * @param parsed
18
+ * @param query
19
+ */
20
+ export const findUpdateValues = (parsed: ParsedQuery, query: string): string => {
21
+ const clauseFound: RegExpMatchArray = query.match(setClauseMatch)
22
+ parsed['updateValues'] = {}
23
+ if (!clauseFound) {
24
+ return query
25
+ }
26
+ const assignmentsFound: IterableIterator<RegExpMatchArray> = clauseFound[2].matchAll(assignmentMatch)
27
+ // @ts-ignore
28
+ for (const assignment of assignmentsFound) {
29
+ parsed['updateValues'][assignment[1]] = parseLiteralValue(assignment, 3)
30
+ }
31
+ return removeFromQuery(clauseFound[0], query)
32
+ }
@@ -0,0 +1 @@
1
+ export const isEntityProperty = (property: string): boolean => /^[a-z0-9_-]+\.([a-z0-9_-]+)$/i.test(property)
@@ -0,0 +1,41 @@
1
+ import { parseLiteralValue } from './parseLiteralValue'
2
+
3
+ describe('parseLiteralValue', () => {
4
+ const groupMatch = (regex, str) => str.match(regex)
5
+
6
+ test('extracts a quoted string', () => {
7
+ const regex = /(["'](.*)['"]|([0-9]+)|(\[.*])|(null)|(true)|(false))/
8
+ const match = groupMatch(regex, "'foo'")
9
+ expect(parseLiteralValue(match, 2)).toBe('foo')
10
+ })
11
+
12
+ test('extracts a number', () => {
13
+ const regex = /(["'](.*)['"]|([0-9]+)|(\[.*])|(null)|(true)|(false))/
14
+ const match = groupMatch(regex, '42')
15
+ expect(parseLiteralValue(match, 2)).toBe(42)
16
+ })
17
+
18
+ test('extracts an array', () => {
19
+ const regex = /(["'](.*)['"]|([0-9]+)|(\[.*])|(null)|(true)|(false))/
20
+ const match = groupMatch(regex, '[1,2,3]')
21
+ expect(parseLiteralValue(match, 2)).toEqual([1, 2, 3])
22
+ })
23
+
24
+ test('extracts null', () => {
25
+ const regex = /(["'](.*)['"]|([0-9]+)|(\[.*])|(null)|(true)|(false))/
26
+ const match = groupMatch(regex, 'null')
27
+ expect(parseLiteralValue(match, 2)).toBeNull()
28
+ })
29
+
30
+ test('extracts true/false', () => {
31
+ const regex = /(["'](.*)['"]|([0-9]+)|(\[.*])|(null)|(true)|(false))/
32
+ expect(parseLiteralValue(groupMatch(regex, 'true'), 2)).toBe(true)
33
+ expect(parseLiteralValue(groupMatch(regex, 'false'), 2)).toBe(false)
34
+ })
35
+
36
+ test('honors a different baseIndex for a differently-shaped parent regex', () => {
37
+ const regex = /([a-z]+)\s*=\s*(["'](.*)['"]|([0-9]+)|(\[.*])|(null)|(true)|(false))/
38
+ const match = groupMatch(regex, 'reps=10')
39
+ expect(parseLiteralValue(match, 3)).toBe(10)
40
+ })
41
+ })
@@ -0,0 +1,29 @@
1
+ export type LiteralValue = string | number | boolean | null | any[]
2
+
3
+ /**
4
+ * Several parsers (findConditions, findInsertValues, findUpdateValues) capture a query-string
5
+ * literal into one of six consecutive alternation groups depending on its shape - quoted string,
6
+ * number, array, null, true, false - since a single regex can't otherwise tell them apart. Given
7
+ * the match and the index of the first of those six groups (which shifts depending on how many
8
+ * groups come before it in the parent regex), return the literal with its real JS type.
9
+ * @param match
10
+ * @param baseIndex
11
+ */
12
+ export const parseLiteralValue = (match: RegExpMatchArray, baseIndex: number): LiteralValue => {
13
+ if (typeof match[baseIndex] !== 'undefined') {
14
+ return match[baseIndex]
15
+ }
16
+ if (typeof match[baseIndex + 1] !== 'undefined') {
17
+ return Number(match[baseIndex + 1])
18
+ }
19
+ if (typeof match[baseIndex + 2] !== 'undefined') {
20
+ return JSON.parse(match[baseIndex + 2])
21
+ }
22
+ if (typeof match[baseIndex + 3] !== 'undefined') {
23
+ return null
24
+ }
25
+ if (typeof match[baseIndex + 4] !== 'undefined') {
26
+ return true
27
+ }
28
+ return false
29
+ }
@@ -0,0 +1,73 @@
1
+ import siFunciona from 'si-funciona'
2
+ import { findCommand, ParsedCommand, ParsedEntity } from './findCommand'
3
+ import { findInsertValues, ParsedInsertRow } from './findInsertValues'
4
+ import { findUpdateValues, ParsedUpdateValues } from './findUpdateValues'
5
+ import { findJoinEntity, ParsedJoinEntity } from './findJoinEntity'
6
+ import { findSelects, ParsedSelect } from './findSelects'
7
+ import { findConditions, ParsedCondition } from './findConditions'
8
+ import { findJoinClauses, ParsedJoinClause } from './findJoinClauses'
9
+ import { findMergeJoins, ParsedMergeJoin } from './findMergeJoins'
10
+ import { findSortClauses, ParsedSortClause } from './findSortClauses'
11
+ import { findGroupBy, ParsedGroupBy } from './findGroupBy'
12
+ import { findLimit, ParsedLimit } from './findLimit'
13
+ import { findOffset, ParsedOffset } from './findOffset'
14
+
15
+ export type ParsedQuery = {
16
+ command: ParsedCommand | undefined
17
+ entity: ParsedEntity | undefined
18
+ joinEntity: ParsedJoinEntity | undefined
19
+ selectClauses: ParsedSelect[]
20
+ insertValues: ParsedInsertRow[]
21
+ updateValues: ParsedUpdateValues
22
+ conditions: ParsedCondition[]
23
+ joinClauses: ParsedJoinClause[]
24
+ mergeJoins: ParsedMergeJoin[]
25
+ sortClauses: ParsedSortClause[]
26
+ groupBy: ParsedGroupBy | undefined
27
+ limit: ParsedLimit | undefined
28
+ offset: ParsedOffset | undefined
29
+ }
30
+
31
+ /**
32
+ * Break a query down into its components.
33
+ * @param query
34
+ */
35
+ export const parseQuery = (query: string): ParsedQuery => {
36
+ let parsedQuery: ParsedQuery = {
37
+ command: undefined,
38
+ entity: undefined,
39
+ joinEntity: undefined,
40
+ selectClauses: [],
41
+ insertValues: [],
42
+ updateValues: {},
43
+ conditions: [],
44
+ joinClauses: [],
45
+ mergeJoins: [],
46
+ sortClauses: [],
47
+ groupBy: undefined,
48
+ limit: undefined,
49
+ offset: undefined,
50
+ }
51
+
52
+ const { curry, pipe } = siFunciona
53
+
54
+ query = pipe(
55
+ curry(findCommand)(parsedQuery),
56
+ curry(findInsertValues)(parsedQuery),
57
+ curry(findUpdateValues)(parsedQuery),
58
+ curry(findJoinEntity)(parsedQuery),
59
+ curry(findSelects)(parsedQuery),
60
+ curry(findConditions)(parsedQuery),
61
+ curry(findJoinClauses)(parsedQuery),
62
+ curry(findMergeJoins)(parsedQuery),
63
+ curry(findSortClauses)(parsedQuery),
64
+ curry(findGroupBy)(parsedQuery),
65
+ curry(findLimit)(parsedQuery),
66
+ curry(findOffset)(parsedQuery)
67
+ )(query)
68
+
69
+ if (query) {
70
+ throw new Error(`Unrecognized query value: ${query}`)
71
+ }
72
+ return parsedQuery
73
+ }
@@ -0,0 +1 @@
1
+ export const removeFromQuery = (substring: string, query: string): string => query.replace(substring, '').trim()
@@ -0,0 +1,8 @@
1
+ import { splitEntityProperty } from './splitEntityProperty'
2
+
3
+ describe('splitEntityProperty', () => {
4
+ test('can parse entity property', () => {
5
+ const result = splitEntityProperty('workouts.exercise_id')
6
+ expect(result).toEqual({ entity: 'workouts', property: 'exercise_id' })
7
+ })
8
+ })
@@ -0,0 +1,17 @@
1
+ const entityMatch = /^[a-z0-9_-]+/i
2
+ const propertyMatch = /\.([a-z0-9_-]+)$/i
3
+
4
+ export const splitEntityProperty = entityProp => {
5
+ const entityFound = entityProp.match(entityMatch)
6
+ if (!entityFound) {
7
+ throw new Error(`Unable to use property: ${entityProp}`)
8
+ }
9
+ const propFound = entityProp.match(propertyMatch)
10
+ if (!propFound) {
11
+ throw new Error(`Unable to use property: ${entityProp}`)
12
+ }
13
+ return {
14
+ entity: entityFound[0],
15
+ property: propFound[1]
16
+ }
17
+ }
@@ -0,0 +1,33 @@
1
+ import { splitQueries } from './splitQueries'
2
+
3
+ const sampleQueries = [
4
+ 'read workouts where date = \'2024-06-02\'',
5
+ 'read workouts.muscles'
6
+ + ' on workouts.exercise_id = exercises._id'
7
+ + ' and on exercises._id = exercise_muscle.exercise_id'
8
+ + ' and on exercise_muscle.muscle_id = muscles._id'
9
+ + ' where muscles.alias = \'chest\'',
10
+ 'read workouts.muscles'
11
+ + ' on workouts.exercise_id = exercises._id'
12
+ + ' and on exercises._id = exercise_muscle.exercise_id'
13
+ + ' and on exercise_muscle.muscle_id = muscles._id'
14
+ + ' merge workouts.exercise_id with exercises._id'
15
+ + ' merge exercise_muscle.muscle_id with muscles._id'
16
+ + ' where muscles.alias = \'chest\'',
17
+ 'read workouts sort date desc, order',
18
+ 'read workouts group by date',
19
+ 'read workouts.exercises'
20
+ + ' select exercises.name as exercise, workouts.sets as sets, reps'
21
+ + ' on workouts.exercise_id = exercises._id'
22
+ + ' merge workouts.exercise_id with exercises._id'
23
+ + ' limit 2'
24
+ + ' offset 1'
25
+ ]
26
+
27
+ describe('splitQueries', () => {
28
+ test('can identify all queries', () => {
29
+ const queries = sampleQueries.reduce((concatQueries, query) => concatQueries = `${concatQueries} ${query}`, '')
30
+ const result = splitQueries(queries)
31
+ expect(result).toEqual(sampleQueries)
32
+ })
33
+ })
@@ -0,0 +1,4 @@
1
+ const queryMatch = /\s*(?=(?:delete|insert|read|update)\s+[a-z0-9._-]+)\s*/i
2
+
3
+ export const splitQueries = (queries: string = ''): string[] =>
4
+ queries.split(queryMatch).filter((query) => query.length > 0)
@@ -0,0 +1,38 @@
1
+ import { reconcileJoin } from './reconcileJoin'
2
+
3
+ describe('reconcileJoin', () => {
4
+ test('will apply found join with changes', () => {
5
+ const dataSet = {
6
+ workouts: [
7
+ {
8
+ _id: 1,
9
+ exercise_id: 1,
10
+ weight_effort: '115lbs',
11
+ reps: 10,
12
+ sets: 3,
13
+ note: '',
14
+ date: '2024-06-02',
15
+ muscles: [{ _id: 11, name: 'Pectorals', alias: 'chest', image: '' }]
16
+ }
17
+ ],
18
+ muscles: [
19
+ {
20
+ _id: 11,
21
+ name: 'Pectorals',
22
+ alias: 'chest',
23
+ image: '',
24
+ 'exercise_muscle._id': 1,
25
+ 'exercise_muscle.exercise_id': 1,
26
+ 'exercise_muscle.muscle_rank': 100
27
+ },
28
+ { _id: 14, name: 'Triceps', alias: '', image: '' }
29
+ ]
30
+ }
31
+ const entity = 'workouts'
32
+ const index = 0
33
+ const joinEntity = 'muscles'
34
+ const joinProperty = '_id'
35
+ const result = reconcileJoin(dataSet, entity, index, joinEntity, joinProperty)
36
+ expect(result[entity][index][joinEntity][0]).toEqual(dataSet[joinEntity][0])
37
+ })
38
+ })
@@ -0,0 +1,23 @@
1
+ import { where } from '../queries/where'
2
+
3
+ export const reconcileJoin = (dataSet, entityName, entityKey, joinEntity, joinProp) => {
4
+ const entity = dataSet[entityName][entityKey]
5
+ if (entity.hasOwnProperty(joinEntity) && Array.isArray(entity[joinEntity])) {
6
+ entity[joinEntity].forEach(
7
+ (mergedEntity, k) => {
8
+ const matchedEntity = where(
9
+ dataSet[joinEntity],
10
+ {
11
+ property: joinProp,
12
+ comparator: '=',
13
+ value: mergedEntity[joinProp]
14
+ }
15
+ )
16
+ if (matchedEntity.length) {
17
+ dataSet[entityName][entityKey][joinEntity][k] = matchedEntity[0]
18
+ }
19
+ }
20
+ )
21
+ }
22
+ return dataSet
23
+ }
@@ -0,0 +1,160 @@
1
+ import { reconcileJoins } from './reconcileJoins'
2
+
3
+ describe('reconcileJoins', () => {
4
+ test('reconciles several joins', () => {
5
+ const propertyA = 'muscles._id'
6
+ const propertyB = 'exercise_muscle.muscle_id'
7
+ const dataSet = {
8
+ workouts: [
9
+ {
10
+ _id: 1,
11
+ exercise_id: 1,
12
+ weight_effort: '115lbs',
13
+ reps: 10,
14
+ sets: 3,
15
+ note: '',
16
+ date: '2024-06-02',
17
+ muscles: [{ _id: 11, name: 'Pectorals', alias: 'chest', image: '' }]
18
+ },
19
+ {
20
+ _id: 2,
21
+ exercise_id: 2,
22
+ weight_effort: '155lbs',
23
+ reps: 10,
24
+ sets: 3,
25
+ note: '',
26
+ date: '2024-06-02',
27
+ muscles: [{ _id: 8, name: 'Hamstrings', alias: 'abs', image: '' }]
28
+ },
29
+ {
30
+ _id: 3,
31
+ exercise_id: 3,
32
+ weight_effort: '155lbs',
33
+ reps: 10,
34
+ sets: 3,
35
+ note: '',
36
+ date: '2024-06-02',
37
+ muscles: [{ _id: 12, name: 'Quadriceps', alias: 'quads', image: '' }]
38
+ }
39
+ ],
40
+ muscles: [
41
+ {
42
+ _id: 1,
43
+ name: 'Abdominal',
44
+ alias: 'abs',
45
+ image: '../img/abdominals.jpg'
46
+ },
47
+ { _id: 2, name: 'Biceps', alias: '', image: '' },
48
+ { _id: 3, name: 'Calves', alias: '', image: '' },
49
+ { _id: 4, name: 'Deltoids', alias: 'shoulders', image: '' },
50
+ {
51
+ _id: 5,
52
+ name: 'Erector Spinae',
53
+ alias: 'mid back, along spine',
54
+ image: ''
55
+ },
56
+ { _id: 6, name: 'Forearms', alias: 'abs', image: '' },
57
+ { _id: 7, name: 'Gluteus Maximus', alias: 'abs', image: '' },
58
+ {
59
+ _id: 8,
60
+ name: 'Hamstrings',
61
+ alias: 'abs',
62
+ image: '',
63
+ 'exercise_muscle._id': 2,
64
+ 'exercise_muscle.exercise_id': 2,
65
+ 'exercise_muscle.muscle_rank': 100
66
+ },
67
+ {
68
+ _id: 9,
69
+ name: 'Latissimus Dorsi',
70
+ alias: 'outer lower back',
71
+ image: ''
72
+ },
73
+ { _id: 10, name: 'Obliques', alias: 'outer abs', image: '' },
74
+ {
75
+ _id: 11,
76
+ name: 'Pectorals',
77
+ alias: 'chest',
78
+ image: '',
79
+ 'exercise_muscle._id': 1,
80
+ 'exercise_muscle.exercise_id': 1,
81
+ 'exercise_muscle.muscle_rank': 100
82
+ },
83
+ {
84
+ _id: 12,
85
+ name: 'Quadriceps',
86
+ alias: 'quads',
87
+ image: '',
88
+ 'exercise_muscle._id': 3,
89
+ 'exercise_muscle.exercise_id': 3,
90
+ 'exercise_muscle.muscle_rank': 100
91
+ },
92
+ { _id: 13, name: 'Trapezius', alias: 'upper back', image: '' },
93
+ { _id: 14, name: 'Triceps', alias: '', image: '' }
94
+ ]
95
+ }
96
+ const result = reconcileJoins(propertyA, propertyB, dataSet)
97
+ expect(result['workouts']).toEqual([
98
+ {
99
+ _id: 1,
100
+ exercise_id: 1,
101
+ weight_effort: '115lbs',
102
+ reps: 10,
103
+ sets: 3,
104
+ note: '',
105
+ date: '2024-06-02',
106
+ muscles: [
107
+ {
108
+ _id: 11,
109
+ name: 'Pectorals',
110
+ alias: 'chest',
111
+ image: '',
112
+ 'exercise_muscle._id': 1,
113
+ 'exercise_muscle.exercise_id': 1,
114
+ 'exercise_muscle.muscle_rank': 100
115
+ }
116
+ ]
117
+ },
118
+ {
119
+ _id: 2,
120
+ exercise_id: 2,
121
+ weight_effort: '155lbs',
122
+ reps: 10,
123
+ sets: 3,
124
+ note: '',
125
+ date: '2024-06-02',
126
+ muscles: [
127
+ {
128
+ _id: 8,
129
+ name: 'Hamstrings',
130
+ alias: 'abs',
131
+ image: '',
132
+ 'exercise_muscle._id': 2,
133
+ 'exercise_muscle.exercise_id': 2,
134
+ 'exercise_muscle.muscle_rank': 100
135
+ }
136
+ ]
137
+ },
138
+ {
139
+ _id: 3,
140
+ exercise_id: 3,
141
+ weight_effort: '155lbs',
142
+ reps: 10,
143
+ sets: 3,
144
+ note: '',
145
+ date: '2024-06-02',
146
+ muscles: [
147
+ {
148
+ _id: 12,
149
+ name: 'Quadriceps',
150
+ alias: 'quads',
151
+ image: '',
152
+ 'exercise_muscle._id': 3,
153
+ 'exercise_muscle.exercise_id': 3,
154
+ 'exercise_muscle.muscle_rank': 100
155
+ }
156
+ ]
157
+ }
158
+ ])
159
+ })
160
+ })
@@ -0,0 +1,15 @@
1
+ import { splitEntityProperty } from './parsers/splitEntityProperty'
2
+ import { reconcileJoin } from './reconcileJoin'
3
+
4
+ export const reconcileJoins = (propertyA, propertyB, dataSet) => {
5
+ const { entity: entityA, property: propA } = splitEntityProperty(propertyA)
6
+ const { entity: entityB, property: propB } = splitEntityProperty(propertyB)
7
+ for (let entityName in dataSet) {
8
+ for (let entityKey in dataSet[entityName]) {
9
+ const entity = dataSet[entityName][entityKey]
10
+ dataSet = reconcileJoin(dataSet, entityName, entityKey, entityA, propA)
11
+ dataSet = reconcileJoin(dataSet, entityName, entityKey, entityB, propB)
12
+ }
13
+ }
14
+ return dataSet
15
+ }