@carlonicora/nextjs-jsonapi 5.4.0 → 5.6.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 (237) hide show
  1. package/dist/{BlockNoteEditor-4YCAIEPT.js → BlockNoteEditor-AE3ZTEEH.js} +20 -20
  2. package/dist/{BlockNoteEditor-4YCAIEPT.js.map → BlockNoteEditor-AE3ZTEEH.js.map} +1 -1
  3. package/dist/{BlockNoteEditor-YQL2SGFR.mjs → BlockNoteEditor-NEYG5L6W.mjs} +5 -5
  4. package/dist/{BlockNoteViewer-AEJKJ27Q.mjs → BlockNoteViewer-3OUT5UFY.mjs} +3 -3
  5. package/dist/{BlockNoteViewer-YL3J7J2Y.js → BlockNoteViewer-4CFKQM7U.js} +4 -4
  6. package/dist/{BlockNoteViewer-YL3J7J2Y.js.map → BlockNoteViewer-4CFKQM7U.js.map} +1 -1
  7. package/dist/billing/index.d.mts +186 -25
  8. package/dist/billing/index.d.ts +186 -25
  9. package/dist/billing/index.js +1149 -588
  10. package/dist/billing/index.js.map +1 -1
  11. package/dist/billing/index.mjs +786 -225
  12. package/dist/billing/index.mjs.map +1 -1
  13. package/dist/{chunk-5PPG6PL7.js → chunk-3I5AAJXV.js} +3 -3
  14. package/dist/{chunk-5PPG6PL7.js.map → chunk-3I5AAJXV.js.map} +1 -1
  15. package/dist/{chunk-YW4ZCEWB.js → chunk-53BAULDP.js} +4 -4
  16. package/dist/{chunk-YW4ZCEWB.js.map → chunk-53BAULDP.js.map} +1 -1
  17. package/dist/{chunk-XCHSX3VC.mjs → chunk-BTPUYUQ3.mjs} +2 -2
  18. package/dist/{chunk-WC63PJSC.mjs → chunk-EYA2F6AN.mjs} +756 -24
  19. package/dist/chunk-EYA2F6AN.mjs.map +1 -0
  20. package/dist/{chunk-NFBOSPNJ.js → chunk-HKZAESS6.js} +954 -222
  21. package/dist/chunk-HKZAESS6.js.map +1 -0
  22. package/dist/{chunk-6DC2WVVB.mjs → chunk-KQHBONL4.mjs} +2 -2
  23. package/dist/{chunk-3NLAXVIN.js → chunk-LQ4DK4JF.js} +1988 -1089
  24. package/dist/chunk-LQ4DK4JF.js.map +1 -0
  25. package/dist/{chunk-YNCQSWQW.js → chunk-RL3PL3KV.js} +8 -8
  26. package/dist/{chunk-YNCQSWQW.js.map → chunk-RL3PL3KV.js.map} +1 -1
  27. package/dist/{chunk-EUKTBOI2.mjs → chunk-SFYPXCK4.mjs} +3382 -2483
  28. package/dist/chunk-SFYPXCK4.mjs.map +1 -0
  29. package/dist/{chunk-QMYQRPQC.mjs → chunk-Y7RR57EW.mjs} +2 -2
  30. package/dist/client/index.js +5 -5
  31. package/dist/client/index.js.map +1 -1
  32. package/dist/client/index.mjs +4 -4
  33. package/dist/components/editors/server.d.mts +15 -0
  34. package/dist/components/editors/server.d.ts +15 -0
  35. package/dist/components/editors/server.js +38 -0
  36. package/dist/components/editors/server.js.map +1 -0
  37. package/dist/components/editors/server.mjs +38 -0
  38. package/dist/components/editors/server.mjs.map +1 -0
  39. package/dist/components/index.d.mts +33 -10
  40. package/dist/components/index.d.ts +33 -10
  41. package/dist/components/index.js +7 -5
  42. package/dist/components/index.js.map +1 -1
  43. package/dist/components/index.mjs +8 -6
  44. package/dist/contexts/index.d.mts +9 -1
  45. package/dist/contexts/index.d.ts +9 -1
  46. package/dist/contexts/index.js +5 -5
  47. package/dist/contexts/index.mjs +4 -4
  48. package/dist/core/index.d.mts +242 -3
  49. package/dist/core/index.d.ts +242 -3
  50. package/dist/core/index.js +36 -4
  51. package/dist/core/index.js.map +1 -1
  52. package/dist/core/index.mjs +35 -3
  53. package/dist/email-automations/index.d.mts +3 -0
  54. package/dist/email-automations/index.d.ts +3 -0
  55. package/dist/email-automations/index.js +99 -95
  56. package/dist/email-automations/index.js.map +1 -1
  57. package/dist/email-automations/index.mjs +30 -26
  58. package/dist/email-automations/index.mjs.map +1 -1
  59. package/dist/features/analytics/index.d.mts +11 -4
  60. package/dist/features/analytics/index.d.ts +11 -4
  61. package/dist/features/analytics/index.js +127 -135
  62. package/dist/features/analytics/index.js.map +1 -1
  63. package/dist/features/analytics/index.mjs +16 -24
  64. package/dist/features/analytics/index.mjs.map +1 -1
  65. package/dist/features/analytics/server.d.mts +5 -2
  66. package/dist/features/analytics/server.d.ts +5 -2
  67. package/dist/features/analytics/server.js +7 -7
  68. package/dist/features/analytics/server.js.map +1 -1
  69. package/dist/features/analytics/server.mjs +5 -5
  70. package/dist/features/analytics/server.mjs.map +1 -1
  71. package/dist/features/blog/index.d.mts +12 -2
  72. package/dist/features/blog/index.d.ts +12 -2
  73. package/dist/features/blog/index.js +206 -195
  74. package/dist/features/blog/index.js.map +1 -1
  75. package/dist/features/blog/index.mjs +71 -60
  76. package/dist/features/blog/index.mjs.map +1 -1
  77. package/dist/features/blog/server.d.mts +4 -1
  78. package/dist/features/blog/server.d.ts +4 -1
  79. package/dist/features/blog/server.js +49 -21
  80. package/dist/features/blog/server.js.map +1 -1
  81. package/dist/features/blog/server.mjs +36 -8
  82. package/dist/features/blog/server.mjs.map +1 -1
  83. package/dist/features/help/index.js +38 -38
  84. package/dist/features/help/index.mjs +4 -4
  85. package/dist/features/tokenusage/index.d.mts +1 -3
  86. package/dist/features/tokenusage/index.d.ts +1 -3
  87. package/dist/features/tokenusage/index.js +127 -135
  88. package/dist/features/tokenusage/index.js.map +1 -1
  89. package/dist/features/tokenusage/index.mjs +10 -18
  90. package/dist/features/tokenusage/index.mjs.map +1 -1
  91. package/dist/{stripe-promotion-code.interface-C3qqh3mi.d.ts → format-options-BtX3o0Yu.d.ts} +104 -1
  92. package/dist/{stripe-promotion-code.interface-ClZ7DxS9.d.mts → format-options-D6c7FNDi.d.mts} +104 -1
  93. package/dist/index.d.mts +2 -2
  94. package/dist/index.d.ts +2 -2
  95. package/dist/index.js +37 -5
  96. package/dist/index.js.map +1 -1
  97. package/dist/index.mjs +36 -4
  98. package/dist/server/index.js +4 -4
  99. package/dist/server/index.mjs +3 -3
  100. package/messages/en.json +125 -3
  101. package/messages/it.json +125 -3
  102. package/package.json +9 -1
  103. package/scripts/validate-messages.mjs +1 -0
  104. package/src/billing/index.ts +1 -0
  105. package/src/client/index.ts +4 -0
  106. package/src/components/editors/server/BlockNoteServerContent.tsx +28 -0
  107. package/src/components/editors/server/__tests__/renderBlockNoteHTML.spec.ts +44 -0
  108. package/src/components/editors/server/renderBlockNoteHTML.ts +26 -0
  109. package/src/components/editors/server-entry.ts +7 -0
  110. package/src/components/index.ts +1 -0
  111. package/src/components/viewers/BlockNoteStaticViewer.tsx +44 -0
  112. package/src/core/index.ts +1 -0
  113. package/src/core/registry/ModuleRegistry.ts +3 -0
  114. package/src/features/administration/components/AdminIndexContainer.tsx +61 -33
  115. package/src/features/administration/components/__tests__/AdminIndexContainer.spec.tsx +61 -1
  116. package/src/features/administration/components/index.ts +2 -1
  117. package/src/features/administration/contexts/AdministrationContext.tsx +11 -3
  118. package/src/features/administration/contexts/__tests__/AdministrationContext.spec.tsx +40 -0
  119. package/src/features/ai-connection/ai-connection.module.ts +2 -0
  120. package/src/features/ai-connection/contexts/AiConnectionsContext.tsx +3 -16
  121. package/src/features/ai-connection/contexts/__tests__/AiConnectionsContext.spec.tsx +33 -0
  122. package/src/features/analytics/__tests__/server-entry.spec.tsx +2 -1
  123. package/src/features/analytics/analytics.modules.ts +22 -5
  124. package/src/features/analytics/components/AnalyticsAdminContainer.tsx +4 -3
  125. package/src/features/analytics/components/AnalyticsAdminPageContainer.tsx +6 -3
  126. package/src/features/analytics/components/AnalyticsJourneyContainer.tsx +4 -3
  127. package/src/features/analytics/components/__tests__/AnalyticsJourneyContainer.spec.tsx +11 -0
  128. package/src/features/analytics/components/__tests__/AnalyticsPageContainers.spec.tsx +12 -1
  129. package/src/features/analytics/components/server/AnalyticsAdminPage.tsx +6 -3
  130. package/src/features/analytics/contexts/AnalyticsAdminContext.tsx +8 -17
  131. package/src/features/analytics/contexts/__tests__/AnalyticsAdminContext.spec.tsx +17 -0
  132. package/src/features/billing/components/cards/InvoicesSummaryCard.tsx +3 -2
  133. package/src/features/billing/components/cards/SubscriptionSummaryCard.tsx +4 -3
  134. package/src/features/billing/components/containers/BillingDashboardContainer.tsx +22 -5
  135. package/src/features/billing/components/utils/__tests__/discount.spec.ts +59 -0
  136. package/src/features/billing/components/utils/__tests__/url.spec.ts +32 -0
  137. package/src/features/billing/components/utils/discount.ts +38 -0
  138. package/src/features/billing/components/utils/index.ts +2 -0
  139. package/src/features/billing/components/utils/url.ts +12 -0
  140. package/src/features/billing/contexts/CouponContext.tsx +211 -0
  141. package/src/features/billing/contexts/index.ts +1 -0
  142. package/src/features/billing/i18n-keys.ts +79 -0
  143. package/src/features/billing/stripe-coupon/components/containers/CouponContainer.tsx +38 -0
  144. package/src/features/billing/stripe-coupon/components/containers/index.ts +1 -0
  145. package/src/features/billing/stripe-coupon/components/details/CouponDetails.tsx +69 -0
  146. package/src/features/billing/stripe-coupon/components/details/index.ts +1 -0
  147. package/src/features/billing/stripe-coupon/components/forms/CouponCodeEditor.tsx +79 -0
  148. package/src/features/billing/stripe-coupon/components/forms/CouponCodeFields.tsx +192 -0
  149. package/src/features/billing/stripe-coupon/components/forms/CouponEditor.tsx +333 -0
  150. package/src/features/billing/stripe-coupon/components/forms/CouponRefresher.tsx +45 -0
  151. package/src/features/billing/stripe-coupon/components/forms/index.ts +6 -0
  152. package/src/features/billing/stripe-coupon/components/index.ts +5 -0
  153. package/src/features/billing/stripe-coupon/components/lists/CouponCodesList.tsx +61 -0
  154. package/src/features/billing/stripe-coupon/components/lists/CouponsList.tsx +67 -0
  155. package/src/features/billing/stripe-coupon/components/lists/index.ts +2 -0
  156. package/src/features/billing/stripe-coupon/components/widgets/CouponCodeActions.tsx +80 -0
  157. package/src/features/billing/stripe-coupon/components/widgets/index.ts +1 -0
  158. package/src/features/billing/stripe-coupon/data/__tests__/stripe-coupon-models.spec.ts +114 -0
  159. package/src/features/billing/stripe-coupon/data/index.ts +10 -0
  160. package/src/features/billing/stripe-coupon/data/stripe-coupon-code.fields.ts +8 -0
  161. package/src/features/billing/stripe-coupon/data/stripe-coupon-code.interface.ts +44 -0
  162. package/src/features/billing/stripe-coupon/data/stripe-coupon-code.service.ts +92 -0
  163. package/src/features/billing/stripe-coupon/data/stripe-coupon-code.ts +132 -0
  164. package/src/features/billing/stripe-coupon/data/stripe-coupon-offer.interface.ts +17 -0
  165. package/src/features/billing/stripe-coupon/data/stripe-coupon-offer.ts +70 -0
  166. package/src/features/billing/stripe-coupon/data/stripe-coupon.fields.ts +7 -0
  167. package/src/features/billing/stripe-coupon/data/stripe-coupon.interface.ts +51 -0
  168. package/src/features/billing/stripe-coupon/data/stripe-coupon.service.ts +93 -0
  169. package/src/features/billing/stripe-coupon/data/stripe-coupon.ts +165 -0
  170. package/src/features/billing/stripe-coupon/hooks/useStripeCouponCodeTableStructure.tsx +154 -0
  171. package/src/features/billing/stripe-coupon/hooks/useStripeCouponTableStructure.tsx +113 -0
  172. package/src/features/billing/stripe-coupon/index.ts +5 -0
  173. package/src/features/billing/stripe-coupon/stripe-coupon-code.module.ts +14 -0
  174. package/src/features/billing/stripe-coupon/stripe-coupon-offer.module.ts +10 -0
  175. package/src/features/billing/stripe-coupon/stripe-coupon.module.ts +18 -0
  176. package/src/features/billing/stripe-coupon/utils/__tests__/coupon-places.spec.ts +19 -0
  177. package/src/features/billing/stripe-coupon/utils/__tests__/to-promotion-code-result.spec.ts +41 -0
  178. package/src/features/billing/stripe-coupon/utils/coupon-places.ts +23 -0
  179. package/src/features/billing/stripe-coupon/utils/format-coupon-discount.ts +36 -0
  180. package/src/features/billing/stripe-coupon/utils/index.ts +3 -0
  181. package/src/features/billing/stripe-coupon/utils/to-promotion-code-result.ts +23 -0
  182. package/src/features/billing/stripe-customer/components/forms/PaymentMethodForm.tsx +24 -8
  183. package/src/features/billing/stripe-price/stripe-price.module.ts +2 -0
  184. package/src/features/billing/stripe-product/components/containers/ProductsListContainer.tsx +21 -6
  185. package/src/features/billing/stripe-product/stripe-product.module.ts +2 -0
  186. package/src/features/billing/stripe-promotion-code/components/PromoCodeInput.tsx +60 -19
  187. package/src/features/billing/stripe-promotion-code/data/stripe-promotion-code.interface.ts +2 -0
  188. package/src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx +24 -5
  189. package/src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx +21 -2
  190. package/src/features/billing/stripe-subscription/components/wizards/SubscriptionWizard.tsx +1 -1
  191. package/src/features/billing/stripe-subscription/components/wizards/WizardStepPaymentMethod.tsx +1 -1
  192. package/src/features/billing/stripe-subscription/components/wizards/WizardStepReview.tsx +60 -49
  193. package/src/features/billing/stripe-subscription/components/wizards/__tests__/review-card.spec.ts +34 -0
  194. package/src/features/billing/stripe-subscription/components/wizards/review-card.ts +24 -0
  195. package/src/features/billing/stripe-subscription/data/__tests__/stripe-subscription.discount.spec.ts +67 -0
  196. package/src/features/billing/stripe-subscription/data/stripe-subscription.interface.ts +14 -0
  197. package/src/features/billing/stripe-subscription/data/stripe-subscription.service.ts +39 -0
  198. package/src/features/billing/stripe-subscription/data/stripe-subscription.ts +21 -0
  199. package/src/features/billing/stripe-subscription/hooks/__tests__/wizard-payment.spec.ts +48 -0
  200. package/src/features/billing/stripe-subscription/hooks/__tests__/wizard-promotion.spec.ts +132 -0
  201. package/src/features/billing/stripe-subscription/hooks/useSubscriptionWizard.ts +138 -12
  202. package/src/features/billing/stripe-subscription/hooks/wizard-payment.ts +30 -0
  203. package/src/features/billing/stripe-subscription/hooks/wizard-promotion.ts +54 -0
  204. package/src/features/blog/components/admin/BlogAdminContainer.tsx +13 -6
  205. package/src/features/blog/components/admin/BlogCategoriesList.tsx +1 -1
  206. package/src/features/blog/components/admin/BlogCoverImageField.tsx +1 -1
  207. package/src/features/blog/components/admin/BlogPostContainer.tsx +0 -1
  208. package/src/features/blog/components/admin/BlogPostEditor.tsx +42 -33
  209. package/src/features/blog/components/admin/BlogPostTranslationEditor.tsx +12 -4
  210. package/src/features/blog/components/admin/BlogPostsList.tsx +1 -1
  211. package/src/features/blog/components/public/BlogPostCard.tsx +2 -9
  212. package/src/features/blog/components/public/BlogPostMeta.tsx +2 -2
  213. package/src/features/blog/components/public/BlogPostView.tsx +9 -3
  214. package/src/features/blog/components/public/__tests__/BlogList.spec.tsx +2 -0
  215. package/src/features/blog/components/public/__tests__/BlogPostView.spec.tsx +17 -11
  216. package/src/features/blog/server/fetchers.ts +57 -8
  217. package/src/features/email-automation/components/containers/EmailAutomationsListContainer.tsx +12 -3
  218. package/src/features/rbac/contexts/RbacContext.tsx +4 -7
  219. package/src/features/rbac/contexts/__tests__/RbacContext.spec.tsx +42 -0
  220. package/src/features/tokenusage/components/TokenUsageAdminContainer.tsx +4 -3
  221. package/src/features/tokenusage/contexts/TokenUsageAdminContext.tsx +3 -18
  222. package/src/features/tokenusage/contexts/__tests__/TokenUsageAdminContext.spec.tsx +17 -0
  223. package/src/features/tokenusage/tokenusage-admin.module.ts +4 -3
  224. package/src/features/tokenusage/tokenusage.modules.ts +12 -2
  225. package/src/features/user/contexts/CurrentUserContext.tsx +25 -0
  226. package/src/features/user/contexts/UserContext.tsx +18 -3
  227. package/src/features/user/contexts/__tests__/CurrentUserContext.spec.tsx +121 -2
  228. package/src/features/user/contexts/__tests__/UserContext.spec.tsx +95 -0
  229. package/dist/chunk-3NLAXVIN.js.map +0 -1
  230. package/dist/chunk-EUKTBOI2.mjs.map +0 -1
  231. package/dist/chunk-NFBOSPNJ.js.map +0 -1
  232. package/dist/chunk-WC63PJSC.mjs.map +0 -1
  233. /package/dist/{BlockNoteEditor-YQL2SGFR.mjs.map → BlockNoteEditor-NEYG5L6W.mjs.map} +0 -0
  234. /package/dist/{BlockNoteViewer-AEJKJ27Q.mjs.map → BlockNoteViewer-3OUT5UFY.mjs.map} +0 -0
  235. /package/dist/{chunk-XCHSX3VC.mjs.map → chunk-BTPUYUQ3.mjs.map} +0 -0
  236. /package/dist/{chunk-6DC2WVVB.mjs.map → chunk-KQHBONL4.mjs.map} +0 -0
  237. /package/dist/{chunk-QMYQRPQC.mjs.map → chunk-Y7RR57EW.mjs.map} +0 -0
