create-nextblock 0.13.7 → 0.13.9

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 (44) hide show
  1. package/package.json +1 -1
  2. package/templates/nextblock-template/app/(auth-pages)/two-factor/actions.ts +21 -1
  3. package/templates/nextblock-template/app/(auth-pages)/two-factor/components/TwoFactorForm.tsx +34 -10
  4. package/templates/nextblock-template/app/actions/email.ts +78 -7
  5. package/templates/nextblock-template/app/actions/feedback.ts +57 -14
  6. package/templates/nextblock-template/app/actions/interactions.test.ts +3 -0
  7. package/templates/nextblock-template/app/actions/productGridActions.ts +40 -0
  8. package/templates/nextblock-template/app/actions.ts +17 -4
  9. package/templates/nextblock-template/app/api/cms/ecommerce/product-picker/route.ts +151 -0
  10. package/templates/nextblock-template/app/cms/CmsClientLayout.tsx +4 -1
  11. package/templates/nextblock-template/app/cms/blocks/components/BlockTypeSelector.tsx +17 -5
  12. package/templates/nextblock-template/app/cms/blocks/components/MultiEntityPicker.tsx +251 -0
  13. package/templates/nextblock-template/app/cms/blocks/editors/ProductGridBlockEditor.tsx +375 -18
  14. package/templates/nextblock-template/app/cms/components/EcommerceActiveContext.tsx +27 -0
  15. package/templates/nextblock-template/app/cms/settings/bot-protection/actions.ts +9 -6
  16. package/templates/nextblock-template/app/cms/settings/bot-protection/components/BotProtectionForm.tsx +1 -5
  17. package/templates/nextblock-template/app/cms/settings/copyright/actions.ts +9 -6
  18. package/templates/nextblock-template/app/cms/settings/copyright/components/CopyrightForm.tsx +1 -5
  19. package/templates/nextblock-template/app/cms/settings/cortex-ai/actions.ts +18 -8
  20. package/templates/nextblock-template/app/cms/settings/email/actions.ts +59 -29
  21. package/templates/nextblock-template/app/cms/settings/email/components/EmailForm.tsx +5 -1
  22. package/templates/nextblock-template/app/cms/settings/global-css/actions.ts +6 -5
  23. package/templates/nextblock-template/app/cms/settings/global-css/components/GlobalCssForm.tsx +2 -1
  24. package/templates/nextblock-template/app/cms/settings/google-analytics/actions.ts +18 -7
  25. package/templates/nextblock-template/app/cms/settings/google-analytics/components/GoogleAnalyticsForm.tsx +1 -1
  26. package/templates/nextblock-template/app/cms/settings/privacy/actions.ts +16 -7
  27. package/templates/nextblock-template/app/cms/settings/privacy/components/PrivacyForm.tsx +1 -1
  28. package/templates/nextblock-template/app/cms/settings/registration/actions.ts +18 -7
  29. package/templates/nextblock-template/app/cms/settings/registration/components/RegistrationForm.tsx +1 -1
  30. package/templates/nextblock-template/app/cms/settings/security/actions.ts +227 -131
  31. package/templates/nextblock-template/app/cms/settings/security/components/SecurityPanel.tsx +134 -18
  32. package/templates/nextblock-template/components/blocks/ProductGridClient.tsx +114 -0
  33. package/templates/nextblock-template/lib/auth/twoFactor.test.ts +254 -0
  34. package/templates/nextblock-template/lib/auth/twoFactor.ts +56 -13
  35. package/templates/nextblock-template/lib/blocks/ProductGridBlock.tsx +78 -139
  36. package/templates/nextblock-template/lib/blocks/blockRegistry.ts +3 -3
  37. package/templates/nextblock-template/lib/blocks/blockTypes.ts +19 -0
  38. package/templates/nextblock-template/lib/blocks/ecommerce-block-schemas.ts +61 -2
  39. package/templates/nextblock-template/lib/blocks/product-grid-data.ts +210 -0
  40. package/templates/nextblock-template/lib/cms/action-result.ts +12 -0
  41. package/templates/nextblock-template/lib/config/email-settings.ts +40 -3
  42. package/templates/nextblock-template/next-env.d.ts +1 -1
  43. package/templates/nextblock-template/package.json +1 -1
  44. package/templates/nextblock-template/tsconfig.tsbuildinfo +1 -1
