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,54 @@
1
+ const likeMatch = (dataValue, pattern) => {
2
+ if (typeof dataValue !== 'string' || typeof pattern !== 'string') {
3
+ return false
4
+ }
5
+ const regexPattern = pattern
6
+ .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
7
+ .replace(/%/g, '.*')
8
+ .replace(/_/g, '.')
9
+ return new RegExp(`^${regexPattern}$`, 'i').test(dataValue)
10
+ }
11
+
12
+ const makeCondition = (data, property, comparator, value) => {
13
+ if (!data.hasOwnProperty(property)) {
14
+ return false
15
+ }
16
+ const dataValue = data[property]
17
+ switch (comparator) {
18
+ case '=':
19
+ return dataValue == value
20
+ case '!=':
21
+ case '<>':
22
+ return dataValue != value
23
+ case '>':
24
+ return dataValue > value
25
+ case '>=':
26
+ return dataValue >= value
27
+ case '<':
28
+ return dataValue < value
29
+ case '<=':
30
+ return dataValue <= value
31
+ case 'in':
32
+ return Array.isArray(value) && value.includes(dataValue)
33
+ case 'between':
34
+ return Array.isArray(value) && value.length === 2 && dataValue >= value[0] && dataValue <= value[1]
35
+ case 'like':
36
+ return likeMatch(dataValue, value)
37
+ }
38
+ return false
39
+ }
40
+
41
+ export const where = (
42
+ dataSet = [],
43
+ {
44
+ property = '',
45
+ joinEntity = undefined,
46
+ comparator = '=',
47
+ value = null
48
+ } = {}
49
+ ) => {
50
+ return dataSet.filter((data) => {
51
+ const testProperty = joinEntity ? `${joinEntity}.${property}` : property
52
+ return makeCondition(data, testProperty, comparator, value)
53
+ })
54
+ }
@@ -0,0 +1,26 @@
1
+ import { registerRecord } from './registerRecord'
2
+ import { deregisterRecord } from './deregisterRecord'
3
+ import { testHelpers } from 'js-build-tools/testHelpers'
4
+
5
+ const databasePath = 'deregister-record-database/'
6
+ const gulpConfig = testHelpers.gulpConfig
7
+ gulpConfig.set('databasePath', databasePath)
8
+ testHelpers.setDefaults(databasePath)
9
+
10
+ beforeEach(testHelpers.beforeEach)
11
+
12
+ afterEach(testHelpers.afterEach)
13
+
14
+ describe('deregisterRecord', () => {
15
+ test('does nothing when the registry does not exist yet', async () => {
16
+ const result = await deregisterRecord('foo')
17
+ expect(result).toBeNull()
18
+ })
19
+
20
+ test('removes a record from the registry, keeping other entries', async () => {
21
+ await registerRecord('foo')
22
+ await registerRecord('bar')
23
+ const result = await deregisterRecord('foo')
24
+ expect(result.entries).toEqual(['bar.json'])
25
+ })
26
+ })
@@ -0,0 +1,24 @@
1
+ import { recordDefinition } from '../introspect/definitions/record'
2
+
3
+ const gulpConfig = require('js-build-tools/gulp.config')
4
+ const { readFile, writeFile } = require('fs/promises')
5
+
6
+ /**
7
+ * Remove a record's filename from the __RECORDS registry. A missing registry file is left
8
+ * untouched rather than created, since there's nothing to remove from it.
9
+ * @param recordName
10
+ */
11
+ export const deregisterRecord = async (recordName: string): Promise<recordDefinition | null> => {
12
+ const databasePath = gulpConfig.get('databasePath', 'database/')
13
+ const registryPath = `${databasePath}__RECORDS.json`
14
+ let registry: recordDefinition
15
+ try {
16
+ registry = JSON.parse(await readFile(registryPath, 'utf8'))
17
+ } catch (err) {
18
+ return null
19
+ }
20
+ const fileName = `${recordName}.json`
21
+ registry.entries = registry.entries.filter(entry => entry !== fileName)
22
+ await writeFile(registryPath, JSON.stringify(registry, null, 2))
23
+ return registry
24
+ }
@@ -0,0 +1,43 @@
1
+ import { isEntityProperty } from './parsers/isEntityProperty'
2
+ import { splitEntityProperty } from './parsers/splitEntityProperty'
3
+ import { retrieveRecord } from './retrieveRecord'
4
+ import { where } from '../queries/where'
5
+ import { retrieveFile } from './retrieveFile'
6
+ import { ParsedQuery } from './parsers/parseQuery'
7
+ import { getMatchingIndexes } from './getMatchingIndexes'
8
+
9
+ export const getConditionIndexedList = async (parsed: ParsedQuery, recordData, dataSet) => {
10
+ let reducedConditions = []
11
+ for (let condition of parsed.conditions) {
12
+ let entity = parsed.entity
13
+ let property = condition.property
14
+ if (isEntityProperty(property)) {
15
+ const entityProperty = splitEntityProperty(property)
16
+ entity = entityProperty.entity
17
+ property = entityProperty.property
18
+ }
19
+ if (!recordData.hasOwnProperty(entity)) {
20
+ recordData[entity] = await retrieveRecord(entity)
21
+ }
22
+ const indexed = {}
23
+ const retrieveMatchedFiles = async (entity, property, recordData, condition, dataSet, indexed) => {
24
+ const matchedRecords = where(indexed[entity][property], {
25
+ property: 'value',
26
+ comparator: condition.comparator,
27
+ value: condition.value
28
+ })
29
+ for (let matchedRecord of matchedRecords) {
30
+ for (let file of matchedRecord.record) {
31
+ dataSet[entity].push(await retrieveFile(`${entity}/${file}`))
32
+ }
33
+ }
34
+ }
35
+ let isIndexed = await getMatchingIndexes(entity, property, recordData, condition, dataSet, indexed, retrieveMatchedFiles)
36
+ if (!isIndexed) {
37
+ reducedConditions.push(condition)
38
+ }
39
+ }
40
+ parsed.conditions = reducedConditions
41
+ return parsed
42
+
43
+ }
@@ -0,0 +1,53 @@
1
+ import siFunciona from 'si-funciona'
2
+ import { splitEntityProperty } from './parsers/splitEntityProperty'
3
+ import { retrieveRecord } from './retrieveRecord'
4
+ import { ParsedQuery } from './parsers/parseQuery'
5
+ import { getMatchingIndexes } from './getMatchingIndexes'
6
+ import { matchIndexedJoins } from './matchIndexedJoins'
7
+ import { restrictIndexedList } from './restrictIndexedList'
8
+
9
+ export const getJoinIndexedList = async (parsed: ParsedQuery, recordData, dataSets) => {
10
+ let reducedJoins = []
11
+ const indexed = {}
12
+ let firstIteration = true
13
+ const entity = parsed.entity
14
+ const joinEntity = parsed.joinEntity
15
+ const joinClauses = parsed.joinClauses
16
+ for (const anEntity in dataSets[entity]) {
17
+ const currentEntity = dataSets[entity][anEntity]
18
+ // Loop over each of the main entities
19
+ let filterJoins = {}
20
+ filterJoins[entity] = [siFunciona.cloneObject(currentEntity)]
21
+ for (let joinClause of joinClauses) {
22
+ let indexedClone = siFunciona.cloneObject(indexed)
23
+ const { entity: entityA, property: propertyA } = splitEntityProperty(joinClause.propertyA)
24
+ const { entity: entityB, property: propertyB } = splitEntityProperty(joinClause.propertyB)
25
+
26
+ // Get the record for the entities A and B, store on the recordData
27
+ if (!recordData.hasOwnProperty(entityA)) {
28
+ recordData[entityA] = await retrieveRecord(entityA)
29
+ }
30
+ if (!recordData.hasOwnProperty(entityB)) {
31
+ recordData[entityB] = await retrieveRecord(entityB)
32
+ }
33
+
34
+ indexedClone = restrictIndexedList(joinClause, filterJoins, indexedClone)
35
+
36
+ const retrieveMatchedFiles = matchIndexedJoins(entity, indexedClone, dataSets)
37
+
38
+ // Check if there are matching keys for the join condition
39
+ const matchAResult = await getMatchingIndexes(entityA, propertyA, recordData, joinClause, filterJoins, indexed)
40
+ const matchBResult = await getMatchingIndexes(entityB, propertyB, recordData, joinClause, filterJoins, indexed, retrieveMatchedFiles)
41
+
42
+ const isIndexed = matchAResult || matchBResult
43
+
44
+ if (!isIndexed && firstIteration) {
45
+ reducedJoins.push(joinClause)
46
+ firstIteration = false
47
+ }
48
+ }
49
+ dataSets[entity][anEntity][joinEntity] = filterJoins[joinEntity]
50
+ }
51
+ parsed.joinClauses = reducedJoins
52
+ return parsed
53
+ }
@@ -0,0 +1,21 @@
1
+ import { retrieveIndexes } from './retrieveIndexes'
2
+
3
+ export const getMatchingIndexes = async (entity: string, property: string, recordData: Object, clause: Object, dataSet: Object, indexed: Object, cb: Function = null): Promise<boolean> => {
4
+ let isIndexed = false
5
+ for (let key of recordData[entity].keys) {
6
+ if (key.fields.includes(property)) {
7
+ dataSet[entity] = []
8
+ if (!indexed.hasOwnProperty(entity)) {
9
+ indexed[entity] = {}
10
+ }
11
+ if (!indexed[entity].hasOwnProperty(property)) {
12
+ indexed[entity][property] = (await retrieveIndexes(entity, [property], recordData))[property]
13
+ }
14
+ if (typeof cb === 'function') {
15
+ await cb(entity, property, recordData, clause, dataSet, indexed)
16
+ }
17
+ isIndexed = true
18
+ }
19
+ }
20
+ return isIndexed
21
+ }
@@ -0,0 +1,45 @@
1
+ import siFunciona from 'si-funciona'
2
+ import { where } from '../queries/where'
3
+ import { retrieveFile } from './retrieveFile'
4
+ import { splitEntityProperty } from './parsers/splitEntityProperty'
5
+
6
+ export const matchIndexedJoins = (entity, indexedClone, dataSets) => async (focusEntity, property, recordData, joinClause, filterJoins, indexed) => {
7
+ const { entity: entityA, property: propertyA } = splitEntityProperty(joinClause.propertyA)
8
+ const { entity: entityB, property: propertyB } = splitEntityProperty(joinClause.propertyB)
9
+ const properties = [
10
+ { entityFirst: entityA, propertyFirst: propertyA, entitySecond: entityB, propertySecond: propertyB },
11
+ { entityFirst: entityB, propertyFirst: propertyB, entitySecond: entityA, propertySecond: propertyA },
12
+ ]
13
+ for (let checkProp of properties) {
14
+ if (!indexedClone.hasOwnProperty(checkProp.entitySecond)) {
15
+ indexedClone[checkProp.entitySecond] = siFunciona.cloneObject(indexed[checkProp.entitySecond])
16
+ }
17
+ const matchedRecords = indexedClone[checkProp.entitySecond][checkProp.propertySecond].reduce(
18
+ (dataA, dataB) => siFunciona.mergeArrays(
19
+ dataA,
20
+ where(indexedClone[checkProp.entityFirst][checkProp.propertyFirst], {
21
+ property: 'value',
22
+ comparator: joinClause.comparator,
23
+ value: dataB.value
24
+ })
25
+ ),
26
+ []
27
+ )
28
+ let skipPush = checkProp.entityFirst === entity
29
+ if (!dataSets.hasOwnProperty(checkProp.entityFirst)) {
30
+ dataSets[checkProp.entityFirst] = []
31
+ }
32
+ for (let matchedRecord of matchedRecords) {
33
+ for (let file of matchedRecord.record) {
34
+ let entityRecord = file
35
+ if (typeof file === 'string') {
36
+ entityRecord = await retrieveFile(`${checkProp.entityFirst}/${file}`)
37
+ }
38
+ if (!skipPush) {
39
+ dataSets[checkProp.entityFirst].push(entityRecord)
40
+ }
41
+ filterJoins[checkProp.entityFirst].push(entityRecord)
42
+ }
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,102 @@
1
+ import { mergeJoin } from './mergeJoin'
2
+ import { testHelpers } from 'js-build-tools/testHelpers'
3
+ import { copyDatabase } from '../../../test-data/copyDatabase'
4
+
5
+ const databasePath = 'merge-join-database/'
6
+ const gulpConfig = testHelpers.gulpConfig
7
+ gulpConfig.set('databasePath', databasePath)
8
+ testHelpers.setDefaults(databasePath)
9
+
10
+ beforeEach(
11
+ () => testHelpers.beforeEach()
12
+ .then(() => copyDatabase(databasePath))
13
+ )
14
+
15
+ afterEach(testHelpers.afterEach)
16
+
17
+ describe('mergeJoin', () => {
18
+ test('can combine both entities', async () => {
19
+ const results = await mergeJoin('workouts.exercise_id', 'exercises._id')
20
+ expect(results).toEqual({
21
+ workouts: [
22
+ {
23
+ _id: 1,
24
+ exercise_id: 1,
25
+ weight_effort: '115lbs',
26
+ reps: 10,
27
+ sets: 3,
28
+ note: '',
29
+ order: 0,
30
+ date: '2024-06-02',
31
+ 'exercises.name': 'Bench Press',
32
+ 'exercises.description': ''
33
+ },
34
+ {
35
+ _id: 2,
36
+ exercise_id: 2,
37
+ weight_effort: '155lbs',
38
+ reps: 10,
39
+ sets: 3,
40
+ note: '',
41
+ order: 1,
42
+ date: '2024-06-02',
43
+ 'exercises.name': 'Deadlift',
44
+ 'exercises.description': ''
45
+ },
46
+ {
47
+ _id: 3,
48
+ exercise_id: 3,
49
+ weight_effort: '155lbs',
50
+ reps: 10,
51
+ sets: 3,
52
+ note: '',
53
+ order: 2,
54
+ date: '2024-06-02',
55
+ 'exercises.name': 'Squat',
56
+ 'exercises.description': ''
57
+ },
58
+ {
59
+ _id: 4,
60
+ exercise_id: 1,
61
+ weight_effort: '120lbs',
62
+ reps: 10,
63
+ sets: 3,
64
+ note: '',
65
+ order: 0,
66
+ date: '2024-06-05',
67
+ 'exercises.name': 'Bench Press',
68
+ 'exercises.description': ''
69
+ },
70
+ {
71
+ _id: 5,
72
+ exercise_id: 2,
73
+ weight_effort: '160lbs',
74
+ reps: 10,
75
+ sets: 3,
76
+ note: '',
77
+ order: 1,
78
+ date: '2024-06-05',
79
+ 'exercises.name': 'Deadlift',
80
+ 'exercises.description': ''
81
+ },
82
+ {
83
+ _id: 6,
84
+ exercise_id: 3,
85
+ weight_effort: '160lbs',
86
+ reps: 10,
87
+ sets: 3,
88
+ note: '',
89
+ order: 2,
90
+ date: '2024-06-05',
91
+ 'exercises.name': 'Squat',
92
+ 'exercises.description': ''
93
+ }
94
+ ],
95
+ exercises: [
96
+ { _id: 1, name: 'Bench Press', description: '' },
97
+ { _id: 2, name: 'Deadlift', description: '' },
98
+ { _id: 3, name: 'Squat', description: '' }
99
+ ]
100
+ })
101
+ })
102
+ })
@@ -0,0 +1,28 @@
1
+ import { readEntity } from '../queries/readEntity'
2
+ import { splitEntityProperty } from './parsers/splitEntityProperty'
3
+ import { where } from '../queries/where'
4
+
5
+ export const mergeJoin = async (propertyA = '', propertyB = '', dataSets = {}) => {
6
+ const { entity: entityA, property: propA } = splitEntityProperty(propertyA)
7
+ const { entity: entityB, property: propB } = splitEntityProperty(propertyB)
8
+
9
+ dataSets = await readEntity(entityA, dataSets)
10
+ dataSets = await readEntity(entityB, dataSets)
11
+
12
+ dataSets[entityA] = dataSets[entityA].map((dataA) => {
13
+ const matches = where(dataSets[entityB], { property: propB, comparator: '=', value: dataA[propA] })
14
+ if (!matches.length) {
15
+ return dataA
16
+ }
17
+ const mergeMatch = matches[0]
18
+ for (let prop in mergeMatch) {
19
+ if (prop === propB) {
20
+ // Skip the condition property since it is irrelevant
21
+ continue
22
+ }
23
+ dataA[`${entityB}.${prop}`] = mergeMatch[prop]
24
+ }
25
+ return dataA
26
+ })
27
+ return dataSets
28
+ }
@@ -0,0 +1,25 @@
1
+ import { removeFromQuery } from './removeFromQuery'
2
+ import { ParsedQuery } from './parseQuery'
3
+
4
+ const commandMatch: RegExp = /^(delete|insert|read|update)\s+([a-z0-9_-]+)[\w\n]*/i
5
+
6
+ export type ParsedCommand = string | 'delete' | 'insert' | 'read' | 'update'
7
+
8
+ export type ParsedEntity = string
9
+
10
+ /**
11
+ * Extract command clauses from the query.
12
+ * @param parsed
13
+ * @param query
14
+ */
15
+ export const findCommand = (parsed: ParsedQuery, query: string): string => {
16
+ const commandFound: RegExpMatchArray = query.match(commandMatch)
17
+ parsed['command'] = undefined
18
+ parsed['entity'] = undefined
19
+ if (commandFound) {
20
+ parsed['command'] = commandFound[1]
21
+ parsed['entity'] = commandFound[2]
22
+ return removeFromQuery(commandFound[0], query)
23
+ }
24
+ return query
25
+ }
@@ -0,0 +1,38 @@
1
+ import { findConditions } from './findConditions'
2
+
3
+ const parse = (query) => {
4
+ const parsed = { conditions: [] }
5
+ const remaining = findConditions(parsed, query)
6
+ return { parsed, remaining }
7
+ }
8
+
9
+ describe('findConditions', () => {
10
+ test('extracts a quoted string value', () => {
11
+ const { parsed, remaining } = parse("where date = '2024-06-02'")
12
+ expect(parsed.conditions).toEqual([{ property: 'date', comparator: '=', value: '2024-06-02' }])
13
+ expect(remaining).toBe('')
14
+ })
15
+
16
+ test('extracts an unquoted number as a real number', () => {
17
+ const { parsed } = parse('where reps > 10')
18
+ expect(parsed.conditions).toEqual([{ property: 'reps', comparator: '>', value: 10 }])
19
+ })
20
+
21
+ test('extracts an array literal as a real array', () => {
22
+ const { parsed } = parse('where exercise_id in [1,2,3]')
23
+ expect(parsed.conditions).toEqual([{ property: 'exercise_id', comparator: 'in', value: [1, 2, 3] }])
24
+ })
25
+
26
+ test('extracts null as the real null value', () => {
27
+ const { parsed } = parse('where note = null')
28
+ expect(parsed.conditions).toEqual([{ property: 'note', comparator: '=', value: null }])
29
+ })
30
+
31
+ test('extracts true and false as real booleans', () => {
32
+ const { parsed } = parse('where active = true where archived = false')
33
+ expect(parsed.conditions).toEqual([
34
+ { property: 'active', comparator: '=', value: true },
35
+ { property: 'archived', comparator: '=', value: false }
36
+ ])
37
+ })
38
+ })
@@ -0,0 +1,32 @@
1
+ import { removeFromQuery } from './removeFromQuery'
2
+ import { parseLiteralValue, LiteralValue } from './parseLiteralValue'
3
+ import { ParsedQuery } from './parseQuery'
4
+
5
+ const conditionMatch: RegExp = /(and|or)?\s*(where)\s+([a-z0-9_-]+\.?[a-z0-9_-]*)\s+(=|!=|>|<|>=|<=|in|between|like)\s+(["'](.*)['"]|([0-9]+)|(\[.*])|(null)|(true)|(false))/ig
6
+
7
+ export type ConditionValue = LiteralValue
8
+
9
+ export type ParsedCondition = {
10
+ property: string
11
+ comparator: string
12
+ value: ConditionValue
13
+ }
14
+
15
+ /**
16
+ * Extract condition clauses from the query.
17
+ * @param parsed
18
+ * @param query
19
+ */
20
+ export const findConditions = (parsed: ParsedQuery, query: string): string => {
21
+ const conditionsFound: IterableIterator<RegExpMatchArray> = query.matchAll(conditionMatch)
22
+ // @ts-ignore
23
+ for (let condition of conditionsFound) {
24
+ parsed['conditions'].push({
25
+ property: condition[3],
26
+ comparator: condition[4],
27
+ value: parseLiteralValue(condition, 6)
28
+ })
29
+ query = removeFromQuery(condition[0], query)
30
+ }
31
+ return query
32
+ }
@@ -0,0 +1,20 @@
1
+ import { removeFromQuery } from './removeFromQuery'
2
+ import { ParsedQuery } from './parseQuery'
3
+
4
+ const groupMatch: RegExp = /group\s+by\s+(,?[a-z0-9._-]+)+/i
5
+
6
+ export type ParsedGroupBy = string
7
+
8
+ /**
9
+ * Extract the group by clauses from the query.
10
+ * @param parsed
11
+ * @param query
12
+ */
13
+ export const findGroupBy = (parsed: ParsedQuery, query: string): string => {
14
+ const groupFound: RegExpMatchArray = query.match(groupMatch)
15
+ if (groupFound) {
16
+ parsed['groupBy'] = groupFound ? groupFound[1] : undefined
17
+ return removeFromQuery(groupFound[0], query)
18
+ }
19
+ return query
20
+ }
@@ -0,0 +1,26 @@
1
+ import { findInsertValues } from './findInsertValues'
2
+
3
+ const parse = (query) => {
4
+ const parsed = {}
5
+ const remaining = findInsertValues(parsed, query)
6
+ return { parsed, remaining }
7
+ }
8
+
9
+ describe('findInsertValues', () => {
10
+ test('extracts a single row, wrapped in a one-element array', () => {
11
+ const { parsed, remaining } = parse("insert workouts values reps = 12, date = '2024-06-02'")
12
+ expect(parsed.insertValues).toEqual([{ reps: 12, date: '2024-06-02' }])
13
+ expect(remaining).toBe('insert workouts')
14
+ })
15
+
16
+ test('extracts every literal shape', () => {
17
+ const { parsed } = parse('values active = true, tags = [1,2,3], note = null')
18
+ expect(parsed.insertValues).toEqual([{ active: true, tags: [1, 2, 3], note: null }])
19
+ })
20
+
21
+ test('leaves the query untouched, with an empty insertValues, when there is no values clause', () => {
22
+ const { parsed, remaining } = parse("read workouts where date = '2024-06-02'")
23
+ expect(parsed.insertValues).toEqual([])
24
+ expect(remaining).toBe("read workouts where date = '2024-06-02'")
25
+ })
26
+ })
@@ -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 valuesClauseMatch: RegExp = new RegExp(`(values)\\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 ParsedInsertRow = { [field: string]: any }
10
+
11
+ /**
12
+ * Extract an insert's "values field = value, field2 = value2" clause from the query, the same way
13
+ * findUpdateValues() does for "set". insertEntity() accepts an array of rows for bulk inserts, but
14
+ * a query string only describes a single row for now - wrapped in a one-element array to match.
15
+ * @param parsed
16
+ * @param query
17
+ */
18
+ export const findInsertValues = (parsed: ParsedQuery, query: string): string => {
19
+ const clauseFound: RegExpMatchArray = query.match(valuesClauseMatch)
20
+ parsed['insertValues'] = []
21
+ if (!clauseFound) {
22
+ return query
23
+ }
24
+ const row = {}
25
+ const assignmentsFound: IterableIterator<RegExpMatchArray> = clauseFound[2].matchAll(assignmentMatch)
26
+ // @ts-ignore
27
+ for (const assignment of assignmentsFound) {
28
+ row[assignment[1]] = parseLiteralValue(assignment, 3)
29
+ }
30
+ parsed['insertValues'] = [row]
31
+ return removeFromQuery(clauseFound[0], query)
32
+ }
@@ -0,0 +1,29 @@
1
+ import { removeFromQuery } from './removeFromQuery'
2
+ import { ParsedQuery } from './parseQuery'
3
+
4
+ const joinClauseMatch: RegExp = /(and)?\s*on\s+([a-z0-9_-]+\.[a-z0-9_-]+)\s+(=|!=|>|<|>=|<=|in|between|like)\s+([a-z0-9_-]+\.[a-z0-9_-]+)/ig
5
+
6
+ export type ParsedJoinClause = {
7
+ propertyA: string
8
+ comparator: string
9
+ propertyB: string
10
+ }
11
+
12
+ /**
13
+ * Extract condition clauses from the query.
14
+ * @param parsed
15
+ * @param query
16
+ */
17
+ export const findJoinClauses = (parsed: ParsedQuery, query: string): string => {
18
+ const joinClausesFound: IterableIterator<RegExpMatchArray> = query.matchAll(joinClauseMatch)
19
+ // @ts-ignore
20
+ for (let joinClause of joinClausesFound) {
21
+ parsed['joinClauses'].push({
22
+ propertyA: joinClause[2],
23
+ comparator: joinClause[3],
24
+ propertyB: joinClause[4]
25
+ })
26
+ query = removeFromQuery(joinClause[0], query)
27
+ }
28
+ return query
29
+ }
@@ -0,0 +1,20 @@
1
+ import { removeFromQuery } from './removeFromQuery'
2
+ import { ParsedQuery } from './parseQuery'
3
+
4
+ const joinEntityMatch: RegExp = /\.([a-z0-9_-]+)/i
5
+
6
+ export type ParsedJoinEntity = string
7
+
8
+ /**
9
+ * Extract the main join entity from the query.
10
+ * @param parsed
11
+ * @param query
12
+ */
13
+ export const findJoinEntity = (parsed: ParsedQuery, query: string): string => {
14
+ const joinEntityFound: RegExpMatchArray = query.match(joinEntityMatch)
15
+ if (joinEntityFound) {
16
+ parsed['joinEntity'] = joinEntityFound ? joinEntityFound[1] : undefined
17
+ return removeFromQuery(joinEntityFound[0], query)
18
+ }
19
+ return query
20
+ }
@@ -0,0 +1,20 @@
1
+ import { removeFromQuery } from './removeFromQuery'
2
+ import { ParsedQuery } from './parseQuery'
3
+
4
+ const limitMatch: RegExp = /limit\s*(\d+)/i
5
+
6
+ export type ParsedLimit = number
7
+
8
+ /**
9
+ * Extract the limit clauses from the query.
10
+ * @param parsed
11
+ * @param query
12
+ */
13
+ export const findLimit = (parsed: ParsedQuery, query: string): string => {
14
+ const limitFound: RegExpMatchArray = query.match(limitMatch)
15
+ if (limitFound) {
16
+ parsed['limit'] = limitFound ? parseInt(limitFound[1]) : undefined
17
+ return removeFromQuery(limitFound[0], query)
18
+ }
19
+ return query
20
+ }