@@ -10,7 +10,10 @@ declare function fetchPublicBlogPosts(params: {
10
10
  language: string;
11
11
  categorySlug?: string;
12
12
  search?: string;
13
- page: number;
13
+ /** 1-based list page; ignored with `all`. */
14
+ page?: number;
15
+ /** Every matching post, read in API-sized pages (a sitemap). `hasMore` is then false. */
16
+ all?: boolean;
14
17
  }): Promise<PublicBlogList>;
15
18
  declare function fetchPublicBlogPost(params: {
16
19
  language: string;
@@ -10,7 +10,10 @@ declare function fetchPublicBlogPosts(params: {
10
10
  language: string;
11
11
  categorySlug?: string;
12
12
  search?: string;
13
- page: number;
13
+ /** 1-based list page; ignored with `all`. */
14
+ page?: number;
15
+ /** Every matching post, read in API-sized pages (a sitemap). `hasMore` is then false. */
16
+ all?: boolean;
14
17
  }): Promise<PublicBlogList>;
15
18
  declare function fetchPublicBlogPost(params: {
16
19
  language: string;
@@ -9,10 +9,10 @@ require('../../chunk-6TUB7Y6T.js');
9
9
 
10
10
 
11
11
 
12
- var _chunkNFBOSPNJjs = require('../../chunk-NFBOSPNJ.js');
12
+ var _chunkHKZAESS6js = require('../../chunk-HKZAESS6.js');
13
+ require('../../chunk-GHE4VT2R.js');
13
14
  require('../../chunk-LXKSUWAV.js');
14
15
  require('../../chunk-JTPRJNT2.js');
15
- require('../../chunk-GHE4VT2R.js');
16
16
 
17
17
 
18
18
  var _chunk7QVYU63Ejs = require('../../chunk-7QVYU63E.js');
@@ -50,19 +50,15 @@ _chunk7QVYU63Ejs.__name.call(void 0, toPublicBlogCategory, "toPublicBlogCategory
50
50
 
51
51
  // src/features/blog/server/fetchers.ts
52
52
  var BLOG_PAGE_SIZE = 12;
53
- var publicPostsEndpoint = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, () => `${_chunkNFBOSPNJjs.BLOG_PUBLIC_PREFIX}/${_chunkNFBOSPNJjs.Modules.BlogPost.name}`, "publicPostsEndpoint");
53
+ var publicPostsEndpoint = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, () => `${_chunkHKZAESS6js.BLOG_PUBLIC_PREFIX}/${_chunkHKZAESS6js.Modules.BlogPost.name}`, "publicPostsEndpoint");
54
54
  var asArray = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (data) => Array.isArray(data) ? data : data ? [data] : [], "asArray");
55
55
  async function fetchPublicBlogPosts(params) {
56
+ if (params.all) return { posts: await fetchEveryPublicBlogPost(params), hasMore: false };
56
57
  const page = Math.min(10, Math.max(1, Math.floor(params.page || 1)));
57
58
  const size = BLOG_PAGE_SIZE * page;
58
- const endpoint = new (0, _chunkNFBOSPNJjs.EndpointCreator)({ endpoint: publicPostsEndpoint() });
59
- endpoint.addAdditionalParam("language", params.language);
60
- if (params.categorySlug) endpoint.addAdditionalParam("category", encodeURIComponent(params.categorySlug));
61
- if (params.search) endpoint.addAdditionalParam("search", encodeURIComponent(params.search));
62
- endpoint.addAdditionalParam("page[size]", String(size));
63
59
  const res = await _chunkKSYQEKJXjs.ServerJsonApiGet.call(void 0, {
64
- classKey: { ..._chunkNFBOSPNJjs.Modules.BlogPost, cache: "minutes" },
65
- endpoint: endpoint.generate(),
60
+ classKey: { ..._chunkHKZAESS6js.Modules.BlogPost, cache: "minutes" },
61
+ endpoint: publicPostsListEndpoint({ ...params, size }),
66
62
  language: params.language
67
63
  });
68
64
  if (!res.ok) return { posts: [], hasMore: false };
@@ -72,11 +68,43 @@ async function fetchPublicBlogPosts(params) {
72
68
  return { posts, hasMore };
73
69
  }
74
70
  _chunk7QVYU63Ejs.__name.call(void 0, fetchPublicBlogPosts, "fetchPublicBlogPosts");
71
+ function publicPostsListEndpoint(params) {
72
+ const endpoint = new (0, _chunkHKZAESS6js.EndpointCreator)({ endpoint: publicPostsEndpoint() });
73
+ endpoint.addAdditionalParam("language", params.language);
74
+ if (params.categorySlug) endpoint.addAdditionalParam("category", encodeURIComponent(params.categorySlug));
75
+ if (params.search) endpoint.addAdditionalParam("search", encodeURIComponent(params.search));
76
+ endpoint.addAdditionalParam("page[size]", String(params.size));
77
+ if (params.offset) endpoint.addAdditionalParam("page[offset]", String(params.offset));
78
+ return endpoint.generate();
79
+ }
80
+ _chunk7QVYU63Ejs.__name.call(void 0, publicPostsListEndpoint, "publicPostsListEndpoint");
81
+ var PUBLIC_MAX_PAGE_SIZE = 120;
82
+ var MAX_ALL_PAGES = 100;
83
+ async function fetchEveryPublicBlogPost(params) {
84
+ const posts = [];
85
+ for (let index = 0; index < MAX_ALL_PAGES; index++) {
86
+ const res = await _chunkKSYQEKJXjs.ServerJsonApiGet.call(void 0, {
87
+ classKey: { ..._chunkHKZAESS6js.Modules.BlogPost, cache: "minutes" },
88
+ endpoint: publicPostsListEndpoint({
89
+ ...params,
90
+ size: PUBLIC_MAX_PAGE_SIZE,
91
+ offset: index * PUBLIC_MAX_PAGE_SIZE
92
+ }),
93
+ language: params.language
94
+ });
95
+ if (!res.ok) break;
96
+ const batch = asArray(res.data);
97
+ posts.push(...batch.map(toPublicBlogPost));
98
+ if (batch.length < PUBLIC_MAX_PAGE_SIZE) break;
99
+ }
100
+ return posts;
101
+ }
102
+ _chunk7QVYU63Ejs.__name.call(void 0, fetchEveryPublicBlogPost, "fetchEveryPublicBlogPost");
75
103
  async function fetchPublicBlogPost(params) {
76
- const endpoint = new (0, _chunkNFBOSPNJjs.EndpointCreator)({ endpoint: publicPostsEndpoint(), id: encodeURIComponent(params.slug) });
104
+ const endpoint = new (0, _chunkHKZAESS6js.EndpointCreator)({ endpoint: publicPostsEndpoint(), id: encodeURIComponent(params.slug) });
77
105
  endpoint.addAdditionalParam("language", params.language);
78
106
  const res = await _chunkKSYQEKJXjs.ServerJsonApiGet.call(void 0, {
79
- classKey: { ..._chunkNFBOSPNJjs.Modules.BlogPost, cache: "minutes" },
107
+ classKey: { ..._chunkHKZAESS6js.Modules.BlogPost, cache: "minutes" },
80
108
  endpoint: endpoint.generate(),
81
109
  language: params.language
82
110
  });
@@ -86,14 +114,14 @@ async function fetchPublicBlogPost(params) {
86
114
  }
87
115
  _chunk7QVYU63Ejs.__name.call(void 0, fetchPublicBlogPost, "fetchPublicBlogPost");
88
116
  async function fetchRelatedBlogPosts(params) {
89
- const endpoint = new (0, _chunkNFBOSPNJjs.EndpointCreator)({
117
+ const endpoint = new (0, _chunkHKZAESS6js.EndpointCreator)({
90
118
  endpoint: publicPostsEndpoint(),
91
119
  id: encodeURIComponent(params.slug),
92
- childEndpoint: _chunkNFBOSPNJjs.BLOG_ACTION.related
120
+ childEndpoint: _chunkHKZAESS6js.BLOG_ACTION.related
93
121
  });
94
122
  endpoint.addAdditionalParam("language", params.language);
95
123
  const res = await _chunkKSYQEKJXjs.ServerJsonApiGet.call(void 0, {
96
- classKey: { ..._chunkNFBOSPNJjs.Modules.BlogPost, cache: "minutes" },
124
+ classKey: { ..._chunkHKZAESS6js.Modules.BlogPost, cache: "minutes" },
97
125
  endpoint: endpoint.generate(),
98
126
  language: params.language
99
127
  });
@@ -102,10 +130,10 @@ async function fetchRelatedBlogPosts(params) {
102
130
  }
103
131
  _chunk7QVYU63Ejs.__name.call(void 0, fetchRelatedBlogPosts, "fetchRelatedBlogPosts");
104
132
  async function fetchPublicBlogCategories(params) {
105
- const endpoint = new (0, _chunkNFBOSPNJjs.EndpointCreator)({ endpoint: `${_chunkNFBOSPNJjs.BLOG_PUBLIC_PREFIX}/${_chunkNFBOSPNJjs.Modules.BlogCategory.name}` });
133
+ const endpoint = new (0, _chunkHKZAESS6js.EndpointCreator)({ endpoint: `${_chunkHKZAESS6js.BLOG_PUBLIC_PREFIX}/${_chunkHKZAESS6js.Modules.BlogCategory.name}` });
106
134
  endpoint.addAdditionalParam("language", params.language);
107
135
  const res = await _chunkKSYQEKJXjs.ServerJsonApiGet.call(void 0, {
108
- classKey: { ..._chunkNFBOSPNJjs.Modules.BlogCategory, cache: "minutes" },
136
+ classKey: { ..._chunkHKZAESS6js.Modules.BlogCategory, cache: "minutes" },
109
137
  endpoint: endpoint.generate(),
110
138
  language: params.language
111
139
  });
@@ -116,13 +144,13 @@ _chunk7QVYU63Ejs.__name.call(void 0, fetchPublicBlogCategories, "fetchPublicBlog
116
144
  async function fetchBlogSettings() {
117
145
  const fallback = { listLayout: "featured" };
118
146
  const res = await _chunkKSYQEKJXjs.ServerJsonApiGet.call(void 0, {
119
- classKey: { ..._chunkNFBOSPNJjs.Modules.BlogSettings, cache: "minutes" },
120
- endpoint: new (0, _chunkNFBOSPNJjs.EndpointCreator)({ endpoint: `${_chunkNFBOSPNJjs.BLOG_PUBLIC_PREFIX}/${_chunkNFBOSPNJjs.Modules.BlogSettings.name}` }).generate(),
147
+ classKey: { ..._chunkHKZAESS6js.Modules.BlogSettings, cache: "minutes" },
148
+ endpoint: new (0, _chunkHKZAESS6js.EndpointCreator)({ endpoint: `${_chunkHKZAESS6js.BLOG_PUBLIC_PREFIX}/${_chunkHKZAESS6js.Modules.BlogSettings.name}` }).generate(),
121
149
  language: "en"
122
150
  });
123
151
  if (!res.ok) return fallback;
124
152
  const settings = asArray(res.data)[0];
125
- if (!settings || !_chunkNFBOSPNJjs.BLOG_LIST_LAYOUTS.includes(settings.listLayout)) return fallback;
153
+ if (!settings || !_chunkHKZAESS6js.BLOG_LIST_LAYOUTS.includes(settings.listLayout)) return fallback;
126
154
  return { listLayout: settings.listLayout };
127
155
  }
128
156
  _chunk7QVYU63Ejs.__name.call(void 0, fetchBlogSettings, "fetchBlogSettings");
@@ -135,5 +163,5 @@ _chunk7QVYU63Ejs.__name.call(void 0, fetchBlogSettings, "fetchBlogSettings");
135
163
 
136
164
 
137
165
 
138
- exports.BLOG_LIST_LAYOUTS = _chunkNFBOSPNJjs.BLOG_LIST_LAYOUTS; exports.fetchBlogSettings = fetchBlogSettings; exports.fetchPublicBlogCategories = fetchPublicBlogCategories; exports.fetchPublicBlogPost = fetchPublicBlogPost; exports.fetchPublicBlogPosts = fetchPublicBlogPosts; exports.fetchRelatedBlogPosts = fetchRelatedBlogPosts; exports.toPublicBlogCategory = toPublicBlogCategory; exports.toPublicBlogPost = toPublicBlogPost;
166
+ exports.BLOG_LIST_LAYOUTS = _chunkHKZAESS6js.BLOG_LIST_LAYOUTS; exports.fetchBlogSettings = fetchBlogSettings; exports.fetchPublicBlogCategories = fetchPublicBlogCategories; exports.fetchPublicBlogPost = fetchPublicBlogPost; exports.fetchPublicBlogPosts = fetchPublicBlogPosts; exports.fetchRelatedBlogPosts = fetchRelatedBlogPosts; exports.toPublicBlogCategory = toPublicBlogCategory; exports.toPublicBlogPost = toPublicBlogPost;
139
167
  //# sourceMappingURL=server.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/features/blog/server.js","../../../src/features/blog/server/toPublic.ts","../../../src/features/blog/server/fetchers.ts"],"names":[],"mappings":"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","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/features/blog/server.js","sourcesContent":[null,"import { BlogCategoryInterface } from \"../data/BlogCategoryInterface\";\nimport { BlogPostInterface } from \"../data/BlogPostInterface\";\nimport { PublicBlogCategory, PublicBlogPost } from \"../types/blog-public.types\";\n\n// Serialisation boundary: a rehydrated model (class instance, Date getters)\n// becomes plain data a server page can pass to the public client components.\n\nexport function toPublicBlogPost(post: BlogPostInterface): PublicBlogPost {\n const publishedAt = post.publishedAt ?? post.createdAt;\n\n return {\n id: post.id,\n language: post.language ?? post.originalLanguage,\n title: post.title ?? \"\",\n slug: post.slug ?? \"\",\n summary: post.summary,\n body: post.body,\n coverImage: post.coverImage,\n coverImageAlt: post.coverImageAlt,\n readingMinutes: post.readingMinutes ?? 1,\n publishedAt: publishedAt.toISOString(),\n updatedAt: post.updatedAt.toISOString(),\n authorName: post.authorName,\n categoryIds: [...post.categoryIds],\n };\n}\n\nexport function toPublicBlogCategory(category: BlogCategoryInterface): PublicBlogCategory {\n return {\n id: category.id,\n name: category.name ?? \"\",\n slug: category.slug ?? \"\",\n description: category.description,\n image: category.image,\n };\n}\n","import { EndpointCreator, Modules } from \"../../../core\";\nimport { ServerJsonApiGet } from \"../../../server/JsonApiServer\";\nimport { BlogCategoryInterface } from \"../data/BlogCategoryInterface\";\nimport { BlogPostInterface } from \"../data/BlogPostInterface\";\nimport { BlogSettingsInterface } from \"../data/BlogSettingsInterface\";\nimport { BLOG_ACTION, BLOG_LIST_LAYOUTS, BLOG_PUBLIC_PREFIX, BlogListLayout } from \"../types/blog.constants\";\nimport { PublicBlogCategory, PublicBlogList, PublicBlogPost } from \"../types/blog-public.types\";\nimport { toPublicBlogCategory, toPublicBlogPost } from \"./toPublic\";\n\n// Public, token-free reads for the marketing blog pages.\n//\n// `cache: \"minutes\"` is a cacheLife profile name: the GET goes through\n// cachedServerGet (\"use cache\"), so an admin change shows up within about a\n// minute. Nothing connects API or worker writes to the web cache, and\n// translations finish asynchronously in the worker, so there is no tag to expire.\n//\n// Each classKey is built INSIDE the function, never at module scope: reading\n// Modules.X while the module evaluates throws \"Module X not registered\" in build\n// workers that never ran the app's bootstrapper (see the app's publicHowTo.ts).\n\nconst BLOG_PAGE_SIZE = 12;\n\nconst publicPostsEndpoint = () => `${BLOG_PUBLIC_PREFIX}/${Modules.BlogPost.name}`;\n\nconst asArray = <T>(data: unknown): T[] => (Array.isArray(data) ? data : data ? [data] : []) as T[];\n\nexport async function fetchPublicBlogPosts(params: {\n language: string;\n categorySlug?: string;\n search?: string;\n page: number;\n}): Promise<PublicBlogList> {\n // Matches the API cap (120 = 10 pages of 12); a larger ?page= is served as the last allowed one.\n const page = Math.min(10, Math.max(1, Math.floor(params.page || 1)));\n const size = BLOG_PAGE_SIZE * page;\n\n const endpoint = new EndpointCreator({ endpoint: publicPostsEndpoint() });\n endpoint.addAdditionalParam(\"language\", params.language);\n if (params.categorySlug) endpoint.addAdditionalParam(\"category\", encodeURIComponent(params.categorySlug));\n if (params.search) endpoint.addAdditionalParam(\"search\", encodeURIComponent(params.search));\n endpoint.addAdditionalParam(\"page[size]\", String(size));\n\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogPost, cache: \"minutes\" },\n endpoint: endpoint.generate(),\n language: params.language,\n });\n if (!res.ok) return { posts: [], hasMore: false };\n\n const posts = asArray<BlogPostInterface>(res.data).map(toPublicBlogPost);\n const total = Number(res.meta?.total);\n const hasMore = Number.isFinite(total) ? total > posts.length : false;\n\n return { posts, hasMore };\n}\n\nexport async function fetchPublicBlogPost(params: { language: string; slug: string }): Promise<PublicBlogPost | null> {\n const endpoint = new EndpointCreator({ endpoint: publicPostsEndpoint(), id: encodeURIComponent(params.slug) });\n endpoint.addAdditionalParam(\"language\", params.language);\n\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogPost, cache: \"minutes\" },\n endpoint: endpoint.generate(),\n language: params.language,\n });\n if (!res.ok) return null;\n\n const post = asArray<BlogPostInterface>(res.data)[0];\n return post ? toPublicBlogPost(post) : null;\n}\n\nexport async function fetchRelatedBlogPosts(params: { language: string; slug: string }): Promise<PublicBlogPost[]> {\n const endpoint = new EndpointCreator({\n endpoint: publicPostsEndpoint(),\n id: encodeURIComponent(params.slug),\n childEndpoint: BLOG_ACTION.related,\n });\n endpoint.addAdditionalParam(\"language\", params.language);\n\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogPost, cache: \"minutes\" },\n endpoint: endpoint.generate(),\n language: params.language,\n });\n if (!res.ok) return [];\n\n return asArray<BlogPostInterface>(res.data).map(toPublicBlogPost);\n}\n\nexport async function fetchPublicBlogCategories(params: { language: string }): Promise<PublicBlogCategory[]> {\n const endpoint = new EndpointCreator({ endpoint: `${BLOG_PUBLIC_PREFIX}/${Modules.BlogCategory.name}` });\n endpoint.addAdditionalParam(\"language\", params.language);\n\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogCategory, cache: \"minutes\" },\n endpoint: endpoint.generate(),\n language: params.language,\n });\n if (!res.ok) return [];\n\n return asArray<BlogCategoryInterface>(res.data).map(toPublicBlogCategory);\n}\n\nexport async function fetchBlogSettings(): Promise<{ listLayout: BlogListLayout }> {\n const fallback: { listLayout: BlogListLayout } = { listLayout: \"featured\" };\n\n // The settings are language-neutral; the language only fills the required\n // request header, so one fixed value keeps a single cache entry.\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogSettings, cache: \"minutes\" },\n endpoint: new EndpointCreator({ endpoint: `${BLOG_PUBLIC_PREFIX}/${Modules.BlogSettings.name}` }).generate(),\n language: \"en\",\n });\n if (!res.ok) return fallback;\n\n const settings = asArray<BlogSettingsInterface>(res.data)[0];\n if (!settings || !BLOG_LIST_LAYOUTS.includes(settings.listLayout)) return fallback;\n\n return { listLayout: settings.listLayout };\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/features/blog/server.js","../../../src/features/blog/server/toPublic.ts","../../../src/features/blog/server/fetchers.ts"],"names":[],"mappings":"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","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/features/blog/server.js","sourcesContent":[null,"import { BlogCategoryInterface } from \"../data/BlogCategoryInterface\";\nimport { BlogPostInterface } from \"../data/BlogPostInterface\";\nimport { PublicBlogCategory, PublicBlogPost } from \"../types/blog-public.types\";\n\n// Serialisation boundary: a rehydrated model (class instance, Date getters)\n// becomes plain data a server page can pass to the public client components.\n\nexport function toPublicBlogPost(post: BlogPostInterface): PublicBlogPost {\n const publishedAt = post.publishedAt ?? post.createdAt;\n\n return {\n id: post.id,\n language: post.language ?? post.originalLanguage,\n title: post.title ?? \"\",\n slug: post.slug ?? \"\",\n summary: post.summary,\n body: post.body,\n coverImage: post.coverImage,\n coverImageAlt: post.coverImageAlt,\n readingMinutes: post.readingMinutes ?? 1,\n publishedAt: publishedAt.toISOString(),\n updatedAt: post.updatedAt.toISOString(),\n authorName: post.authorName,\n categoryIds: [...post.categoryIds],\n };\n}\n\nexport function toPublicBlogCategory(category: BlogCategoryInterface): PublicBlogCategory {\n return {\n id: category.id,\n name: category.name ?? \"\",\n slug: category.slug ?? \"\",\n description: category.description,\n image: category.image,\n };\n}\n","import { EndpointCreator, Modules } from \"../../../core\";\nimport { ServerJsonApiGet } from \"../../../server/JsonApiServer\";\nimport { BlogCategoryInterface } from \"../data/BlogCategoryInterface\";\nimport { BlogPostInterface } from \"../data/BlogPostInterface\";\nimport { BlogSettingsInterface } from \"../data/BlogSettingsInterface\";\nimport { BLOG_ACTION, BLOG_LIST_LAYOUTS, BLOG_PUBLIC_PREFIX, BlogListLayout } from \"../types/blog.constants\";\nimport { PublicBlogCategory, PublicBlogList, PublicBlogPost } from \"../types/blog-public.types\";\nimport { toPublicBlogCategory, toPublicBlogPost } from \"./toPublic\";\n\n// Public, token-free reads for the marketing blog pages.\n//\n// `cache: \"minutes\"` is a cacheLife profile name: the GET goes through\n// cachedServerGet (\"use cache\"), so an admin change shows up within about a\n// minute. Nothing connects API or worker writes to the web cache, and\n// translations finish asynchronously in the worker, so there is no tag to expire.\n//\n// Each classKey is built INSIDE the function, never at module scope: reading\n// Modules.X while the module evaluates throws \"Module X not registered\" in build\n// workers that never ran the app's bootstrapper (see the app's publicHowTo.ts).\n\nconst BLOG_PAGE_SIZE = 12;\n\nconst publicPostsEndpoint = () => `${BLOG_PUBLIC_PREFIX}/${Modules.BlogPost.name}`;\n\nconst asArray = <T>(data: unknown): T[] => (Array.isArray(data) ? data : data ? [data] : []) as T[];\n\nexport async function fetchPublicBlogPosts(params: {\n language: string;\n categorySlug?: string;\n search?: string;\n /** 1-based list page; ignored with `all`. */\n page?: number;\n /** Every matching post, read in API-sized pages (a sitemap). `hasMore` is then false. */\n all?: boolean;\n}): Promise<PublicBlogList> {\n if (params.all) return { posts: await fetchEveryPublicBlogPost(params), hasMore: false };\n\n // Matches the API cap (120 = 10 pages of 12); a larger ?page= is served as the last allowed one.\n const page = Math.min(10, Math.max(1, Math.floor(params.page || 1)));\n const size = BLOG_PAGE_SIZE * page;\n\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogPost, cache: \"minutes\" },\n endpoint: publicPostsListEndpoint({ ...params, size }),\n language: params.language,\n });\n if (!res.ok) return { posts: [], hasMore: false };\n\n const posts = asArray<BlogPostInterface>(res.data).map(toPublicBlogPost);\n const total = Number(res.meta?.total);\n const hasMore = Number.isFinite(total) ? total > posts.length : false;\n\n return { posts, hasMore };\n}\n\nfunction publicPostsListEndpoint(params: {\n language: string;\n categorySlug?: string;\n search?: string;\n size: number;\n offset?: number;\n}): string {\n const endpoint = new EndpointCreator({ endpoint: publicPostsEndpoint() });\n endpoint.addAdditionalParam(\"language\", params.language);\n if (params.categorySlug) endpoint.addAdditionalParam(\"category\", encodeURIComponent(params.categorySlug));\n if (params.search) endpoint.addAdditionalParam(\"search\", encodeURIComponent(params.search));\n endpoint.addAdditionalParam(\"page[size]\", String(params.size));\n if (params.offset) endpoint.addAdditionalParam(\"page[offset]\", String(params.offset));\n return endpoint.generate();\n}\n\n// The API serves at most PUBLIC_MAX_PAGE_SIZE posts per request, so \"all\" walks\n// page[offset] until a short page comes back. MAX_ALL_PAGES only stops a runaway loop.\nconst PUBLIC_MAX_PAGE_SIZE = 120;\nconst MAX_ALL_PAGES = 100;\n\nasync function fetchEveryPublicBlogPost(params: {\n language: string;\n categorySlug?: string;\n search?: string;\n}): Promise<PublicBlogPost[]> {\n const posts: PublicBlogPost[] = [];\n\n // In sequence: a failing cached call throws, and parallel failing cached calls\n // never close the response.\n for (let index = 0; index < MAX_ALL_PAGES; index++) {\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogPost, cache: \"minutes\" },\n endpoint: publicPostsListEndpoint({\n ...params,\n size: PUBLIC_MAX_PAGE_SIZE,\n offset: index * PUBLIC_MAX_PAGE_SIZE,\n }),\n language: params.language,\n });\n if (!res.ok) break;\n\n const batch = asArray<BlogPostInterface>(res.data);\n posts.push(...batch.map(toPublicBlogPost));\n if (batch.length < PUBLIC_MAX_PAGE_SIZE) break;\n }\n\n return posts;\n}\n\nexport async function fetchPublicBlogPost(params: { language: string; slug: string }): Promise<PublicBlogPost | null> {\n const endpoint = new EndpointCreator({ endpoint: publicPostsEndpoint(), id: encodeURIComponent(params.slug) });\n endpoint.addAdditionalParam(\"language\", params.language);\n\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogPost, cache: \"minutes\" },\n endpoint: endpoint.generate(),\n language: params.language,\n });\n if (!res.ok) return null;\n\n const post = asArray<BlogPostInterface>(res.data)[0];\n return post ? toPublicBlogPost(post) : null;\n}\n\nexport async function fetchRelatedBlogPosts(params: { language: string; slug: string }): Promise<PublicBlogPost[]> {\n const endpoint = new EndpointCreator({\n endpoint: publicPostsEndpoint(),\n id: encodeURIComponent(params.slug),\n childEndpoint: BLOG_ACTION.related,\n });\n endpoint.addAdditionalParam(\"language\", params.language);\n\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogPost, cache: \"minutes\" },\n endpoint: endpoint.generate(),\n language: params.language,\n });\n if (!res.ok) return [];\n\n return asArray<BlogPostInterface>(res.data).map(toPublicBlogPost);\n}\n\nexport async function fetchPublicBlogCategories(params: { language: string }): Promise<PublicBlogCategory[]> {\n const endpoint = new EndpointCreator({ endpoint: `${BLOG_PUBLIC_PREFIX}/${Modules.BlogCategory.name}` });\n endpoint.addAdditionalParam(\"language\", params.language);\n\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogCategory, cache: \"minutes\" },\n endpoint: endpoint.generate(),\n language: params.language,\n });\n if (!res.ok) return [];\n\n return asArray<BlogCategoryInterface>(res.data).map(toPublicBlogCategory);\n}\n\nexport async function fetchBlogSettings(): Promise<{ listLayout: BlogListLayout }> {\n const fallback: { listLayout: BlogListLayout } = { listLayout: \"featured\" };\n\n // The settings are language-neutral; the language only fills the required\n // request header, so one fixed value keeps a single cache entry.\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogSettings, cache: \"minutes\" },\n endpoint: new EndpointCreator({ endpoint: `${BLOG_PUBLIC_PREFIX}/${Modules.BlogSettings.name}` }).generate(),\n language: \"en\",\n });\n if (!res.ok) return fallback;\n\n const settings = asArray<BlogSettingsInterface>(res.data)[0];\n if (!settings || !BLOG_LIST_LAYOUTS.includes(settings.listLayout)) return fallback;\n\n return { listLayout: settings.listLayout };\n}\n"]}
@@ -9,10 +9,10 @@ import {
9
9
  BLOG_PUBLIC_PREFIX,
10
10
  EndpointCreator,
11
11
  Modules
12
- } from "../../chunk-WC63PJSC.mjs";
12
+ } from "../../chunk-EYA2F6AN.mjs";
13
+ import "../../chunk-V5MI7RNB.mjs";
13
14
  import "../../chunk-AUXK7QSA.mjs";
14
15
  import "../../chunk-PI56A4DG.mjs";
15
- import "../../chunk-V5MI7RNB.mjs";
16
16
  import {
17
17
  __name
18
18
  } from "../../chunk-PAWJFY3S.mjs";
@@ -53,16 +53,12 @@ var BLOG_PAGE_SIZE = 12;
53
53
  var publicPostsEndpoint = /* @__PURE__ */ __name(() => `${BLOG_PUBLIC_PREFIX}/${Modules.BlogPost.name}`, "publicPostsEndpoint");
54
54
  var asArray = /* @__PURE__ */ __name((data) => Array.isArray(data) ? data : data ? [data] : [], "asArray");
55
55
  async function fetchPublicBlogPosts(params) {
56
+ if (params.all) return { posts: await fetchEveryPublicBlogPost(params), hasMore: false };
56
57
  const page = Math.min(10, Math.max(1, Math.floor(params.page || 1)));
57
58
  const size = BLOG_PAGE_SIZE * page;
58
- const endpoint = new EndpointCreator({ endpoint: publicPostsEndpoint() });
59
- endpoint.addAdditionalParam("language", params.language);
60
- if (params.categorySlug) endpoint.addAdditionalParam("category", encodeURIComponent(params.categorySlug));
61
- if (params.search) endpoint.addAdditionalParam("search", encodeURIComponent(params.search));
62
- endpoint.addAdditionalParam("page[size]", String(size));
63
59
  const res = await ServerJsonApiGet({
64
60
  classKey: { ...Modules.BlogPost, cache: "minutes" },
65
- endpoint: endpoint.generate(),
61
+ endpoint: publicPostsListEndpoint({ ...params, size }),
66
62
  language: params.language
67
63
  });
68
64
  if (!res.ok) return { posts: [], hasMore: false };
@@ -72,6 +68,38 @@ async function fetchPublicBlogPosts(params) {
72
68
  return { posts, hasMore };
73
69
  }
74
70
  __name(fetchPublicBlogPosts, "fetchPublicBlogPosts");
71
+ function publicPostsListEndpoint(params) {
72
+ const endpoint = new EndpointCreator({ endpoint: publicPostsEndpoint() });
73
+ endpoint.addAdditionalParam("language", params.language);
74
+ if (params.categorySlug) endpoint.addAdditionalParam("category", encodeURIComponent(params.categorySlug));
75
+ if (params.search) endpoint.addAdditionalParam("search", encodeURIComponent(params.search));
76
+ endpoint.addAdditionalParam("page[size]", String(params.size));
77
+ if (params.offset) endpoint.addAdditionalParam("page[offset]", String(params.offset));
78
+ return endpoint.generate();
79
+ }
80
+ __name(publicPostsListEndpoint, "publicPostsListEndpoint");
81
+ var PUBLIC_MAX_PAGE_SIZE = 120;
82
+ var MAX_ALL_PAGES = 100;
83
+ async function fetchEveryPublicBlogPost(params) {
84
+ const posts = [];
85
+ for (let index = 0; index < MAX_ALL_PAGES; index++) {
86
+ const res = await ServerJsonApiGet({
87
+ classKey: { ...Modules.BlogPost, cache: "minutes" },
88
+ endpoint: publicPostsListEndpoint({
89
+ ...params,
90
+ size: PUBLIC_MAX_PAGE_SIZE,
91
+ offset: index * PUBLIC_MAX_PAGE_SIZE
92
+ }),
93
+ language: params.language
94
+ });
95
+ if (!res.ok) break;
96
+ const batch = asArray(res.data);
97
+ posts.push(...batch.map(toPublicBlogPost));
98
+ if (batch.length < PUBLIC_MAX_PAGE_SIZE) break;
99
+ }
100
+ return posts;
101
+ }
102
+ __name(fetchEveryPublicBlogPost, "fetchEveryPublicBlogPost");
75
103
  async function fetchPublicBlogPost(params) {
76
104
  const endpoint = new EndpointCreator({ endpoint: publicPostsEndpoint(), id: encodeURIComponent(params.slug) });
77
105
  endpoint.addAdditionalParam("language", params.language);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/features/blog/server/toPublic.ts","../../../src/features/blog/server/fetchers.ts"],"sourcesContent":["import { BlogCategoryInterface } from \"../data/BlogCategoryInterface\";\nimport { BlogPostInterface } from \"../data/BlogPostInterface\";\nimport { PublicBlogCategory, PublicBlogPost } from \"../types/blog-public.types\";\n\n// Serialisation boundary: a rehydrated model (class instance, Date getters)\n// becomes plain data a server page can pass to the public client components.\n\nexport function toPublicBlogPost(post: BlogPostInterface): PublicBlogPost {\n const publishedAt = post.publishedAt ?? post.createdAt;\n\n return {\n id: post.id,\n language: post.language ?? post.originalLanguage,\n title: post.title ?? \"\",\n slug: post.slug ?? \"\",\n summary: post.summary,\n body: post.body,\n coverImage: post.coverImage,\n coverImageAlt: post.coverImageAlt,\n readingMinutes: post.readingMinutes ?? 1,\n publishedAt: publishedAt.toISOString(),\n updatedAt: post.updatedAt.toISOString(),\n authorName: post.authorName,\n categoryIds: [...post.categoryIds],\n };\n}\n\nexport function toPublicBlogCategory(category: BlogCategoryInterface): PublicBlogCategory {\n return {\n id: category.id,\n name: category.name ?? \"\",\n slug: category.slug ?? \"\",\n description: category.description,\n image: category.image,\n };\n}\n","import { EndpointCreator, Modules } from \"../../../core\";\nimport { ServerJsonApiGet } from \"../../../server/JsonApiServer\";\nimport { BlogCategoryInterface } from \"../data/BlogCategoryInterface\";\nimport { BlogPostInterface } from \"../data/BlogPostInterface\";\nimport { BlogSettingsInterface } from \"../data/BlogSettingsInterface\";\nimport { BLOG_ACTION, BLOG_LIST_LAYOUTS, BLOG_PUBLIC_PREFIX, BlogListLayout } from \"../types/blog.constants\";\nimport { PublicBlogCategory, PublicBlogList, PublicBlogPost } from \"../types/blog-public.types\";\nimport { toPublicBlogCategory, toPublicBlogPost } from \"./toPublic\";\n\n// Public, token-free reads for the marketing blog pages.\n//\n// `cache: \"minutes\"` is a cacheLife profile name: the GET goes through\n// cachedServerGet (\"use cache\"), so an admin change shows up within about a\n// minute. Nothing connects API or worker writes to the web cache, and\n// translations finish asynchronously in the worker, so there is no tag to expire.\n//\n// Each classKey is built INSIDE the function, never at module scope: reading\n// Modules.X while the module evaluates throws \"Module X not registered\" in build\n// workers that never ran the app's bootstrapper (see the app's publicHowTo.ts).\n\nconst BLOG_PAGE_SIZE = 12;\n\nconst publicPostsEndpoint = () => `${BLOG_PUBLIC_PREFIX}/${Modules.BlogPost.name}`;\n\nconst asArray = <T>(data: unknown): T[] => (Array.isArray(data) ? data : data ? [data] : []) as T[];\n\nexport async function fetchPublicBlogPosts(params: {\n language: string;\n categorySlug?: string;\n search?: string;\n page: number;\n}): Promise<PublicBlogList> {\n // Matches the API cap (120 = 10 pages of 12); a larger ?page= is served as the last allowed one.\n const page = Math.min(10, Math.max(1, Math.floor(params.page || 1)));\n const size = BLOG_PAGE_SIZE * page;\n\n const endpoint = new EndpointCreator({ endpoint: publicPostsEndpoint() });\n endpoint.addAdditionalParam(\"language\", params.language);\n if (params.categorySlug) endpoint.addAdditionalParam(\"category\", encodeURIComponent(params.categorySlug));\n if (params.search) endpoint.addAdditionalParam(\"search\", encodeURIComponent(params.search));\n endpoint.addAdditionalParam(\"page[size]\", String(size));\n\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogPost, cache: \"minutes\" },\n endpoint: endpoint.generate(),\n language: params.language,\n });\n if (!res.ok) return { posts: [], hasMore: false };\n\n const posts = asArray<BlogPostInterface>(res.data).map(toPublicBlogPost);\n const total = Number(res.meta?.total);\n const hasMore = Number.isFinite(total) ? total > posts.length : false;\n\n return { posts, hasMore };\n}\n\nexport async function fetchPublicBlogPost(params: { language: string; slug: string }): Promise<PublicBlogPost | null> {\n const endpoint = new EndpointCreator({ endpoint: publicPostsEndpoint(), id: encodeURIComponent(params.slug) });\n endpoint.addAdditionalParam(\"language\", params.language);\n\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogPost, cache: \"minutes\" },\n endpoint: endpoint.generate(),\n language: params.language,\n });\n if (!res.ok) return null;\n\n const post = asArray<BlogPostInterface>(res.data)[0];\n return post ? toPublicBlogPost(post) : null;\n}\n\nexport async function fetchRelatedBlogPosts(params: { language: string; slug: string }): Promise<PublicBlogPost[]> {\n const endpoint = new EndpointCreator({\n endpoint: publicPostsEndpoint(),\n id: encodeURIComponent(params.slug),\n childEndpoint: BLOG_ACTION.related,\n });\n endpoint.addAdditionalParam(\"language\", params.language);\n\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogPost, cache: \"minutes\" },\n endpoint: endpoint.generate(),\n language: params.language,\n });\n if (!res.ok) return [];\n\n return asArray<BlogPostInterface>(res.data).map(toPublicBlogPost);\n}\n\nexport async function fetchPublicBlogCategories(params: { language: string }): Promise<PublicBlogCategory[]> {\n const endpoint = new EndpointCreator({ endpoint: `${BLOG_PUBLIC_PREFIX}/${Modules.BlogCategory.name}` });\n endpoint.addAdditionalParam(\"language\", params.language);\n\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogCategory, cache: \"minutes\" },\n endpoint: endpoint.generate(),\n language: params.language,\n });\n if (!res.ok) return [];\n\n return asArray<BlogCategoryInterface>(res.data).map(toPublicBlogCategory);\n}\n\nexport async function fetchBlogSettings(): Promise<{ listLayout: BlogListLayout }> {\n const fallback: { listLayout: BlogListLayout } = { listLayout: \"featured\" };\n\n // The settings are language-neutral; the language only fills the required\n // request header, so one fixed value keeps a single cache entry.\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogSettings, cache: \"minutes\" },\n endpoint: new EndpointCreator({ endpoint: `${BLOG_PUBLIC_PREFIX}/${Modules.BlogSettings.name}` }).generate(),\n language: \"en\",\n });\n if (!res.ok) return fallback;\n\n const settings = asArray<BlogSettingsInterface>(res.data)[0];\n if (!settings || !BLOG_LIST_LAYOUTS.includes(settings.listLayout)) return fallback;\n\n return { listLayout: settings.listLayout };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/features/blog/server/toPublic.ts","../../../src/features/blog/server/fetchers.ts"],"sourcesContent":["import { BlogCategoryInterface } from \"../data/BlogCategoryInterface\";\nimport { BlogPostInterface } from \"../data/BlogPostInterface\";\nimport { PublicBlogCategory, PublicBlogPost } from \"../types/blog-public.types\";\n\n// Serialisation boundary: a rehydrated model (class instance, Date getters)\n// becomes plain data a server page can pass to the public client components.\n\nexport function toPublicBlogPost(post: BlogPostInterface): PublicBlogPost {\n const publishedAt = post.publishedAt ?? post.createdAt;\n\n return {\n id: post.id,\n language: post.language ?? post.originalLanguage,\n title: post.title ?? \"\",\n slug: post.slug ?? \"\",\n summary: post.summary,\n body: post.body,\n coverImage: post.coverImage,\n coverImageAlt: post.coverImageAlt,\n readingMinutes: post.readingMinutes ?? 1,\n publishedAt: publishedAt.toISOString(),\n updatedAt: post.updatedAt.toISOString(),\n authorName: post.authorName,\n categoryIds: [...post.categoryIds],\n };\n}\n\nexport function toPublicBlogCategory(category: BlogCategoryInterface): PublicBlogCategory {\n return {\n id: category.id,\n name: category.name ?? \"\",\n slug: category.slug ?? \"\",\n description: category.description,\n image: category.image,\n };\n}\n","import { EndpointCreator, Modules } from \"../../../core\";\nimport { ServerJsonApiGet } from \"../../../server/JsonApiServer\";\nimport { BlogCategoryInterface } from \"../data/BlogCategoryInterface\";\nimport { BlogPostInterface } from \"../data/BlogPostInterface\";\nimport { BlogSettingsInterface } from \"../data/BlogSettingsInterface\";\nimport { BLOG_ACTION, BLOG_LIST_LAYOUTS, BLOG_PUBLIC_PREFIX, BlogListLayout } from \"../types/blog.constants\";\nimport { PublicBlogCategory, PublicBlogList, PublicBlogPost } from \"../types/blog-public.types\";\nimport { toPublicBlogCategory, toPublicBlogPost } from \"./toPublic\";\n\n// Public, token-free reads for the marketing blog pages.\n//\n// `cache: \"minutes\"` is a cacheLife profile name: the GET goes through\n// cachedServerGet (\"use cache\"), so an admin change shows up within about a\n// minute. Nothing connects API or worker writes to the web cache, and\n// translations finish asynchronously in the worker, so there is no tag to expire.\n//\n// Each classKey is built INSIDE the function, never at module scope: reading\n// Modules.X while the module evaluates throws \"Module X not registered\" in build\n// workers that never ran the app's bootstrapper (see the app's publicHowTo.ts).\n\nconst BLOG_PAGE_SIZE = 12;\n\nconst publicPostsEndpoint = () => `${BLOG_PUBLIC_PREFIX}/${Modules.BlogPost.name}`;\n\nconst asArray = <T>(data: unknown): T[] => (Array.isArray(data) ? data : data ? [data] : []) as T[];\n\nexport async function fetchPublicBlogPosts(params: {\n language: string;\n categorySlug?: string;\n search?: string;\n /** 1-based list page; ignored with `all`. */\n page?: number;\n /** Every matching post, read in API-sized pages (a sitemap). `hasMore` is then false. */\n all?: boolean;\n}): Promise<PublicBlogList> {\n if (params.all) return { posts: await fetchEveryPublicBlogPost(params), hasMore: false };\n\n // Matches the API cap (120 = 10 pages of 12); a larger ?page= is served as the last allowed one.\n const page = Math.min(10, Math.max(1, Math.floor(params.page || 1)));\n const size = BLOG_PAGE_SIZE * page;\n\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogPost, cache: \"minutes\" },\n endpoint: publicPostsListEndpoint({ ...params, size }),\n language: params.language,\n });\n if (!res.ok) return { posts: [], hasMore: false };\n\n const posts = asArray<BlogPostInterface>(res.data).map(toPublicBlogPost);\n const total = Number(res.meta?.total);\n const hasMore = Number.isFinite(total) ? total > posts.length : false;\n\n return { posts, hasMore };\n}\n\nfunction publicPostsListEndpoint(params: {\n language: string;\n categorySlug?: string;\n search?: string;\n size: number;\n offset?: number;\n}): string {\n const endpoint = new EndpointCreator({ endpoint: publicPostsEndpoint() });\n endpoint.addAdditionalParam(\"language\", params.language);\n if (params.categorySlug) endpoint.addAdditionalParam(\"category\", encodeURIComponent(params.categorySlug));\n if (params.search) endpoint.addAdditionalParam(\"search\", encodeURIComponent(params.search));\n endpoint.addAdditionalParam(\"page[size]\", String(params.size));\n if (params.offset) endpoint.addAdditionalParam(\"page[offset]\", String(params.offset));\n return endpoint.generate();\n}\n\n// The API serves at most PUBLIC_MAX_PAGE_SIZE posts per request, so \"all\" walks\n// page[offset] until a short page comes back. MAX_ALL_PAGES only stops a runaway loop.\nconst PUBLIC_MAX_PAGE_SIZE = 120;\nconst MAX_ALL_PAGES = 100;\n\nasync function fetchEveryPublicBlogPost(params: {\n language: string;\n categorySlug?: string;\n search?: string;\n}): Promise<PublicBlogPost[]> {\n const posts: PublicBlogPost[] = [];\n\n // In sequence: a failing cached call throws, and parallel failing cached calls\n // never close the response.\n for (let index = 0; index < MAX_ALL_PAGES; index++) {\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogPost, cache: \"minutes\" },\n endpoint: publicPostsListEndpoint({\n ...params,\n size: PUBLIC_MAX_PAGE_SIZE,\n offset: index * PUBLIC_MAX_PAGE_SIZE,\n }),\n language: params.language,\n });\n if (!res.ok) break;\n\n const batch = asArray<BlogPostInterface>(res.data);\n posts.push(...batch.map(toPublicBlogPost));\n if (batch.length < PUBLIC_MAX_PAGE_SIZE) break;\n }\n\n return posts;\n}\n\nexport async function fetchPublicBlogPost(params: { language: string; slug: string }): Promise<PublicBlogPost | null> {\n const endpoint = new EndpointCreator({ endpoint: publicPostsEndpoint(), id: encodeURIComponent(params.slug) });\n endpoint.addAdditionalParam(\"language\", params.language);\n\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogPost, cache: \"minutes\" },\n endpoint: endpoint.generate(),\n language: params.language,\n });\n if (!res.ok) return null;\n\n const post = asArray<BlogPostInterface>(res.data)[0];\n return post ? toPublicBlogPost(post) : null;\n}\n\nexport async function fetchRelatedBlogPosts(params: { language: string; slug: string }): Promise<PublicBlogPost[]> {\n const endpoint = new EndpointCreator({\n endpoint: publicPostsEndpoint(),\n id: encodeURIComponent(params.slug),\n childEndpoint: BLOG_ACTION.related,\n });\n endpoint.addAdditionalParam(\"language\", params.language);\n\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogPost, cache: \"minutes\" },\n endpoint: endpoint.generate(),\n language: params.language,\n });\n if (!res.ok) return [];\n\n return asArray<BlogPostInterface>(res.data).map(toPublicBlogPost);\n}\n\nexport async function fetchPublicBlogCategories(params: { language: string }): Promise<PublicBlogCategory[]> {\n const endpoint = new EndpointCreator({ endpoint: `${BLOG_PUBLIC_PREFIX}/${Modules.BlogCategory.name}` });\n endpoint.addAdditionalParam(\"language\", params.language);\n\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogCategory, cache: \"minutes\" },\n endpoint: endpoint.generate(),\n language: params.language,\n });\n if (!res.ok) return [];\n\n return asArray<BlogCategoryInterface>(res.data).map(toPublicBlogCategory);\n}\n\nexport async function fetchBlogSettings(): Promise<{ listLayout: BlogListLayout }> {\n const fallback: { listLayout: BlogListLayout } = { listLayout: \"featured\" };\n\n // The settings are language-neutral; the language only fills the required\n // request header, so one fixed value keeps a single cache entry.\n const res = await ServerJsonApiGet({\n classKey: { ...Modules.BlogSettings, cache: \"minutes\" },\n endpoint: new EndpointCreator({ endpoint: `${BLOG_PUBLIC_PREFIX}/${Modules.BlogSettings.name}` }).generate(),\n language: \"en\",\n });\n if (!res.ok) return fallback;\n\n const settings = asArray<BlogSettingsInterface>(res.data)[0];\n if (!settings || !BLOG_LIST_LAYOUTS.includes(settings.listLayout)) return fallback;\n\n return { listLayout: settings.listLayout };\n}\n"],"mappings":"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","names":[]}
@@ -23,17 +23,17 @@ var _chunkYBZVWLPHjs = require('../../chunk-YBZVWLPH.js');
23
23
 
24
24
 
25
25
 
26
- var _chunk3NLAXVINjs = require('../../chunk-3NLAXVIN.js');
26
+ var _chunkLQ4DK4JFjs = require('../../chunk-LQ4DK4JF.js');
27
27
 
28
28
 
29
- var _chunkYNCQSWQWjs = require('../../chunk-YNCQSWQW.js');
29
+ var _chunkRL3PL3KVjs = require('../../chunk-RL3PL3KV.js');
30
30
  require('../../chunk-G4JR3SFV.js');
31
31
 
32
32
 
33
- var _chunkNFBOSPNJjs = require('../../chunk-NFBOSPNJ.js');
33
+ var _chunkHKZAESS6js = require('../../chunk-HKZAESS6.js');
34
+ require('../../chunk-GHE4VT2R.js');
34
35
  require('../../chunk-LXKSUWAV.js');
35
36
  require('../../chunk-JTPRJNT2.js');
36
- require('../../chunk-GHE4VT2R.js');
37
37
  require('../../chunk-3EPNHTMH.js');
38
38
 
39
39
 
@@ -44,7 +44,7 @@ var _react = require('react');
44
44
  var _jsxruntime = require('react/jsx-runtime');
45
45
  var HelpContext = _react.createContext.call(void 0, null);
46
46
  function HelpProvider({ children }) {
47
- const cfg = _chunkYNCQSWQWjs._getStaticHelpContent.call(void 0, );
47
+ const cfg = _chunkRL3PL3KVjs._getStaticHelpContent.call(void 0, );
48
48
  if (!cfg) {
49
49
  throw new Error(
50
50
  "Help content not configured \u2014 call configureJsonApi({ helpContent: {...} }) before importing help components."
@@ -76,29 +76,29 @@ var _lucidereact = require('lucide-react');
76
76
 
77
77
 
78
78
  function HelpAssistantSheet({ open, onOpenChange }) {
79
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.Sheet, { open, onOpenChange, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
80
- _chunk3NLAXVINjs.SheetContent,
79
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLQ4DK4JFjs.Sheet, { open, onOpenChange, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
80
+ _chunkLQ4DK4JFjs.SheetContent,
81
81
  {
82
82
  side: "end",
83
83
  className: "flex w-full flex-col data-[side=right]:sm:max-w-2xl data-[side=right]:lg:max-w-3xl data-[side=left]:sm:max-w-2xl data-[side=left]:lg:max-w-3xl",
84
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.AssistantProvider, { manageUrl: false, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HelpAssistantSheetBody, {}) })
84
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLQ4DK4JFjs.AssistantProvider, { manageUrl: false, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HelpAssistantSheetBody, {}) })
85
85
  }
86
86
  ) });
87
87
  }
88
88
  _chunk7QVYU63Ejs.__name.call(void 0, HelpAssistantSheet, "HelpAssistantSheet");
89
89
  function HelpAssistantSheetBody() {
90
90
  const t = _nextintl.useTranslations.call(void 0, );
91
- const ctx = _chunk3NLAXVINjs.useAssistantContext.call(void 0, );
91
+ const ctx = _chunkLQ4DK4JFjs.useAssistantContext.call(void 0, );
92
92
  const showThread = !!ctx.assistant || ctx.sending || ctx.messages.length > 0;
93
93
  const send = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (content) => ctx.sendMessage(content, { howToMode: true }), "send");
94
94
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
95
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk3NLAXVINjs.SheetHeader, { children: [
96
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.SheetTitle, { children: t("help.askAi.sheet.title") }),
97
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.SheetDescription, { children: t("help.askAi.sheet.subtitle") })
95
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkLQ4DK4JFjs.SheetHeader, { children: [
96
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLQ4DK4JFjs.SheetTitle, { children: t("help.askAi.sheet.title") }),
97
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLQ4DK4JFjs.SheetDescription, { children: t("help.askAi.sheet.subtitle") })
98
98
  ] }),
99
- !showThread ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.AssistantEmptyState, { onSend: send }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
99
+ !showThread ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLQ4DK4JFjs.AssistantEmptyState, { onSend: send }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
100
100
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
101
- _chunk3NLAXVINjs.AssistantThread,
101
+ _chunkLQ4DK4JFjs.AssistantThread,
102
102
  {
103
103
  messages: ctx.messages,
104
104
  sending: ctx.sending,
@@ -108,7 +108,7 @@ function HelpAssistantSheetBody() {
108
108
  onRetry: ctx.retrySend
109
109
  }
110
110
  ),
111
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.AssistantComposer, { onSend: send, disabled: ctx.sending })
111
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLQ4DK4JFjs.AssistantComposer, { onSend: send, disabled: ctx.sending })
112
112
  ] })
