@kaspernj/api-maker 1.0.2011 → 1.0.2012

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 (410) hide show
  1. package/{.eslintrc.cjs → .eslintrc.js} +10 -1
  2. package/README.md +35 -0
  3. package/android/build.gradle +43 -0
  4. package/android/src/main/AndroidManifest.xml +2 -0
  5. package/android/src/main/java/expo/modules/api_maker/ApiMakerModule.kt +50 -0
  6. package/android/src/main/java/expo/modules/api_maker/ApiMakerView.kt +30 -0
  7. package/build/api.js +120 -0
  8. package/build/attribute-not-loaded-error.js +2 -0
  9. package/build/base-component.js +5 -0
  10. package/build/base-error.js +33 -0
  11. package/build/base-model/attribute.js +25 -0
  12. package/build/base-model/column.js +11 -0
  13. package/build/base-model/reflection.js +14 -0
  14. package/build/base-model/scope.js +11 -0
  15. package/build/base-model.js +828 -0
  16. package/build/bootstrap/attribute-row.js +135 -0
  17. package/build/bootstrap/attribute-rows.js +31 -0
  18. package/build/bootstrap/card.js +138 -0
  19. package/build/bootstrap/checkbox.js +97 -0
  20. package/build/bootstrap/checkboxes.js +183 -0
  21. package/build/bootstrap/index.js +2 -0
  22. package/build/bootstrap/input.js +129 -0
  23. package/build/bootstrap/invalid-feedback.js +27 -0
  24. package/build/bootstrap/paginate.js +150 -0
  25. package/build/bootstrap/radio-buttons.js +72 -0
  26. package/build/bootstrap/select.js +88 -0
  27. package/build/bootstrap/sort-link.js +131 -0
  28. package/build/cable-connection-pool.js +128 -0
  29. package/build/cable-subscription-pool.js +207 -0
  30. package/build/cable-subscription.js +21 -0
  31. package/build/cache-key-generator.js +81 -0
  32. package/build/can-can.js +134 -0
  33. package/build/channels-consumer.js +9 -0
  34. package/build/collection-loader.js +48 -0
  35. package/build/collection.js +280 -0
  36. package/build/command-submit-data.js +81 -0
  37. package/build/commands-pool.js +195 -0
  38. package/build/compose.js +9 -0
  39. package/build/config.js +62 -0
  40. package/build/custom-error.js +5 -0
  41. package/build/data-set-to-attributes.js +10 -0
  42. package/build/deserializer.js +56 -0
  43. package/build/destroy-error.js +5 -0
  44. package/build/devise.js +112 -0
  45. package/build/draggable-sort/controller.js +136 -0
  46. package/build/draggable-sort/index.js +114 -0
  47. package/build/draggable-sort/item.js +188 -0
  48. package/build/error-logger.js +101 -0
  49. package/build/error-messages.js +13 -0
  50. package/build/event-connection.js +32 -0
  51. package/build/event-emitter-listener.js +15 -0
  52. package/build/event-model-class.js +24 -0
  53. package/build/events.js +5 -0
  54. package/build/flash-message.js +79 -0
  55. package/build/form.js +83 -0
  56. package/build/history-expo.js +20 -0
  57. package/build/history-react-native.js +20 -0
  58. package/build/history.js +3 -0
  59. package/build/index.js +3 -0
  60. package/build/inputs/attachment.js +133 -0
  61. package/build/inputs/auto-submit.js +36 -0
  62. package/build/inputs/checkbox.js +138 -0
  63. package/build/inputs/checkboxes.js +112 -0
  64. package/build/inputs/id-for-component.js +15 -0
  65. package/build/inputs/input-wrapper.js +19 -0
  66. package/build/inputs/input.js +243 -0
  67. package/build/inputs/money.js +179 -0
  68. package/build/inputs/name-for-component.js +13 -0
  69. package/build/inputs/select.js +93 -0
  70. package/build/instance-of-class-name.js +23 -0
  71. package/build/key-value-store.js +53 -0
  72. package/build/link.js +73 -0
  73. package/build/logger.js +30 -0
  74. package/build/modal.js +38 -0
  75. package/build/model-class-require.js +13 -0
  76. package/build/model-events.js +30 -0
  77. package/build/model-name.js +28 -0
  78. package/build/model-prop-type.js +101 -0
  79. package/build/model-recipes-loader.js +32 -0
  80. package/build/model-recipes-model-loader.js +357 -0
  81. package/build/models-response-reader.js +40 -0
  82. package/build/models.js +8 -0
  83. package/build/money-formatter.js +78 -0
  84. package/build/not-loaded-error.js +2 -0
  85. package/build/params.js +61 -0
  86. package/build/preloaded.js +38 -0
  87. package/build/resize-observer.js +11 -0
  88. package/build/result.js +13 -0
  89. package/build/router/route.js +270 -0
  90. package/build/router/switch.js +72 -0
  91. package/build/router.js +59 -0
  92. package/build/routes-native.js +202 -0
  93. package/build/routes.js +50 -0
  94. package/build/run-last.js +35 -0
  95. package/build/serializer.js +63 -0
  96. package/build/services.js +20 -0
  97. package/build/session-status-updater.js +134 -0
  98. package/build/source-maps-loader.js +184 -0
  99. package/build/super-admin/config-reader.js +85 -0
  100. package/build/super-admin/edit-page/edit-attribute-checkbox.js +85 -0
  101. package/build/super-admin/edit-page/edit-attribute-content.js +55 -0
  102. package/build/super-admin/edit-page/edit-attribute-input.js +79 -0
  103. package/build/super-admin/edit-page/edit-attribute.js +77 -0
  104. package/build/super-admin/edit-page.js +123 -0
  105. package/build/super-admin/has-edit-config.js +12 -0
  106. package/build/super-admin/index-page.js +25 -0
  107. package/build/super-admin/index.js +181 -0
  108. package/build/super-admin/layout/header/index.js +161 -0
  109. package/build/super-admin/layout/index.js +164 -0
  110. package/build/super-admin/layout/menu/index.js +206 -0
  111. package/build/super-admin/layout/menu/menu-content.js +46 -0
  112. package/build/super-admin/layout/menu/menu-item.js +84 -0
  113. package/build/super-admin/layout/no-access.js +27 -0
  114. package/build/super-admin/model-class-table.js +61 -0
  115. package/build/super-admin/models.js +8 -0
  116. package/build/super-admin/show-nav.js +51 -0
  117. package/build/super-admin/show-page/belongs-to-attribute-row.js +29 -0
  118. package/build/super-admin/show-page/index.js +141 -0
  119. package/build/super-admin/show-reflection-actions.js +47 -0
  120. package/build/super-admin/show-reflection-link.js +48 -0
  121. package/build/super-admin/show-reflection-page.js +48 -0
  122. package/build/table/column-content.js +117 -0
  123. package/build/table/column-identifier.js +18 -0
  124. package/build/table/column-visible.js +7 -0
  125. package/build/table/components/column.js +21 -0
  126. package/build/table/components/flat-list.js +21 -0
  127. package/build/table/components/header.js +26 -0
  128. package/build/table/components/row.js +26 -0
  129. package/build/table/filters/attribute-element.js +44 -0
  130. package/build/table/filters/filter-form.js +402 -0
  131. package/build/table/filters/filter.js +90 -0
  132. package/build/table/filters/index.js +184 -0
  133. package/build/table/filters/load-search-modal.js +175 -0
  134. package/build/table/filters/reflection-element.js +37 -0
  135. package/build/table/filters/save-search-modal.js +88 -0
  136. package/build/table/filters/scope-element.js +42 -0
  137. package/build/table/header-column-content.js +68 -0
  138. package/build/table/header-column.js +144 -0
  139. package/build/table/header-select.js +105 -0
  140. package/build/table/model-callback-args.js +10 -0
  141. package/build/table/model-column.js +97 -0
  142. package/build/table/model-row.js +193 -0
  143. package/build/table/select-calculator.js +63 -0
  144. package/build/table/settings/column-row.js +97 -0
  145. package/build/table/settings/download-action.js +79 -0
  146. package/build/table/settings/index.js +92 -0
  147. package/build/table/table-settings.js +219 -0
  148. package/build/table/table.js +972 -0
  149. package/build/table/use-sorting.js +34 -0
  150. package/build/table/widths.js +75 -0
  151. package/build/table/worker-plugins-check-all-checkbox.js +125 -0
  152. package/build/table/worker-plugins-checkbox.js +115 -0
  153. package/build/translated-attributes.js +10 -0
  154. package/build/translated-collections.js +12 -0
  155. package/build/updated-attribute.js +76 -0
  156. package/build/url-encode.js +15 -0
  157. package/build/use-breakpoint.js +62 -0
  158. package/build/use-can-can.js +55 -0
  159. package/build/use-collection.js +225 -0
  160. package/build/use-created-event.js +52 -0
  161. package/build/use-current-user.js +76 -0
  162. package/build/use-destroyed-event.js +60 -0
  163. package/build/use-event-emitter.js +13 -0
  164. package/build/use-event-listener.js +16 -0
  165. package/build/use-input.js +137 -0
  166. package/build/use-model-event.js +60 -0
  167. package/build/use-model.js +169 -0
  168. package/build/use-resize-observer.js +23 -0
  169. package/build/use-router.js +104 -0
  170. package/build/use-screen-layout.js +39 -0
  171. package/build/use-updated-event.js +60 -0
  172. package/build/use-validation-errors.js +30 -0
  173. package/build/utils/card.js +51 -0
  174. package/build/utils/checkbox.js +78 -0
  175. package/build/utils/checkboxes.js +163 -0
  176. package/build/utils/default-style.js +18 -0
  177. package/build/utils/icon.js +23 -0
  178. package/build/utils/invalid-feedback.js +19 -0
  179. package/build/utils/modal.js +62 -0
  180. package/build/utils/text.js +19 -0
  181. package/build/validation-error.js +28 -0
  182. package/build/validation-errors.js +98 -0
  183. package/build/with-api-maker.js +29 -0
  184. package/build/with-collection.js +14 -0
  185. package/build/with-current-user.js +10 -0
  186. package/build/with-model.js +15 -0
  187. package/build/with-router.js +22 -0
  188. package/expo-module.config.json +17 -0
  189. package/ios/ApiMaker.podspec +29 -0
  190. package/ios/ApiMakerModule.swift +48 -0
  191. package/ios/ApiMakerView.swift +38 -0
  192. package/link.sh +8 -0
  193. package/package.json +49 -46
  194. package/src/{api.mjs → api.js} +38 -37
  195. package/src/base-component.jsx +5 -0
  196. package/src/{base-error.mjs → base-error.js} +4 -6
  197. package/src/base-model/attribute.js +33 -0
  198. package/src/base-model/column.js +13 -0
  199. package/src/base-model/reflection.js +15 -0
  200. package/src/base-model/scope.js +12 -0
  201. package/src/{base-model.mjs → base-model.js} +302 -144
  202. package/src/bootstrap/attribute-row.jsx +135 -0
  203. package/src/bootstrap/attribute-rows.jsx +27 -0
  204. package/src/bootstrap/card.jsx +149 -0
  205. package/src/bootstrap/checkbox.jsx +86 -0
  206. package/src/bootstrap/checkboxes.jsx +185 -0
  207. package/src/bootstrap/index.js +0 -0
  208. package/src/bootstrap/input.jsx +173 -0
  209. package/src/bootstrap/invalid-feedback.jsx +31 -0
  210. package/src/bootstrap/paginate.jsx +187 -0
  211. package/src/bootstrap/radio-buttons.jsx +87 -0
  212. package/src/bootstrap/select.jsx +110 -0
  213. package/src/bootstrap/sort-link.jsx +106 -0
  214. package/src/{cable-connection-pool.mjs → cable-connection-pool.js} +16 -36
  215. package/src/{cable-subscription-pool.mjs → cable-subscription-pool.js} +26 -21
  216. package/src/{cable-subscription.mjs → cable-subscription.js} +6 -4
  217. package/src/cache-key-generator.js +100 -0
  218. package/src/{can-can.mjs → can-can.js} +13 -12
  219. package/src/channels-consumer.js +10 -0
  220. package/src/collection-loader.jsx +58 -224
  221. package/src/{collection.mjs → collection.js} +98 -44
  222. package/src/{command-submit-data.mjs → command-submit-data.js} +2 -7
  223. package/src/{commands-pool.mjs → commands-pool.js} +57 -41
  224. package/src/compose.js +11 -0
  225. package/src/{config.mjs → config.js} +6 -2
  226. package/src/{custom-error.mjs → custom-error.js} +1 -1
  227. package/src/data-set-to-attributes.js +13 -0
  228. package/src/{deserializer.mjs → deserializer.js} +3 -3
  229. package/src/destroy-error.js +7 -0
  230. package/src/devise.js +129 -0
  231. package/src/draggable-sort/controller.js +137 -0
  232. package/src/draggable-sort/index.jsx +108 -0
  233. package/src/draggable-sort/item.jsx +174 -0
  234. package/src/{error-logger.mjs → error-logger.js} +12 -7
  235. package/src/{error-messages.mjs → error-messages.js} +1 -0
  236. package/src/event-connection.jsx +1 -1
  237. package/src/event-emitter-listener.jsx +8 -27
  238. package/src/event-model-class.jsx +2 -4
  239. package/src/events.js +7 -0
  240. package/src/flash-message.js +70 -0
  241. package/src/form.jsx +91 -0
  242. package/src/history-expo.js +23 -0
  243. package/src/history-react-native.js +25 -0
  244. package/src/history.js +3 -0
  245. package/src/index.js +3 -0
  246. package/src/inputs/attachment.jsx +108 -0
  247. package/src/inputs/auto-submit.js +37 -0
  248. package/src/inputs/checkbox.jsx +125 -0
  249. package/src/inputs/checkboxes.jsx +116 -0
  250. package/src/inputs/id-for-component.js +15 -0
  251. package/src/inputs/input-wrapper.jsx +16 -0
  252. package/src/inputs/input.jsx +260 -0
  253. package/src/inputs/money.jsx +187 -0
  254. package/src/inputs/name-for-component.js +15 -0
  255. package/src/inputs/select.jsx +104 -0
  256. package/src/{key-value-store.mjs → key-value-store.js} +1 -1
  257. package/src/link.jsx +54 -9
  258. package/src/logger.js +38 -0
  259. package/src/modal.jsx +37 -0
  260. package/src/model-class-require.js +17 -0
  261. package/src/{model-events.mjs → model-events.js} +1 -1
  262. package/src/{model-name.mjs → model-name.js} +8 -8
  263. package/src/{model-recipes-loader.mjs → model-recipes-loader.js} +1 -1
  264. package/src/{model-recipes-model-loader.mjs → model-recipes-model-loader.js} +5 -5
  265. package/src/{models-response-reader.mjs → models-response-reader.js} +3 -4
  266. package/src/models.js +7 -0
  267. package/src/{models.mjs.erb → models.js.erb} +6 -3
  268. package/src/{money-formatter.mjs → money-formatter.js} +5 -4
  269. package/src/{params.mjs → params.js} +17 -7
  270. package/src/{preloaded.mjs → preloaded.js} +2 -2
  271. package/src/resize-observer.jsx +10 -0
  272. package/src/result.js +13 -0
  273. package/src/router/route.jsx +246 -0
  274. package/src/router/switch.jsx +76 -0
  275. package/src/router.jsx +23 -21
  276. package/src/{routes-native.mjs → routes-native.js} +12 -6
  277. package/src/{routes.mjs → routes.js} +1 -1
  278. package/src/run-last.js +39 -0
  279. package/src/{serializer.mjs → serializer.js} +2 -2
  280. package/src/{services.mjs → services.js} +1 -1
  281. package/src/session-status-updater.js +172 -0
  282. package/src/{source-maps-loader.mjs → source-maps-loader.js} +54 -28
  283. package/src/super-admin/config-reader.jsx +93 -0
  284. package/src/super-admin/edit-page/edit-attribute-checkbox.jsx +81 -0
  285. package/src/super-admin/edit-page/edit-attribute-content.jsx +57 -0
  286. package/src/super-admin/edit-page/edit-attribute-input.jsx +71 -0
  287. package/src/super-admin/edit-page/edit-attribute.jsx +81 -0
  288. package/src/super-admin/edit-page.jsx +117 -0
  289. package/src/super-admin/has-edit-config.js +15 -0
  290. package/src/super-admin/index-page.jsx +23 -0
  291. package/src/super-admin/index.jsx +197 -0
  292. package/src/super-admin/layout/header/index.jsx +144 -0
  293. package/src/super-admin/layout/header/style.scss +45 -0
  294. package/src/super-admin/layout/index.jsx +154 -0
  295. package/src/super-admin/layout/menu/index.jsx +171 -0
  296. package/src/super-admin/layout/menu/menu-content.jsx +43 -0
  297. package/src/super-admin/layout/menu/menu-item.jsx +70 -0
  298. package/src/super-admin/layout/menu/style.scss +11 -0
  299. package/src/super-admin/layout/no-access.jsx +26 -0
  300. package/src/super-admin/model-class-table.jsx +66 -0
  301. package/src/super-admin/models.js +11 -0
  302. package/src/super-admin/show-nav.jsx +44 -0
  303. package/src/super-admin/show-page/belongs-to-attribute-row.jsx +30 -0
  304. package/src/super-admin/show-page/index.jsx +141 -0
  305. package/src/super-admin/show-reflection-actions.jsx +49 -0
  306. package/src/super-admin/show-reflection-link.jsx +40 -0
  307. package/src/super-admin/show-reflection-page.jsx +47 -0
  308. package/src/super-admin/stylesheets/variables.scss +11 -0
  309. package/src/table/column-content.jsx +122 -0
  310. package/src/table/column-identifier.js +23 -0
  311. package/src/table/column-visible.js +7 -0
  312. package/src/table/components/column.jsx +19 -0
  313. package/src/table/components/flat-list.jsx +19 -0
  314. package/src/table/components/header.jsx +21 -0
  315. package/src/table/components/row.jsx +23 -0
  316. package/src/table/filters/attribute-element.jsx +47 -0
  317. package/src/table/filters/filter-form.jsx +407 -0
  318. package/src/table/filters/filter.jsx +70 -0
  319. package/src/table/filters/index.jsx +170 -0
  320. package/src/table/filters/load-search-modal.jsx +146 -0
  321. package/src/table/filters/reflection-element.jsx +38 -0
  322. package/src/table/filters/save-search-modal.jsx +74 -0
  323. package/src/table/filters/scope-element.jsx +44 -0
  324. package/src/table/header-column-content.jsx +55 -0
  325. package/src/table/header-column.jsx +129 -0
  326. package/src/table/header-select.jsx +73 -0
  327. package/src/table/model-callback-args.js +10 -0
  328. package/src/table/model-column.jsx +82 -0
  329. package/src/table/model-row.jsx +136 -0
  330. package/src/table/select-calculator.js +65 -0
  331. package/src/table/settings/column-row.jsx +93 -0
  332. package/src/table/settings/download-action.jsx +68 -0
  333. package/src/table/settings/index.jsx +65 -0
  334. package/src/table/table-settings.js +263 -0
  335. package/src/table/table.jsx +950 -0
  336. package/src/table/use-sorting.js +35 -0
  337. package/src/table/variables.scss +11 -0
  338. package/src/table/widths.jsx +87 -0
  339. package/src/table/worker-plugins-check-all-checkbox.jsx +112 -0
  340. package/src/table/worker-plugins-checkbox.jsx +104 -0
  341. package/src/translated-attributes.js +11 -0
  342. package/src/{translated-collections.mjs → translated-collections.js} +3 -2
  343. package/src/updated-attribute.jsx +1 -1
  344. package/src/url-encode.js +18 -0
  345. package/src/use-breakpoint.js +76 -0
  346. package/src/use-can-can.js +55 -0
  347. package/src/use-collection.js +280 -0
  348. package/src/use-created-event.js +55 -0
  349. package/src/use-current-user.js +88 -0
  350. package/src/use-destroyed-event.js +60 -0
  351. package/src/use-event-emitter.js +15 -0
  352. package/src/use-event-listener.js +19 -0
  353. package/src/use-input.js +157 -0
  354. package/src/use-model-event.js +60 -0
  355. package/src/use-model.js +189 -0
  356. package/src/use-resize-observer.js +24 -0
  357. package/src/use-router.jsx +128 -0
  358. package/src/use-screen-layout.js +49 -0
  359. package/src/use-updated-event.js +60 -0
  360. package/src/use-validation-errors.js +33 -0
  361. package/src/utils/card.jsx +49 -0
  362. package/src/utils/checkbox.jsx +80 -0
  363. package/src/utils/checkboxes.jsx +158 -0
  364. package/src/utils/default-style.jsx +25 -0
  365. package/src/utils/icon.jsx +21 -0
  366. package/src/utils/invalid-feedback.jsx +20 -0
  367. package/src/utils/modal.jsx +60 -0
  368. package/src/utils/text.jsx +16 -0
  369. package/src/{validation-error.mjs → validation-error.js} +9 -5
  370. package/src/{validation-errors.mjs → validation-errors.js} +15 -27
  371. package/src/with-api-maker.jsx +31 -0
  372. package/src/with-collection.jsx +17 -0
  373. package/src/with-current-user.jsx +7 -25
  374. package/src/with-model.jsx +16 -0
  375. package/src/with-router.jsx +7 -129
  376. package/__tests__/base-model.test.js +0 -71
  377. package/__tests__/cable-connection-pool.test.js +0 -227
  378. package/__tests__/cable-subscription-pool.test.js +0 -26
  379. package/__tests__/can-can.test.js +0 -34
  380. package/__tests__/collection.test.js +0 -51
  381. package/__tests__/custom-error.test.js +0 -13
  382. package/__tests__/model-name.test.js +0 -34
  383. package/__tests__/model-prop-type.test.js +0 -113
  384. package/__tests__/params.test.js +0 -40
  385. package/__tests__/routes-native.test.js +0 -103
  386. package/__tests__/routes.test.js +0 -46
  387. package/__tests__/serializer.test.js +0 -30
  388. package/__tests__/support/task.js +0 -27
  389. package/__tests__/support/user.js +0 -32
  390. package/index.js +0 -1
  391. package/jest.config.js +0 -4
  392. package/src/can-can-loader.jsx +0 -54
  393. package/src/channels-consumer.mjs +0 -3
  394. package/src/destroy-error.mjs +0 -7
  395. package/src/devise.mjs +0 -122
  396. package/src/event-created.jsx +0 -65
  397. package/src/event-destroyed.jsx +0 -29
  398. package/src/event-listener.jsx +0 -38
  399. package/src/event-updated.jsx +0 -74
  400. package/src/logger.mjs +0 -25
  401. package/src/model-class-require.mjs +0 -10
  402. package/src/model-load-wrapper.jsx +0 -116
  403. package/src/result.mjs +0 -29
  404. package/src/session-status-updater.mjs +0 -116
  405. package/webpack.config.js +0 -15
  406. /package/src/{attribute-not-loaded-error.mjs → attribute-not-loaded-error.js} +0 -0
  407. /package/src/{instance-of-class-name.mjs → instance-of-class-name.js} +0 -0
  408. /package/src/{model-prop-type.mjs → model-prop-type.js} +0 -0
  409. /package/src/{not-loaded-error.mjs → not-loaded-error.js} +0 -0
  410. /package/src/{translated-collections-data.mjs.erb → translated-collections-data.js.erb} +0 -0
