@nextsparkjs/core 0.1.0-beta.187 → 0.1.0-beta.189

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 (414) hide show
  1. package/dist/components/api/keys/ApiKeyDisplay.js +19 -19
  2. package/dist/components/api/keys/CreateApiKeyDialog.js +21 -21
  3. package/dist/components/app/layouts/PublicNavbar.d.ts.map +1 -1
  4. package/dist/components/app/layouts/PublicNavbar.js +34 -16
  5. package/dist/components/app/misc/ThemeToggle.d.ts.map +1 -1
  6. package/dist/components/app/misc/ThemeToggle.js +3 -4
  7. package/dist/components/auth/SessionCookieRefresher.d.ts +5 -0
  8. package/dist/components/auth/SessionCookieRefresher.d.ts.map +1 -1
  9. package/dist/components/auth/SessionCookieRefresher.js +7 -1
  10. package/dist/components/auth/forms/LoginForm.d.ts.map +1 -1
  11. package/dist/components/auth/forms/LoginForm.js +49 -12
  12. package/dist/components/auth/forms/SignupForm.d.ts.map +1 -1
  13. package/dist/components/auth/forms/SignupForm.js +4 -3
  14. package/dist/components/dashboard/block-editor/block-settings-panel.js +1 -1
  15. package/dist/components/dashboard/block-editor/floating-block-toolbar.js +1 -1
  16. package/dist/components/dashboard/block-editor/sortable-block.js +1 -1
  17. package/dist/components/dashboard/layouts/Sidebar.d.ts.map +1 -1
  18. package/dist/components/dashboard/layouts/Sidebar.js +8 -6
  19. package/dist/components/dashboard/layouts/TopNavbar.d.ts.map +1 -1
  20. package/dist/components/dashboard/layouts/TopNavbar.js +51 -54
  21. package/dist/components/dashboard/misc/NotificationsDropdown.d.ts.map +1 -1
  22. package/dist/components/dashboard/misc/NotificationsDropdown.js +17 -15
  23. package/dist/components/dashboard/misc/SearchDropdown.d.ts.map +1 -1
  24. package/dist/components/dashboard/misc/SearchDropdown.js +19 -22
  25. package/dist/components/dashboard/mobile/MobileBottomNav.js +1 -1
  26. package/dist/components/dashboard/mobile/MobileTopBar.d.ts +10 -1
  27. package/dist/components/dashboard/mobile/MobileTopBar.d.ts.map +1 -1
  28. package/dist/components/dashboard/mobile/MobileTopBar.js +4 -3
  29. package/dist/components/dashboard/navigation/DynamicNavigation.js +5 -5
  30. package/dist/components/devtools/BlockDetailViewer.js +1 -1
  31. package/dist/components/devtools/BlocksViewer.js +1 -1
  32. package/dist/components/entities/EntityChildManager.js +5 -5
  33. package/dist/components/entities/EntityDetailPage.d.ts.map +1 -1
  34. package/dist/components/entities/EntityDetailPage.js +16 -15
  35. package/dist/components/entities/EntityFieldRenderer.d.ts.map +1 -1
  36. package/dist/components/entities/EntityFieldRenderer.js +12 -7
  37. package/dist/components/entities/EntityPageHeader.js +5 -5
  38. package/dist/components/entities/ErrorBoundary.d.ts.map +1 -1
  39. package/dist/components/entities/ErrorBoundary.js +20 -21
  40. package/dist/components/entities/wrappers/EntityDetailWrapper.js +5 -5
  41. package/dist/components/entities/wrappers/EntityFormWrapper.js +2 -2
  42. package/dist/components/entities/wrappers/EntityListWrapper.js +3 -3
  43. package/dist/components/permissions/NoPermission.js +10 -10
  44. package/dist/components/public/pageBuilder/PageRenderer.d.ts.map +1 -1
  45. package/dist/components/public/pageBuilder/PageRenderer.js +2 -1
  46. package/dist/components/settings/SettingsPageSkeleton.js +4 -4
  47. package/dist/components/settings/layouts/SettingsSidebar.js +6 -6
  48. package/dist/components/shared/MultiSelectFilter.d.ts +3 -1
  49. package/dist/components/shared/MultiSelectFilter.d.ts.map +1 -1
  50. package/dist/components/shared/MultiSelectFilter.js +7 -3
  51. package/dist/components/shared/SearchInput.d.ts +2 -0
  52. package/dist/components/shared/SearchInput.d.ts.map +1 -1
  53. package/dist/components/shared/SearchInput.js +64 -6
  54. package/dist/components/ui/address-input.js +18 -18
  55. package/dist/components/ui/audio-upload.js +9 -9
  56. package/dist/components/ui/combobox.d.ts.map +1 -1
  57. package/dist/components/ui/combobox.js +4 -4
  58. package/dist/components/ui/country-select.d.ts.map +1 -1
  59. package/dist/components/ui/country-select.js +3 -3
  60. package/dist/components/ui/currency-select.d.ts.map +1 -1
  61. package/dist/components/ui/currency-select.js +3 -3
  62. package/dist/components/ui/dynamic-icon.d.ts.map +1 -1
  63. package/dist/components/ui/dynamic-icon.js +3 -2
  64. package/dist/components/ui/file-upload.js +7 -7
  65. package/dist/components/ui/image-upload.js +8 -8
  66. package/dist/components/ui/multi-select.d.ts +2 -1
  67. package/dist/components/ui/multi-select.d.ts.map +1 -1
  68. package/dist/components/ui/multi-select.js +4 -3
  69. package/dist/components/ui/phone-input.d.ts.map +1 -1
  70. package/dist/components/ui/phone-input.js +3 -3
  71. package/dist/components/ui/relation-display.js +1 -1
  72. package/dist/components/ui/simple-relation-select.d.ts +2 -1
  73. package/dist/components/ui/simple-relation-select.d.ts.map +1 -1
  74. package/dist/components/ui/simple-relation-select.js +7 -6
  75. package/dist/components/ui/tags-input.d.ts.map +1 -1
  76. package/dist/components/ui/tags-input.js +1 -1
  77. package/dist/components/ui/timezone-select.d.ts.map +1 -1
  78. package/dist/components/ui/timezone-select.js +3 -3
  79. package/dist/components/ui/user-display.js +4 -4
  80. package/dist/components/ui/user-select.d.ts.map +1 -1
  81. package/dist/components/ui/user-select.js +9 -9
  82. package/dist/components/ui/video-upload.js +9 -9
  83. package/dist/contexts/SubscriptionContext.d.ts.map +1 -1
  84. package/dist/contexts/SubscriptionContext.js +5 -1
  85. package/dist/contexts/TeamContext.d.ts.map +1 -1
  86. package/dist/contexts/TeamContext.js +83 -26
  87. package/dist/emails/otp-verification.d.ts.map +1 -1
  88. package/dist/emails/otp-verification.js +3 -2
  89. package/dist/hooks/useAccountPreferencesSync.d.ts +13 -0
  90. package/dist/hooks/useAccountPreferencesSync.d.ts.map +1 -0
  91. package/dist/hooks/useAccountPreferencesSync.js +95 -0
  92. package/dist/hooks/useAuth.d.ts +202 -15
  93. package/dist/hooks/useAuth.d.ts.map +1 -1
  94. package/dist/hooks/useAuth.js +49 -13
  95. package/dist/hooks/useEntityConfig.js +2 -2
  96. package/dist/hooks/useEntitySearch.js +10 -10
  97. package/dist/hooks/useNotifications.js +12 -12
  98. package/dist/hooks/usePrefetch.d.ts.map +1 -1
  99. package/dist/hooks/usePrefetch.js +6 -2
  100. package/dist/hooks/useSearch.js +15 -15
  101. package/dist/hooks/useSessionCookieRefresh.d.ts +18 -1
  102. package/dist/hooks/useSessionCookieRefresh.d.ts.map +1 -1
  103. package/dist/hooks/useSessionCookieRefresh.js +17 -4
  104. package/dist/hooks/useSessionHint.d.ts +12 -0
  105. package/dist/hooks/useSessionHint.d.ts.map +1 -0
  106. package/dist/hooks/useSessionHint.js +15 -0
  107. package/dist/hooks/useTranslationPreload.js +6 -6
  108. package/dist/i18n.d.ts +13 -0
  109. package/dist/i18n.d.ts.map +1 -1
  110. package/dist/i18n.js +2 -27
  111. package/dist/lib/actions/entity.actions.d.ts.map +1 -1
  112. package/dist/lib/actions/entity.actions.js +3 -2
  113. package/dist/lib/api/auth/dual-auth.d.ts +4 -1
  114. package/dist/lib/api/auth/dual-auth.d.ts.map +1 -1
  115. package/dist/lib/api/auth/dual-auth.js +5 -16
  116. package/dist/lib/api/entities.js +33 -33
  117. package/dist/lib/api/keys.d.ts +27 -27
  118. package/dist/lib/api/keys.js +27 -27
  119. package/dist/lib/auth/callback-url.d.ts +11 -0
  120. package/dist/lib/auth/callback-url.d.ts.map +1 -0
  121. package/dist/lib/auth/callback-url.js +14 -0
  122. package/dist/lib/auth/otp-config.d.ts +55 -0
  123. package/dist/lib/auth/otp-config.d.ts.map +1 -0
  124. package/dist/lib/auth/otp-config.js +48 -0
  125. package/dist/lib/auth/registration-helpers.d.ts.map +1 -1
  126. package/dist/lib/auth/registration-helpers.js +3 -1
  127. package/dist/lib/auth/session-hint.d.ts +31 -0
  128. package/dist/lib/auth/session-hint.d.ts.map +1 -0
  129. package/dist/lib/auth/session-hint.js +37 -0
  130. package/dist/lib/auth.d.ts.map +1 -1
  131. package/dist/lib/auth.js +6 -4
  132. package/dist/lib/blocks/loader.d.ts +3 -11
  133. package/dist/lib/blocks/loader.d.ts.map +1 -1
  134. package/dist/lib/blocks/loader.js +1 -9
  135. package/dist/lib/blocks/loader.server.d.ts +18 -0
  136. package/dist/lib/blocks/loader.server.d.ts.map +1 -0
  137. package/dist/lib/blocks/loader.server.js +11 -0
  138. package/dist/lib/blocks/sanitize-html.d.ts +31 -0
  139. package/dist/lib/blocks/sanitize-html.d.ts.map +1 -0
  140. package/dist/lib/blocks/sanitize-html.js +60 -0
  141. package/dist/lib/config/config-sync.d.ts +1 -0
  142. package/dist/lib/config/config-sync.d.ts.map +1 -1
  143. package/dist/lib/config/config-sync.js +4 -1
  144. package/dist/lib/config/types.d.ts +48 -0
  145. package/dist/lib/config/types.d.ts.map +1 -1
  146. package/dist/lib/email/types.d.ts +6 -0
  147. package/dist/lib/email/types.d.ts.map +1 -1
  148. package/dist/lib/entities/serialization.d.ts.map +1 -1
  149. package/dist/lib/entities/serialization.js +3 -6
  150. package/dist/lib/icons.d.ts +12 -0
  151. package/dist/lib/icons.d.ts.map +1 -0
  152. package/dist/lib/icons.js +30 -0
  153. package/dist/lib/locale.d.ts +25 -1
  154. package/dist/lib/locale.d.ts.map +1 -1
  155. package/dist/lib/locale.js +49 -35
  156. package/dist/lib/mcp/engine.js +1 -1
  157. package/dist/lib/mcp/errors.js +17 -17
  158. package/dist/lib/mcp/schema-builder.js +16 -16
  159. package/dist/lib/mcp/tool-generator.js +18 -18
  160. package/dist/lib/search-highlighting.d.ts +7 -0
  161. package/dist/lib/search-highlighting.d.ts.map +1 -1
  162. package/dist/lib/search-highlighting.js +6 -2
  163. package/dist/lib/selectors/core-selectors.d.ts +2 -0
  164. package/dist/lib/selectors/core-selectors.d.ts.map +1 -1
  165. package/dist/lib/selectors/domains/auth.selectors.d.ts +1 -0
  166. package/dist/lib/selectors/domains/auth.selectors.d.ts.map +1 -1
  167. package/dist/lib/selectors/domains/auth.selectors.js +1 -0
  168. package/dist/lib/selectors/domains/entities.selectors.d.ts +2 -0
  169. package/dist/lib/selectors/domains/entities.selectors.d.ts.map +1 -1
  170. package/dist/lib/selectors/domains/entities.selectors.js +2 -0
  171. package/dist/lib/selectors/selectors.d.ts +4 -0
  172. package/dist/lib/selectors/selectors.d.ts.map +1 -1
  173. package/dist/lib/services/block.service.js +1 -1
  174. package/dist/lib/teams/active-team-cookie.d.ts +24 -0
  175. package/dist/lib/teams/active-team-cookie.d.ts.map +1 -0
  176. package/dist/lib/teams/active-team-cookie.js +17 -0
  177. package/dist/lib/teams/dashboard-team.d.ts +20 -0
  178. package/dist/lib/teams/dashboard-team.d.ts.map +1 -0
  179. package/dist/lib/teams/dashboard-team.js +38 -0
  180. package/dist/lib/teams/schema.d.ts.map +1 -1
  181. package/dist/lib/teams/schema.js +1 -1
  182. package/dist/lib/template-resolver.d.ts.map +1 -1
  183. package/dist/lib/template-resolver.js +0 -1
  184. package/dist/lib/theme/get-default-theme-mode.d.ts +7 -4
  185. package/dist/lib/theme/get-default-theme-mode.d.ts.map +1 -1
  186. package/dist/lib/theme/get-default-theme-mode.js +2 -44
  187. package/dist/messages/de/auth.json +4 -2
  188. package/dist/messages/de/common.json +83 -3
  189. package/dist/messages/de/email.json +1 -1
  190. package/dist/messages/de/index.d.ts +87 -0
  191. package/dist/messages/de/index.d.ts.map +1 -1
  192. package/dist/messages/de/settings.json +5 -0
  193. package/dist/messages/en/auth.json +4 -2
  194. package/dist/messages/en/common.json +83 -3
  195. package/dist/messages/en/email.json +1 -1
  196. package/dist/messages/en/index.d.ts +86 -0
  197. package/dist/messages/en/index.d.ts.map +1 -1
  198. package/dist/messages/en/settings.json +4 -0
  199. package/dist/messages/es/auth.json +4 -2
  200. package/dist/messages/es/common.json +83 -3
  201. package/dist/messages/es/email.json +1 -1
  202. package/dist/messages/es/index.d.ts +86 -0
  203. package/dist/messages/es/index.d.ts.map +1 -1
  204. package/dist/messages/es/settings.json +4 -0
  205. package/dist/messages/fr/auth.json +4 -2
  206. package/dist/messages/fr/common.json +83 -3
  207. package/dist/messages/fr/email.json +1 -1
  208. package/dist/messages/fr/index.d.ts +87 -0
  209. package/dist/messages/fr/index.d.ts.map +1 -1
  210. package/dist/messages/fr/settings.json +5 -0
  211. package/dist/messages/it/auth.json +4 -2
  212. package/dist/messages/it/common.json +83 -3
  213. package/dist/messages/it/email.json +1 -1
  214. package/dist/messages/it/index.d.ts +87 -0
  215. package/dist/messages/it/index.d.ts.map +1 -1
  216. package/dist/messages/it/settings.json +5 -0
  217. package/dist/messages/pt/auth.json +4 -2
  218. package/dist/messages/pt/common.json +83 -3
  219. package/dist/messages/pt/email.json +1 -1
  220. package/dist/messages/pt/index.d.ts +87 -0
  221. package/dist/messages/pt/index.d.ts.map +1 -1
  222. package/dist/messages/pt/settings.json +5 -0
  223. package/dist/nextspark-registries.d.ts +54 -0
  224. package/dist/providers/DashboardProviders.d.ts +13 -10
  225. package/dist/providers/DashboardProviders.d.ts.map +1 -1
  226. package/dist/providers/DashboardProviders.js +7 -1
  227. package/dist/templates/app/(auth)/forgot-password/page.tsx +2 -2
  228. package/dist/templates/app/(auth)/reset-password/page.tsx +6 -6
  229. package/dist/templates/app/403/page.tsx +6 -6
  230. package/dist/templates/app/api/v1/teams/switch/route.ts +24 -5
  231. package/dist/templates/app/dashboard/(main)/[entity]/layout.tsx +9 -7
  232. package/dist/templates/app/dashboard/(main)/layout.tsx +4 -3
  233. package/dist/templates/app/dashboard/settings/api-keys/page.tsx +36 -34
  234. package/dist/templates/app/dashboard/settings/profile/page.tsx +7 -6
  235. package/dist/templates/app/dashboard/settings/security/page.tsx +5 -4
  236. package/dist/templates/app/layout.ppr.tsx +8 -8
  237. package/dist/templates/app/layout.tsx +12 -17
  238. package/dist/templates/blocks/cta-section/component.tsx +5 -2
  239. package/dist/templates/blocks/cta-section/config.ts +3 -2
  240. package/dist/templates/blocks/cta-section/fields.ts +2 -2
  241. package/dist/templates/blocks/cta-section/schema.ts +2 -2
  242. package/dist/templates/blocks/features-grid/component.tsx +10 -2
  243. package/dist/templates/blocks/features-grid/config.ts +3 -2
  244. package/dist/templates/blocks/features-grid/fields.ts +2 -2
  245. package/dist/templates/blocks/features-grid/schema.ts +2 -2
  246. package/dist/templates/blocks/hero/component.tsx +6 -3
  247. package/dist/templates/blocks/hero/config.ts +3 -2
  248. package/dist/templates/blocks/hero/fields.ts +2 -2
  249. package/dist/templates/blocks/hero/schema.ts +2 -2
  250. package/dist/templates/blocks/testimonials/component.tsx +6 -3
  251. package/dist/templates/blocks/testimonials/config.ts +3 -2
  252. package/dist/templates/blocks/testimonials/fields.ts +2 -2
  253. package/dist/templates/blocks/testimonials/schema.ts +2 -2
  254. package/dist/templates/blocks/text-content/component.tsx +7 -3
  255. package/dist/templates/blocks/text-content/config.ts +3 -2
  256. package/dist/templates/blocks/text-content/fields.ts +2 -2
  257. package/dist/templates/blocks/text-content/schema.ts +2 -2
  258. package/dist/templates/contents/themes/starter/blocks/cta-section/component.tsx +102 -0
  259. package/dist/templates/contents/themes/starter/blocks/cta-section/config.ts +11 -0
  260. package/dist/templates/contents/themes/starter/blocks/cta-section/fields.ts +89 -0
  261. package/dist/templates/contents/themes/starter/blocks/cta-section/index.ts +6 -0
  262. package/dist/templates/contents/themes/starter/blocks/cta-section/schema.ts +32 -0
  263. package/dist/templates/contents/themes/starter/blocks/cta-section/thumbnail.png +0 -0
  264. package/dist/templates/contents/themes/starter/blocks/features-grid/component.tsx +119 -0
  265. package/dist/templates/contents/themes/starter/blocks/features-grid/config.ts +11 -0
  266. package/dist/templates/contents/themes/starter/blocks/features-grid/fields.ts +97 -0
  267. package/dist/templates/contents/themes/starter/blocks/features-grid/index.ts +6 -0
  268. package/dist/templates/contents/themes/starter/blocks/features-grid/schema.ts +40 -0
  269. package/dist/templates/contents/themes/starter/blocks/features-grid/thumbnail.png +0 -0
  270. package/dist/templates/contents/themes/starter/blocks/hero/component.tsx +105 -0
  271. package/dist/templates/contents/themes/starter/blocks/hero/config.ts +11 -0
  272. package/dist/templates/contents/themes/starter/blocks/hero/fields.ts +60 -0
  273. package/dist/templates/contents/themes/starter/blocks/hero/index.ts +6 -0
  274. package/dist/templates/contents/themes/starter/blocks/hero/schema.ts +33 -0
  275. package/dist/templates/contents/themes/starter/blocks/hero/thumbnail.png +0 -0
  276. package/dist/templates/contents/themes/starter/blocks/testimonials/component.tsx +116 -0
  277. package/dist/templates/contents/themes/starter/blocks/testimonials/config.ts +11 -0
  278. package/dist/templates/contents/themes/starter/blocks/testimonials/fields.ts +105 -0
  279. package/dist/templates/contents/themes/starter/blocks/testimonials/index.ts +6 -0
  280. package/dist/templates/contents/themes/starter/blocks/testimonials/schema.ts +41 -0
  281. package/dist/templates/contents/themes/starter/blocks/testimonials/thumbnail.png +0 -0
  282. package/dist/templates/contents/themes/starter/blocks/text-content/component.tsx +100 -0
  283. package/dist/templates/contents/themes/starter/blocks/text-content/config.ts +11 -0
  284. package/dist/templates/contents/themes/starter/blocks/text-content/fields.ts +88 -0
  285. package/dist/templates/contents/themes/starter/blocks/text-content/index.ts +6 -0
  286. package/dist/templates/contents/themes/starter/blocks/text-content/schema.ts +30 -0
  287. package/dist/templates/contents/themes/starter/blocks/text-content/thumbnail.png +0 -0
  288. package/dist/templates/contents/themes/starter/config/app.config.ts +8 -0
  289. package/dist/templates/contents/themes/starter/entities/tasks/tasks.config.ts +7 -0
  290. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_utils/devtools/access.cy.ts +9 -1
  291. package/dist/templates/contents/themes/starter/tests/cypress/e2e/api/entities/tasks/TaskAPIController.js +2 -2
  292. package/dist/templates/contents/themes/starter/tests/cypress/e2e/uat/entities/tasks/tasks-crud.cy.ts +45 -38
  293. package/dist/templates/contents/themes/starter/tests/cypress/fixtures/entities.json +16 -0
  294. package/dist/templates/contents/themes/starter/tests/cypress/src/components/DevKeyringPOM.ts +3 -1
  295. package/dist/templates/contents/themes/starter/tests/cypress/src/core/BlockEditorBasePOM.ts +3 -3
  296. package/dist/templates/contents/themes/starter/tests/cypress/src/entities/PagesPOM.ts +137 -0
  297. package/dist/templates/contents/themes/starter/tests/cypress/src/entities/index.ts +2 -0
  298. package/dist/templates/contents/themes/starter/tests/cypress/src/index.ts +1 -0
  299. package/dist/templates/contents/themes/starter/tests/cypress/src/session-helpers.ts +42 -11
  300. package/dist/templates/contents/themes/starter/tests/cypress/support/commands.ts +29 -18
  301. package/dist/templates/features/blog/blocks/post-content/component.tsx +5 -1
  302. package/dist/templates/features/blog/blocks/post-content/schema.ts +1 -1
  303. package/dist/templates/features/pages/blocks/hero/component.tsx +3 -0
  304. package/dist/templates/features/pages/blocks/hero/schema.ts +1 -1
  305. package/dist/templates/proxy.ts +138 -53
  306. package/dist/types/blocks.d.ts.map +1 -1
  307. package/dist/types/blocks.js +1 -1
  308. package/dist/types/task.types.d.ts +1 -1
  309. package/dist/types/task.types.js +7 -7
  310. package/dist/utils/dev/TranslationDebugger.js +2 -2
  311. package/package.json +14 -5
  312. package/scripts/build/registry/__tests__/block-registry.test.mjs +73 -0
  313. package/scripts/build/registry/__tests__/icons-discovery.test.mjs +130 -0
  314. package/scripts/build/registry/__tests__/identifier.test.mjs +65 -0
  315. package/scripts/build/registry/__tests__/page-generator.test.mjs +430 -0
  316. package/scripts/build/registry/__tests__/scheduled-actions-registry.test.mjs +41 -0
  317. package/scripts/build/registry/__tests__/template-registry.test.mjs +89 -0
  318. package/scripts/build/registry/discovery/icons.mjs +275 -0
  319. package/scripts/build/registry/discovery/index.mjs +1 -0
  320. package/scripts/build/registry/generators/block-registry.mjs +203 -55
  321. package/scripts/build/registry/generators/feature-registry.mjs +9 -2
  322. package/scripts/build/registry/generators/icon-registry.mjs +56 -0
  323. package/scripts/build/registry/generators/identifier.mjs +28 -0
  324. package/scripts/build/registry/generators/index.mjs +1 -0
  325. package/scripts/build/registry/generators/plugin-registry.mjs +4 -3
  326. package/scripts/build/registry/generators/scheduled-actions-registry.mjs +4 -2
  327. package/scripts/build/registry/generators/template-registry.mjs +49 -41
  328. package/scripts/build/registry/generators/theme-registry.mjs +6 -7
  329. package/scripts/build/registry/post-build/page-generator.mjs +380 -59
  330. package/scripts/build/registry.mjs +9 -1
  331. package/templates/app/(auth)/forgot-password/page.tsx +2 -2
  332. package/templates/app/(auth)/reset-password/page.tsx +6 -6
  333. package/templates/app/403/page.tsx +6 -6
  334. package/templates/app/api/v1/teams/switch/route.ts +24 -5
  335. package/templates/app/dashboard/(main)/[entity]/layout.tsx +9 -7
  336. package/templates/app/dashboard/(main)/layout.tsx +4 -3
  337. package/templates/app/dashboard/settings/api-keys/page.tsx +36 -34
  338. package/templates/app/dashboard/settings/profile/page.tsx +7 -6
  339. package/templates/app/dashboard/settings/security/page.tsx +5 -4
  340. package/templates/app/layout.ppr.tsx +8 -8
  341. package/templates/app/layout.tsx +12 -17
  342. package/templates/blocks/cta-section/component.tsx +5 -2
  343. package/templates/blocks/cta-section/config.ts +3 -2
  344. package/templates/blocks/cta-section/fields.ts +2 -2
  345. package/templates/blocks/cta-section/schema.ts +2 -2
  346. package/templates/blocks/features-grid/component.tsx +10 -2
  347. package/templates/blocks/features-grid/config.ts +3 -2
  348. package/templates/blocks/features-grid/fields.ts +2 -2
  349. package/templates/blocks/features-grid/schema.ts +2 -2
  350. package/templates/blocks/hero/component.tsx +6 -3
  351. package/templates/blocks/hero/config.ts +3 -2
  352. package/templates/blocks/hero/fields.ts +2 -2
  353. package/templates/blocks/hero/schema.ts +2 -2
  354. package/templates/blocks/testimonials/component.tsx +6 -3
  355. package/templates/blocks/testimonials/config.ts +3 -2
  356. package/templates/blocks/testimonials/fields.ts +2 -2
  357. package/templates/blocks/testimonials/schema.ts +2 -2
  358. package/templates/blocks/text-content/component.tsx +7 -3
  359. package/templates/blocks/text-content/config.ts +3 -2
  360. package/templates/blocks/text-content/fields.ts +2 -2
  361. package/templates/blocks/text-content/schema.ts +2 -2
  362. package/templates/contents/themes/starter/blocks/cta-section/component.tsx +102 -0
  363. package/templates/contents/themes/starter/blocks/cta-section/config.ts +11 -0
  364. package/templates/contents/themes/starter/blocks/cta-section/fields.ts +89 -0
  365. package/templates/contents/themes/starter/blocks/cta-section/index.ts +6 -0
  366. package/templates/contents/themes/starter/blocks/cta-section/schema.ts +32 -0
  367. package/templates/contents/themes/starter/blocks/cta-section/thumbnail.png +0 -0
  368. package/templates/contents/themes/starter/blocks/features-grid/component.tsx +119 -0
  369. package/templates/contents/themes/starter/blocks/features-grid/config.ts +11 -0
  370. package/templates/contents/themes/starter/blocks/features-grid/fields.ts +97 -0
  371. package/templates/contents/themes/starter/blocks/features-grid/index.ts +6 -0
  372. package/templates/contents/themes/starter/blocks/features-grid/schema.ts +40 -0
  373. package/templates/contents/themes/starter/blocks/features-grid/thumbnail.png +0 -0
  374. package/templates/contents/themes/starter/blocks/hero/component.tsx +105 -0
  375. package/templates/contents/themes/starter/blocks/hero/config.ts +11 -0
  376. package/templates/contents/themes/starter/blocks/hero/fields.ts +60 -0
  377. package/templates/contents/themes/starter/blocks/hero/index.ts +6 -0
  378. package/templates/contents/themes/starter/blocks/hero/schema.ts +33 -0
  379. package/templates/contents/themes/starter/blocks/hero/thumbnail.png +0 -0
  380. package/templates/contents/themes/starter/blocks/testimonials/component.tsx +116 -0
  381. package/templates/contents/themes/starter/blocks/testimonials/config.ts +11 -0
  382. package/templates/contents/themes/starter/blocks/testimonials/fields.ts +105 -0
  383. package/templates/contents/themes/starter/blocks/testimonials/index.ts +6 -0
  384. package/templates/contents/themes/starter/blocks/testimonials/schema.ts +41 -0
  385. package/templates/contents/themes/starter/blocks/testimonials/thumbnail.png +0 -0
  386. package/templates/contents/themes/starter/blocks/text-content/component.tsx +100 -0
  387. package/templates/contents/themes/starter/blocks/text-content/config.ts +11 -0
  388. package/templates/contents/themes/starter/blocks/text-content/fields.ts +88 -0
  389. package/templates/contents/themes/starter/blocks/text-content/index.ts +6 -0
  390. package/templates/contents/themes/starter/blocks/text-content/schema.ts +30 -0
  391. package/templates/contents/themes/starter/blocks/text-content/thumbnail.png +0 -0
  392. package/templates/contents/themes/starter/config/app.config.ts +8 -0
  393. package/templates/contents/themes/starter/entities/tasks/tasks.config.ts +7 -0
  394. package/templates/contents/themes/starter/tests/cypress/e2e/_utils/devtools/access.cy.ts +9 -1
  395. package/templates/contents/themes/starter/tests/cypress/e2e/api/entities/tasks/TaskAPIController.js +2 -2
  396. package/templates/contents/themes/starter/tests/cypress/e2e/uat/entities/tasks/tasks-crud.cy.ts +45 -38
  397. package/templates/contents/themes/starter/tests/cypress/fixtures/entities.json +16 -0
  398. package/templates/contents/themes/starter/tests/cypress/src/components/DevKeyringPOM.ts +3 -1
  399. package/templates/contents/themes/starter/tests/cypress/src/core/BlockEditorBasePOM.ts +3 -3
  400. package/templates/contents/themes/starter/tests/cypress/src/entities/PagesPOM.ts +137 -0
  401. package/templates/contents/themes/starter/tests/cypress/src/entities/index.ts +2 -0
  402. package/templates/contents/themes/starter/tests/cypress/src/index.ts +1 -0
  403. package/templates/contents/themes/starter/tests/cypress/src/session-helpers.ts +42 -11
  404. package/templates/contents/themes/starter/tests/cypress/support/commands.ts +29 -18
  405. package/templates/features/blog/blocks/post-content/component.tsx +5 -1
  406. package/templates/features/blog/blocks/post-content/schema.ts +1 -1
  407. package/templates/features/pages/blocks/hero/component.tsx +3 -0
  408. package/templates/features/pages/blocks/hero/schema.ts +1 -1
  409. package/templates/proxy.ts +138 -53
  410. package/tests/jest/__mocks__/@nextsparkjs/registries/block-registry.client.ts +9 -0
  411. package/tests/jest/__mocks__/@nextsparkjs/registries/block-registry.lazy.ts +5 -0
  412. package/tests/jest/__mocks__/@nextsparkjs/registries/icon-registry.ts +42 -0
  413. package/tests/jest/__mocks__/next-intl-server.js +85 -5
  414. package/tests/jest/__mocks__/next-server.js +32 -0
