@carlonicora/nextjs-jsonapi 1.15.0 → 1.17.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 (321) hide show
  1. package/dist/ApiData-DPKNfY-9.d.mts +10 -0
  2. package/dist/ApiData-DPKNfY-9.d.ts +10 -0
  3. package/dist/ApiRequestDataTypeInterface-DIEOFn9s.d.mts +40 -0
  4. package/dist/ApiRequestDataTypeInterface-DIEOFn9s.d.ts +40 -0
  5. package/dist/{ApiResponseInterface-QLDnxLA9.d.ts → ApiResponseInterface-BKyod24U.d.ts} +3 -11
  6. package/dist/{ApiResponseInterface-B4QdWh-y.d.mts → ApiResponseInterface-Dqvu09tz.d.mts} +3 -11
  7. package/dist/{BlockNoteEditor-FGXYUAWI.js → BlockNoteEditor-34T5CY27.js} +17 -16
  8. package/dist/BlockNoteEditor-34T5CY27.js.map +1 -0
  9. package/dist/{BlockNoteEditor-ITJLAOXC.mjs → BlockNoteEditor-4Z6TZBJE.mjs} +7 -6
  10. package/dist/{BlockNoteEditor-ITJLAOXC.mjs.map → BlockNoteEditor-4Z6TZBJE.mjs.map} +1 -1
  11. package/dist/JsonApiContext-Bsm_Q2oe.d.mts +41 -0
  12. package/dist/JsonApiContext-Bsm_Q2oe.d.ts +41 -0
  13. package/dist/JsonApiRequest-54ZBO7WQ.js +24 -0
  14. package/dist/{JsonApiRequest-FXZCYIER.js.map → JsonApiRequest-54ZBO7WQ.js.map} +1 -1
  15. package/dist/{JsonApiRequest-HFWXMKMA.mjs → JsonApiRequest-XWQWTFEQ.mjs} +2 -2
  16. package/dist/chunk-3EPNHTMH.js +26 -0
  17. package/dist/chunk-3EPNHTMH.js.map +1 -0
  18. package/dist/{chunk-TGBXBUWM.mjs → chunk-3VM3WAOV.mjs} +8 -1
  19. package/dist/chunk-3VM3WAOV.mjs.map +1 -0
  20. package/dist/{chunk-6YD42BP6.js → chunk-7DTKRMYW.js} +31 -19
  21. package/dist/chunk-7DTKRMYW.js.map +1 -0
  22. package/dist/{chunk-PK5DRSUD.js → chunk-D7H7SRWB.js} +4104 -793
  23. package/dist/chunk-D7H7SRWB.js.map +1 -0
  24. package/dist/{chunk-JGVXZS7M.mjs → chunk-KUFWHMMY.mjs} +1592 -133
  25. package/dist/chunk-KUFWHMMY.mjs.map +1 -0
  26. package/dist/{chunk-SJIVGCNM.mjs → chunk-KX7YG6LY.mjs} +27 -15
  27. package/dist/chunk-KX7YG6LY.mjs.map +1 -0
  28. package/dist/{chunk-FPZPD4JI.js → chunk-LI6CPNJI.js} +17 -10
  29. package/dist/chunk-LI6CPNJI.js.map +1 -0
  30. package/dist/{chunk-WAFOKMKT.mjs → chunk-SXPXC2TY.mjs} +3729 -418
  31. package/dist/chunk-SXPXC2TY.mjs.map +1 -0
  32. package/dist/{chunk-C6QXZGL7.js → chunk-UYY34W7R.js} +1622 -163
  33. package/dist/chunk-UYY34W7R.js.map +1 -0
  34. package/dist/chunk-VOXD3ZLY.mjs +26 -0
  35. package/dist/chunk-VOXD3ZLY.mjs.map +1 -0
  36. package/dist/client/index.d.mts +11 -45
  37. package/dist/client/index.d.ts +11 -45
  38. package/dist/client/index.js +10 -6
  39. package/dist/client/index.js.map +1 -1
  40. package/dist/client/index.mjs +13 -9
  41. package/dist/components/index.d.mts +254 -9
  42. package/dist/components/index.d.ts +254 -9
  43. package/dist/components/index.js +85 -6
  44. package/dist/components/index.js.map +1 -1
  45. package/dist/components/index.mjs +84 -5
  46. package/dist/{config-C5tGGrYf.d.mts → config--nwiW74Z.d.ts} +7 -2
  47. package/dist/{config-eceYM5kN.d.ts → config-BKSQmUWU.d.mts} +7 -2
  48. package/dist/{content.interface-CxBBC7ec.d.mts → content.interface-4VICFRA0.d.ts} +2 -1
  49. package/dist/{content.interface-TB2MfJGs.d.ts → content.interface-CFc97-Cj.d.mts} +2 -1
  50. package/dist/contexts/index.d.mts +3 -2
  51. package/dist/contexts/index.d.ts +3 -2
  52. package/dist/contexts/index.js +7 -6
  53. package/dist/contexts/index.js.map +1 -1
  54. package/dist/contexts/index.mjs +6 -5
  55. package/dist/core/index.d.mts +524 -18
  56. package/dist/core/index.d.ts +524 -18
  57. package/dist/core/index.js +54 -4
  58. package/dist/core/index.js.map +1 -1
  59. package/dist/core/index.mjs +53 -3
  60. package/dist/index.d.mts +16 -12
  61. package/dist/index.d.ts +16 -12
  62. package/dist/index.js +57 -5
  63. package/dist/index.js.map +1 -1
  64. package/dist/index.mjs +58 -6
  65. package/dist/{notification.interface-lG6UpTpt.d.mts → notification.interface-BGaPiCUM.d.mts} +3 -42
  66. package/dist/{notification.interface-lG6UpTpt.d.ts → notification.interface-CqwaOIgM.d.ts} +3 -42
  67. package/dist/{s3.service-DP_hsssD.d.mts → s3.service-BYs88XEE.d.ts} +21 -2
  68. package/dist/{s3.service-Dq-PTUNa.d.ts → s3.service-C0BjOdvn.d.mts} +21 -2
  69. package/dist/scripts/generate-web-module/generator.d.ts.map +1 -1
  70. package/dist/scripts/generate-web-module/generator.js +66 -0
  71. package/dist/scripts/generate-web-module/generator.js.map +1 -1
  72. package/dist/scripts/generate-web-module/templates/index.d.ts +8 -0
  73. package/dist/scripts/generate-web-module/templates/index.d.ts.map +1 -1
  74. package/dist/scripts/generate-web-module/templates/index.js +18 -1
  75. package/dist/scripts/generate-web-module/templates/index.js.map +1 -1
  76. package/dist/scripts/generate-web-module/templates/project/bootstrapper.template.d.ts +7 -0
  77. package/dist/scripts/generate-web-module/templates/project/bootstrapper.template.d.ts.map +1 -0
  78. package/dist/scripts/generate-web-module/templates/project/bootstrapper.template.js +141 -0
  79. package/dist/scripts/generate-web-module/templates/project/bootstrapper.template.js.map +1 -0
  80. package/dist/scripts/generate-web-module/templates/project/env.template.d.ts +7 -0
  81. package/dist/scripts/generate-web-module/templates/project/env.template.d.ts.map +1 -0
  82. package/dist/scripts/generate-web-module/templates/project/env.template.js +110 -0
  83. package/dist/scripts/generate-web-module/templates/project/env.template.js.map +1 -0
  84. package/dist/scripts/generate-web-module/templates/project/main-layout.template.d.ts +7 -0
  85. package/dist/scripts/generate-web-module/templates/project/main-layout.template.d.ts.map +1 -0
  86. package/dist/scripts/generate-web-module/templates/project/main-layout.template.js +101 -0
  87. package/dist/scripts/generate-web-module/templates/project/main-layout.template.js.map +1 -0
  88. package/dist/scripts/generate-web-module/templates/project/middleware-env.template.d.ts +7 -0
  89. package/dist/scripts/generate-web-module/templates/project/middleware-env.template.d.ts.map +1 -0
  90. package/dist/scripts/generate-web-module/templates/project/middleware-env.template.js +66 -0
  91. package/dist/scripts/generate-web-module/templates/project/middleware-env.template.js.map +1 -0
  92. package/dist/scripts/generate-web-module/templates/project/settings-container.template.d.ts +7 -0
  93. package/dist/scripts/generate-web-module/templates/project/settings-container.template.d.ts.map +1 -0
  94. package/dist/scripts/generate-web-module/templates/project/settings-container.template.js +257 -0
  95. package/dist/scripts/generate-web-module/templates/project/settings-container.template.js.map +1 -0
  96. package/dist/scripts/generate-web-module/templates/project/settings-context.template.d.ts +7 -0
  97. package/dist/scripts/generate-web-module/templates/project/settings-context.template.d.ts.map +1 -0
  98. package/dist/scripts/generate-web-module/templates/project/settings-context.template.js +124 -0
  99. package/dist/scripts/generate-web-module/templates/project/settings-context.template.js.map +1 -0
  100. package/dist/scripts/generate-web-module/templates/project/settings-module-page.template.d.ts +7 -0
  101. package/dist/scripts/generate-web-module/templates/project/settings-module-page.template.d.ts.map +1 -0
  102. package/dist/scripts/generate-web-module/templates/project/settings-module-page.template.js +78 -0
  103. package/dist/scripts/generate-web-module/templates/project/settings-module-page.template.js.map +1 -0
  104. package/dist/scripts/generate-web-module/templates/project/settings-page.template.d.ts +7 -0
  105. package/dist/scripts/generate-web-module/templates/project/settings-page.template.d.ts.map +1 -0
  106. package/dist/scripts/generate-web-module/templates/project/settings-page.template.js +75 -0
  107. package/dist/scripts/generate-web-module/templates/project/settings-page.template.js.map +1 -0
  108. package/dist/scripts/generate-web-module/types/template-data.interface.d.ts +1 -1
  109. package/dist/scripts/generate-web-module/types/template-data.interface.d.ts.map +1 -1
  110. package/dist/server/index.d.mts +6 -4
  111. package/dist/server/index.d.ts +6 -4
  112. package/dist/server/index.js +13 -13
  113. package/dist/server/index.js.map +1 -1
  114. package/dist/server/index.mjs +3 -3
  115. package/dist/stripe-subscription.interface-B-TM40Io.d.ts +226 -0
  116. package/dist/stripe-subscription.interface-DDxnpj0F.d.mts +226 -0
  117. package/dist/testing/index.d.mts +338 -0
  118. package/dist/testing/index.d.ts +338 -0
  119. package/dist/testing/index.js +323 -0
  120. package/dist/testing/index.js.map +1 -0
  121. package/dist/testing/index.mjs +323 -0
  122. package/dist/testing/index.mjs.map +1 -0
  123. package/dist/{useSocket-Bua6MwLi.d.mts → useSocket-BNj9PrRw.d.mts} +1 -1
  124. package/dist/{useSocket-D5dhUp4m.d.ts → useSocket-Dwt8cz1x.d.ts} +1 -1
  125. package/package.json +29 -3
  126. package/scripts/generate-web-module/generator.ts +83 -0
  127. package/scripts/generate-web-module/templates/index.ts +10 -0
  128. package/scripts/generate-web-module/templates/project/bootstrapper.template.ts +108 -0
  129. package/scripts/generate-web-module/templates/project/env.template.ts +77 -0
  130. package/scripts/generate-web-module/templates/project/main-layout.template.tsx +68 -0
  131. package/scripts/generate-web-module/templates/project/middleware-env.template.ts +33 -0
  132. package/scripts/generate-web-module/templates/project/settings-container.template.tsx +224 -0
  133. package/scripts/generate-web-module/templates/project/settings-context.template.tsx +91 -0
  134. package/scripts/generate-web-module/templates/project/settings-module-page.template.tsx +45 -0
  135. package/scripts/generate-web-module/templates/project/settings-page.template.tsx +42 -0
  136. package/scripts/generate-web-module/types/template-data.interface.ts +1 -1
  137. package/src/client/config.ts +9 -0
  138. package/src/client/hooks/__tests__/useJsonApiGet.test.tsx +229 -0
  139. package/src/client/hooks/__tests__/useJsonApiMutation.test.tsx +348 -0
  140. package/src/client/hooks/__tests__/useRehydration.test.ts +188 -0
  141. package/src/components/forms/__tests__/FormCheckbox.test.tsx +238 -0
  142. package/src/components/forms/__tests__/FormDate.test.tsx +212 -0
  143. package/src/components/forms/__tests__/FormInput.test.tsx +292 -0
  144. package/src/components/forms/__tests__/FormSelect.test.tsx +173 -0
  145. package/src/components/index.ts +7 -0
  146. package/src/components/tables/__tests__/ContentListTable.test.tsx +411 -0
  147. package/src/core/abstracts/AbstractService.ts +104 -0
  148. package/src/core/endpoint/EndpointCreator.ts +7 -4
  149. package/src/core/endpoint/__tests__/EndpointCreator.test.ts +168 -0
  150. package/src/core/factories/__tests__/JsonApiDataFactory.test.ts +109 -0
  151. package/src/core/factories/__tests__/RehydrationFactory.test.ts +151 -0
  152. package/src/core/index.ts +12 -4
  153. package/src/core/interfaces/ApiResponseInterface.ts +1 -0
  154. package/src/core/registry/ModuleRegistry.ts +11 -2
  155. package/src/core/registry/__tests__/DataClassRegistry.test.ts +136 -0
  156. package/src/core/registry/__tests__/ModuleRegistrar.test.ts +159 -0
  157. package/src/core/utils/translateResponse.ts +17 -0
  158. package/src/features/auth/components/details/LandingComponent.tsx +14 -12
  159. package/src/features/billing/components/cards/BillingUsageSummaryCard.tsx +97 -0
  160. package/src/features/billing/components/cards/CustomerInfoCard.tsx +112 -0
  161. package/src/features/billing/components/cards/InvoicesSummaryCard.tsx +114 -0
  162. package/src/features/billing/components/cards/PaymentMethodSummaryCard.tsx +119 -0
  163. package/src/features/billing/components/cards/SubscriptionSummaryCard.tsx +146 -0
  164. package/src/features/billing/components/cards/index.ts +5 -0
  165. package/src/features/billing/components/containers/BillingDashboardContainer.tsx +427 -0
  166. package/src/features/billing/components/containers/index.ts +1 -0
  167. package/src/features/billing/components/index.ts +6 -0
  168. package/src/features/billing/components/modals/BillingDetailModal.tsx +36 -0
  169. package/src/features/billing/components/modals/index.ts +1 -0
  170. package/src/features/billing/components/providers/StripeProvider.tsx +48 -0
  171. package/src/features/billing/components/providers/index.ts +1 -0
  172. package/src/features/billing/components/utils/currency.ts +49 -0
  173. package/src/features/billing/components/utils/date.ts +21 -0
  174. package/src/features/billing/components/utils/index.ts +2 -0
  175. package/src/features/billing/components/widgets/BillingAlertBanner.tsx +63 -0
  176. package/src/features/billing/components/widgets/index.ts +1 -0
  177. package/src/features/billing/data/Billing.ts +17 -0
  178. package/src/features/billing/data/billing.service.ts +58 -0
  179. package/src/features/billing/data/index.ts +5 -0
  180. package/src/features/billing/index.ts +3 -0
  181. package/src/features/billing/modules/billing.module.ts +9 -0
  182. package/src/features/billing/modules/index.ts +1 -0
  183. package/src/features/billing/stripe-customer/components/containers/PaymentMethodsContainer.tsx +79 -0
  184. package/src/features/billing/stripe-customer/components/containers/index.ts +1 -0
  185. package/src/features/billing/stripe-customer/components/details/PaymentMethodCard.tsx +151 -0
  186. package/src/features/billing/stripe-customer/components/details/index.ts +1 -0
  187. package/src/features/billing/stripe-customer/components/forms/PaymentMethodEditor.tsx +186 -0
  188. package/src/features/billing/stripe-customer/components/forms/index.ts +1 -0
  189. package/src/features/billing/stripe-customer/components/index.ts +4 -0
  190. package/src/features/billing/stripe-customer/components/lists/PaymentMethodsList.tsx +19 -0
  191. package/src/features/billing/stripe-customer/components/lists/index.ts +1 -0
  192. package/src/features/billing/stripe-customer/data/index.ts +5 -0
  193. package/src/features/billing/stripe-customer/data/payment-method.interface.ts +27 -0
  194. package/src/features/billing/stripe-customer/data/payment-method.ts +119 -0
  195. package/src/features/billing/stripe-customer/data/stripe-customer.interface.ts +16 -0
  196. package/src/features/billing/stripe-customer/data/stripe-customer.service.ts +128 -0
  197. package/src/features/billing/stripe-customer/data/stripe-customer.ts +71 -0
  198. package/src/features/billing/stripe-customer/index.ts +3 -0
  199. package/src/features/billing/stripe-customer/stripe-customer.module.ts +9 -0
  200. package/src/features/billing/stripe-customer/stripe-payment-method.module.ts +9 -0
  201. package/src/features/billing/stripe-invoice/components/containers/InvoicesContainer.tsx +66 -0
  202. package/src/features/billing/stripe-invoice/components/containers/index.ts +1 -0
  203. package/src/features/billing/stripe-invoice/components/details/InvoiceDetails.tsx +172 -0
  204. package/src/features/billing/stripe-invoice/components/details/index.ts +1 -0
  205. package/src/features/billing/stripe-invoice/components/index.ts +4 -0
  206. package/src/features/billing/stripe-invoice/components/lists/InvoicesList.tsx +84 -0
  207. package/src/features/billing/stripe-invoice/components/lists/index.ts +1 -0
  208. package/src/features/billing/stripe-invoice/components/widgets/InvoiceStatusBadge.tsx +41 -0
  209. package/src/features/billing/stripe-invoice/components/widgets/index.ts +1 -0
  210. package/src/features/billing/stripe-invoice/data/index.ts +3 -0
  211. package/src/features/billing/stripe-invoice/data/stripe-invoice.interface.ts +65 -0
  212. package/src/features/billing/stripe-invoice/data/stripe-invoice.service.ts +64 -0
  213. package/src/features/billing/stripe-invoice/data/stripe-invoice.ts +177 -0
  214. package/src/features/billing/stripe-invoice/index.ts +2 -0
  215. package/src/features/billing/stripe-invoice/stripe-invoice.module.ts +9 -0
  216. package/src/features/billing/stripe-price/components/forms/PriceEditor.tsx +304 -0
  217. package/src/features/billing/stripe-price/components/forms/index.ts +1 -0
  218. package/src/features/billing/stripe-price/components/index.ts +2 -0
  219. package/src/features/billing/stripe-price/components/lists/PricesList.tsx +283 -0
  220. package/src/features/billing/stripe-price/components/lists/index.ts +1 -0
  221. package/src/features/billing/stripe-price/data/index.ts +3 -0
  222. package/src/features/billing/stripe-price/data/stripe-price.interface.ts +48 -0
  223. package/src/features/billing/stripe-price/data/stripe-price.service.ts +123 -0
  224. package/src/features/billing/stripe-price/data/stripe-price.ts +156 -0
  225. package/src/features/billing/stripe-price/index.ts +2 -0
  226. package/src/features/billing/stripe-price/stripe-price.module.ts +9 -0
  227. package/src/features/billing/stripe-product/components/containers/ProductsAdminContainer.tsx +86 -0
  228. package/src/features/billing/stripe-product/components/containers/index.ts +1 -0
  229. package/src/features/billing/stripe-product/components/forms/ProductEditor.tsx +100 -0
  230. package/src/features/billing/stripe-product/components/forms/index.ts +1 -0
  231. package/src/features/billing/stripe-product/components/index.ts +3 -0
  232. package/src/features/billing/stripe-product/components/lists/ProductsList.tsx +206 -0
  233. package/src/features/billing/stripe-product/components/lists/index.ts +1 -0
  234. package/src/features/billing/stripe-product/data/index.ts +3 -0
  235. package/src/features/billing/stripe-product/data/stripe-product.interface.ts +18 -0
  236. package/src/features/billing/stripe-product/data/stripe-product.service.ts +112 -0
  237. package/src/features/billing/stripe-product/data/stripe-product.ts +74 -0
  238. package/src/features/billing/stripe-product/index.ts +2 -0
  239. package/src/features/billing/stripe-product/stripe-product.module.ts +9 -0
  240. package/src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx +304 -0
  241. package/src/features/billing/stripe-subscription/components/containers/index.ts +1 -0
  242. package/src/features/billing/stripe-subscription/components/details/SubscriptionDetails.tsx +223 -0
  243. package/src/features/billing/stripe-subscription/components/details/index.ts +1 -0
  244. package/src/features/billing/stripe-subscription/components/forms/CancelSubscriptionDialog.tsx +116 -0
  245. package/src/features/billing/stripe-subscription/components/forms/SubscriptionEditor.tsx +331 -0
  246. package/src/features/billing/stripe-subscription/components/forms/index.ts +2 -0
  247. package/src/features/billing/stripe-subscription/components/index.ts +5 -0
  248. package/src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx +104 -0
  249. package/src/features/billing/stripe-subscription/components/lists/index.ts +1 -0
  250. package/src/features/billing/stripe-subscription/components/widgets/PricingCard.tsx +95 -0
  251. package/src/features/billing/stripe-subscription/components/widgets/PricingCardsGrid.tsx +110 -0
  252. package/src/features/billing/stripe-subscription/components/widgets/ProrationPreview.tsx +41 -0
  253. package/src/features/billing/stripe-subscription/components/widgets/SubscriptionStatusBadge.tsx +60 -0
  254. package/src/features/billing/stripe-subscription/components/widgets/index.ts +4 -0
  255. package/src/features/billing/stripe-subscription/data/index.ts +3 -0
  256. package/src/features/billing/stripe-subscription/data/stripe-subscription.interface.ts +66 -0
  257. package/src/features/billing/stripe-subscription/data/stripe-subscription.service.ts +193 -0
  258. package/src/features/billing/stripe-subscription/data/stripe-subscription.ts +135 -0
  259. package/src/features/billing/stripe-subscription/hooks/index.ts +1 -0
  260. package/src/features/billing/stripe-subscription/hooks/useConfirmSubscriptionPayment.ts +111 -0
  261. package/src/features/billing/stripe-subscription/index.ts +5 -0
  262. package/src/features/billing/stripe-subscription/stripe-subscription.module.ts +9 -0
  263. package/src/features/billing/stripe-usage/components/containers/UsageContainer.tsx +109 -0
  264. package/src/features/billing/stripe-usage/components/containers/index.ts +1 -0
  265. package/src/features/billing/stripe-usage/components/details/UsageSummaryCard.tsx +90 -0
  266. package/src/features/billing/stripe-usage/components/details/index.ts +1 -0
  267. package/src/features/billing/stripe-usage/components/index.ts +4 -0
  268. package/src/features/billing/stripe-usage/components/lists/UsageHistoryTable.tsx +72 -0
  269. package/src/features/billing/stripe-usage/components/lists/index.ts +1 -0
  270. package/src/features/billing/stripe-usage/components/widgets/UsageSummaryCards.tsx +19 -0
  271. package/src/features/billing/stripe-usage/components/widgets/index.ts +1 -0
  272. package/src/features/billing/stripe-usage/data/index.ts +3 -0
  273. package/src/features/billing/stripe-usage/data/stripe-usage.interface.ts +55 -0
  274. package/src/features/billing/stripe-usage/data/stripe-usage.service.ts +129 -0
  275. package/src/features/billing/stripe-usage/data/stripe-usage.ts +70 -0
  276. package/src/features/billing/stripe-usage/index.ts +2 -0
  277. package/src/features/billing/stripe-usage/stripe-usage.module.ts +9 -0
  278. package/src/features/company/components/forms/CompanyEditor.tsx +2 -2
  279. package/src/features/company/contexts/CompanyContext.tsx +2 -2
  280. package/src/features/feature/components/forms/FormFeatures.tsx +13 -106
  281. package/src/features/feature/data/feature.interface.ts +1 -1
  282. package/src/features/feature/data/feature.ts +4 -4
  283. package/src/features/index.ts +7 -0
  284. package/src/features/module/data/module.interface.ts +0 -1
  285. package/src/features/module/data/module.ts +0 -6
  286. package/src/features/user/components/lists/ContributorsList.tsx +2 -2
  287. package/src/features/user/components/widgets/UserAvatar.tsx +1 -1
  288. package/src/hooks/__tests__/useDataListRetriever.test.ts +321 -0
  289. package/src/hooks/__tests__/useDebounce.test.ts +170 -0
  290. package/src/index.ts +5 -2
  291. package/src/login/config.ts +27 -0
  292. package/src/login/index.ts +2 -0
  293. package/src/shadcnui/custom/link.tsx +16 -6
  294. package/src/testing/factories/createMockApiData.ts +143 -0
  295. package/src/testing/factories/createMockModule.ts +32 -0
  296. package/src/testing/factories/createMockResponse.ts +93 -0
  297. package/src/testing/factories/createMockService.ts +79 -0
  298. package/src/testing/index.ts +70 -0
  299. package/src/testing/matchers/jsonApiMatchers.ts +174 -0
  300. package/src/testing/providers/MockJsonApiProvider.tsx +58 -0
  301. package/src/testing/utils/renderWithProviders.tsx +76 -0
  302. package/src/utils/__tests__/date-formatter.test.ts +161 -0
  303. package/src/utils/__tests__/exists.test.ts +100 -0
  304. package/src/utils/blocknote-diff.util.ts +2 -1
  305. package/src/utils/blocknote-word-diff-renderer.util.ts +8 -7
  306. package/src/utils/cn.test.ts +44 -0
  307. package/dist/AuthComponent-hxOPs9o8.d.mts +0 -11
  308. package/dist/AuthComponent-hxOPs9o8.d.ts +0 -11
  309. package/dist/BlockNoteEditor-FGXYUAWI.js.map +0 -1
  310. package/dist/JsonApiRequest-FXZCYIER.js +0 -24
  311. package/dist/chunk-6YD42BP6.js.map +0 -1
  312. package/dist/chunk-C6QXZGL7.js.map +0 -1
  313. package/dist/chunk-FPZPD4JI.js.map +0 -1
  314. package/dist/chunk-JGVXZS7M.mjs.map +0 -1
  315. package/dist/chunk-PK5DRSUD.js.map +0 -1
  316. package/dist/chunk-SJIVGCNM.mjs.map +0 -1
  317. package/dist/chunk-TGBXBUWM.mjs.map +0 -1
  318. package/dist/chunk-WAFOKMKT.mjs.map +0 -1
  319. package/src/discord/config.ts +0 -15
  320. package/src/discord/index.ts +0 -1
  321. /package/dist/{JsonApiRequest-HFWXMKMA.mjs.map → JsonApiRequest-XWQWTFEQ.mjs.map} +0 -0