@@ -170,14 +170,46 @@ export async function saveEmailSettings(input: SaveEmailSettingsInput): Promise<
170
170
  throw new Error('Failed to save email credentials.');
171
171
  }
172
172
  }
173
+
174
+ // The mailer memoizes the resolved transport config; make the new values live now.
175
+ invalidateEmailConfigCache();
176
+ }
177
+
178
+ // Resolving SMTP costs two service-role reads plus an AES decrypt of each secret, and
179
+ // transactional email (2FA codes especially) is latency-sensitive. The values only change
180
+ // when an admin saves the form, so memoize briefly and bust the cache on save.
181
+ const CONFIG_CACHE_TTL_MS = 60_000;
182
+ let configCache: { value: ResolvedEmailConfig | null; expiresAt: number } | null = null;
183
+
184
+ /** Drop the memoized SMTP config so the next resolve re-reads the DB. */
185
+ export function invalidateEmailConfigCache(): void {
186
+ configCache = null;
187
+ }
188
+
189
+ /**
190
+ * Cheap "can this instance actually send mail right now?" check for UI gating. Never
191
+ * logs — an unconfigured instance is an expected state here, not an error condition.
192
+ */
193
+ export async function isEmailConfigured(): Promise<boolean> {
194
+ return (await resolveEmailServerConfig({ silent: true })) !== null;
173
195
  }
174
196
 
175
197
  /**
176
198
  * Resolve the full SMTP transport config, DB-first with an env fallback. Uses the
177
199
  * service-role client so it works from any context (the secret row is ADMIN-only under
178
200
  * RLS). Returns null when host/user/pass/from cannot be resolved from either source.
201
+ *
202
+ * Memoized for CONFIG_CACHE_TTL_MS; pass `silent` when "not configured" is an expected
203
+ * answer (UI gating) rather than a misconfiguration worth warning about.
179
204
  */
180
- export async function resolveEmailServerConfig(): Promise<ResolvedEmailConfig | null> {
205
+ export async function resolveEmailServerConfig(
206
+ options: { silent?: boolean } = {},
207
+ ): Promise<ResolvedEmailConfig | null> {
208
+ const cached = configCache;
209
+ if (cached && cached.expiresAt > Date.now()) {
210
+ return cached.value;
211
+ }
212
+
181
213
  let pub: EmailPublicSettings = DEFAULT_EMAIL_PUBLIC_SETTINGS;
182
214
  let secret: Record<string, unknown> = {};
183
215
 
@@ -201,12 +233,15 @@ export async function resolveEmailServerConfig(): Promise<ResolvedEmailConfig |
201
233
  const pass = resolveConfigValue(tryDecryptWithEnvKey(secret['pass']), 'SMTP_PASS');
202
234
 
203
235
  if (!host || !port || !user || !pass || !fromEmail) {
204
- console.warn('Email is not configured (CMS or SMTP_* env). Outbound email will not be sent.');
236
+ if (!options.silent) {
237
+ console.warn('Email is not configured (CMS or SMTP_* env). Outbound email will not be sent.');
238
+ }
239
+ configCache = { value: null, expiresAt: Date.now() + CONFIG_CACHE_TTL_MS };
205
240
  return null;
206
241
  }
207
242
 
208
243
  const portNumber = Number(port);
209
- return {
244
+ const resolved: ResolvedEmailConfig = {
210
245
  host,
211
246
  port: portNumber,
212
247
  // Honor the CMS toggle; fall back to the SMTPS convention (465 ⇒ implicit TLS).
@@ -214,4 +249,6 @@ export async function resolveEmailServerConfig(): Promise<ResolvedEmailConfig |
214
249
  auth: { user, pass },
215
250
  from: fromName ? `"${fromName}" <${fromEmail}>` : fromEmail,
216
251
  };
252
+ configCache = { value: resolved, expiresAt: Date.now() + CONFIG_CACHE_TTL_MS };
253
+ return resolved;
217
254
  }
@@ -1,6 +1,6 @@
1
1
  /// <reference types="next" />
2
2
  /// <reference types="next/image-types/global" />
3
- import "./.next/dev/types/routes.d.ts";
3
+ import "./.next/types/routes.d.ts";
4
4
 
5
5
  // NOTE: This file should not be edited
6
6
  // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextblock-cms/template",
3
- "version": "0.13.7",
3
+ "version": "0.13.9",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "dev": "next dev",