@@ -17,8 +17,8 @@ function UserSelect({
17
17
  maxUsers,
18
18
  disabled = false,
19
19
  className,
20
- placeholder = "Seleccionar usuarios...",
21
- searchPlaceholder = "Buscar usuarios...",
20
+ placeholder = "Select users...",
21
+ searchPlaceholder = "Search users...",
22
22
  onSearch,
23
23
  onCreate,
24
24
  allowCreate = false,
@@ -229,15 +229,15 @@ function UserSelect({
229
229
  disabled: disabled || !!(maxUsers && resolvedValue.length >= maxUsers),
230
230
  children: isLoadingMembers ? /* @__PURE__ */ jsxs(Fragment, { children: [
231
231
  /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
232
- "Cargando..."
232
+ "Loading..."
233
233
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
234
234
  /* @__PURE__ */ jsx(User, { className: "mr-2 h-4 w-4" }),
235
- resolvedValue.length > 0 ? `${resolvedValue.length} usuario${resolvedValue.length > 1 ? "s" : ""} seleccionado${resolvedValue.length > 1 ? "s" : ""}` : placeholder
235
+ resolvedValue.length > 0 ? `${resolvedValue.length} user${resolvedValue.length > 1 ? "s" : ""} selected` : placeholder
236
236
  ] })
237
237
  }
238
238
  ) }),