@@ -0,0 +1,280 @@
1
+ import debounce from "debounce"
2
+ import {digg} from "diggerize"
3
+ import * as inflection from "inflection"
4
+ import ModelEvents from "./model-events"
5
+ import {useCallback, useLayoutEffect, useMemo} from "react"
6
+ import useCreatedEvent from "./use-created-event"
7
+ import useShape from "set-state-compare/src/use-shape"
8
+ import useQueryParams from "on-location-changed/build/use-query-params"
9
+
10
+ const useCollection = (props, cacheKeys = []) => {
11
+ const {
12
+ abilities,
13
+ collection,
14
+ defaultParams,
15
+ groupBy,
16
+ ifCondition,
17
+ limit,
18
+ modelClass,
19
+ noRecordsAvailableContent = undefined,
20
+ noRecordsFoundContent = undefined,
21
+ onModelsLoaded,
22
+ pagination = false,
23
+ preloads = [],
24
+ queryMethod,
25
+ queryName: initialQueryName,
26
+ ransack,
27
+ select = {},
28
+ selectColumns,
29
+ ...restProps
30
+ } = props
31
+
32
+ if (Object.keys(restProps).length > 0) {
33
+ throw new Error(`Unknown props given to useCollection: ${Object.keys(restProps).join(", ")}`)
34
+ }
35
+
36
+ const s = useShape(props)
37
+ const queryName = initialQueryName || digg(modelClass.modelClassData(), "collectionKey")
38
+
39
+ s.meta.queryParams = useQueryParams()
40
+
41
+ const hasQParams = useCallback(() => {
42
+ if (s.s.queryQName in s.m.queryParams) return true
43
+
44
+ return false
45
+ }, [])
46
+
47
+ const qParams = useCallback(() => {
48
+ if (hasQParams()) return JSON.parse(digg(s.m.queryParams, s.s.queryQName))
49
+
50
+ return {}
51
+ }, [])
52
+
53
+ s.useStates({
54
+ models: undefined,
55
+ overallCount: undefined,
56
+ query: undefined,
57
+ queryName,
58
+ queryPerKey: `${queryName}_per`,
59
+ queryQName: `${queryName}_q`,
60
+ querySName: `${queryName}_s`,
61
+ queryPageName: `${queryName}_page`,
62
+ result: undefined,
63
+ searchParams: undefined,
64
+ showNoRecordsAvailableContent: false,
65
+ showNoRecordsFoundContent: false
66
+ })
67
+ s.useStates({
68
+ qParams: () => qParams()
69
+ })
70
+
71
+ let modelIdsCacheString
72
+
73
+ if (s.s.models === undefined) {
74
+ modelIdsCacheString = "models-undefined"
75
+ } else if (s.s.models.length === 0) {
76
+ modelIdsCacheString = "no-models"
77
+ } else {
78
+ modelIdsCacheString = s.s.models.map((model) => model.cacheKey())?.join("---")
79
+ }
80
+
81
+ const loadOverallCount = useCallback(async () => {
82
+ const baseQuery = s.p.collection || s.p.modelClass.all()
83
+ const overallCount = await baseQuery.count()
84
+
85
+ s.set({
86
+ overallCount,
87
+ showNoRecordsAvailableContent: showNoRecordsAvailableContent({overallCount}),
88
+ showNoRecordsFoundContent: showNoRecordsFoundContent({overallCount})
89
+ })
90
+ }, [])
91
+
92
+ const loadQParams = useCallback(() => {
93
+ const qParamsToSet = hasQParams() ? qParams() : Object.assign({}, s.props.defaultParams)
94
+ const searchParams = []
95
+
96
+ if (s.m.queryParams[s.s.querySName]) {
97
+ for (const rawSearchParam of s.m.queryParams[s.s.querySName]) {
98
+ const parsedSearchParam = JSON.parse(rawSearchParam)
99
+
100
+ searchParams.push(parsedSearchParam)
101
+ }
102
+ }
103
+
104
+ s.set({
105
+ qParams: qParamsToSet,
106
+ searchParams
107
+ })
108
+ }, [])
109
+
110
+ const loadModels = useCallback(async () => {
111
+ let query = s.props.collection?.clone() || s.p.modelClass.ransack()
112
+
113
+ if (s.props.pagination) {
114
+ const page = s.m.queryParams[s.s.queryPageName] || 1
115
+ let per = s.m.queryParams[s.s.queryPerKey] || 30
116
+
117
+ if (per == "all") {
118
+ per = 999_999_999
119
+ } else {
120
+ per = Number(per)
121
+ }
122
+
123
+ query.page(page).per(per)
124
+ }
125
+
126
+ if (s.props.groupBy) query = query.groupBy(...s.p.groupBy)
127
+
128
+ query = query
129
+ .ransack(s.s.qParams)
130
+ .search(s.s.searchParams)
131
+ .searchKey(s.s.queryQName)
132
+ .pageKey(s.s.queryPageName)
133
+ .perKey(s.s.queryPerKey)
134
+
135
+ if (s.props.abilities) query.abilities(s.p.abilities)
136
+ if (s.props.limit !== undefined) query.limit(s.p.limit)
137
+ if (s.props.preloads) query.preload(s.p.preloads)
138
+ if (s.props.ransack) query.ransack(s.props.ransack)
139
+ if (s.props.select) query.select(s.p.select)
140
+ if (s.props.selectColumns) query.selectColumns(s.p.selectColumns)
141
+
142
+ let result
143
+
144
+ if (s.props.queryMethod) {
145
+ result = await s.p.queryMethod({query})
146
+ } else {
147
+ result = await query.result()
148
+ }
149
+
150
+ const models = result.models()
151
+
152
+ if (s.props.onModelsLoaded) {
153
+ s.p.onModelsLoaded({
154
+ models,
155
+ qParams: s.s.qParams,
156
+ query,
157
+ result
158
+ })
159
+ }
160
+
161
+ s.set({
162
+ models: result.models(),
163
+ query,
164
+ result,
165
+ showNoRecordsAvailableContent: showNoRecordsAvailableContent({models}),
166
+ showNoRecordsFoundContent: showNoRecordsFoundContent({models})
167
+ })
168
+ }, [])
169
+
170
+ const loadModelsDebounce = useCallback(debounce(loadModels), [])
171
+ const onModelDestroyed = useCallback((args) => {
172
+ s.set({
173
+ models: s.s.models.filter((model) => model.id() != args.model.id())
174
+ })
175
+ }, [])
176
+
177
+ const onModelUpdated = useCallback((args) => {
178
+ const updatedModel = digg(args, "model")
179
+ const foundModel = s.s.models.find((model) => model.id() == updatedModel.id())
180
+
181
+ if (foundModel) loadModelsDebounce()
182
+ }, [])
183
+
184
+ const showNoRecordsAvailableContent = useCallback((args) => {
185
+ let models, overallCount
186
+
187
+ if (args.models !== undefined) {
188
+ models = args.models
189
+ } else if (s.s.models !== undefined) {
190
+ models = s.s.models
191
+ }
192
+
193
+ if (args.overallCount !== undefined) {
194
+ overallCount = args.overallCount
195
+ } else if (s.s.overallCount !== undefined) {
196
+ overallCount = s.s.overallCount
197
+ }
198
+
199
+ if (models === undefined || overallCount === undefined || s.p.noRecordsAvailableContent === undefined) return false
200
+ if (models.length === 0 && overallCount === 0 && s.p.noRecordsAvailableContent) return true
201
+ }, [])
202
+
203
+ const showNoRecordsFoundContent = useCallback((args) => {
204
+ let models, overallCount
205
+
206
+ if (args.models !== undefined) {
207
+ models = args.models
208
+ } else if (s.s.models !== undefined) {
209
+ models = s.s.models
210
+ }
211
+
212
+ if (args.overallCount !== undefined) {
213
+ overallCount = args.overallCount
214
+ } else if (s.s.overallCount !== undefined) {
215
+ overallCount = s.s.overallCount
216
+ }
217
+
218
+ if (models === undefined || s.props.noRecordsFoundContent === undefined) return false
219
+
220
+ // Dont show noRecordsAvailableContent together with noRecordsAvailableContent
221
+ if (models.length === 0 && overallCount === 0 && s.props.noRecordsAvailableContent) return false
222
+ if (models.length === 0 && s.props.noRecordsFoundContent) return true
223
+ }, [])
224
+
225
+ const onCreated = useCallback(() => {
226
+ loadModels()
227
+ }, [])
228
+
229
+ useMemo(
230
+ () => {
231
+ if (!("ifCondition" in s.props) || s.props.ifCondition) {
232
+ loadQParams()
233
+ loadModels()
234
+ }
235
+ },
236
+ [
237
+ s.props.ifCondition,
238
+ s.m.queryParams[s.s.queryQName],
239
+ s.m.queryParams[s.s.queryPageName],
240
+ s.m.queryParams[s.s.queryPerKey],
241
+ s.m.queryParams[s.s.querySName],
242
+ collection
243
+ ].concat(cacheKeys)
244
+ )
245
+
246
+ useMemo(() => {
247
+ if (s.props.noRecordsAvailableContent) {
248
+ loadOverallCount()
249
+ }
250
+ }, [])
251
+
252
+ useCreatedEvent(s.p.modelClass, onCreated)
253
+
254
+ useLayoutEffect(() => {
255
+ const connections = []
256
+
257
+ if (s.s.models) {
258
+ for(const model of s.s.models) {
259
+ connections.push(ModelEvents.connectUpdated(model, onModelUpdated))
260
+ connections.push(ModelEvents.connectDestroyed(model, onModelDestroyed))
261
+ }
262
+ }
263
+
264
+ return () => {
265
+ for(const connection of connections) {
266
+ connection.unsubscribe()
267
+ }
268
+ }
269
+ }, [modelIdsCacheString])
270
+
271
+ const result = Object.assign({}, s.state)
272
+ const modelVariableName = inflection.pluralize(inflection.camelize(modelClass.modelClassData().name, true))
273
+
274
+ result.modelIdsCacheString = modelIdsCacheString
275
+ result[modelVariableName] = s.s.models
276
+
277
+ return result
278
+ }
279
+
280
+ export default useCollection
@@ -0,0 +1,55 @@
1
+ import debounceFunction from "debounce"
2
+ import ModelEvents from "./model-events"
3
+ import PropTypes from "prop-types"
4
+ import propTypesExact from "prop-types-exact"
5
+ import {useCallback, useLayoutEffect} from "react"
6
+ import useShape from "set-state-compare/src/use-shape"
7
+
8
+ const ApiMakerUseCreatedEvent = (modelClass, onCreated, args = {}) => {
9
+ const {active = true, debounce} = args
10
+ const s = useShape({active, debounce, modelClass, onCreated})
11
+
12
+ const eventDebounce = useCallback(() => {
13
+ if (!s.meta.debounceInstance) {
14
+ if (typeof this.props.debounce == "number") {
15
+ s.meta.debounceInstance = debounceFunction(s.p.onCreated, s.p.debounce)
16
+ } else {
17
+ s.meta.debounceInstance = debounceFunction(s.p.onCreated)
18
+ }
19
+ }
20
+
21
+ return s.meta.debounceInstance
22
+ }, [])
23
+
24
+ const onCreatedCallback = useCallback((...args) => {
25
+ if (!s.p.active) {
26
+ return
27
+ }
28
+
29
+ if (s.p.debounce) {
30
+ eventDebounce()(...args)
31
+ } else {
32
+ s.p.onCreated(...args)
33
+ }
34
+ }, [])
35
+
36
+ useLayoutEffect(() => {
37
+ const connectCreated = ModelEvents.connectCreated(s.p.modelClass, (...args) => onCreatedCallback(...args))
38
+
39
+ return () => {
40
+ connectCreated.unsubscribe()
41
+ }
42
+ }, [])
43
+ }
44
+
45
+ ApiMakerUseCreatedEvent.propTypes = propTypesExact({
46
+ active: PropTypes.bool.isRequired,
47
+ debounce: PropTypes.oneOfType([
48
+ PropTypes.bool,
49
+ PropTypes.number
50
+ ]),
51
+ modelClass: PropTypes.func.isRequired,
52
+ onCreated: PropTypes.func.isRequired
53
+ })
54
+
55
+ export default ApiMakerUseCreatedEvent
@@ -0,0 +1,88 @@
1
+ import {useCallback, useMemo} from "react"
2
+ import Devise from "./devise"
3
+ import {digg} from "diggerize"
4
+ import * as inflection from "inflection"
5
+ import Logger from "./logger"
6
+ import Services from "./services"
7
+ import useEventEmitter from "./use-event-emitter"
8
+ import useShape from "set-state-compare/src/use-shape"
9
+
10
+ const logger = new Logger({name: "ApiMaker / useCurrentUser"})
11
+
12
+ // logger.setDebug(true)
13
+
14
+ const useCurrentUser = (args) => {
15
+ const s = useShape(args || {})
16
+ const scope = args?.scope || "user"
17
+ const scopeName = `current${inflection.camelize(scope)}`
18
+
19
+ s.meta.scope = scope
20
+ s.meta.scopeName = scopeName
21
+
22
+ const loadCurrentUserFromRequest = useCallback(async () => {
23
+ const {scope, scopeName} = s.m
24
+ const getArgsMethodName = `get${inflection.camelize(scope)}Args`
25
+ const args = Devise[getArgsMethodName]()
26
+
27
+ logger.debug(() => `Loading ${scope} with request`)
28
+
29
+ const result = await Services.current().sendRequest("Devise::Current", {query: args.query, scope})
30
+ const current = digg(result, "current")[0]
31
+
32
+ if (!(scopeName in s.setStates)) throw new Error(`'${scopeName}' not found in setStates`)
33
+ if (current) Devise.updateSession(current)
34
+
35
+ s.setStates[scopeName](current)
36
+
37
+ if (s.props.onCurrentUserLoaded) setTimeout(() => s.props.onCurrentUserLoaded(current), 0)
38
+ }, [])
39
+
40
+ const defaultCurrentUser = useCallback(() => {
41
+ const {scope, scopeName} = s.m
42
+ let current
43
+
44
+ if (Devise.current().hasCurrentScope(s.m.scope)) {
45
+ current = Devise.current().getCurrentScope(scope)
46
+
47
+ logger.debug(() => `Setting ${scope} from current scope: ${current?.id()}`)
48
+ } else if (Devise.current().hasGlobalCurrentScope(scope)) {
49
+ current = Devise[scopeName]()
50
+
51
+ logger.debug(() => `Setting ${scope} from global current scope: ${current?.id()}`)
52
+ }
53
+
54
+ if (current && s.props.onCurrentUserLoaded) {
55
+ setTimeout(() => s.props.onCurrentUserLoaded(current), 0)
56
+ }
57
+
58
+ return current
59
+ }, [])
60
+
61
+ const useStatesArgument = {}
62
+
63
+ useStatesArgument[scopeName] = () => defaultCurrentUser()
64
+
65
+ s.useStates(useStatesArgument)
66
+
67
+ const updateCurrentUser = useCallback(() => {
68
+ const setStatesArgument = {}
69
+
70
+ setStatesArgument[s.m.scopeName] = Devise[s.m.scopeName]()
71
+
72
+ s.set(setStatesArgument)
73
+ }, [])
74
+
75
+ useMemo(() => {
76
+ if (!Devise.current().hasGlobalCurrentScope(s.m.scope) && !Devise.current().hasCurrentScope(s.m.scope)) {
77
+ logger.debug(() => `Devise hasn't got current scope ${s.m.scope} so loading from request`)
78
+ loadCurrentUserFromRequest()
79
+ }
80
+ }, [])
81
+
82
+ useEventEmitter(Devise.events(), "onDeviseSignIn", updateCurrentUser)
83
+ useEventEmitter(Devise.events(), "onDeviseSignOut", updateCurrentUser)
84
+
85
+ return s.s[scopeName]
86
+ }
87
+
88
+ export default useCurrentUser
@@ -0,0 +1,60 @@
1
+ import {useCallback, useLayoutEffect, useMemo} from "react"
2
+ import debounceFunction from "debounce"
3
+ import ModelEvents from "./model-events"
4
+ import useShape from "set-state-compare/src/use-shape"
5
+
6
+ const apiMakerUseDestroyedEvent = (model, onDestroyed, props) => {
7
+ const {active = true, debounce, onConnected, ...restProps} = props || {}
8
+
9
+ if (Object.keys(restProps).length > 0) {
10
+ throw new Error(`Unknown props given to useDestroyedEvent: ${Object.keys(restProps).join(", ")}`)
11
+ }
12
+
13
+ const s = useShape({active, debounce, model, onDestroyed})
14
+
15
+ const debounceCallback = useMemo(() => {
16
+ if (typeof debounce == "number") {
17
+ return debounceFunction(s.p.onDestroyed, debounce)
18
+ } else {
19
+ return debounceFunction(s.p.onDestroyed)
20
+ }
21
+ }, [debounce])
22
+
23
+ s.updateMeta({debounceCallback})
24
+
25
+ const onDestroyedCallback = useCallback((...args) => {
26
+ if (!s.p.active) {
27
+ return
28
+ }
29
+
30
+ if (s.p.debounce) {
31
+ s.m.debounceCallback(...args)
32
+ } else {
33
+ s.p.onDestroyed(...args)
34
+ }
35
+ }, [])
36
+
37
+ useLayoutEffect(() => {
38
+ let connectDestroyed, onConnectedListener
39
+
40
+ if (model) {
41
+ connectDestroyed = ModelEvents.connectDestroyed(model, onDestroyedCallback)
42
+
43
+ if (onConnected) {
44
+ onConnectedListener = connectDestroyed.events.addListener("connected", onConnected)
45
+ }
46
+ }
47
+
48
+ return () => {
49
+ if (onConnectedListener) {
50
+ connectDestroyed.events.removeListener("connected", onConnected)
51
+ }
52
+
53
+ if (connectDestroyed) {
54
+ connectDestroyed.unsubscribe()
55
+ }
56
+ }
57
+ }, [model?.id()])
58
+ }
59
+
60
+ export default apiMakerUseDestroyedEvent
@@ -0,0 +1,15 @@
1
+ import {useLayoutEffect} from "react"
2
+
3
+ const ApiMakerUseEventEmitter = (events, event, onCalled) => {
4
+ useLayoutEffect(() => {
5
+ if (events) {
6
+ events.addListener(event, onCalled)
7
+
8
+ return () => {
9
+ events.removeListener(event, onCalled)
10
+ }
11
+ }
12
+ }, [events, event, onCalled])
13
+ }
14
+
15
+ export default ApiMakerUseEventEmitter
@@ -0,0 +1,19 @@
1
+ import {useCallback, useLayoutEffect} from "react"
2
+
3
+ const ApiMakerUseEventListener = (target, event, onCalled) => {
4
+ const onCalledCallback = useCallback((...args) => {
5
+ onCalled.apply(null, args)
6
+ }, [target, event, onCalled])
7
+
8
+ useLayoutEffect(() => {
9
+ if (target) {
10
+ target.addEventListener(event, onCalledCallback)
11
+
12
+ return () => {
13
+ target.removeEventListener(event, onCalledCallback)
14
+ }
15
+ }
16
+ }, [target, event, onCalled])
17
+ }
18
+
19
+ export default ApiMakerUseEventListener
@@ -0,0 +1,157 @@
1
+ import {dig, digg} from "diggerize"
2
+ import {useCallback, useEffect, useMemo, useRef} from "react"
3
+ import idForComponent from "./inputs/id-for-component"
4
+ import nameForComponent from "./inputs/name-for-component"
5
+ import strftime from "strftime"
6
+ import useShape from "set-state-compare/src/use-shape"
7
+ import useValidationErrors from "./use-validation-errors"
8
+
9
+ const useInput = ({props, wrapperOptions, ...useInputRestProps}) => {
10
+ const useInputRestPropsKeys = Object.keys(useInputRestProps)
11
+
12
+ if (useInputRestPropsKeys.length > 0) {
13
+ throw new Error(`Unknown props given to useInput: ${useInputRestPropsKeys.join(", ")}`)
14
+ }
15
+
16
+ const s = useShape(props)
17
+ const backupRef = useRef()
18
+
19
+ s.useStates({
20
+ form: undefined
21
+ })
22
+
23
+ useEffect(() => {
24
+ setForm()
25
+ }, [s.props.inputRef?.current])
26
+
27
+ s.meta.fakeComponent = {props}
28
+ s.meta.isCheckbox = props.type == "checkbox" || wrapperOptions?.type == "checkbox"
29
+ s.meta.isSelect = wrapperOptions?.type == "select"
30
+
31
+ const formatValue = useCallback((value) => {
32
+ const {formatValue} = s.props
33
+
34
+ if (formatValue) {
35
+ return formatValue(value)
36
+ } else if (value instanceof Date && !isNaN(value.getTime())) {
37
+ // We need to use a certain format for datetime-local
38
+ if (inputType() == "datetime-local") {
39
+ return strftime("%Y-%m-%dT%H:%M:%S", value)
40
+ } else if (inputType() == "date") {
41
+ return strftime("%Y-%m-%d", value)
42
+ }
43
+ }
44
+
45
+ return value
46
+ }, [])
47
+
48
+ const inputDefaultChecked = useCallback(() => {
49
+ if ("defaultChecked" in s.props) {
50
+ return s.props.defaultChecked
51
+ } else if (s.props.attribute && s.props.model) {
52
+ if (!s.props.model[s.props.attribute])
53
+ throw new Error(`No such attribute: ${s.props.attribute}`)
54
+
55
+ return s.props.model[s.props.attribute]()
56
+ }
57
+ }, [])
58
+
59
+ const inputDefaultValue = useCallback(() => {
60
+ if ("defaultValue" in s.props) {
61
+ return formatValue(s.props.defaultValue)
62
+ } else if (s.props.model && s.props.attribute) {
63
+ if (!s.props.model[s.props.attribute]) {
64
+ throw new Error(`No such attribute defined on resource: ${digg(s.props.model.modelClassData(), "name")}#${s.props.attribute}`)
65
+ }
66
+
67
+ return formatValue(s.props.model[s.props.attribute]())
68
+ }
69
+ }, [])
70
+
71
+ const inputRef = useCallback(() => s.props.inputRef || backupRef)
72
+
73
+ const inputType = useCallback(() => {
74
+ if ("type" in s.props) {
75
+ return s.props.type
76
+ } else if (s.m.isCheckbox) {
77
+ return "checkbox"
78
+ } else {
79
+ return "text"
80
+ }
81
+ }, [])
82
+
83
+ const label = useCallback(() => {
84
+ if ("label" in s.props) {
85
+ return s.props.label
86
+ } else if (s.props.attribute && s.props.model) {
87
+ return s.props.model.modelClass().humanAttributeName(s.props.attribute)
88
+ }
89
+ }, [])
90
+
91
+ const setForm = useCallback(() => {
92
+ const inputElement = inputRef().current
93
+
94
+ let form
95
+
96
+ if (inputElement) form = dig(inputElement, "form")
97
+ if (form && form != s.s.form) s.set({form})
98
+ }, [])
99
+
100
+ const getId = useCallback(() => idForComponent(s.m.fakeComponent), [])
101
+ const getName = useCallback(() => nameForComponent(s.m.fakeComponent), [])
102
+
103
+ const getInputProps = useCallback(() => {
104
+ const givenInputProps = s.props.inputProps || {}
105
+ const inputProps = Object.assign(
106
+ {
107
+ id: getId(),
108
+ name: getName(),
109
+ ref: inputRef()
110
+ },
111
+ givenInputProps
112
+ )
113
+
114
+ if (s.m.isCheckbox) {
115
+ if ("checked" in s.props) {
116
+ inputProps.checked = s.props.checked
117
+ }
118
+
119
+ if ("defaultChecked" in s.props || (s.props.attribute && s.props.model)) {
120
+ inputProps.defaultChecked = inputDefaultChecked()
121
+ }
122
+ } else if ("value" in s.props) {
123
+ inputProps.value = s.props.value
124
+ } else if (!("value" in s.props)) {
125
+ inputProps.defaultValue = inputDefaultValue()
126
+ }
127
+
128
+ return inputProps
129
+ }, [])
130
+
131
+ const {inputProps: oldInputProps, wrapperOpts: oldWrapperOpts, ...restProps} = props
132
+ const type = inputType()
133
+
134
+ s.meta.inputProps = getInputProps()
135
+ s.meta.inputNameWithoutId = useMemo(() => s.m.inputProps.name?.replace(/\[(.+)_id\]$/, "[$1]"), [s.m.inputProps.name])
136
+
137
+ if (!s.m.inputProps.ref) throw new Error("No input ref?")
138
+ if (!s.m.isSelect) s.m.inputProps.type = type
139
+
140
+ const {validationErrors} = useValidationErrors((validationError) =>
141
+ validationError.inputName == s.m.inputProps.name || validationError.inputName == s.m.inputNameWithoutId
142
+ )
143
+
144
+ const wrapperOpts = {
145
+ errors: validationErrors,
146
+ form: s.s.form,
147
+ label: label()
148
+ }
149
+
150
+ return {
151
+ inputProps: s.m.inputProps,
152
+ wrapperOpts,
153
+ restProps
154
+ }
155
+ }
156
+
157
+ export default useInput