@@ -1,15 +1,6 @@
1
1
  "use client";
2
2
 
3
- import {
4
- Accordion,
5
- AccordionContent,
6
- AccordionItem,
7
- AccordionTrigger,
8
- Checkbox,
9
- FormLabel,
10
- FormMessage,
11
- } from "../../../../shadcnui";
12
- import { ModuleInterface } from "../../../module";
3
+ import { Checkbox, FormLabel, FormMessage, ScrollArea } from "../../../../shadcnui";
13
4
  import { FeatureInterface } from "../../data";
14
5
 
15
6
  type FormFeaturesProps = {
@@ -17,88 +8,35 @@ type FormFeaturesProps = {
17
8
  name?: string;
18
9
  features: FeatureInterface[];
19
10
  featureField?: string;
20
- moduleField?: string;
21
11
  };
22
12
 
23
- export function FormFeatures({
24
- form,
25
- name,
26
- features,
27
- featureField = "featureIds",
28
- moduleField = "moduleIds",
29
- }: FormFeaturesProps) {
13
+ export function FormFeatures({ form, name, features, featureField = "featureIds" }: FormFeaturesProps) {
30
14
  const selectedFeatures: string[] = form.watch(featureField);
31
- const selectedModules: string[] = form.watch(moduleField);
32
15
 
33
16
  const toggleFeature = (feature: FeatureInterface, checked: boolean) => {
34
17
  let newFeatureIds = [...selectedFeatures];
35
- let newModuleIds = [...selectedModules];
36
18
 
37
19
  if (checked) {
38
20
  if (!newFeatureIds.includes(feature.id)) {
39
21
  newFeatureIds.push(feature.id);
40
22
  }
41
- feature.modules.forEach((module) => {
42
- if (!newModuleIds.includes(module.id)) {
43
- newModuleIds.push(module.id);
44
- }
45
- });
46
23
  } else {
47
24
  newFeatureIds = newFeatureIds.filter((id) => id !== feature.id);
48
- feature.modules.forEach((module) => {
49
- newModuleIds = newModuleIds.filter((id) => id !== module.id);
50
- });
51
25
  }
52
26
  form.setValue(featureField, newFeatureIds);
53
- form.setValue(moduleField, newModuleIds);
54
27
  };
55
28
 
56
- const toggleModule = (feature: FeatureInterface, module: ModuleInterface, checked: boolean) => {
57
- const modulesForFeature = feature.modules.map((m) => m.id);
58
- let newModuleIds = [...selectedModules];
59
-
60
- if (checked) {
61
- if (!selectedFeatures.includes(feature.id)) {
62
- newModuleIds = newModuleIds.filter((id) => !modulesForFeature.includes(id));
63
- newModuleIds.push(module.id);
64
- form.setValue(featureField, [...selectedFeatures, feature.id]);
65
- } else {
66
- if (!newModuleIds.includes(module.id)) {
67
- newModuleIds.push(module.id);
68
- }
69
- }
70
- } else {
71
- newModuleIds = newModuleIds.filter((id) => id !== module.id);
72
- const remaining = feature.modules.filter((m) => newModuleIds.includes(m.id));
73
- if (remaining.length === 0) {
74
- form.setValue(
75
- featureField,
76
- selectedFeatures.filter((id) => id !== feature.id),
77
- );
78
- }
79
- }
80
- form.setValue(moduleField, newModuleIds);
81
- };
82
-
83
- const isFeatureChecked = (feature: FeatureInterface) =>
84
- selectedFeatures.includes(feature.id) || feature.modules.every((module) => selectedModules.includes(module.id));
29
+ const isFeatureChecked = (feature: FeatureInterface) => selectedFeatures.includes(feature.id);
85
30
 
86
31
  return (
87
32
  <div className="flex w-full flex-col">
88
- {name && <h2 className="mb-5 font-semibold">{name}</h2>}
89
- {features.map((feature) => (
90
- <Accordion
91
- key={feature.id}
92
- type="single"
93
- collapsible
94
- // className={`w-full p-0 ${feature.modules.filter((module) => !module.isCore).length === 0 ? "border-t" : ""}`}
95
- className={`w-full p-0`}
96
- >
97
- <AccordionItem value={feature.id} className="p-0">
98
- <div
99
- className={`flex items-center justify-between p-0 ${feature.modules.filter((module) => !module.isCore).length === 0 ? "py-4" : ""}`}
100
- >
101
- <div className="flex items-center" onClick={(e) => e.stopPropagation()}>
33
+ {name && <h2 className="mb-4 border-b text-lg font-semibold">{name}</h2>}
34
+ <ScrollArea className="h-[40vh]">
35
+ <div className="flex flex-col gap-y-2 pr-4">
36
+ {features
37
+ .filter((feature) => !feature.isCore)
38
+ .map((feature) => (
39
+ <div key={feature.id} className="flex items-center">
102
40
  <Checkbox
103
41
  id={feature.id}
104
42
  checked={isFeatureChecked(feature)}
@@ -110,40 +48,9 @@ export function FormFeatures({
110
48
  {feature.name}
111
49
  </FormLabel>
112
50
  </div>
113
- {feature.modules.filter((module) => !module.isCore).length > 0 && (
114
- <AccordionTrigger asChild>
115
- <div className="w-full"></div>
116
- </AccordionTrigger>
117
- )}
118
- </div>
119
- {feature.modules.filter((module) => !module.isCore).length > 0 && (
120
- <AccordionContent className="pl-6">
121
- {feature.modules
122
- .filter((module) => !module.isCore)
123
- .sort((a: ModuleInterface, b: ModuleInterface) => a.name.localeCompare(b.name))
124
- .map((module: ModuleInterface) => (
125
- <div
126
- key={module.id}
127
- className="flex items-center border-t py-2"
128
- onClick={(e) => e.stopPropagation()}
129
- >
130
- <Checkbox
131
- id={module.id}
132
- checked={selectedModules.includes(module.id)}
133
- onCheckedChange={(val) => {
134
- toggleModule(feature, module, val === true);
135
- }}
136
- />
137
- <FormLabel htmlFor={module.id} className="ml-3 cursor-pointer font-normal">
138
- {module.name}
139
- </FormLabel>
140
- </div>
141
- ))}
142
- </AccordionContent>
143
- )}
144
- </AccordionItem>
145
- </Accordion>
146
- ))}
51
+ ))}
52
+ </div>
53
+ </ScrollArea>
147
54
  <FormMessage />
148
55
  </div>
149
56
  );
@@ -3,7 +3,7 @@ import { ModuleInterface } from "../../module";
3
3
 
4
4
  export interface FeatureInterface extends ApiDataInterface {
5
5
  get name(): string;
6
- get isProduction(): boolean;
6
+ get isCore(): boolean;
7
7
 
8
8
  get modules(): ModuleInterface[];
9
9
  }
@@ -4,7 +4,7 @@ import { FeatureInterface } from "./feature.interface";
4
4
 
5
5
  export class Feature extends AbstractApiData implements FeatureInterface {
6
6
  private _name?: string;
7
- private _isProduction?: boolean;
7
+ private _isCore?: boolean;
8
8
 
9
9
  private _modules: ModuleInterface[] = [];
10
10
 
@@ -12,8 +12,8 @@ export class Feature extends AbstractApiData implements FeatureInterface {
12
12
  return this._name ?? "";
13
13
  }
14
14
 
15
- get isProduction(): boolean {
16
- return this._isProduction == true ? true : false;
15
+ get isCore(): boolean {
16
+ return this._isCore == true ? true : false;
17
17
  }
18
18
 
19
19
  get modules(): ModuleInterface[] {
@@ -24,7 +24,7 @@ export class Feature extends AbstractApiData implements FeatureInterface {
24
24
  super.rehydrate(data);
25
25
 
26
26
  this._name = data.jsonApi.attributes.name;
27
- this._isProduction = data.jsonApi.attributes.isProduction ?? false;
27
+ this._isCore = data.jsonApi.attributes.isCore ?? false;
28
28
 
29
29
  this._modules = this._readIncluded(data, `modules`, Modules.Module) as ModuleInterface[];
30
30
 
@@ -1,5 +1,12 @@
1
1
  // S3 feature exports
2
2
  export * from "./auth";
3
+ export * from "./billing";
4
+ export * from "./billing/stripe-customer";
5
+ export * from "./billing/stripe-invoice";
6
+ export * from "./billing/stripe-price";
7
+ export * from "./billing/stripe-product";
8
+ export * from "./billing/stripe-subscription";
9
+ export * from "./billing/stripe-usage";
3
10
  export * from "./company";
4
11
  export * from "./content";
5
12
  export * from "./feature";
@@ -2,7 +2,6 @@ import { ApiDataInterface } from "../../../core";
2
2
 
3
3
  export interface ModuleInterface extends ApiDataInterface {
4
4
  get name(): string;
5
- get isCore(): boolean;
6
5
  get permissions(): {
7
6
  create: boolean | string;
8
7
  read: boolean | string;
@@ -3,7 +3,6 @@ import { ModuleInterface } from "./module.interface";
3
3
 
4
4
  export class Module extends AbstractApiData implements ModuleInterface {
5
5
  private _name?: string;
6
- private _isCore?: boolean;
7
6
  private _permissions?: {
8
7
  create: boolean | string;
9
8
  read: boolean | string;
@@ -16,10 +15,6 @@ export class Module extends AbstractApiData implements ModuleInterface {
16
15
  return this._name ?? "";
17
16
  }
18
17
 
19
- get isCore(): boolean {
20
- return this._isCore ?? false;
21
- }
22
-
23
18
  get permissions(): {
24
19
  create: boolean | string;
25
20
  read: boolean | string;
@@ -34,7 +29,6 @@ export class Module extends AbstractApiData implements ModuleInterface {
34
29
  super.rehydrate(data);
35
30
 
36
31
  this._name = data.jsonApi.attributes.name;
37
- this._isCore = data.jsonApi.attributes.isCore;
38
32
  this._permissions = data.jsonApi.meta.permissions;
39
33
 
40
34
  return this;
@@ -19,7 +19,7 @@ export function ContributorsList({ content }: ContributorsListProps) {
19
19
  <Link
20
20
  key={content.author.id}
21
21
  href={generateUrl({ page: Modules.User, id: content.author.id })}
22
- onClick={(e) => e.stopPropagation()}
22
+ onClick={(e: React.MouseEvent<HTMLAnchorElement>) => e.stopPropagation()}
23
23
  >
24
24
  <UserAvatar user={content.author} className="mr-1 h-6 w-6" />
25
25
  </Link>
@@ -30,7 +30,7 @@ export function ContributorsList({ content }: ContributorsListProps) {
30
30
  <Link
31
31
  key={editor.id}
32
32
  href={generateUrl({ page: Modules.User, id: editor.id })}
33
- onClick={(e) => e.stopPropagation()}
33
+ onClick={(e: React.MouseEvent<HTMLAnchorElement>) => e.stopPropagation()}
34
34
  >
35
35
  <UserAvatar user={editor} className="h-5 w-5" />
36
36
  </Link>
@@ -65,7 +65,7 @@ export function UserAvatar({ user, className, showFull, showLink }: UserAvatarPr
65
65
  <Link
66
66
  href={generateUrl({ page: Modules.User, id: user.id })}
67
67
  className={cn(`mb-2 flex w-full flex-row items-center justify-start gap-x-2 text-sm`, className)}
68
- onClick={(e) => e.stopPropagation()}
68
+ onClick={(e: React.MouseEvent<HTMLAnchorElement>) => e.stopPropagation()}
69
69
  >
70
70
  <div className="flex w-full flex-row items-center gap-x-2">
71
71
  {getAvatar()}
@@ -0,0 +1,321 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { renderHook, waitFor, act } from "@testing-library/react";
3
+ import { useDataListRetriever } from "../useDataListRetriever";
4
+ import { createMockModule, createMockApiData } from "../../testing";
5
+
6
+ describe("useDataListRetriever", () => {
7
+ const mockModule = createMockModule({ name: "articles" });
8
+
9
+ beforeEach(() => {
10
+ vi.clearAllMocks();
11
+ });
12
+
13
+ afterEach(() => {
14
+ vi.useRealTimers();
15
+ });
16
+
17
+ describe("initialization", () => {
18
+ it("should initialize with default state", async () => {
19
+ const retriever = vi.fn().mockResolvedValue([]);
20
+
21
+ const { result } = renderHook(() =>
22
+ useDataListRetriever({
23
+ retriever,
24
+ module: mockModule,
25
+ })
26
+ );
27
+
28
+ // Initially should not be loaded
29
+ expect(result.current.ready).toBe(true);
30
+ expect(result.current.isSearch).toBe(false);
31
+ });
32
+
33
+ it("should respect ready=false", async () => {
34
+ const retriever = vi.fn().mockResolvedValue([]);
35
+
36
+ const { result } = renderHook(() =>
37
+ useDataListRetriever({
38
+ retriever,
39
+ module: mockModule,
40
+ ready: false,
41
+ })
42
+ );
43
+
44
+ expect(result.current.ready).toBe(false);
45
+ // Retriever should not be called when not ready
46
+ expect(retriever).not.toHaveBeenCalled();
47
+ });
48
+ });
49
+
50
+ describe("data fetching", () => {
51
+ it("should fetch data when ready", async () => {
52
+ const mockData = [
53
+ createMockApiData({ type: "articles", id: "1", attributes: { title: "Article 1" } }),
54
+ createMockApiData({ type: "articles", id: "2", attributes: { title: "Article 2" } }),
55
+ ];
56
+ const retriever = vi.fn().mockResolvedValue(mockData);
57
+
58
+ const { result } = renderHook(() =>
59
+ useDataListRetriever({
60
+ retriever,
61
+ module: mockModule,
62
+ })
63
+ );
64
+
65
+ await waitFor(() => {
66
+ expect(result.current.isLoaded).toBe(true);
67
+ });
68
+
69
+ expect(result.current.data).toHaveLength(2);
70
+ expect(retriever).toHaveBeenCalled();
71
+ });
72
+
73
+ it("should handle fetch errors gracefully", async () => {
74
+ const consoleError = vi.spyOn(console, "error").mockImplementation(() => {});
75
+ const retriever = vi.fn().mockRejectedValue(new Error("Fetch failed"));
76
+
77
+ const { result } = renderHook(() =>
78
+ useDataListRetriever({
79
+ retriever,
80
+ module: mockModule,
81
+ })
82
+ );
83
+
84
+ await waitFor(() => {
85
+ expect(result.current.isLoaded).toBe(true);
86
+ });
87
+
88
+ expect(consoleError).toHaveBeenCalled();
89
+ consoleError.mockRestore();
90
+ });
91
+ });
92
+
93
+ describe("search", () => {
94
+ it("should search and call retriever with search term", async () => {
95
+ const mockData = [
96
+ createMockApiData({ type: "articles", id: "1", attributes: { title: "Search Result" } }),
97
+ ];
98
+ const retriever = vi.fn().mockResolvedValue(mockData);
99
+
100
+ const { result } = renderHook(() =>
101
+ useDataListRetriever({
102
+ retriever,
103
+ module: mockModule,
104
+ })
105
+ );
106
+
107
+ await waitFor(() => {
108
+ expect(result.current.isLoaded).toBe(true);
109
+ });
110
+
111
+ const callCountBefore = retriever.mock.calls.length;
112
+
113
+ await act(async () => {
114
+ await result.current.search("test query");
115
+ });
116
+
117
+ await waitFor(() => {
118
+ // Verify retriever was called again with the search term
119
+ expect(retriever.mock.calls.length).toBeGreaterThan(callCountBefore);
120
+ const lastCall = retriever.mock.calls[retriever.mock.calls.length - 1][0];
121
+ expect(lastCall.search).toBe("test query");
122
+ });
123
+ });
124
+
125
+ it("should not search if query is unchanged", async () => {
126
+ const retriever = vi.fn().mockResolvedValue([]);
127
+
128
+ const { result } = renderHook(() =>
129
+ useDataListRetriever({
130
+ retriever,
131
+ module: mockModule,
132
+ })
133
+ );
134
+
135
+ await waitFor(() => {
136
+ expect(result.current.isLoaded).toBe(true);
137
+ });
138
+
139
+ const callCountBefore = retriever.mock.calls.length;
140
+
141
+ // Search with same empty query
142
+ await act(async () => {
143
+ await result.current.search("");
144
+ });
145
+
146
+ // Should not trigger additional fetch
147
+ expect(retriever.mock.calls.length).toBe(callCountBefore);
148
+ });
149
+ });
150
+
151
+ describe("refresh", () => {
152
+ it("should refresh data", async () => {
153
+ const mockData = [createMockApiData({ type: "articles", id: "1" })];
154
+ const retriever = vi.fn().mockResolvedValue(mockData);
155
+
156
+ const { result } = renderHook(() =>
157
+ useDataListRetriever({
158
+ retriever,
159
+ module: mockModule,
160
+ })
161
+ );
162
+
163
+ await waitFor(() => {
164
+ expect(result.current.isLoaded).toBe(true);
165
+ });
166
+
167
+ const callCountBefore = retriever.mock.calls.length;
168
+
169
+ await act(async () => {
170
+ await result.current.refresh();
171
+ });
172
+
173
+ await waitFor(() => {
174
+ expect(retriever.mock.calls.length).toBeGreaterThan(callCountBefore);
175
+ });
176
+ });
177
+ });
178
+
179
+ describe("setReady", () => {
180
+ it("should allow setting ready state", async () => {
181
+ const retriever = vi.fn().mockResolvedValue([]);
182
+
183
+ const { result } = renderHook(() =>
184
+ useDataListRetriever({
185
+ retriever,
186
+ module: mockModule,
187
+ ready: false,
188
+ })
189
+ );
190
+
191
+ expect(result.current.ready).toBe(false);
192
+
193
+ act(() => {
194
+ result.current.setReady(true);
195
+ });
196
+
197
+ expect(result.current.ready).toBe(true);
198
+ });
199
+ });
200
+
201
+ describe("element management", () => {
202
+ it("should update element with setRefreshedElement", async () => {
203
+ const mockData = [
204
+ createMockApiData({ type: "articles", id: "1", attributes: { title: "Original" } }),
205
+ ];
206
+ const retriever = vi.fn().mockResolvedValue(mockData);
207
+
208
+ const { result } = renderHook(() =>
209
+ useDataListRetriever({
210
+ retriever,
211
+ module: mockModule,
212
+ })
213
+ );
214
+
215
+ await waitFor(() => {
216
+ expect(result.current.isLoaded).toBe(true);
217
+ });
218
+
219
+ const updatedElement = createMockApiData({
220
+ type: "articles",
221
+ id: "1",
222
+ attributes: { title: "Updated" },
223
+ });
224
+
225
+ act(() => {
226
+ result.current.setRefreshedElement(updatedElement as any);
227
+ });
228
+
229
+ // Element should be updated in place
230
+ expect(result.current.data?.[0]).toBe(updatedElement);
231
+ });
232
+
233
+ it("should remove element with removeElement", async () => {
234
+ const mockData = [
235
+ createMockApiData({ type: "articles", id: "1" }),
236
+ createMockApiData({ type: "articles", id: "2" }),
237
+ ];
238
+ const retriever = vi.fn().mockResolvedValue(mockData);
239
+
240
+ const { result } = renderHook(() =>
241
+ useDataListRetriever({
242
+ retriever,
243
+ module: mockModule,
244
+ })
245
+ );
246
+
247
+ await waitFor(() => {
248
+ expect(result.current.isLoaded).toBe(true);
249
+ });
250
+
251
+ expect(result.current.data).toHaveLength(2);
252
+
253
+ act(() => {
254
+ result.current.removeElement(mockData[0] as any);
255
+ });
256
+
257
+ expect(result.current.data).toHaveLength(1);
258
+ expect(result.current.data?.[0].id).toBe("2");
259
+ });
260
+ });
261
+
262
+ describe("additional parameters", () => {
263
+ it("should add additional parameter", async () => {
264
+ const retriever = vi.fn().mockResolvedValue([]);
265
+
266
+ const { result } = renderHook(() =>
267
+ useDataListRetriever({
268
+ retriever,
269
+ module: mockModule,
270
+ })
271
+ );
272
+
273
+ await waitFor(() => {
274
+ expect(result.current.isLoaded).toBe(true);
275
+ });
276
+
277
+ act(() => {
278
+ result.current.addAdditionalParameter("filter", "active");
279
+ });
280
+
281
+ await waitFor(() => {
282
+ expect(retriever).toHaveBeenCalledWith(
283
+ expect.objectContaining({ filter: "active" })
284
+ );
285
+ });
286
+ });
287
+
288
+ it("should remove additional parameter", async () => {
289
+ const retriever = vi.fn().mockResolvedValue([]);
290
+
291
+ const { result } = renderHook(() =>
292
+ useDataListRetriever({
293
+ retriever,
294
+ module: mockModule,
295
+ })
296
+ );
297
+
298
+ await waitFor(() => {
299
+ expect(result.current.isLoaded).toBe(true);
300
+ });
301
+
302
+ act(() => {
303
+ result.current.addAdditionalParameter("filter", "active");
304
+ });
305
+
306
+ await waitFor(() => {
307
+ expect(result.current.isLoaded).toBe(true);
308
+ });
309
+
310
+ act(() => {
311
+ result.current.removeAdditionalParameter("filter");
312
+ });
313
+
314
+ // Should refetch without the parameter
315
+ await waitFor(() => {
316
+ const lastCall = retriever.mock.calls[retriever.mock.calls.length - 1][0];
317
+ expect(lastCall.filter).toBeUndefined();
318
+ });
319
+ });
320
+ });
321
+ });