239
239
  /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-md", children: [
240
- /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: "Seleccionar Usuarios" }) }),
240
+ /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: "Select Users" }) }),
241
241
  /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
242
242
  /* @__PURE__ */ jsxs("div", { className: "relative", children: [
243
243
  /* @__PURE__ */ jsx(Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
@@ -252,7 +252,7 @@ function UserSelect({
252
252
  )
253
253
  ] }),
254
254
  stableRoleFilter.length > 0 && /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground", children: [
255
- "Filtrando por roles: ",
255
+ "Filtering by roles: ",
256
256
  stableRoleFilter.join(", ")
257
257
  ] }),
258
258
  allowCreate && onCreate && /* @__PURE__ */ jsxs(
@@ -263,13 +263,13 @@ function UserSelect({
263
263
  onClick: onCreate,
264
264
  children: [
265
265
  /* @__PURE__ */ jsx(Plus, { className: "mr-2 h-4 w-4" }),
266
- "Invitar nuevo usuario"
266
+ "Invite new user"
267
267
  ]
268
268
  }
269
269
  ),
270
270
  /* @__PURE__ */ jsx("div", { className: "max-h-60 overflow-auto space-y-2", children: isSearching ? /* @__PURE__ */ jsxs("div", { className: "text-center text-muted-foreground py-4", children: [
271
271
  /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin inline mr-2" }),
272
- "Buscando usuarios..."
272
+ "Searching users..."
273
273
  ] }) : displayUsers.length > 0 ? displayUsers.map((user) => /* @__PURE__ */ jsx(
274
274
  Card,
275
275
  {
@@ -299,7 +299,7 @@ function UserSelect({
299
299
  ] }) })
300
300
  },
301
301
  user.id
302
- )) : /* @__PURE__ */ jsx("div", { className: "text-center text-muted-foreground py-4", children: searchQuery ? "No se encontraron usuarios" : "No hay usuarios disponibles" }) })
302
+ )) : /* @__PURE__ */ jsx("div", { className: "text-center text-muted-foreground py-4", children: searchQuery ? "No users found" : "No users available" }) })
303
303
  ] })