113
113
  ] });
114
114
  }
@@ -118,20 +118,20 @@ _chunk7QVYU63Ejs.__name.call(void 0, HelpAssistantSheetBody, "HelpAssistantSheet
118
118
 
119
119
  function HelpAskAi() {
120
120
  const t = _nextintl.useTranslations.call(void 0, );
121
- const { currentUser } = _chunk3NLAXVINjs.useCurrentUserContext.call(void 0, );
121
+ const { currentUser } = _chunkLQ4DK4JFjs.useCurrentUserContext.call(void 0, );
122
122
  const [open, setOpen] = _react.useState.call(void 0, false);
123
123
  const disabled = !currentUser;
124
124
  if (disabled) {
125
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk3NLAXVINjs.Tooltip, { children: [
126
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk3NLAXVINjs.TooltipTrigger, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.Button, { variant: "outline", size: "sm", disabled: true }), children: [
125
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkLQ4DK4JFjs.Tooltip, { children: [
126
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkLQ4DK4JFjs.TooltipTrigger, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLQ4DK4JFjs.Button, { variant: "outline", size: "sm", disabled: true }), children: [
127
127
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.SparklesIcon, { className: "h-4 w-4" }),
128
128
  t("help.askAi.button")
129
129
  ] }),
130
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.TooltipContent, { children: t("help.askAi.loginTooltip") })
130
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLQ4DK4JFjs.TooltipContent, { children: t("help.askAi.loginTooltip") })
131
131
  ] });
