create-nextblock 0.12.8 → 0.12.11

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 (293) hide show
  1. package/docker-template/.dockerignore +23 -23
  2. package/docker-template/.env.docker.example +69 -69
  3. package/docker-template/docker/db/init/99-jwt.sql +6 -6
  4. package/docker-template/docker/db/init/99-roles.sql +25 -25
  5. package/docker-template/docker/kong/kong.yml +112 -112
  6. package/docker-template/scripts/docker-setup.mjs +310 -310
  7. package/libs/db/tsconfig.lib.json +3 -3
  8. package/libs/editor/tsconfig.lib.json +3 -3
  9. package/libs/ui/tsconfig.lib.json +3 -3
  10. package/libs/utils/tsconfig.json +3 -3
  11. package/package.json +1 -1
  12. package/project.json +19 -19
  13. package/templates/nextblock-template/.browserslistrc +11 -11
  14. package/templates/nextblock-template/.dockerignore +23 -23
  15. package/templates/nextblock-template/README.md +34 -34
  16. package/templates/nextblock-template/app/(auth-pages)/layout.tsx +9 -9
  17. package/templates/nextblock-template/app/(auth-pages)/post-sign-in/page.tsx +27 -27
  18. package/templates/nextblock-template/app/(auth-pages)/sign-up/SignUpForm.tsx +141 -141
  19. package/templates/nextblock-template/app/(auth-pages)/sign-up/page.tsx +46 -46
  20. package/templates/nextblock-template/app/(auth-pages)/two-factor/actions.ts +91 -91
  21. package/templates/nextblock-template/app/(auth-pages)/two-factor/components/TwoFactorForm.tsx +123 -123
  22. package/templates/nextblock-template/app/(auth-pages)/two-factor/page.tsx +51 -51
  23. package/templates/nextblock-template/app/ToasterProvider.tsx +17 -17
  24. package/templates/nextblock-template/app/[slug]/pageClientActions.ts +7 -7
  25. package/templates/nextblock-template/app/actions/consent.ts +57 -57
  26. package/templates/nextblock-template/app/actions/interactions.test.ts +301 -301
  27. package/templates/nextblock-template/app/actions/interactions.ts +373 -373
  28. package/templates/nextblock-template/app/actions/postActions.ts +146 -146
  29. package/templates/nextblock-template/app/actions/twoFactorEmail.ts +22 -22
  30. package/templates/nextblock-template/app/api/ai/cortex/build-widget/route.ts +153 -153
  31. package/templates/nextblock-template/app/api/ai/generate-blocks/route.ts +96 -96
  32. package/templates/nextblock-template/app/api/ai/global-agent/route.ts +964 -964
  33. package/templates/nextblock-template/app/api/brand/email-logo/route.ts +48 -48
  34. package/templates/nextblock-template/app/api/cms/check-updates/route.ts +44 -44
  35. package/templates/nextblock-template/app/api/cms/full-backup/export/route.ts +33 -33
  36. package/templates/nextblock-template/app/api/cms/full-backup/restore/route.ts +63 -63
  37. package/templates/nextblock-template/app/api/cron/reset-sandbox/route.ts +3490 -3490
  38. package/templates/nextblock-template/app/api/cron/reset-sandbox/sandboxResetSql.ts +5597 -5597
  39. package/templates/nextblock-template/app/api/cron/sync-currencies/route.ts +39 -39
  40. package/templates/nextblock-template/app/api/custom-blocks/db-relations/route.ts +92 -92
  41. package/templates/nextblock-template/app/api/custom-blocks/editor-definitions/route.ts +43 -43
  42. package/templates/nextblock-template/app/api/media/library/route.ts +69 -69
  43. package/templates/nextblock-template/app/api/media/r2-presigned/route.ts +53 -53
  44. package/templates/nextblock-template/app/api/media/record/route.ts +160 -160
  45. package/templates/nextblock-template/app/api/search/route.ts +43 -43
  46. package/templates/nextblock-template/app/article/[slug]/PostClientContent.tsx +441 -441
  47. package/templates/nextblock-template/app/auth/callback/route.ts +31 -31
  48. package/templates/nextblock-template/app/cart/page.tsx +7 -7
  49. package/templates/nextblock-template/app/cms/blocks/components/CustomBlockEditorPreview.tsx +160 -160
  50. package/templates/nextblock-template/app/cms/blocks/components/MediaLibraryModal.tsx +149 -149
  51. package/templates/nextblock-template/app/cms/blocks/editors/DynamicCustomBlockEditor.tsx +167 -167
  52. package/templates/nextblock-template/app/cms/blocks/editors/ImageBlockEditor.tsx +29 -29
  53. package/templates/nextblock-template/app/cms/blocks/editors/TextBlockEditor.tsx +90 -90
  54. package/templates/nextblock-template/app/cms/components/ConnectGitHubButton.tsx +122 -122
  55. package/templates/nextblock-template/app/cms/components/CortexAiPageContext.tsx +58 -58
  56. package/templates/nextblock-template/app/cms/components/FeatureImageField.tsx +244 -244
  57. package/templates/nextblock-template/app/cms/components/FeedbackModal.tsx +36 -36
  58. package/templates/nextblock-template/app/cms/components/SystemAlertsBanner.tsx +112 -112
  59. package/templates/nextblock-template/app/cms/components/TwoFactorReminderBanner.tsx +45 -45
  60. package/templates/nextblock-template/app/cms/components/github-connect-actions.ts +102 -102
  61. package/templates/nextblock-template/app/cms/components/system-alerts-actions.ts +31 -31
  62. package/templates/nextblock-template/app/cms/custom-blocks/[id]/edit/page.tsx +66 -66
  63. package/templates/nextblock-template/app/cms/custom-blocks/actions.ts +519 -519
  64. package/templates/nextblock-template/app/cms/custom-blocks/components/BlockComposer.tsx +1522 -1522
  65. package/templates/nextblock-template/app/cms/custom-blocks/components/BlocksLibraryTransferControls.tsx +256 -256
  66. package/templates/nextblock-template/app/cms/custom-blocks/components/DBRelationSelect.tsx +384 -384
  67. package/templates/nextblock-template/app/cms/custom-blocks/components/ImageR2Picker.tsx +221 -221
  68. package/templates/nextblock-template/app/cms/custom-blocks/new/page.tsx +12 -12
  69. package/templates/nextblock-template/app/cms/custom-blocks/page.tsx +438 -438
  70. package/templates/nextblock-template/app/cms/dashboard/actions.ts +228 -228
  71. package/templates/nextblock-template/app/cms/dashboard/components/DashboardOnboarding.tsx +130 -130
  72. package/templates/nextblock-template/app/cms/import-export/ContentTransferControls.tsx +431 -391
  73. package/templates/nextblock-template/app/cms/import-export/actions.ts +226 -226
  74. package/templates/nextblock-template/app/cms/interactions/InteractionsModerationClient.tsx +408 -408
  75. package/templates/nextblock-template/app/cms/interactions/page.tsx +51 -51
  76. package/templates/nextblock-template/app/cms/layout.tsx +73 -73
  77. package/templates/nextblock-template/app/cms/media/components/FolderNavigator.tsx +273 -273
  78. package/templates/nextblock-template/app/cms/media/components/FolderTree.tsx +122 -122
  79. package/templates/nextblock-template/app/cms/media/components/MediaEditForm.tsx +26 -26
  80. package/templates/nextblock-template/app/cms/media/components/MediaGridClient.tsx +69 -69
  81. package/templates/nextblock-template/app/cms/media/components/MediaPickerDialog.tsx +149 -149
  82. package/templates/nextblock-template/app/cms/media/components/MediaUploadForm.tsx +101 -101
  83. package/templates/nextblock-template/app/cms/navigation/components/NavigationMenuDnd.tsx +3 -3
  84. package/templates/nextblock-template/app/cms/pages/page.tsx +18 -17
  85. package/templates/nextblock-template/app/cms/posts/page.tsx +19 -18
  86. package/templates/nextblock-template/app/cms/products/attributes/page.tsx +12 -12
  87. package/templates/nextblock-template/app/cms/products/categories/page.tsx +12 -12
  88. package/templates/nextblock-template/app/cms/products/inventory/page.tsx +13 -13
  89. package/templates/nextblock-template/app/cms/products/new/page.tsx +135 -135
  90. package/templates/nextblock-template/app/cms/products/page.tsx +39 -27
  91. package/templates/nextblock-template/app/cms/products/productFormData.ts +133 -133
  92. package/templates/nextblock-template/app/cms/products/settings/page.tsx +5 -5
  93. package/templates/nextblock-template/app/cms/promotions/PromotionsWorkspace.tsx +456 -456
  94. package/templates/nextblock-template/app/cms/promotions/actions.ts +115 -115
  95. package/templates/nextblock-template/app/cms/promotions/page.tsx +31 -31
  96. package/templates/nextblock-template/app/cms/revisions/service.ts +19 -19
  97. package/templates/nextblock-template/app/cms/revisions/utils.ts +132 -132
  98. package/templates/nextblock-template/app/cms/settings/backup-restore/BackupRestoreWorkspace.tsx +1004 -1004
  99. package/templates/nextblock-template/app/cms/settings/backup-restore/page.tsx +29 -29
  100. package/templates/nextblock-template/app/cms/settings/bot-protection/actions.ts +93 -93
  101. package/templates/nextblock-template/app/cms/settings/bot-protection/components/BotProtectionForm.tsx +129 -129
  102. package/templates/nextblock-template/app/cms/settings/bot-protection/page.tsx +24 -24
  103. package/templates/nextblock-template/app/cms/settings/cortex-ai/SandboxCortexAiSettingsClient.tsx +497 -497
  104. package/templates/nextblock-template/app/cms/settings/cortex-ai/StoredCortexAiSettingsClient.tsx +410 -410
  105. package/templates/nextblock-template/app/cms/settings/cortex-ai/actions.ts +246 -246
  106. package/templates/nextblock-template/app/cms/settings/cortex-ai/page.tsx +80 -80
  107. package/templates/nextblock-template/app/cms/settings/currencies/actions.ts +331 -331
  108. package/templates/nextblock-template/app/cms/settings/currencies/page.tsx +494 -494
  109. package/templates/nextblock-template/app/cms/settings/email/actions.ts +64 -64
  110. package/templates/nextblock-template/app/cms/settings/email/components/EmailForm.tsx +181 -181
  111. package/templates/nextblock-template/app/cms/settings/email/page.tsx +28 -28
  112. package/templates/nextblock-template/app/cms/settings/extra-translations/ExtraTranslationsWorkspace.tsx +767 -767
  113. package/templates/nextblock-template/app/cms/settings/extra-translations/page.tsx +93 -93
  114. package/templates/nextblock-template/app/cms/settings/google-analytics/actions.ts +60 -60
  115. package/templates/nextblock-template/app/cms/settings/google-analytics/components/GoogleAnalyticsForm.tsx +129 -129
  116. package/templates/nextblock-template/app/cms/settings/google-analytics/page.tsx +26 -26
  117. package/templates/nextblock-template/app/cms/settings/languages/actions.ts +16 -16
  118. package/templates/nextblock-template/app/cms/settings/logos/[id]/edit/page.tsx +7 -7
  119. package/templates/nextblock-template/app/cms/settings/logos/components/BrandingSettingsForm.tsx +339 -339
  120. package/templates/nextblock-template/app/cms/settings/logos/components/DeleteLogoButton.tsx +21 -21
  121. package/templates/nextblock-template/app/cms/settings/logos/components/LogoForm.tsx +20 -20
  122. package/templates/nextblock-template/app/cms/settings/logos/components/SetActiveLogoButton.tsx +42 -42
  123. package/templates/nextblock-template/app/cms/settings/logos/components/SiteSeoSettingsForm.tsx +133 -133
  124. package/templates/nextblock-template/app/cms/settings/logos/new/page.tsx +8 -8
  125. package/templates/nextblock-template/app/cms/settings/packages/package-card.tsx +122 -122
  126. package/templates/nextblock-template/app/cms/settings/privacy/actions.ts +52 -52
  127. package/templates/nextblock-template/app/cms/settings/privacy/components/PrivacyForm.tsx +148 -148
  128. package/templates/nextblock-template/app/cms/settings/privacy/page.tsx +27 -27
  129. package/templates/nextblock-template/app/cms/settings/registration/actions.ts +44 -44
  130. package/templates/nextblock-template/app/cms/settings/registration/components/RegistrationForm.tsx +65 -65
  131. package/templates/nextblock-template/app/cms/settings/registration/page.tsx +27 -27
  132. package/templates/nextblock-template/app/cms/settings/security/actions.ts +284 -284
  133. package/templates/nextblock-template/app/cms/settings/security/components/SecurityPanel.tsx +522 -522
  134. package/templates/nextblock-template/app/cms/settings/security/page.tsx +33 -33
  135. package/templates/nextblock-template/app/cms/settings/taxes/page.tsx +21 -21
  136. package/templates/nextblock-template/app/cms/shipping/page.tsx +20 -20
  137. package/templates/nextblock-template/app/cms/users/actions.ts +222 -222
  138. package/templates/nextblock-template/app/cms/users/components/DeleteUserButton.tsx +12 -12
  139. package/templates/nextblock-template/app/cms/users/components/UserForm.tsx +44 -44
  140. package/templates/nextblock-template/app/lib/site-settings.ts +105 -105
  141. package/templates/nextblock-template/app/lib/sitemap-utils.ts +253 -253
  142. package/templates/nextblock-template/app/profile/ProfileAccountSidebar.tsx +73 -73
  143. package/templates/nextblock-template/app/profile/ProfilePageHeader.tsx +16 -16
  144. package/templates/nextblock-template/app/profile/ProfilePageMissingState.tsx +9 -9
  145. package/templates/nextblock-template/app/profile/account-data.ts +37 -37
  146. package/templates/nextblock-template/app/profile/account-links.ts +22 -22
  147. package/templates/nextblock-template/app/profile/account-types.ts +11 -11
  148. package/templates/nextblock-template/app/profile/orders/CustomerOrdersPageClient.tsx +124 -124
  149. package/templates/nextblock-template/app/profile/orders/[id]/CustomerOrderDetailPageClient.tsx +79 -79
  150. package/templates/nextblock-template/app/profile/orders/[id]/page.tsx +32 -32
  151. package/templates/nextblock-template/app/profile/orders/page.tsx +19 -19
  152. package/templates/nextblock-template/app/profile/page.tsx +42 -42
  153. package/templates/nextblock-template/app/profile/password/PasswordSettingsPageClient.tsx +128 -128
  154. package/templates/nextblock-template/app/profile/password/actions.ts +59 -59
  155. package/templates/nextblock-template/app/profile/password/page.tsx +27 -27
  156. package/templates/nextblock-template/app/setup/SetupWizard.tsx +678 -678
  157. package/templates/nextblock-template/app/setup/layout.tsx +13 -13
  158. package/templates/nextblock-template/app/setup/page.tsx +111 -111
  159. package/templates/nextblock-template/app/sitemap.ts +130 -130
  160. package/templates/nextblock-template/components/CartDrawerLoader.tsx +7 -7
  161. package/templates/nextblock-template/components/DeferredCartDrawer.tsx +23 -23
  162. package/templates/nextblock-template/components/DeferredGoogleAnalytics.tsx +70 -70
  163. package/templates/nextblock-template/components/DeferredGoogleTagManager.tsx +70 -70
  164. package/templates/nextblock-template/components/DeferredSpeedInsights.tsx +69 -69
  165. package/templates/nextblock-template/components/FeatureImageHero.tsx +47 -47
  166. package/templates/nextblock-template/components/FooterNavigation.tsx +32 -32
  167. package/templates/nextblock-template/components/GitHubLoginButton.tsx +15 -15
  168. package/templates/nextblock-template/components/HtmlScriptExecutor.tsx +47 -47
  169. package/templates/nextblock-template/components/LanguageSwitcher.tsx +2 -2
  170. package/templates/nextblock-template/components/PostCommentsSection.tsx +369 -369
  171. package/templates/nextblock-template/components/ProductReviewsSection.tsx +419 -419
  172. package/templates/nextblock-template/components/PublicEnvBootstrap.tsx +30 -30
  173. package/templates/nextblock-template/components/ResponsiveNav.tsx +14 -14
  174. package/templates/nextblock-template/components/auth/AuthBotProtection.tsx +182 -182
  175. package/templates/nextblock-template/components/blocks/PostCardSkeleton.tsx +12 -12
  176. package/templates/nextblock-template/components/blocks/PostsGridBlock.tsx +12 -12
  177. package/templates/nextblock-template/components/blocks/ecommerceRendererLoaders.ts +23 -23
  178. package/templates/nextblock-template/components/blocks/renderers/FormBlockRenderer.tsx +249 -249
  179. package/templates/nextblock-template/components/blocks/types.ts +7 -7
  180. package/templates/nextblock-template/components/env-var-warning.tsx +3 -3
  181. package/templates/nextblock-template/components/form-message.tsx +32 -32
  182. package/templates/nextblock-template/components/privacy/ConsentBanner.tsx +170 -170
  183. package/templates/nextblock-template/components/privacy/ConsentGatedAnalytics.tsx +70 -70
  184. package/templates/nextblock-template/components/renderers/CachedDynamicLayoutEngine.tsx +28 -28
  185. package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.test.tsx +166 -166
  186. package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.tsx +464 -464
  187. package/templates/nextblock-template/components/submit-button.tsx +23 -23
  188. package/templates/nextblock-template/components/theme-switcher.tsx +8 -8
  189. package/templates/nextblock-template/components/visual-editing/DeferredVisualEditing.tsx +21 -21
  190. package/templates/nextblock-template/context/AuthContext.tsx +23 -23
  191. package/templates/nextblock-template/context/LanguageContext.tsx +16 -16
  192. package/templates/nextblock-template/context/language-rest-client.ts +32 -32
  193. package/templates/nextblock-template/docker/db/init/99-jwt.sql +6 -6
  194. package/templates/nextblock-template/docker/db/init/99-roles.sql +25 -25
  195. package/templates/nextblock-template/docker/kong/kong.yml +112 -112
  196. package/templates/nextblock-template/docs/01-PROJECT-OVERVIEW.md +94 -94
  197. package/templates/nextblock-template/docs/02-ECOMMERCE-CAPABILITIES.md +364 -364
  198. package/templates/nextblock-template/docs/03-CMS-AND-EDITOR.md +202 -202
  199. package/templates/nextblock-template/docs/04-DATABASE-AND-AUTH.md +246 -246
  200. package/templates/nextblock-template/docs/06-CLI-AND-SCAFFOLDING.md +176 -176
  201. package/templates/nextblock-template/docs/07-BLOCK-SDK-AND-EXTENSIBILITY.md +146 -146
  202. package/templates/nextblock-template/docs/08-NEXTBLOCK-CORTEX-AI-ARCHITECTURE.md +1319 -1319
  203. package/templates/nextblock-template/docs/10-CUSTOM-BLOCKS.md +222 -222
  204. package/templates/nextblock-template/docs/11-SELF-HOSTED-DOCKER.md +173 -173
  205. package/templates/nextblock-template/docs/12-VERCEL-DEPLOYMENT.md +170 -170
  206. package/templates/nextblock-template/docs/13-STAYING-UP-TO-DATE.md +151 -151
  207. package/templates/nextblock-template/docs/README.md +39 -39
  208. package/templates/nextblock-template/docs/TECHNICAL_SPECIFICATION.md +12505 -12505
  209. package/templates/nextblock-template/hooks/use-hotkeys.ts +21 -21
  210. package/templates/nextblock-template/hooks/useGlobalSearch.ts +101 -101
  211. package/templates/nextblock-template/index.d.ts +7 -7
  212. package/templates/nextblock-template/lib/app-secrets.ts +39 -39
  213. package/templates/nextblock-template/lib/auth/cookies.ts +47 -47
  214. package/templates/nextblock-template/lib/auth/crypto.ts +45 -45
  215. package/templates/nextblock-template/lib/auth/trustedDevices.ts +92 -92
  216. package/templates/nextblock-template/lib/auth/twoFactor.ts +208 -208
  217. package/templates/nextblock-template/lib/auth-redirects.ts +46 -46
  218. package/templates/nextblock-template/lib/blocks/README.md +13 -13
  219. package/templates/nextblock-template/lib/blocks/blockRegistry.ts +6 -6
  220. package/templates/nextblock-template/lib/blocks/blockTypes.ts +18 -18
  221. package/templates/nextblock-template/lib/botProtection/verify.ts +134 -134
  222. package/templates/nextblock-template/lib/cms-transfer/csv.test.ts +100 -77
  223. package/templates/nextblock-template/lib/cms-transfer/csv.ts +403 -399
  224. package/templates/nextblock-template/lib/cms-transfer/server.ts +2243 -2243
  225. package/templates/nextblock-template/lib/cms-transfer/types.ts +145 -145
  226. package/templates/nextblock-template/lib/config/email-settings.ts +217 -217
  227. package/templates/nextblock-template/lib/custom-block-definitions.ts +87 -87
  228. package/templates/nextblock-template/lib/custom-block-r2-upload-shared.ts +178 -178
  229. package/templates/nextblock-template/lib/custom-block-r2-upload.test.ts +140 -140
  230. package/templates/nextblock-template/lib/custom-block-r2-upload.ts +88 -88
  231. package/templates/nextblock-template/lib/custom-block-relation-registry.ts +256 -256
  232. package/templates/nextblock-template/lib/custom-block-relations.test.ts +227 -227
  233. package/templates/nextblock-template/lib/custom-block-relations.ts +279 -279
  234. package/templates/nextblock-template/lib/custom-block-safelist.ts +14 -14
  235. package/templates/nextblock-template/lib/editor/dynamic-extension-core.test.ts +172 -172
  236. package/templates/nextblock-template/lib/editor/dynamic-extension-core.ts +213 -213
  237. package/templates/nextblock-template/lib/editor/dynamic-extension-loader.ts +22 -22
  238. package/templates/nextblock-template/lib/editor/dynamic-extensions.tsx +193 -193
  239. package/templates/nextblock-template/lib/email/branding-format.test.ts +133 -133
  240. package/templates/nextblock-template/lib/email/branding-format.ts +123 -123
  241. package/templates/nextblock-template/lib/email/branding.ts +76 -76
  242. package/templates/nextblock-template/lib/full-backup/manifest.test.ts +121 -121
  243. package/templates/nextblock-template/lib/full-backup/manifest.ts +206 -206
  244. package/templates/nextblock-template/lib/full-backup/server.ts +743 -743
  245. package/templates/nextblock-template/lib/logos/active-logo.ts +53 -53
  246. package/templates/nextblock-template/lib/media/resolveMediaUrl.ts +54 -54
  247. package/templates/nextblock-template/lib/onboarding/actions.ts +31 -31
  248. package/templates/nextblock-template/lib/onboarding/status.ts +222 -222
  249. package/templates/nextblock-template/lib/posts/readTime.ts +60 -60
  250. package/templates/nextblock-template/lib/privacy/consent-client.ts +57 -57
  251. package/templates/nextblock-template/lib/privacy/contact-emails.ts +64 -64
  252. package/templates/nextblock-template/lib/privacy/settings.ts +115 -115
  253. package/templates/nextblock-template/lib/privacy/types.ts +69 -69
  254. package/templates/nextblock-template/lib/promotions/server.test.ts +74 -74
  255. package/templates/nextblock-template/lib/promotions/server.ts +741 -741
  256. package/templates/nextblock-template/lib/resolve-block-relations.test.ts +142 -142
  257. package/templates/nextblock-template/lib/resolve-block-relations.ts +255 -255
  258. package/templates/nextblock-template/lib/search/server.ts +585 -585
  259. package/templates/nextblock-template/lib/search/types.ts +27 -27
  260. package/templates/nextblock-template/lib/setup/actions.ts +460 -460
  261. package/templates/nextblock-template/lib/setup/env-status.ts +125 -125
  262. package/templates/nextblock-template/lib/setup/env-write.ts +111 -111
  263. package/templates/nextblock-template/lib/setup/migrations-bundle.ts +37 -37
  264. package/templates/nextblock-template/lib/setup/provisioning.ts +59 -59
  265. package/templates/nextblock-template/lib/setup/schema-apply.ts +408 -408
  266. package/templates/nextblock-template/lib/setup/system-config.ts +105 -105
  267. package/templates/nextblock-template/lib/setup/types.ts +18 -18
  268. package/templates/nextblock-template/lib/site-url.ts +48 -48
  269. package/templates/nextblock-template/lib/storage/provider.ts +66 -66
  270. package/templates/nextblock-template/lib/storage/supabase-storage.ts +103 -103
  271. package/templates/nextblock-template/lib/updates/check-upstream.ts +441 -441
  272. package/templates/nextblock-template/lib/updates/github-device.ts +206 -206
  273. package/templates/nextblock-template/lib/updates/repo-identity.ts +56 -56
  274. package/templates/nextblock-template/next.config.js +6 -0
  275. package/templates/nextblock-template/package.json +1 -1
  276. package/templates/nextblock-template/postcss.config.js +6 -6
  277. package/templates/nextblock-template/scripts/backup.js +115 -115
  278. package/templates/nextblock-template/scripts/docker-setup.mjs +310 -310
  279. package/templates/nextblock-template/scripts/restore.js +385 -385
  280. package/templates/nextblock-template/scripts/verify-cortex-ai-build-widget.tsx +98 -98
  281. package/templates/nextblock-template/scripts/verify-cortex-ai-generate-blocks.ts +62 -62
  282. package/templates/nextblock-template/scripts/verify-cortex-ai-global-tools.ts +537 -537
  283. package/templates/nextblock-template/scripts/verify-cortex-ai-routing.ts +58 -58
  284. package/templates/nextblock-template/scripts/verify-custom-block-definitions.ts +188 -188
  285. package/templates/nextblock-template/scripts/verify-dynamic-custom-block-extensions.ts +123 -123
  286. package/templates/nextblock-template/scripts/verify-dynamic-layout-engine.tsx +133 -133
  287. package/templates/nextblock-template/scripts/verify-milestone-2-custom-blocks.ts +65 -65
  288. package/templates/nextblock-template/tailwind.config.js +25 -25
  289. package/templates/nextblock-template/tools/build-migrate.mjs +209 -209
  290. package/templates/nextblock-template/tools/configure-supabase-auth.js +282 -282
  291. package/templates/nextblock-template/types/jsdom.d.ts +6 -6
  292. package/tsconfig.base.json +3 -3
  293. package/templates/nextblock-template/tsconfig.tsbuildinfo +0 -1