304
304
  ] })
305
305
  ] })
@@ -34,16 +34,16 @@ function VideoUpload({
34
34
  return new Promise((resolve) => {
35
35
  var _a;
36
36
  if (maxSize && file.size > maxSize * 1024 * 1024) {
37
- resolve(`El video es muy grande. M\xE1ximo ${maxSize}MB.`);
37
+ resolve(`Video is too large. Maximum ${maxSize}MB.`);
38
38
  return;
39
39
  }
40
40
  if (!file.type.startsWith("video/")) {
41
- resolve("El archivo debe ser un video.");
41
+ resolve("The file must be a video.");
42
42
  return;
43
43
  }
44
44
  const fileExtension = (_a = file.name.split(".").pop()) == null ? void 0 : _a.toLowerCase();
45
45
  if (fileExtension && !acceptedFormats.includes(fileExtension)) {
46
- resolve(`Formato no soportado. Formatos aceptados: ${acceptedFormats.join(", ")}`);
46
+ resolve(`Unsupported format. Accepted formats: ${acceptedFormats.join(", ")}`);
47
47
  return;
48
48
  }
49
49
  resolve(null);
@@ -76,7 +76,7 @@ function VideoUpload({
76
76
  const errors = [];
77
77
  for (const file of Array.from(files)) {
78
78
  if (value.length + newVideos.length >= maxVideos) {
79
- errors.push(`M\xE1ximo ${maxVideos} videos permitidos`);
79
+ errors.push(`Maximum ${maxVideos} videos allowed`);
80
80
  break;
81
81
  }
82
82
  const error = await validateVideo(file);
@@ -151,16 +151,16 @@ function VideoUpload({
151
151
  children: [
152
152
  /* @__PURE__ */ jsx(Video, { className: "mx-auto h-8 w-8 text-muted-foreground" }),
153
153
  /* @__PURE__ */ jsxs("p", { className: "mt-2 text-sm text-muted-foreground", children: [
154
- "Arrastra videos aqu\xED o",
154
+ "Drag videos here or",
155
155
  " ",
156
- /* @__PURE__ */ jsx("span", { className: "font-medium text-primary", children: "haz clic para seleccionar" })
156
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-primary", children: "click to select" })
157
157
  ] }),
158
158
  /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground mt-1", children: [
159
- maxVideos > 1 ? `Hasta ${maxVideos} videos` : "Un video",
160
- maxSize && `, m\xE1ximo ${maxSize}MB cada uno`
159
+ maxVideos > 1 ? `Up to ${maxVideos} videos` : "One video",
160
+ maxSize && `, maximum ${maxSize}MB each`
161
161
  ] }),
162
162
  /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
163
- "Formatos: ",
163
+ "Formats: ",
164
164
  acceptedFormats.join(", ")
165
165
  ] }),
166
166
  /* @__PURE__ */ jsx(
@@ -1 +1 @@
1
- {"version":3,"file":"SubscriptionContext.d.ts","sourceRoot":"","sources":["../../src/contexts/SubscriptionContext.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA6B,SAAS,EAAW,MAAM,OAAO,CAAA;AAGrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAG3D,UAAU,SAAS;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAE9B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAGrC,IAAI,EAAE,oBAAoB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAA;IACzC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,MAAM,EAAE,oBAAoB,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAA;IAC7C,UAAU,EAAE,OAAO,CAAA;IACnB,QAAQ,EAAE,OAAO,CAAA;IAGjB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;CAClC;AAED,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,oBAAoB,GAAG,IAAI,CAAA;IACzC,IAAI,EAAE,oBAAoB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAA;IACzC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,MAAM,EAAE,oBAAoB,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAA;IAC7C,UAAU,EAAE,OAAO,CAAA;IACnB,QAAQ,EAAE,OAAO,CAAA;IACjB,SAAS,EAAE,OAAO,CAAA;IAClB,UAAU,EAAE,OAAO,CAAA;IACnB,SAAS,EAAE,OAAO,CAAA;IAClB,oFAAoF;IACpF,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;IACnB,OAAO,EAAE,MAAM,IAAI,CAAA;IAEnB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAEjC,eAAe,EAAE,eAAe,CAAA;CACjC;AAID,wBAAgB,oBAAoB,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,2CAmGzE;AAED,wBAAgB,sBAAsB,6BAMrC"}
1
+ {"version":3,"file":"SubscriptionContext.d.ts","sourceRoot":"","sources":["../../src/contexts/SubscriptionContext.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA6B,SAAS,EAAW,MAAM,OAAO,CAAA;AAGrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAI3D,UAAU,SAAS;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAE9B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAGrC,IAAI,EAAE,oBAAoB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAA;IACzC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,MAAM,EAAE,oBAAoB,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAA;IAC7C,UAAU,EAAE,OAAO,CAAA;IACnB,QAAQ,EAAE,OAAO,CAAA;IAGjB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;CAClC;AAED,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,oBAAoB,GAAG,IAAI,CAAA;IACzC,IAAI,EAAE,oBAAoB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAA;IACzC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,MAAM,EAAE,oBAAoB,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAA;IAC7C,UAAU,EAAE,OAAO,CAAA;IACnB,QAAQ,EAAE,OAAO,CAAA;IACjB,SAAS,EAAE,OAAO,CAAA;IAClB,UAAU,EAAE,OAAO,CAAA;IACnB,SAAS,EAAE,OAAO,CAAA;IAClB,oFAAoF;IACpF,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;IACnB,OAAO,EAAE,MAAM,IAAI,CAAA;IAEnB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAEjC,eAAe,EAAE,eAAe,CAAA;CACjC;AAID,wBAAgB,oBAAoB,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,2CAwGzE;AAED,wBAAgB,sBAAsB,6BAMrC"}
@@ -4,6 +4,7 @@ import { createContext, useContext, useMemo } from "react";
4
4
  import { useQuery } from "@tanstack/react-query";
5
5
  import { useTeam } from "../hooks/useTeam.js";
6
6
  import { BILLING_REGISTRY } from "@nextsparkjs/registries/billing-registry";
7
+ import { ApiError } from "../lib/api/api-error.js";
7
8
  const SubscriptionContext = createContext(void 0);
8
9
  function SubscriptionProvider({ children }) {
9
10
  var _a;
@@ -22,12 +23,15 @@ function SubscriptionProvider({ children }) {
22
23
  const response = await fetch(`/api/v1/teams/${team.id}/subscription`);
23
24
  if (!response.ok) {
24
25
  if (response.status === 404) return null;
25
- throw new Error("Failed to fetch subscription");
26
+ throw new ApiError("Failed to fetch subscription", { status: response.status });
26
27
  }
27
28
  const data = await response.json();
28
29
  return ((_a2 = data.data) == null ? void 0 : _a2.subscription) ?? data.data;
29
30
  },
30
31
  enabled: !!team && BILLING_REGISTRY.plans.length > 0,
32
+ // A 4xx, such as the 403 a role without billing access gets, comes back the
33
+ // same on every attempt, so only other failures are retried.
34
+ retry: (failureCount, error2) => !(error2 instanceof ApiError && error2.status !== void 0 && error2.status >= 400 && error2.status < 500) && failureCount < 3,
31
35
  staleTime: 5 * 60 * 1e3,
32
36
  // 5 minutes
33
37
  refetchOnWindowFocus: false
@@ -1 +1 @@
1
- {"version":3,"file":"TeamContext.d.ts","sourceRoot":"","sources":["../../src/contexts/TeamContext.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAwE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGvG,OAAO,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAM7D,UAAU,gBAAgB;IACxB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,kBAAkB,EAAE,CAAA;IAC/B,SAAS,EAAE,OAAO,CAAA;IAClB,WAAW,EAAE,OAAO,CAAA;IACpB,wBAAwB,EAAE,OAAO,CAAA;IACjC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7C,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAClC;AAKD,eAAO,MAAM,eAAe,yBAA0B,CAAA;AAGtD,wBAAsB,cAAc,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAwBpE;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,2CAqOjE;AAED,wBAAgB,cAAc,qBAM7B;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,GAAG,SAAS,CAErE"}
1
+ {"version":3,"file":"TeamContext.d.ts","sourceRoot":"","sources":["../../src/contexts/TeamContext.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAwE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGvG,OAAO,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAM7D,UAAU,gBAAgB;IACxB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,kBAAkB,EAAE,CAAA;IAC/B,SAAS,EAAE,OAAO,CAAA;IAClB,WAAW,EAAE,OAAO,CAAA;IACpB,wBAAwB,EAAE,OAAO,CAAA;IACjC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7C,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAClC;AAKD,eAAO,MAAM,eAAe,yBAA0B,CAAA;AAuGtD,wBAAsB,cAAc,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAkCpE;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,2CA+OjE;AAED,wBAAgB,cAAc,qBAM7B;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,GAAG,SAAS,CAErE"}
@@ -9,13 +9,69 @@ import { APP_CONFIG_MERGED } from "../lib/config/config-sync.js";
9
9
  import { canUserCreateTeam } from "../lib/teams/helpers.js";
10
10
  const TeamContext = createContext(void 0);
11
11
  const TEAMS_QUERY_KEY = ["user-teams"];
12
+ const activeTeamCookieWrites = /* @__PURE__ */ new WeakMap();
13
+ const activeTeamCookieRequests = /* @__PURE__ */ new WeakMap();
14
+ const ACTIVE_TEAM_COOKIE_RETRIES = 3;
15
+ const ACTIVE_TEAM_REQUEST_TIMEOUT_MS = 1e4;
16
+ function postActiveTeam(teamId) {
17
+ const controller = new AbortController();
18
+ const timeout = setTimeout(() => controller.abort(), ACTIVE_TEAM_REQUEST_TIMEOUT_MS);
19
+ return fetch("/api/v1/teams/switch", {
20
+ method: "POST",
21
+ headers: { "Content-Type": "application/json" },
22
+ body: JSON.stringify({ teamId }),
23
+ signal: controller.signal
24
+ }).then((response) => response.ok, (error) => {
25
+ console.error("Failed to sync team cookie:", error);
26
+ return false;
27
+ }).finally(() => clearTimeout(timeout));
28
+ }
29
+ function writeActiveTeamCookie(queryClient, sessionKey, teamId) {
30
+ const key = `${sessionKey}:${teamId}`;
31
+ const previous = activeTeamCookieWrites.get(queryClient);
32
+ if ((previous == null ? void 0 : previous.key) === key && !previous.failed) return previous.result;
33
+ clearTimeout(previous == null ? void 0 : previous.retryTimer);
34
+ const write = { key, failed: false, result: Promise.resolve(false) };
35
+ const isCurrent = () => activeTeamCookieWrites.get(queryClient) === write;
36
+ const attempt = (retry) => {
37
+ const request = (activeTeamCookieRequests.get(queryClient) ?? Promise.resolve()).then(() => isCurrent() ? postActiveTeam(teamId) : false);
38
+ activeTeamCookieRequests.set(queryClient, request);
39
+ return request.then((ok) => {
40
+ if (ok || !isCurrent()) return ok;
41
+ if (retry >= ACTIVE_TEAM_COOKIE_RETRIES) {
42
+ write.failed = true;
43
+ return false;
44
+ }
45
+ return new Promise((resolve) => {
46
+ write.retryTimer = setTimeout(() => resolve(attempt(retry + 1)), 1e3 * (retry + 1));
47
+ });
48
+ });
49
+ };
50
+ activeTeamCookieWrites.set(queryClient, write);
51
+ write.result = attempt(0);
52
+ return write.result;
53
+ }
54
+ function forgetActiveTeamCookieWrite(queryClient) {
55
+ var _a;
56
+ clearTimeout((_a = activeTeamCookieWrites.get(queryClient)) == null ? void 0 : _a.retryTimer);
57
+ activeTeamCookieWrites.delete(queryClient);
58
+ }
59
+ const MAX_TEAM_PAGES = 50;
12
60
  async function fetchUserTeams() {
13
- const response = await fetch("/api/v1/teams");
14
- const data = await response.json();
15
- if (!response.ok || !data.data) {
16
- throw new Error("Failed to fetch teams");
61
+ var _a;
62
+ const rows = [];
63
+ for (let page = 1; page <= MAX_TEAM_PAGES; page++) {
64
+ const response = await fetch(page === 1 ? "/api/v1/teams" : `/api/v1/teams?page=${page}`);
65
+ const data = await response.json();
66
+ if (!response.ok || !data.data) {
67
+ throw new Error("Failed to fetch teams");
68
+ }
69
+ rows.push(...data.data);
70
+ if (!((_a = data.info) == null ? void 0 : _a.hasNextPage) || data.data.length === 0) break;
17
71
  }
18
- return data.data.map((t) => ({
72
+ const seen = /* @__PURE__ */ new Set();
73
+ const uniqueRows = rows.filter((t) => !seen.has(t.id) && Boolean(seen.add(t.id)));
74
+ return uniqueRows.map((t) => ({
19
75
  team: {
20
76
  id: t.id,
21
77
  name: t.name,
@@ -32,7 +88,9 @@ async function fetchUserTeams() {
32
88
  }));
33
89
  }
34
90
  function TeamProvider({ children }) {
35
- const { user, isLoading: authLoading } = useAuth();
91
+ var _a;
92
+ const { user, session, isLoading: authLoading } = useAuth();
93
+ const sessionKey = ((_a = session == null ? void 0 : session.session) == null ? void 0 : _a.id) ?? (user == null ? void 0 : user.id) ?? "";
36
94
  const router = useRouter();
37
95
  const queryClient = useQueryClient();
38
96
  const [currentTeam, setCurrentTeam] = useState(null);
@@ -45,7 +103,9 @@ function TeamProvider({ children }) {
45
103
  isLoading: teamsLoading,
46
104
  refetch: refetchTeams
47
105
  } = useQuery({
48
- queryKey: TEAMS_QUERY_KEY,
106
+ // Per user: the root layout's query client outlives a sign-out that happens
107
+ // while no TeamProvider is mounted, and one user's teams must not reach the next.
108
+ queryKey: [...TEAMS_QUERY_KEY, (user == null ? void 0 : user.id) ?? null],
49
109
  queryFn: fetchUserTeams,
50
110
  enabled: !!user && !authLoading,
51
111
  staleTime: 1e3 * 60 * 5,
@@ -69,6 +129,9 @@ function TeamProvider({ children }) {
69
129
  }, [userTeams, user]);
70
130
  useEffect(() => {
71
131
  if (!user) return;
132
+ const syncCookie = (teamId) => {
133
+ if (typeof window !== "undefined") void writeActiveTeamCookie(queryClient, sessionKey, teamId);
134
+ };
72
135
  if (!teamsLoading && userTeams.length === 0) {
73
136
  if (currentTeam) {
74
137
  setCurrentTeam(null);
@@ -79,7 +142,10 @@ function TeamProvider({ children }) {
79
142
  return;
80
143
  }
81
144
  if (!userTeams.length) return;
82
- if (currentTeam && userTeams.some((t) => t.team.id === currentTeam.id)) return;
145
+ if (currentTeam && userTeams.some((t) => t.team.id === currentTeam.id)) {
146
+ syncCookie(currentTeam.id);
147
+ return;
148
+ }
83
149
  const storedTeamId = typeof window !== "undefined" ? localStorage.getItem("activeTeamId") : null;
84
150
  const storedTeam = storedTeamId ? userTeams.find((t) => t.team.id === storedTeamId) : null;
85
151
  const defaultTeam = storedTeam ? void 0 : [...userTeams].sort(
@@ -91,27 +157,24 @@ function TeamProvider({ children }) {
91
157
  if (typeof window !== "undefined") {
92
158
  localStorage.setItem("activeTeamId", activeTeam.team.id);
93
159
  }
94
- if (typeof window !== "undefined") {
95
- fetch("/api/v1/teams/switch", {
96
- method: "POST",
97
- headers: { "Content-Type": "application/json" },
98
- body: JSON.stringify({ teamId: activeTeam.team.id })
99
- }).catch((err) => console.error("Failed to sync team cookie:", err));
100
- }
160
+ syncCookie(activeTeam.team.id);
101
161
  }
102
- }, [user, userTeams, currentTeam, teamsLoading]);
162
+ }, [user, userTeams, currentTeam, teamsLoading, queryClient, sessionKey]);
103
163
  useEffect(() => {
104
164
  if (!user && !authLoading) {
105
165
  setCurrentTeam(null);
106
166
  if (typeof window !== "undefined") {
107
167
  localStorage.removeItem("activeTeamId");
108
168
  }
169
+ forgetActiveTeamCookieWrite(queryClient);
109
170
  queryClient.clear();
110
171
  }
111
172
  }, [user, authLoading, queryClient]);
112
- const handleSwitchComplete = useCallback(() => {
173
+ const handleSwitchComplete = useCallback(async () => {
174
+ var _a2;
113
175
  setSwitchModalOpen(false);
114
176
  setIsSwitching(false);
177
+ await ((_a2 = activeTeamCookieWrites.get(queryClient)) == null ? void 0 : _a2.result);
115
178
  queryClient.clear();
116
179
  if (typeof window !== "undefined") {
117
180
  window.dispatchEvent(new CustomEvent("team-switched", { detail: { teamId: targetTeam == null ? void 0 : targetTeam.id } }));
@@ -136,16 +199,10 @@ function TeamProvider({ children }) {
136
199
  if (typeof window !== "undefined") {
137
200
  localStorage.setItem("activeTeamId", teamId);
138
201
  }
139
- try {
140
- await fetch("/api/v1/teams/switch", {
141
- method: "POST",
142
- headers: { "Content-Type": "application/json" },
143
- body: JSON.stringify({ teamId })
144
- });
145
- } catch (error) {
146
- console.error("Failed to update team context on server:", error);
202
+ if (!await writeActiveTeamCookie(queryClient, sessionKey, teamId)) {
203
+ console.error("Failed to update team context on server");
147
204
  }
148
- }, [userTeams, currentTeam]);
205
+ }, [userTeams, currentTeam, queryClient, sessionKey]);
149
206
  const refreshTeams = useCallback(async () => {
150
207
  await queryClient.invalidateQueries({ queryKey: TEAMS_QUERY_KEY });
151
208
  await refetchTeams();
@@ -1 +1 @@
1
- {"version":3,"file":"otp-verification.d.ts","sourceRoot":"","sources":["../../src/emails/otp-verification.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAKjF,wBAA8B,eAAe,CAC3C,IAAI,EAAE,wBAAwB,EAC9B,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,CAAC,CAmEvB"}
1
+ {"version":3,"file":"otp-verification.d.ts","sourceRoot":"","sources":["../../src/emails/otp-verification.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAKjF,wBAA8B,eAAe,CAC3C,IAAI,EAAE,wBAAwB,EAC9B,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,CAAC,CAsEvB"}
@@ -1,10 +1,11 @@
1
1
  import { getTranslations } from "next-intl/server";
2
+ import { DEFAULT_OTP_CONFIG } from "../lib/auth/otp-config.js";
2
3
  const APP_NAME_FALLBACK = process.env.NEXT_PUBLIC_APP_NAME || "Your App";
3
- const OTP_EXPIRES_MINUTES = 5;
4
4
  async function otpVerification(data, locale) {
5
5
  const t = await getTranslations({ locale, namespace: "email.otpVerification" });
6
6
  const appName = data.appName || APP_NAME_FALLBACK;
7
7
  const year = (/* @__PURE__ */ new Date()).getFullYear();
8
+ const expiresInMinutes = Math.floor((data.expiresIn ?? DEFAULT_OTP_CONFIG.expiresIn) / 60);
8
9
  return {
9
10
  subject: t("subject", { otp: data.otp, appName }),
10
11
  html: `
@@ -41,7 +42,7 @@ async function otpVerification(data, locale) {
41
42
  </div>
42
43
 
43
44
  <p style="color: #999999; font-size: 14px; line-height: 1.6; margin: 0;">
44
- ${t("expiresNotice", { minutes: OTP_EXPIRES_MINUTES })}<br>
45
+ ${t("expiresNotice", { minutes: expiresInMinutes })}<br>
45
46
  ${t("ignoreNotice")}
46
47
  </p>
47
48
  </td>
@@ -0,0 +1,13 @@
1
+ import type { SessionRefreshContext, SessionRefreshResult } from './useSessionCookieRefresh';
2
+ /**
3
+ * What to do with each session SessionCookieRefresher reads. Rendering takes
4
+ * the locale and the theme from the request and configuration alone, so the
5
+ * account's own choices are applied here:
6
+ *
7
+ * - No session: forget the session hint, so public pages stop asking for one.
8
+ * - A user: keep the hint; make the locale cookie name the account's language,
9
+ * refreshing the page when it was rendered in another one; and, in a browser
10
+ * where the visitor never chose a theme, apply the one saved to the account.
11
+ */
12
+ export declare function useAccountPreferencesSync(): (result: SessionRefreshResult, session?: SessionRefreshContext) => void;
13
+ //# sourceMappingURL=useAccountPreferencesSync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAccountPreferencesSync.d.ts","sourceRoot":"","sources":["../../src/hooks/useAccountPreferencesSync.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAoE5F;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,aAIX,oBAAoB,YAAY,qBAAqB,UA4ClF"}
@@ -0,0 +1,95 @@
1
+ "use client";
2
+ import { useCallback } from "react";
3
+ import { useRouter } from "next/navigation";
4
+ import { useTheme } from "next-themes";
5
+ import { I18N_CONFIG } from "../lib/config/index.js";
6
+ import { setUserLocaleClient } from "../lib/locale-client.js";
7
+ import { setSessionHint } from "../lib/auth/session-hint.js";
8
+ const THEME_STORAGE_KEY = "theme";
9
+ const THEME_MODES = ["light", "dark", "system"];
10
+ const ACCOUNT_THEME_CHECKED_KEY = "nextspark.account_theme_checked";
11
+ function readCookie(name) {
12
+ var _a;
13
+ const prefix = `${name}=`;
14
+ return (_a = document.cookie.split(";").map((part) => part.trim()).find((part) => part.startsWith(prefix))) == null ? void 0 : _a.slice(prefix.length);
15
+ }
16
+ function hasStoredTheme() {
17
+ try {
18
+ return localStorage.getItem(THEME_STORAGE_KEY) !== null;
19
+ } catch {
20
+ return true;
21
+ }
22
+ }
23
+ function claimAccountThemeCheck(userId) {
24
+ try {
25
+ if (sessionStorage.getItem(ACCOUNT_THEME_CHECKED_KEY) === userId) return false;
26
+ sessionStorage.setItem(ACCOUNT_THEME_CHECKED_KEY, userId);
27
+ return true;
28
+ } catch {
29
+ return false;
30
+ }
31
+ }
32
+ const LOCALE_REFRESHED_KEY = "nextspark.locale_refreshed";
33
+ function claimLocaleRefresh(language) {
34
+ try {
35
+ if (sessionStorage.getItem(LOCALE_REFRESHED_KEY) === language) return false;
36
+ sessionStorage.setItem(LOCALE_REFRESHED_KEY, language);
37
+ return true;
38
+ } catch {
39
+ return true;
40
+ }
41
+ }
42
+ function releaseLocaleRefresh() {
43
+ try {
44
+ sessionStorage.removeItem(LOCALE_REFRESHED_KEY);
45
+ } catch {
46
+ }
47
+ }
48
+ function releaseAccountThemeCheck(userId) {
49
+ try {
50
+ if (sessionStorage.getItem(ACCOUNT_THEME_CHECKED_KEY) === userId) sessionStorage.removeItem(ACCOUNT_THEME_CHECKED_KEY);
51
+ } catch {
52
+ }
53
+ }
54
+ function useAccountPreferencesSync() {
55
+ const router = useRouter();
56
+ const { setTheme, forcedTheme } = useTheme();
57
+ return useCallback((result, session) => {
58
+ var _a;
59
+ if (!result || result.error) return;
60
+ const user = (_a = result.data) == null ? void 0 : _a.user;
61
+ if (!user) {
62
+ setSessionHint(false);
63
+ return;
64
+ }
65
+ setSessionHint(true);
66
+ const language = user.language;
67
+ const localeDetected = I18N_CONFIG.supportedLocales.length > 1 && I18N_CONFIG.localeDetection !== false;
68
+ if (localeDetected && typeof language === "string" && I18N_CONFIG.supportedLocales.includes(language)) {
69
+ if (readCookie(I18N_CONFIG.cookie.name) !== language) setUserLocaleClient(language);
70
+ if (document.documentElement.lang === language) {
71
+ releaseLocaleRefresh();
72
+ } else if (readCookie(I18N_CONFIG.cookie.name) === language && claimLocaleRefresh(language)) {
73
+ router.refresh();
74
+ }
75
+ }
76
+ const userId = typeof user.id === "string" ? user.id : "signed-in";
77
+ if (!forcedTheme && !hasStoredTheme() && claimAccountThemeCheck(userId)) {
78
+ fetch("/api/user/profile?includeMeta=true").then((response) => {
79
+ if (!response.ok) throw new Error(`Profile request failed with status ${response.status}`);
80
+ return response.json();
81
+ }).then((profile) => {
82
+ var _a2, _b;
83
+ if (session && !session.isCurrent()) {
84
+ releaseAccountThemeCheck(userId);
85
+ return;
86
+ }
87
+ const theme = (_b = (_a2 = profile == null ? void 0 : profile.meta) == null ? void 0 : _a2.uiPreferences) == null ? void 0 : _b.theme;
88
+ if (THEME_MODES.includes(theme)) setTheme(theme);
89
+ }).catch(() => releaseAccountThemeCheck(userId));
90
+ }
91
+ }, [router, setTheme, forcedTheme]);
92
+ }
93
+ export {
94
+ useAccountPreferencesSync
95
+ };