132
132
  }
133
133
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
134
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk3NLAXVINjs.Button, { variant: "outline", size: "sm", onClick: () => setOpen(true), children: [
134
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkLQ4DK4JFjs.Button, { variant: "outline", size: "sm", onClick: () => setOpen(true), children: [
135
135
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.SparklesIcon, { className: "h-4 w-4" }),
136
136
  t("help.askAi.button")
137
137
  ] }),
@@ -144,7 +144,7 @@ _chunk7QVYU63Ejs.__name.call(void 0, HelpAskAi, "HelpAskAi");
144
144
 
145
145
  function HelpHeader() {
146
146
  const t = _nextintl.useTranslations.call(void 0, );
147
- const { currentUser } = _chunk3NLAXVINjs.useCurrentUserContext.call(void 0, );
147
+ const { currentUser } = _chunkLQ4DK4JFjs.useCurrentUserContext.call(void 0, );
148
148
  const { brand } = useHelp();
149
149
  const logo = _optionalChain([brand, 'optionalAccess', _ => _.logo]);
150
150
  const label = _nullishCoalesce(_optionalChain([brand, 'optionalAccess', _2 => _2.label]), () => ( t("help.title")));
@@ -160,7 +160,7 @@ function HelpHeader() {
160
160
  ] }),