@@ -1,301 +1,301 @@
1
- import { beforeEach, describe, expect, it, vi } from "vitest";
2
-
3
- const cacheMocks = vi.hoisted(() => ({
4
- revalidatePath: vi.fn(),
5
- }));
6
-
7
- const dbServerMocks = vi.hoisted(() => ({
8
- createClient: vi.fn(),
9
- getServiceRoleSupabaseClient: vi.fn(),
10
- getProfileWithRoleServerSide: vi.fn(),
11
- }));
12
-
13
- const headersMocks = vi.hoisted(() => {
14
- const get = vi.fn();
15
- const set = vi.fn();
16
- return {
17
- cookies: vi.fn().mockResolvedValue({ get, set }),
18
- };
19
- });
20
-
21
- vi.mock("next/cache", () => cacheMocks);
22
- vi.mock("next/headers", () => headersMocks);
23
- vi.mock("@nextblock-cms/db/server", () => dbServerMocks);
24
- vi.mock("server-only", () => ({}));
25
-
26
- import {
27
- submitInteraction,
28
- toggleReaction,
29
- updateInteractionStatus,
30
- getNotificationEmails,
31
- saveNotificationEmails,
32
- } from "./interactions";
33
-
34
- describe("Interactions Server Actions", () => {
35
- beforeEach(() => {
36
- vi.clearAllMocks();
37
- });
38
-
39
- describe("submitInteraction", () => {
40
- it("returns an error if the user is not logged in", async () => {
41
- dbServerMocks.createClient.mockReturnValue({
42
- auth: {
43
- getUser: vi.fn().mockResolvedValue({ data: { user: null }, error: null }),
44
- },
45
- });
46
-
47
- const res = await submitInteraction({
48
- type: "review",
49
- content: "Great product!",
50
- rating: 5,
51
- productId: "prod-1",
52
- });
53
-
54
- expect(res).toEqual({ error: "You must be logged in to submit a review or comment." });
55
- });
56
-
57
- it("inserts a new review successfully and triggers revalidation", async () => {
58
- const singleMock = vi.fn().mockResolvedValue({
59
- data: { id: "int-1", type: "review", status: "pending" },
60
- error: null,
61
- });
62
- const selectMock = vi.fn(() => ({ single: singleMock }));
63
- const insertMock = vi.fn(() => ({ select: selectMock }));
64
- const fromMock = vi.fn(() => ({ insert: insertMock }));
65
-
66
- dbServerMocks.createClient.mockReturnValue({
67
- auth: {
68
- getUser: vi.fn().mockResolvedValue({
69
- data: { user: { id: "user-1" } },
70
- error: null,
71
- }),
72
- },
73
- from: fromMock,
74
- });
75
-
76
- const res = await submitInteraction({
77
- type: "review",
78
- content: "Awesome tool, works perfectly!",
79
- rating: 5,
80
- productId: "prod-1",
81
- });
82
-
83
- expect(res.success).toBe(true);
84
- expect(fromMock).toHaveBeenCalledWith("cms_interactions");
85
- expect(insertMock).toHaveBeenCalledWith({
86
- type: "review",
87
- status: "pending",
88
- content: "Awesome tool, works perfectly!",
89
- rating: 5,
90
- user_id: "user-1",
91
- product_id: "prod-1",
92
- post_id: null,
93
- reactions: {},
94
- });
95
- expect(cacheMocks.revalidatePath).toHaveBeenCalledWith("/cms/interactions");
96
- });
97
- });
98
-
99
- describe("toggleReaction", () => {
100
- it("toggles a reaction and updates cookies", async () => {
101
- const getCookieMock = vi.fn().mockReturnValue(undefined);
102
- const setCookieMock = vi.fn();
103
- headersMocks.cookies.mockResolvedValue({
104
- get: getCookieMock,
105
- set: setCookieMock,
106
- } as any);
107
-
108
- const singleMock = vi.fn().mockResolvedValue({
109
- data: {
110
- reactions: { likes: 3 },
111
- type: "review",
112
- product_id: "prod-1",
113
- post_id: null,
114
- products: { slug: "my-product" },
115
- },
116
- error: null,
117
- });
118
- const eqSelectMock = vi.fn().mockReturnValue({ single: singleMock });
119
- const selectMock = vi.fn().mockReturnValue({ eq: eqSelectMock });
120
- const eqUpdateMock = vi.fn().mockResolvedValue({ error: null });
121
- const updateMock = vi.fn().mockReturnValue({ eq: eqUpdateMock });
122
- const fromMock = vi.fn().mockReturnValue({
123
- select: selectMock,
124
- update: updateMock,
125
- });
126
-
127
- dbServerMocks.getServiceRoleSupabaseClient.mockReturnValue({
128
- from: fromMock,
129
- });
130
-
131
- const res = await toggleReaction("int-1");
132
-
133
- expect(res.success).toBe(true);
134
- expect(res.count).toBe(4);
135
- expect(res.hasReacted).toBe(true);
136
- expect(updateMock).toHaveBeenCalledWith({ reactions: { likes: 4 } });
137
- expect(eqUpdateMock).toHaveBeenCalledWith("id", "int-1");
138
- expect(setCookieMock).toHaveBeenCalledWith(
139
- "reacted_interactions",
140
- JSON.stringify(["int-1"]),
141
- expect.any(Object)
142
- );
143
- expect(cacheMocks.revalidatePath).toHaveBeenCalledWith("/product/my-product");
144
- });
145
- });
146
-
147
- describe("updateInteractionStatus", () => {
148
- it("returns error if non-admin attempts moderation", async () => {
149
- dbServerMocks.createClient.mockReturnValue({
150
- auth: {
151
- getUser: vi.fn().mockResolvedValue({
152
- data: { user: { id: "user-1" } },
153
- error: null,
154
- }),
155
- },
156
- });
157
- dbServerMocks.getProfileWithRoleServerSide.mockResolvedValue({
158
- role: "WRITER",
159
- } as any);
160
-
161
- const res = await updateInteractionStatus("int-1", "approved");
162
- expect(res.error).toContain("Unauthorized");
163
- });
164
-
165
- it("allows admins to approve and triggers path revalidation", async () => {
166
- dbServerMocks.createClient.mockReturnValue({
167
- auth: {
168
- getUser: vi.fn().mockResolvedValue({
169
- data: { user: { id: "admin-1" } },
170
- error: null,
171
- }),
172
- },
173
- });
174
- dbServerMocks.getProfileWithRoleServerSide.mockResolvedValue({
175
- role: "ADMIN",
176
- } as any);
177
-
178
- const singleMock = vi.fn().mockResolvedValue({
179
- data: {
180
- product_id: "prod-1",
181
- post_id: null,
182
- products: { slug: "my-product" },
183
- },
184
- error: null,
185
- });
186
- const eqSelectMock = vi.fn().mockReturnValue({ single: singleMock });
187
- const selectMock = vi.fn().mockReturnValue({ eq: eqSelectMock });
188
- const eqUpdateMock = vi.fn().mockResolvedValue({ error: null });
189
- const updateMock = vi.fn().mockReturnValue({ eq: eqUpdateMock });
190
- const fromMock = vi.fn().mockReturnValue({
191
- select: selectMock,
192
- update: updateMock,
193
- });
194
-
195
- dbServerMocks.getServiceRoleSupabaseClient.mockReturnValue({
196
- from: fromMock,
197
- });
198
-
199
- const res = await updateInteractionStatus("int-1", "approved");
200
-
201
- expect(res.success).toBe(true);
202
- expect(updateMock).toHaveBeenCalledWith({ status: "approved" });
203
- expect(eqUpdateMock).toHaveBeenCalledWith("id", "int-1");
204
- expect(cacheMocks.revalidatePath).toHaveBeenCalledWith("/product/my-product");
205
- expect(cacheMocks.revalidatePath).toHaveBeenCalledWith("/cms/interactions");
206
- });
207
- });
208
-
209
- describe("Notification Emails Settings Actions", () => {
210
- it("returns error if non-admin attempts to get or save configuration", async () => {
211
- dbServerMocks.createClient.mockReturnValue({
212
- auth: {
213
- getUser: vi.fn().mockResolvedValue({
214
- data: { user: { id: "user-1" } },
215
- error: null,
216
- }),
217
- },
218
- });
219
- dbServerMocks.getProfileWithRoleServerSide.mockResolvedValue({
220
- role: "WRITER",
221
- } as any);
222
-
223
- const getRes = await getNotificationEmails();
224
- expect(getRes.error).toContain("Unauthorized");
225
-
226
- const saveRes = await saveNotificationEmails("test@example.com");
227
- expect(saveRes.error).toContain("Unauthorized");
228
- });
229
-
230
- it("allows admins to get configuration", async () => {
231
- dbServerMocks.createClient.mockReturnValue({
232
- auth: {
233
- getUser: vi.fn().mockResolvedValue({
234
- data: { user: { id: "admin-1" } },
235
- error: null,
236
- }),
237
- },
238
- });
239
- dbServerMocks.getProfileWithRoleServerSide.mockResolvedValue({
240
- role: "ADMIN",
241
- } as any);
242
-
243
- const maybeSingleMock = vi.fn().mockResolvedValue({
244
- data: { value: { emails: "a@b.com, c@d.com" } },
245
- error: null,
246
- });
247
- const eqMock = vi.fn().mockReturnValue({ maybeSingle: maybeSingleMock });
248
- const selectMock = vi.fn().mockReturnValue({ eq: eqMock });
249
- const fromMock = vi.fn().mockReturnValue({ select: selectMock });
250
-
251
- dbServerMocks.createClient.mockReturnValue({
252
- auth: {
253
- getUser: vi.fn().mockResolvedValue({
254
- data: { user: { id: "admin-1" } },
255
- error: null,
256
- }),
257
- },
258
- from: fromMock,
259
- });
260
-
261
- const res = await getNotificationEmails();
262
- expect(res.success).toBe(true);
263
- expect(res.emails).toBe("a@b.com, c@d.com");
264
- });
265
-
266
- it("allows admins to save configuration", async () => {
267
- dbServerMocks.createClient.mockReturnValue({
268
- auth: {
269
- getUser: vi.fn().mockResolvedValue({
270
- data: { user: { id: "admin-1" } },
271
- error: null,
272
- }),
273
- },
274
- });
275
- dbServerMocks.getProfileWithRoleServerSide.mockResolvedValue({
276
- role: "ADMIN",
277
- } as any);
278
-
279
- const upsertMock = vi.fn().mockResolvedValue({ error: null });
280
- const fromMock = vi.fn().mockReturnValue({ upsert: upsertMock });
281
-
282
- dbServerMocks.createClient.mockReturnValue({
283
- auth: {
284
- getUser: vi.fn().mockResolvedValue({
285
- data: { user: { id: "admin-1" } },
286
- error: null,
287
- }),
288
- },
289
- from: fromMock,
290
- });
291
-
292
- const res = await saveNotificationEmails(" a@b.com , c@d.com ");
293
- expect(res.success).toBe(true);
294
- expect(res.emails).toBe("a@b.com, c@d.com");
295
- expect(upsertMock).toHaveBeenCalledWith({
296
- key: "interactions_notification_emails",
297
- value: { emails: "a@b.com, c@d.com" },
298
- });
299
- });
300
- });
301
- });
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+
3
+ const cacheMocks = vi.hoisted(() => ({
4
+ revalidatePath: vi.fn(),
5
+ }));
6
+
7
+ const dbServerMocks = vi.hoisted(() => ({
8
+ createClient: vi.fn(),
9
+ getServiceRoleSupabaseClient: vi.fn(),
10
+ getProfileWithRoleServerSide: vi.fn(),
11
+ }));
12
+
13
+ const headersMocks = vi.hoisted(() => {
14
+ const get = vi.fn();
15
+ const set = vi.fn();
16
+ return {
17
+ cookies: vi.fn().mockResolvedValue({ get, set }),
18
+ };
19
+ });
20
+
21
+ vi.mock("next/cache", () => cacheMocks);
22
+ vi.mock("next/headers", () => headersMocks);
23
+ vi.mock("@nextblock-cms/db/server", () => dbServerMocks);
24
+ vi.mock("server-only", () => ({}));
25
+
26
+ import {
27
+ submitInteraction,
28
+ toggleReaction,
29
+ updateInteractionStatus,
30
+ getNotificationEmails,
31
+ saveNotificationEmails,
32
+ } from "./interactions";
33
+
34
+ describe("Interactions Server Actions", () => {
35
+ beforeEach(() => {
36
+ vi.clearAllMocks();
37
+ });
38
+
39
+ describe("submitInteraction", () => {
40
+ it("returns an error if the user is not logged in", async () => {
41
+ dbServerMocks.createClient.mockReturnValue({
42
+ auth: {
43
+ getUser: vi.fn().mockResolvedValue({ data: { user: null }, error: null }),
44
+ },
45
+ });
46
+
47
+ const res = await submitInteraction({
48
+ type: "review",
49
+ content: "Great product!",
50
+ rating: 5,
51
+ productId: "prod-1",
52
+ });
53
+
54
+ expect(res).toEqual({ error: "You must be logged in to submit a review or comment." });
55
+ });
56
+
57
+ it("inserts a new review successfully and triggers revalidation", async () => {
58
+ const singleMock = vi.fn().mockResolvedValue({
59
+ data: { id: "int-1", type: "review", status: "pending" },
60
+ error: null,
61
+ });
62
+ const selectMock = vi.fn(() => ({ single: singleMock }));
63
+ const insertMock = vi.fn(() => ({ select: selectMock }));
64
+ const fromMock = vi.fn(() => ({ insert: insertMock }));
65
+
66
+ dbServerMocks.createClient.mockReturnValue({
67
+ auth: {
68
+ getUser: vi.fn().mockResolvedValue({
69
+ data: { user: { id: "user-1" } },
70
+ error: null,
71
+ }),
72
+ },
73
+ from: fromMock,
74
+ });
75
+
76
+ const res = await submitInteraction({
77
+ type: "review",
78
+ content: "Awesome tool, works perfectly!",
79
+ rating: 5,
80
+ productId: "prod-1",
81
+ });
82
+
83
+ expect(res.success).toBe(true);
84
+ expect(fromMock).toHaveBeenCalledWith("cms_interactions");
85
+ expect(insertMock).toHaveBeenCalledWith({
86
+ type: "review",
87
+ status: "pending",
88
+ content: "Awesome tool, works perfectly!",
89
+ rating: 5,
90
+ user_id: "user-1",
91
+ product_id: "prod-1",
92
+ post_id: null,
93
+ reactions: {},
94
+ });
95
+ expect(cacheMocks.revalidatePath).toHaveBeenCalledWith("/cms/interactions");
96
+ });
97
+ });
98
+
99
+ describe("toggleReaction", () => {
100
+ it("toggles a reaction and updates cookies", async () => {
101
+ const getCookieMock = vi.fn().mockReturnValue(undefined);
102
+ const setCookieMock = vi.fn();
103
+ headersMocks.cookies.mockResolvedValue({
104
+ get: getCookieMock,
105
+ set: setCookieMock,
106
+ } as any);
107
+
108
+ const singleMock = vi.fn().mockResolvedValue({
109
+ data: {
110
+ reactions: { likes: 3 },
111
+ type: "review",
112
+ product_id: "prod-1",
113
+ post_id: null,
114
+ products: { slug: "my-product" },
115
+ },
116
+ error: null,
117
+ });
118
+ const eqSelectMock = vi.fn().mockReturnValue({ single: singleMock });
119
+ const selectMock = vi.fn().mockReturnValue({ eq: eqSelectMock });
120
+ const eqUpdateMock = vi.fn().mockResolvedValue({ error: null });
121
+ const updateMock = vi.fn().mockReturnValue({ eq: eqUpdateMock });
122
+ const fromMock = vi.fn().mockReturnValue({
123
+ select: selectMock,
124
+ update: updateMock,
125
+ });
126
+
127
+ dbServerMocks.getServiceRoleSupabaseClient.mockReturnValue({
128
+ from: fromMock,
129
+ });
130
+
131
+ const res = await toggleReaction("int-1");
132
+
133
+ expect(res.success).toBe(true);
134
+ expect(res.count).toBe(4);
135
+ expect(res.hasReacted).toBe(true);
136
+ expect(updateMock).toHaveBeenCalledWith({ reactions: { likes: 4 } });
137
+ expect(eqUpdateMock).toHaveBeenCalledWith("id", "int-1");
138
+ expect(setCookieMock).toHaveBeenCalledWith(
139
+ "reacted_interactions",
140
+ JSON.stringify(["int-1"]),
141
+ expect.any(Object)
142
+ );
143
+ expect(cacheMocks.revalidatePath).toHaveBeenCalledWith("/product/my-product");
144
+ });
145
+ });
146
+
147
+ describe("updateInteractionStatus", () => {
148
+ it("returns error if non-admin attempts moderation", async () => {
149
+ dbServerMocks.createClient.mockReturnValue({
150
+ auth: {
151
+ getUser: vi.fn().mockResolvedValue({
152
+ data: { user: { id: "user-1" } },
153
+ error: null,
154
+ }),
155
+ },
156
+ });
157
+ dbServerMocks.getProfileWithRoleServerSide.mockResolvedValue({
158
+ role: "WRITER",
159
+ } as any);
160
+
161
+ const res = await updateInteractionStatus("int-1", "approved");
162
+ expect(res.error).toContain("Unauthorized");
163
+ });
164
+
165
+ it("allows admins to approve and triggers path revalidation", async () => {
166
+ dbServerMocks.createClient.mockReturnValue({
167
+ auth: {
168
+ getUser: vi.fn().mockResolvedValue({
169
+ data: { user: { id: "admin-1" } },
170
+ error: null,
171
+ }),
172
+ },
173
+ });
174
+ dbServerMocks.getProfileWithRoleServerSide.mockResolvedValue({
175
+ role: "ADMIN",
176
+ } as any);
177
+
178
+ const singleMock = vi.fn().mockResolvedValue({
179
+ data: {
180
+ product_id: "prod-1",
181
+ post_id: null,
182
+ products: { slug: "my-product" },
183
+ },
184
+ error: null,
185
+ });
186
+ const eqSelectMock = vi.fn().mockReturnValue({ single: singleMock });
187
+ const selectMock = vi.fn().mockReturnValue({ eq: eqSelectMock });
188
+ const eqUpdateMock = vi.fn().mockResolvedValue({ error: null });
189
+ const updateMock = vi.fn().mockReturnValue({ eq: eqUpdateMock });
190
+ const fromMock = vi.fn().mockReturnValue({
191
+ select: selectMock,
192
+ update: updateMock,
193
+ });
194
+
195
+ dbServerMocks.getServiceRoleSupabaseClient.mockReturnValue({
196
+ from: fromMock,
197
+ });
198
+
199
+ const res = await updateInteractionStatus("int-1", "approved");
200
+
201
+ expect(res.success).toBe(true);
202
+ expect(updateMock).toHaveBeenCalledWith({ status: "approved" });
203
+ expect(eqUpdateMock).toHaveBeenCalledWith("id", "int-1");
204
+ expect(cacheMocks.revalidatePath).toHaveBeenCalledWith("/product/my-product");
205
+ expect(cacheMocks.revalidatePath).toHaveBeenCalledWith("/cms/interactions");
206
+ });
207
+ });
208
+
209
+ describe("Notification Emails Settings Actions", () => {
210
+ it("returns error if non-admin attempts to get or save configuration", async () => {
211
+ dbServerMocks.createClient.mockReturnValue({
212
+ auth: {
213
+ getUser: vi.fn().mockResolvedValue({
214
+ data: { user: { id: "user-1" } },
215
+ error: null,
216
+ }),
217
+ },
218
+ });
219
+ dbServerMocks.getProfileWithRoleServerSide.mockResolvedValue({
220
+ role: "WRITER",
221
+ } as any);
222
+
223
+ const getRes = await getNotificationEmails();
224
+ expect(getRes.error).toContain("Unauthorized");
225
+
226
+ const saveRes = await saveNotificationEmails("test@example.com");
227
+ expect(saveRes.error).toContain("Unauthorized");
228
+ });
229
+
230
+ it("allows admins to get configuration", async () => {
231
+ dbServerMocks.createClient.mockReturnValue({
232
+ auth: {
233
+ getUser: vi.fn().mockResolvedValue({
234
+ data: { user: { id: "admin-1" } },
235
+ error: null,
236
+ }),
237
+ },
238
+ });
239
+ dbServerMocks.getProfileWithRoleServerSide.mockResolvedValue({
240
+ role: "ADMIN",
241
+ } as any);
242
+
243
+ const maybeSingleMock = vi.fn().mockResolvedValue({
244
+ data: { value: { emails: "a@b.com, c@d.com" } },
245
+ error: null,
246
+ });
247
+ const eqMock = vi.fn().mockReturnValue({ maybeSingle: maybeSingleMock });
248
+ const selectMock = vi.fn().mockReturnValue({ eq: eqMock });
249
+ const fromMock = vi.fn().mockReturnValue({ select: selectMock });
250
+
251
+ dbServerMocks.createClient.mockReturnValue({
252
+ auth: {
253
+ getUser: vi.fn().mockResolvedValue({
254
+ data: { user: { id: "admin-1" } },
255
+ error: null,
256
+ }),
257
+ },
258
+ from: fromMock,
259
+ });
260
+
261
+ const res = await getNotificationEmails();
262
+ expect(res.success).toBe(true);
263
+ expect(res.emails).toBe("a@b.com, c@d.com");
264
+ });
265
+
266
+ it("allows admins to save configuration", async () => {
267
+ dbServerMocks.createClient.mockReturnValue({
268
+ auth: {
269
+ getUser: vi.fn().mockResolvedValue({
270
+ data: { user: { id: "admin-1" } },
271
+ error: null,
272
+ }),
273
+ },
274
+ });
275
+ dbServerMocks.getProfileWithRoleServerSide.mockResolvedValue({
276
+ role: "ADMIN",
277
+ } as any);
278
+
279
+ const upsertMock = vi.fn().mockResolvedValue({ error: null });
280
+ const fromMock = vi.fn().mockReturnValue({ upsert: upsertMock });
281
+
282
+ dbServerMocks.createClient.mockReturnValue({
283
+ auth: {
284
+ getUser: vi.fn().mockResolvedValue({
285
+ data: { user: { id: "admin-1" } },
286
+ error: null,
287
+ }),
288
+ },
289
+ from: fromMock,
290
+ });
291
+
292
+ const res = await saveNotificationEmails(" a@b.com , c@d.com ");
293
+ expect(res.success).toBe(true);
294
+ expect(res.emails).toBe("a@b.com, c@d.com");
295
+ expect(upsertMock).toHaveBeenCalledWith({
296
+ key: "interactions_notification_emails",
297
+ value: { emails: "a@b.com, c@d.com" },
298
+ });
299
+ });
300
+ });
301
+ });