161
161
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2 max-md:shrink-0", children: [
162
162
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HelpAskAi, {}),
163
- currentUser ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _link2.default, { href: appHref, className: _chunk3NLAXVINjs.buttonVariants.call(void 0, { variant: "outline", size: "sm" }), children: t("help.header.openApp") }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _link2.default, { href: "/login", className: _chunk3NLAXVINjs.buttonVariants.call(void 0, { variant: "outline", size: "sm" }), children: t("help.header.login") })
163
+ currentUser ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _link2.default, { href: appHref, className: _chunkLQ4DK4JFjs.buttonVariants.call(void 0, { variant: "outline", size: "sm" }), children: t("help.header.openApp") }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _link2.default, { href: "/login", className: _chunkLQ4DK4JFjs.buttonVariants.call(void 0, { variant: "outline", size: "sm" }), children: t("help.header.login") })
164
164
  ] })
165
165
  ] });
166
166
  }
@@ -202,12 +202,12 @@ _chunk7QVYU63Ejs.__name.call(void 0, useHelpFilter, "useHelpFilter");
202
202
 
203
203
  function HelpSideNav() {
204
204
  const t = _nextintl.useTranslations.call(void 0, );
205
- const generateUrl = _chunk3NLAXVINjs.usePageUrlGenerator.call(void 0, );
205
+ const generateUrl = _chunkLQ4DK4JFjs.usePageUrlGenerator.call(void 0, );
206
206
  const pathname = _navigation.usePathname.call(void 0, );
207
207
  const [articles, setArticles] = _react.useState.call(void 0, []);
208
208
  _react.useEffect.call(void 0, () => {
209
209
  let active = true;
210
- _chunkNFBOSPNJjs.HowToService.findPublished().then((list) => active && setArticles(list)).catch(() => active && setArticles([]));
210
+ _chunkHKZAESS6js.HowToService.findPublished().then((list) => active && setArticles(list)).catch(() => active && setArticles([]));
211
211
  return () => {
212
212
  active = false;
213
213
  };
@@ -283,7 +283,7 @@ _chunk7QVYU63Ejs.__name.call(void 0, HelpSideNav, "HelpSideNav");
283
283
  function HelpArticleBody(props) {
284
284
  const t = _nextintl.useTranslations.call(void 0, );
285
285
  const format = _nextintl.useFormatter.call(void 0, );
286
- const generateUrl = _chunk3NLAXVINjs.usePageUrlGenerator.call(void 0, );
286
+ const generateUrl = _chunkLQ4DK4JFjs.usePageUrlGenerator.call(void 0, );
287
287
  const { howToType, title, summary, updatedAt, prev, next, children } = props;
288
288
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "article", { className: "prose dark:prose-invert max-w-none", children: [
289
289
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "nav", { className: "text-muted-foreground mb-2 text-xs", children: [
@@ -340,7 +340,7 @@ function HelpTOC({ headings }) {
340
340
  }, [headings]);
341
341
  if (headings.length === 0) return null;
342
342
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "nav", { "aria-label": t("help.toc.title"), className: "hidden lg:block", children: [
343
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.MicroLabel, { className: "mb-2", children: t("help.toc.title") }),
343
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLQ4DK4JFjs.MicroLabel, { className: "mb-2", children: t("help.toc.title") }),
344
344
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "ul", { className: "space-y-1 text-sm", children: headings.map((h) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "li", { style: { paddingInlineStart: `${(h.depth - 2) * 0.75}rem` }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
345
345
  "a",
346
346
  {
@@ -361,13 +361,13 @@ _chunk7QVYU63Ejs.__name.call(void 0, HelpTOC, "HelpTOC");
361
361
 
362
362
  function HelpHint({ contextKey }) {
363
363
  const t = _nextintl.useTranslations.call(void 0, );
364
- const generateUrl = _chunk3NLAXVINjs.usePageUrlGenerator.call(void 0, );
364
+ const generateUrl = _chunkLQ4DK4JFjs.usePageUrlGenerator.call(void 0, );
365
365
  const [open, setOpen] = _react.useState.call(void 0, false);
366
366
  const [picked, setPicked] = _react.useState.call(void 0, null);
367
367
  const [articles, setArticles] = _react.useState.call(void 0, []);
368
368
  _react.useEffect.call(void 0, () => {
369
369
  let active2 = true;
370
- _chunkNFBOSPNJjs.HowToService.findPublished().then((list) => active2 && setArticles(list)).catch(() => active2 && setArticles([]));
370
+ _chunkHKZAESS6js.HowToService.findPublished().then((list) => active2 && setArticles(list)).catch(() => active2 && setArticles([]));
371
371
  return () => {
372
372
  active2 = false;
373
373
  };
@@ -379,7 +379,7 @@ function HelpHint({ contextKey }) {
379
379
  if (matches.length === 0) return null;
380
380
  const active = _nullishCoalesce(picked, () => ( (matches.length === 1 ? matches[0] : null)));
381
381
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
382
- _chunk3NLAXVINjs.Sheet,
382
+ _chunkLQ4DK4JFjs.Sheet,
383
383
  {
384
384
  open,
385
385
  onOpenChange: (o) => {
@@ -387,11 +387,11 @@ function HelpHint({ contextKey }) {
387
387
  if (!o) setPicked(null);
388
388
  },
389
389
  children: [
390
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.SheetTrigger, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.Button, { variant: "ghost", size: "icon-sm", "aria-label": t("help.hint.trigger") }), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.HelpCircleIcon, { className: "h-4 w-4" }) }),
391
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk3NLAXVINjs.SheetContent, { side: "end", className: "w-full max-w-md sm:max-w-lg", children: [
392
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk3NLAXVINjs.SheetHeader, { children: [
393
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.SheetTitle, { children: active ? active.name : t("help.hint.pickArticle") }),
394
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.SheetDescription, { children: _nullishCoalesce(_optionalChain([active, 'optionalAccess', _4 => _4.summary]), () => ( "")) })
390
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLQ4DK4JFjs.SheetTrigger, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLQ4DK4JFjs.Button, { variant: "ghost", size: "icon-sm", "aria-label": t("help.hint.trigger") }), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.HelpCircleIcon, { className: "h-4 w-4" }) }),
391
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkLQ4DK4JFjs.SheetContent, { side: "end", className: "w-full max-w-md sm:max-w-lg", children: [
392
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkLQ4DK4JFjs.SheetHeader, { children: [
393
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLQ4DK4JFjs.SheetTitle, { children: active ? active.name : t("help.hint.pickArticle") }),
394
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLQ4DK4JFjs.SheetDescription, { children: _nullishCoalesce(_optionalChain([active, 'optionalAccess', _4 => _4.summary]), () => ( "")) })
395
395
  ] }),
396
396
  active ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mt-4 space-y-3", children: [
397
397
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-muted-foreground text-sm", children: active.summary }),
@@ -423,18 +423,18 @@ _chunk7QVYU63Ejs.__name.call(void 0, HelpHint, "HelpHint");
423
423
 
424
424
  function HelpSearchResultRow({ result, onSelect }) {
425
425
  const t = _nextintl.useTranslations.call(void 0, );
426
- const generateUrl = _chunk3NLAXVINjs.usePageUrlGenerator.call(void 0, );
426
+ const generateUrl = _chunkLQ4DK4JFjs.usePageUrlGenerator.call(void 0, );
427
427
  const [article, setArticle] = _react.useState.call(void 0, null);
428
428
  _react.useEffect.call(void 0, () => {
429
429
  let active = true;
430
- _chunkNFBOSPNJjs.HowToService.findOne({ id: result.id }).then((a) => active && setArticle(a)).catch(() => active && setArticle(null));
430
+ _chunkHKZAESS6js.HowToService.findOne({ id: result.id }).then((a) => active && setArticle(a)).catch(() => active && setArticle(null));
431
431
  return () => {
432
432
  active = false;
433
433
  };
434
434
  }, [result.id]);
435
435
  if (!article) {
436
436
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
437
- _chunk3NLAXVINjs.CommandItem,
437
+ _chunkLQ4DK4JFjs.CommandItem,
438
438
  {
439
439
  value: result.id,
440
440
  disabled: true,
@@ -443,7 +443,7 @@ function HelpSearchResultRow({ result, onSelect }) {
443
443
  }
444
444
  );
445
445
  }
446
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.CommandItem, { value: result.id, onSelect, className: "cursor-pointer p-0", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
446
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLQ4DK4JFjs.CommandItem, { value: result.id, onSelect, className: "cursor-pointer p-0", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
447
447
  _link2.default,
448
448
  {
449
449
  href: generateUrl({ page: `/help/${article.howToType}/${article.slug}` }),
@@ -23,17 +23,17 @@ import {
23
23
  useAssistantContext,
24
24
  useCurrentUserContext,
25
25
  usePageUrlGenerator
26
- } from "../../chunk-EUKTBOI2.mjs";
26
+ } from "../../chunk-SFYPXCK4.mjs";
27
27
  import {
28
28
  _getStaticHelpContent
29
- } from "../../chunk-QMYQRPQC.mjs";
29
+ } from "../../chunk-Y7RR57EW.mjs";
30
30
  import "../../chunk-PW42LRSL.mjs";
31
31
  import {
32
32
  HowToService
33
- } from "../../chunk-WC63PJSC.mjs";
33
+ } from "../../chunk-EYA2F6AN.mjs";
34
+ import "../../chunk-V5MI7RNB.mjs";
34
35
  import "../../chunk-AUXK7QSA.mjs";
35
36
  import "../../chunk-PI56A4DG.mjs";
36
- import "../../chunk-V5MI7RNB.mjs";
37
37
  import "../../chunk-VOXD3ZLY.mjs";
38
38
  import {
39
39
  __name
@@ -142,8 +142,6 @@ type TokenUsageAdminProviderProps = {
142
142
  initialTo?: string;
143
143
  /** Rows per ranked panel. Defaults to 10. */
144
144
  topN?: number;
145
- /** Route the breadcrumb links back to. */
146
- pageUrl?: string;
147
145
  };
148
146
  /**
149
147
  * Owns every filter the administrative token-usage page reads, fetches the five
@@ -154,7 +152,7 @@ type TokenUsageAdminProviderProps = {
154
152
  * `SharedContext`, and a descendant cannot inject nodes into an ancestor's
155
153
  * provider value. That is why the filter state lives at this level.
156
154
  */
157
- declare const TokenUsageAdminProvider: ({ children, initialCompanyId, initialFrom, initialTo, topN, pageUrl, }: TokenUsageAdminProviderProps) => React.JSX.Element;
155
+ declare const TokenUsageAdminProvider: ({ children, initialCompanyId, initialFrom, initialTo, topN, }: TokenUsageAdminProviderProps) => React.JSX.Element;
158
156
  declare const useTokenUsageAdmin: () => TokenUsageAdminContextType;
159
157
 
160
158
  /**