@nextsparkjs/core 0.1.0-beta.130 → 0.1.0-beta.132

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 (28) hide show
  1. package/dist/components/dashboard/block-editor/builder-editor-view.d.ts +2 -1
  2. package/dist/components/dashboard/block-editor/builder-editor-view.d.ts.map +1 -1
  3. package/dist/components/dashboard/block-editor/builder-editor-view.js +3 -2
  4. package/dist/components/entities/EntityFieldRenderer.d.ts.map +1 -1
  5. package/dist/components/entities/EntityFieldRenderer.js +3 -2
  6. package/dist/components/media/MediaSelector.d.ts +3 -3
  7. package/dist/components/media/MediaSelector.d.ts.map +1 -1
  8. package/dist/components/media/MediaSelector.js +4 -3
  9. package/dist/lib/api/entity/generic-handler.js +4 -4
  10. package/dist/lib/entities/query-generator.js +2 -1
  11. package/dist/lib/entities/schema-generator.d.ts.map +1 -1
  12. package/dist/lib/entities/schema-generator.js +2 -1
  13. package/dist/messages/en/admin.json +17 -2
  14. package/dist/messages/en/index.d.ts +15 -0
  15. package/dist/messages/en/index.d.ts.map +1 -1
  16. package/dist/messages/es/admin.json +17 -2
  17. package/dist/messages/es/index.d.ts +15 -0
  18. package/dist/messages/es/index.d.ts.map +1 -1
  19. package/dist/styles/classes.json +1 -1
  20. package/dist/templates/app/(auth)/accept-invite/[token]/page.tsx +1 -1
  21. package/dist/templates/app/api/v1/billing/webhooks/polar/route.ts +10 -2
  22. package/dist/templates/app/api/v1/billing/webhooks/stripe/route.ts +12 -3
  23. package/package.json +2 -2
  24. package/scripts/build/registry/discovery/templates.mjs +59 -5
  25. package/scripts/build/registry/generators/template-registry.mjs +7 -5
  26. package/templates/app/(auth)/accept-invite/[token]/page.tsx +1 -1
  27. package/templates/app/api/v1/billing/webhooks/polar/route.ts +10 -2
  28. package/templates/app/api/v1/billing/webhooks/stripe/route.ts +12 -3
@@ -4,6 +4,7 @@ export interface BuilderEditorViewProps {
4
4
  entityConfig: ClientEntityConfig;
5
5
  id?: string;
6
6
  mode: 'create' | 'edit';
7
+ onEntityFieldChange?: (field: string, value: unknown) => void;
7
8
  }
8
- export declare function BuilderEditorView({ entitySlug, entityConfig, id, mode }: BuilderEditorViewProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function BuilderEditorView({ entitySlug, entityConfig, id, mode, onEntityFieldChange: onEntityFieldChangeProp }: BuilderEditorViewProps): import("react/jsx-runtime").JSX.Element;
9
10
  //# sourceMappingURL=builder-editor-view.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"builder-editor-view.d.ts","sourceRoot":"","sources":["../../../../src/components/dashboard/block-editor/builder-editor-view.tsx"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAA;AAwCxF,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,kBAAkB,CAAA;IAChC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAA;CACxB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,sBAAsB,2CA+rB/F"}
1
+ {"version":3,"file":"builder-editor-view.d.ts","sourceRoot":"","sources":["../../../../src/components/dashboard/block-editor/builder-editor-view.tsx"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAA;AAwCxF,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,kBAAkB,CAAA;IAChC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAA;IACvB,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;CAC9D;AAED,wBAAgB,iBAAiB,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,EAAE,sBAAsB,2CAgsB7I"}
@@ -41,7 +41,7 @@ function buildApiHeaders(includeContentType = false) {
41
41
  function slugify(text) {
42
42
  return text.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s-]/g, "").trim().replace(/\s+/g, "-").replace(/-+/g, "-");
43
43
  }
44
- function BuilderEditorView({ entitySlug, entityConfig, id, mode }) {
44
+ function BuilderEditorView({ entitySlug, entityConfig, id, mode, onEntityFieldChange: onEntityFieldChangeProp }) {
45
45
  var _a;
46
46
  const router = useRouter();
47
47
  const t = useTranslations("admin.builder");
@@ -311,7 +311,8 @@ function BuilderEditorView({ entitySlug, entityConfig, id, mode }) {
311
311
  }, []);
312
312
  const handleEntityFieldChange = useCallback((field, value) => {
313
313
  setEntityFields((prev) => ({ ...prev, [field]: value }));
314
- }, []);
314
+ onEntityFieldChangeProp == null ? void 0 : onEntityFieldChangeProp(field, value);
315
+ }, [onEntityFieldChangeProp]);
315
316
  const handleLeftSidebarToggle = useCallback((value) => {
316
317
  if (!value || value === leftSidebarMode) {
317
318
  setLeftSidebarMode("none");
@@ -1 +1 @@
1
- {"version":3,"file":"EntityFieldRenderer.d.ts","sourceRoot":"","sources":["../../../src/components/entities/EntityFieldRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AA6CH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAG3D,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,WAAW,CAAA;IAClB,KAAK,EAAE,OAAO,CAAA;IACd,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IACnC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAA;IACjC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KACvB,CAAA;CACF;AAg0BD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,QAAgB,EAChB,QAAQ,EACR,SAAS,EACT,MAAM,EACN,OAAO,GACR,EAAE,wBAAwB,2CAyC1B"}
1
+ {"version":3,"file":"EntityFieldRenderer.d.ts","sourceRoot":"","sources":["../../../src/components/entities/EntityFieldRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AA6CH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAK3D,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,WAAW,CAAA;IAClB,KAAK,EAAE,OAAO,CAAA;IACd,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IACnC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAA;IACjC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KACvB,CAAA;CACF;AAg0BD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,QAAgB,EAChB,QAAQ,EACR,SAAS,EACT,MAAM,EACN,OAAO,GACR,EAAE,wBAAwB,2CAyC1B"}
@@ -30,6 +30,7 @@ import { MediaSelector } from "../media/MediaSelector.js";
30
30
  import { UserSelect } from "../ui/user-select.js";
31
31
  import { ButtonGroup } from "../ui/button-group.js";
32
32
  import { DoubleRange } from "../ui/double-range.js";
33
+ import { resolveMediaUrl } from "../../types/blocks.js";
33
34
  function formatDisplayValue(value, field) {
34
35
  if (value === null || value === void 0) {
35
36
  return "-";
@@ -89,7 +90,7 @@ function formatDisplayValue(value, field) {
89
90
  }
90
91
  return String(value || "");
91
92
  case "media-library":
92
- return value ? String(value) : "";
93
+ return resolveMediaUrl(value) || "";
93
94
  case "file":
94
95
  case "image":
95
96
  case "video":
@@ -402,7 +403,7 @@ function renderFormField(field, value, onChange, error, disabled, required, test
402
403
  MediaSelector,
403
404
  {
404
405
  value,
405
- onChange: (mediaId) => onChange(mediaId),
406
+ onChange: (ref) => onChange(ref),
406
407
  disabled
407
408
  }
408
409
  );
@@ -5,10 +5,10 @@
5
5
  * Opens MediaLibrary modal and displays selected media preview.
6
6
  * Integrates with React Hook Form if used in a form context.
7
7
  */
8
- import type { Media } from '../../lib/media/types';
8
+ import type { MediaRef } from '../../types/blocks';
9
9
  interface MediaSelectorProps {
10
- value?: string | null;
11
- onChange?: (mediaId: string | null, media: Media | null) => void;
10
+ value?: MediaRef | null;
11
+ onChange?: (ref: MediaRef | null) => void;
12
12
  mode?: 'single';
13
13
  allowedTypes?: ('image' | 'video')[];
14
14
  className?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"MediaSelector.d.ts","sourceRoot":"","sources":["../../../src/components/media/MediaSelector.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAaH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAA;AAElD,UAAU,kBAAkB;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,CAAA;IAChE,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,YAAY,CAAC,EAAE,CAAC,OAAO,GAAG,OAAO,CAAC,EAAE,CAAA;IACpC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,QAAQ,EACR,IAAe,EACf,YAAY,EACZ,SAAS,EACT,QAAgB,GACjB,EAAE,kBAAkB,2CA2IpB"}
1
+ {"version":3,"file":"MediaSelector.d.ts","sourceRoot":"","sources":["../../../src/components/media/MediaSelector.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAcH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAGlD,UAAU,kBAAkB;IAC1B,KAAK,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;IACvB,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAA;IACzC,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,YAAY,CAAC,EAAE,CAAC,OAAO,GAAG,OAAO,CAAC,EAAE,CAAA;IACpC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,QAAQ,EACR,IAAe,EACf,YAAY,EACZ,SAAS,EACT,QAAgB,GACjB,EAAE,kBAAkB,2CA8IpB"}
@@ -19,16 +19,17 @@ function MediaSelector({
19
19
  }) {
20
20
  const t = useTranslations("media");
21
21
  const [isLibraryOpen, setIsLibraryOpen] = useState(false);
22
- const { data: selectedMedia, isLoading, isError } = useMediaItem(value || null);
22
+ const mediaId = value ? typeof value === "string" ? value : value.mediaId : null;
23
+ const { data: selectedMedia, isLoading, isError } = useMediaItem(mediaId);
23
24
  const handleSelect = (media) => {
24
25
  if (Array.isArray(media)) {
25
26
  return;
26
27
  }
27
- onChange == null ? void 0 : onChange(media.id, media);
28
+ onChange == null ? void 0 : onChange({ mediaId: media.id, url: media.url });
28
29
  setIsLibraryOpen(false);
29
30
  };
30
31
  const handleRemove = () => {
31
- onChange == null ? void 0 : onChange(null, null);
32
+ onChange == null ? void 0 : onChange(null);
32
33
  };
33
34
  const handleOpenLibrary = () => {
34
35
  if (!disabled) {
@@ -239,7 +239,7 @@ async function handleGenericList(request) {
239
239
  let teamId = null;
240
240
  let isBypass = false;
241
241
  if (!authResult.success && ((_a = resolution.entityConfig.access) == null ? void 0 : _a.public)) {
242
- console.log(`[GenericHandler] Public access allowed for ${resolution.entityConfig.slug} list`);
242
+ teamId = request.headers.get("x-team-id") ?? null;
243
243
  } else if (!authResult.success) {
244
244
  return NextResponse.json(
245
245
  { success: false, error: "Authentication required", code: "AUTHENTICATION_FAILED" },
@@ -338,7 +338,7 @@ async function handleGenericList(request) {
338
338
  const idPlaceholders = specificIds.map(() => `$${paramIndex++}`).join(", ");
339
339
  query = `SELECT ${fields} FROM "${tableName}" t WHERE t.id IN (${idPlaceholders})`;
340
340
  queryParams = [...specificIds];
341
- if (teamId && !skipUserFilter) {
341
+ if (teamId) {
342
342
  query += ` AND t."teamId" = $${paramIndex++}`;
343
343
  queryParams.push(teamId);
344
344
  }
@@ -354,7 +354,7 @@ async function handleGenericList(request) {
354
354
  const parentId = url.searchParams.get("parentId");
355
355
  query = `SELECT ${fields} FROM "${tableName}" t WHERE 1=1`;
356
356
  queryParams = [];
357
- if (teamId && !skipUserFilter) {
357
+ if (teamId) {
358
358
  query += ` AND t."teamId" = $${paramIndex++}`;
359
359
  queryParams.push(teamId);
360
360
  }
@@ -375,7 +375,7 @@ async function handleGenericList(request) {
375
375
  const whereConditions = [];
376
376
  queryParams = [];
377
377
  paramIndex = 1;
378
- if (teamId && !skipUserFilter) {
378
+ if (teamId) {
379
379
  whereConditions.push(`t."teamId" = $${paramIndex++}`);
380
380
  queryParams.push(teamId);
381
381
  }
@@ -404,7 +404,8 @@ function formatFieldValue(value, field) {
404
404
  }
405
405
  switch (field.type) {
406
406
  case "json":
407
- return typeof value === "string" ? value : JSON.stringify(value);
407
+ case "media-library":
408
+ return typeof value === "object" ? JSON.stringify(value) : value;
408
409
  case "boolean":
409
410
  return Boolean(value);
410
411
  case "number":
@@ -1 +1 @@
1
- {"version":3,"file":"schema-generator.d.ts","sourceRoot":"","sources":["../../../src/lib/entities/schema-generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,YAAY,EAAsC,MAAM,SAAS,CAAA;AAE/E,MAAM,WAAW,uBAAuB;IACtC,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAA;IAC9C,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,CAAC,CAAC,SAAS,CAAA;IACnB,MAAM,EAAE,CAAC,CAAC,SAAS,CAAA;IACnB,QAAQ,EAAE,CAAC,CAAC,SAAS,CAAA;IACrB,IAAI,EAAE,CAAC,CAAC,SAAS,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAA;CAC3C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,YAAY,EAC1B,OAAO,GAAE,uBAA4B,GACpC,gBAAgB,CA+FlB;AAuwBD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,YAAY,EAC1B,OAAO,EAAE,gBAAgB,GACxB,MAAM,CAeR;AASD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,YAAY,EAC1B,IAAI,EAAE,OAAO,EACb,UAAU,GAAE,QAAQ,GAAG,QAAQ,GAAG,UAAqB,EACvD,OAAO,GAAE,uBAA4B,GACpC;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAA;CAAE,CAW3E;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,YAAY,EAAE,YAAY,GACzB,MAAM,CAyCR;AAMD,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAOD;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,YAAY,GAAG,uBAAuB,CAsE/F;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,YAAY,GAAG,uBAAuB,CA6C5F;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GACrC,YAAY,EAAE,CAIhB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAE1E;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GACrC;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CA4CpE"}
1
+ {"version":3,"file":"schema-generator.d.ts","sourceRoot":"","sources":["../../../src/lib/entities/schema-generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,YAAY,EAAsC,MAAM,SAAS,CAAA;AAG/E,MAAM,WAAW,uBAAuB;IACtC,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAA;IAC9C,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,CAAC,CAAC,SAAS,CAAA;IACnB,MAAM,EAAE,CAAC,CAAC,SAAS,CAAA;IACnB,QAAQ,EAAE,CAAC,CAAC,SAAS,CAAA;IACrB,IAAI,EAAE,CAAC,CAAC,SAAS,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAA;CAC3C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,YAAY,EAC1B,OAAO,GAAE,uBAA4B,GACpC,gBAAgB,CA+FlB;AAuwBD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,YAAY,EAC1B,OAAO,EAAE,gBAAgB,GACxB,MAAM,CAeR;AASD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,YAAY,EAC1B,IAAI,EAAE,OAAO,EACb,UAAU,GAAE,QAAQ,GAAG,QAAQ,GAAG,UAAqB,EACvD,OAAO,GAAE,uBAA4B,GACpC;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAA;CAAE,CAW3E;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,YAAY,EAAE,YAAY,GACzB,MAAM,CAyCR;AAMD,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAOD;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,YAAY,GAAG,uBAAuB,CAsE/F;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,YAAY,GAAG,uBAAuB,CA6C5F;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GACrC,YAAY,EAAE,CAIhB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAE1E;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GACrC;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CA4CpE"}
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import { mediaRefSchema } from "../../types/blocks.js";
2
3
  function generateEntitySchemas(entityConfig, options = {}) {
3
4
  var _a;
4
5
  const {
@@ -499,7 +500,7 @@ function generateFieldSchema(field, customValidation, strict = true) {
499
500
  break;
500
501
  // Media types
501
502
  case "media-library":
502
- schema = z.string().nullable();
503
+ schema = mediaRefSchema.nullable();
503
504
  break;
504
505
  case "file":
505
506
  case "video":
@@ -275,8 +275,23 @@
275
275
  "tabs": {
276
276
  "content": "Content",
277
277
  "design": "Design",
278
- "advanced": "Advanced"
279
- }
278
+ "advanced": "Advanced",
279
+ "noContentFields": "No content fields",
280
+ "noDesignFields": "No design fields",
281
+ "noAdvancedFields": "No advanced fields"
282
+ },
283
+ "pattern": {
284
+ "title": "Pattern Reference",
285
+ "locked": {
286
+ "title": "Locked Block",
287
+ "description": "This is a pattern reference. Edit the pattern directly to make changes."
288
+ },
289
+ "actions": {
290
+ "edit": "Edit pattern",
291
+ "remove": "Unlink pattern"
292
+ }
293
+ },
294
+ "noFields": "This block has no configurable fields"
280
295
  },
281
296
  "config": {
282
297
  "entityFields": "Entity Fields",
@@ -277,7 +277,22 @@ declare const _default: {
277
277
  content: string;
278
278
  design: string;
279
279
  advanced: string;
280
+ noContentFields: string;
281
+ noDesignFields: string;
282
+ noAdvancedFields: string;
283
+ };
284
+ pattern: {
285
+ title: string;
286
+ locked: {
287
+ title: string;
288
+ description: string;
289
+ };
290
+ actions: {
291
+ edit: string;
292
+ remove: string;
293
+ };
280
294
  };
295
+ noFields: string;
281
296
  };
282
297
  config: {
283
298
  entityFields: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/messages/en/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA,wBAqBU"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/messages/en/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA,wBAqBU"}
@@ -275,8 +275,23 @@
275
275
  "tabs": {
276
276
  "content": "Contenido",
277
277
  "design": "Diseño",
278
- "advanced": "Avanzado"
279
- }
278
+ "advanced": "Avanzado",
279
+ "noContentFields": "No hay campos de contenido",
280
+ "noDesignFields": "No hay campos de diseno",
281
+ "noAdvancedFields": "No hay campos avanzados"
282
+ },
283
+ "pattern": {
284
+ "title": "Referencia a Pattern",
285
+ "locked": {
286
+ "title": "Bloque bloqueado",
287
+ "description": "Este bloque es una referencia a un pattern. Edita el pattern directamente para hacer cambios."
288
+ },
289
+ "actions": {
290
+ "edit": "Editar pattern",
291
+ "remove": "Desvincular pattern"
292
+ }
293
+ },
294
+ "noFields": "Este bloque no tiene campos configurables"
280
295
  },
281
296
  "config": {
282
297
  "entityFields": "Campos de Entidad",
@@ -277,7 +277,22 @@ declare const _default: {
277
277
  content: string;
278
278
  design: string;
279
279
  advanced: string;
280
+ noContentFields: string;
281
+ noDesignFields: string;
282
+ noAdvancedFields: string;
283
+ };
284
+ pattern: {
285
+ title: string;
286
+ locked: {
287
+ title: string;
288
+ description: string;
289
+ };
290
+ actions: {
291
+ edit: string;
292
+ remove: string;
293
+ };
280
294
  };
295
+ noFields: string;
281
296
  };
282
297
  config: {
283
298
  entityFields: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/messages/es/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA,wBAqBU"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/messages/es/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA,wBAqBU"}
@@ -1,5 +1,5 @@
1
1
  {
2
- "generated": "2026-03-26T20:40:48.170Z",
2
+ "generated": "2026-04-01T20:21:39.786Z",
3
3
  "totalClasses": 1078,
4
4
  "classes": [
5
5
  "!text-2xl",
@@ -68,7 +68,7 @@ function AcceptInvitePage() {
68
68
  }
69
69
 
70
70
  // Check email match
71
- if (user.email.toLowerCase() !== data.data.email.toLowerCase()) {
71
+ if ((user.email ?? '').toLowerCase() !== data.data.email.toLowerCase()) {
72
72
  setStatus('email_mismatch')
73
73
  setErrorMessage(`This invitation was sent to ${data.data.email}, but you are logged in as ${user.email}`)
74
74
  return
@@ -22,7 +22,15 @@ import { query, queryOne } from '@nextsparkjs/core/lib/db'
22
22
  import { getBillingGateway } from '@nextsparkjs/core/lib/billing/gateways/factory'
23
23
  import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
24
24
  import type { PolarWebhookExtensions } from '@nextsparkjs/core/lib/billing/polar-webhook'
25
- import { polarWebhookExtensions } from '@/lib/billing/polar-webhook-extensions'
25
+
26
+ async function loadExtensions(): Promise<PolarWebhookExtensions> {
27
+ try {
28
+ const mod = await import('@/lib/billing/polar-webhook-extensions')
29
+ return mod.polarWebhookExtensions
30
+ } catch {
31
+ return {}
32
+ }
33
+ }
26
34
 
27
35
  async function handlePolarWebhook(request: NextRequest) {
28
36
  // 1. Get raw body and ALL headers (Polar needs full headers for verification)
@@ -86,7 +94,7 @@ async function handlePolarWebhook(request: NextRequest) {
86
94
  break
87
95
 
88
96
  case 'order.paid':
89
- await handleOrderPaid(event.data, eventId, polarWebhookExtensions)
97
+ await handleOrderPaid(event.data, eventId, await loadExtensions())
90
98
  break
91
99
 
92
100
  default:
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Handles Stripe subscription lifecycle events.
5
5
  * To add one-time payment handling (credit packs, LTD, upsells),
6
- * override lib/billing/stripe-webhook-extensions.ts in your project.
6
+ * create lib/billing/stripe-webhook-extensions.ts in your project.
7
7
  *
8
8
  * Rate limiting: 500 requests/hour per IP (tier: webhook).
9
9
  * Stripe signature verification is the primary security layer;
@@ -14,12 +14,21 @@
14
14
 
15
15
  import { NextRequest } from 'next/server'
16
16
  import { handleStripeWebhook } from '@nextsparkjs/core/lib/billing/stripe-webhook'
17
- import { stripeWebhookExtensions } from '@/lib/billing/stripe-webhook-extensions'
18
17
  import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
19
18
 
19
+ async function loadExtensions() {
20
+ try {
21
+ const mod = await import('@/lib/billing/stripe-webhook-extensions')
22
+ return mod.stripeWebhookExtensions
23
+ } catch {
24
+ return {}
25
+ }
26
+ }
27
+
20
28
  export const POST = withRateLimitTier(
21
29
  async (request: NextRequest) => {
22
- return handleStripeWebhook(request, stripeWebhookExtensions)
30
+ const extensions = await loadExtensions()
31
+ return handleStripeWebhook(request, extensions)
23
32
  },
24
33
  'webhook'
25
34
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextsparkjs/core",
3
- "version": "0.1.0-beta.130",
3
+ "version": "0.1.0-beta.132",
4
4
  "description": "NextSpark - The complete SaaS framework for Next.js",
5
5
  "license": "MIT",
6
6
  "author": "NextSpark <hello@nextspark.dev>",
@@ -462,7 +462,7 @@
462
462
  "tailwind-merge": "^3.3.1",
463
463
  "uuid": "^13.0.0",
464
464
  "zod": "^4.1.5",
465
- "@nextsparkjs/testing": "0.1.0-beta.130"
465
+ "@nextsparkjs/testing": "0.1.0-beta.132"
466
466
  },
467
467
  "scripts": {
468
468
  "postinstall": "node scripts/postinstall.mjs || true",
@@ -6,7 +6,7 @@
6
6
  * @module core/scripts/build/registry/discovery/templates
7
7
  */
8
8
 
9
- import { readdir, stat, readFile } from 'fs/promises'
9
+ import { readdir, stat, readFile, access } from 'fs/promises'
10
10
  import { join } from 'path'
11
11
 
12
12
  import { CONFIG as DEFAULT_CONFIG } from '../config.mjs'
@@ -100,6 +100,42 @@ export async function discoverThemeTemplates(templatesPath, themeName, relativeP
100
100
  continue
101
101
  }
102
102
 
103
+ // Handle .meta.ts files: skip if companion .tsx exists (handled there),
104
+ // otherwise register as standalone metadata-only template
105
+ if (entry.name.endsWith('.meta.ts')) {
106
+ const companionTsx = entry.name.replace('.meta.ts', '.tsx')
107
+ const companionTs = entry.name.replace('.meta.ts', '.ts')
108
+ const hasTsxCompanion = entries.some(e => e.name === companionTsx)
109
+ const hasTsCompanion = entries.some(e => e.name === companionTs && !e.name.endsWith('.meta.ts'))
110
+
111
+ if (hasTsxCompanion || hasTsCompanion) {
112
+ verbose(`Skipping meta file (companion exists): ${currentRelativePath}`)
113
+ continue
114
+ }
115
+
116
+ // Standalone .meta.ts — register as metadata-only template
117
+ const baseFileName = entry.name.replace('.meta.ts', '.tsx')
118
+ const appPath = relativePath ? `app/${relativePath}/${baseFileName}` : `app/${baseFileName}`
119
+ const templatePath = `@/contents/themes/${themeName}/templates/${currentRelativePath}`
120
+ const templateMetadata = await extractTemplateMetadata(currentPath)
121
+
122
+ if (templateMetadata) {
123
+ verbose(`Standalone metadata template: ${appPath} (from ${currentRelativePath})`)
124
+ templates.push({
125
+ name: `${relativePath || 'root'}/${entry.name.replace('.meta.ts', '')}`.replace(/^\//, ''),
126
+ themeName,
127
+ templateType: entry.name.replace('.meta.ts', ''),
128
+ fileName: entry.name,
129
+ relativePath: currentRelativePath,
130
+ appPath,
131
+ templatePath,
132
+ priority: calculateTemplatePriority(themeName, relativePath, entry.name.replace('.meta.ts', '')),
133
+ metadata: templateMetadata
134
+ })
135
+ }
136
+ continue
137
+ }
138
+
103
139
  // Found a template file
104
140
  const templateType = entry.name.replace(/\.(tsx|ts)$/, '')
105
141
  const appPath = relativePath ? `app/${relativePath}/${entry.name}` : `app/${entry.name}`
@@ -141,10 +177,28 @@ export async function discoverThemeTemplates(templatesPath, themeName, relativeP
141
177
  // Ignore read errors for non-critical validation
142
178
  }
143
179
 
144
- // Extract metadata from template file if it exists
145
- const templateMetadata = await extractTemplateMetadata(currentPath)
146
- if (templateMetadata) {
147
- verbose(`Metadata extracted from ${templatePath}`)
180
+ // Extract metadata: check for companion .meta.ts file first, then inline export
181
+ let templateMetadata = null
182
+
183
+ // Check for companion .meta.ts file (e.g., layout.meta.ts for layout.tsx)
184
+ const metaFileName = entry.name.replace(/\.(tsx|ts)$/, '.meta.ts')
185
+ const metaFilePath = join(templatesPath, metaFileName)
186
+ try {
187
+ await access(metaFilePath)
188
+ templateMetadata = await extractTemplateMetadata(metaFilePath)
189
+ if (templateMetadata) {
190
+ verbose(`Metadata extracted from companion .meta.ts: ${metaFileName}`)
191
+ }
192
+ } catch {
193
+ // No companion .meta.ts file - fall through to inline extraction
194
+ }
195
+
196
+ // Fall back to inline metadata export from the template file itself
197
+ if (!templateMetadata) {
198
+ templateMetadata = await extractTemplateMetadata(currentPath)
199
+ if (templateMetadata) {
200
+ verbose(`Metadata extracted from ${templatePath}`)
201
+ }
148
202
  }
149
203
 
150
204
  templates.push({
@@ -57,9 +57,10 @@ export function generateTemplateRegistry(templates, config) {
57
57
  templatePath = templatePath.slice(0, -3)
58
58
  }
59
59
 
60
- // Skip import for metadata-only templates (PROTECTED_RENDER)
61
- if (!canOverrideComponent(appPath)) {
62
- return `// ${safeName} skipped - PROTECTED_RENDER (metadata-only)`
60
+ // Skip import for metadata-only templates (PROTECTED_RENDER or standalone .meta.ts)
61
+ const isMetaOnly = highestPriorityTemplate.fileName?.endsWith('.meta.ts')
62
+ if (!canOverrideComponent(appPath) || isMetaOnly) {
63
+ return `// ${safeName} skipped - metadata-only${isMetaOnly ? ' (standalone .meta.ts)' : ' (PROTECTED_RENDER)'}`
63
64
  }
64
65
 
65
66
  return `import ${safeName} from '${templatePath}'`
@@ -72,8 +73,9 @@ export function generateTemplateRegistry(templates, config) {
72
73
  const highestPriorityTemplate = pathTemplates[0]
73
74
  const safeName = `Template_${index}`
74
75
 
75
- // For metadata-only templates (PROTECTED_RENDER), don't reference component
76
- const componentRef = canOverrideComponent(appPath) ? safeName : 'null'
76
+ // For metadata-only templates (PROTECTED_RENDER or standalone .meta.ts), don't reference component
77
+ const isMetaOnly = highestPriorityTemplate.fileName?.endsWith('.meta.ts')
78
+ const componentRef = (!canOverrideComponent(appPath) || isMetaOnly) ? 'null' : safeName
77
79
 
78
80
  return ` '${appPath}': {
79
81
  appPath: '${appPath}',
@@ -68,7 +68,7 @@ function AcceptInvitePage() {
68
68
  }
69
69
 
70
70
  // Check email match
71
- if (user.email.toLowerCase() !== data.data.email.toLowerCase()) {
71
+ if ((user.email ?? '').toLowerCase() !== data.data.email.toLowerCase()) {
72
72
  setStatus('email_mismatch')
73
73
  setErrorMessage(`This invitation was sent to ${data.data.email}, but you are logged in as ${user.email}`)
74
74
  return
@@ -22,7 +22,15 @@ import { query, queryOne } from '@nextsparkjs/core/lib/db'
22
22
  import { getBillingGateway } from '@nextsparkjs/core/lib/billing/gateways/factory'
23
23
  import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
24
24
  import type { PolarWebhookExtensions } from '@nextsparkjs/core/lib/billing/polar-webhook'
25
- import { polarWebhookExtensions } from '@/lib/billing/polar-webhook-extensions'
25
+
26
+ async function loadExtensions(): Promise<PolarWebhookExtensions> {
27
+ try {
28
+ const mod = await import('@/lib/billing/polar-webhook-extensions')
29
+ return mod.polarWebhookExtensions
30
+ } catch {
31
+ return {}
32
+ }
33
+ }
26
34
 
27
35
  async function handlePolarWebhook(request: NextRequest) {
28
36
  // 1. Get raw body and ALL headers (Polar needs full headers for verification)
@@ -86,7 +94,7 @@ async function handlePolarWebhook(request: NextRequest) {
86
94
  break
87
95
 
88
96
  case 'order.paid':
89
- await handleOrderPaid(event.data, eventId, polarWebhookExtensions)
97
+ await handleOrderPaid(event.data, eventId, await loadExtensions())
90
98
  break
91
99
 
92
100
  default:
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Handles Stripe subscription lifecycle events.
5
5
  * To add one-time payment handling (credit packs, LTD, upsells),
6
- * override lib/billing/stripe-webhook-extensions.ts in your project.
6
+ * create lib/billing/stripe-webhook-extensions.ts in your project.
7
7
  *
8
8
  * Rate limiting: 500 requests/hour per IP (tier: webhook).
9
9
  * Stripe signature verification is the primary security layer;
@@ -14,12 +14,21 @@
14
14
 
15
15
  import { NextRequest } from 'next/server'
16
16
  import { handleStripeWebhook } from '@nextsparkjs/core/lib/billing/stripe-webhook'
17
- import { stripeWebhookExtensions } from '@/lib/billing/stripe-webhook-extensions'
18
17
  import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
19
18
 
19
+ async function loadExtensions() {
20
+ try {
21
+ const mod = await import('@/lib/billing/stripe-webhook-extensions')
22
+ return mod.stripeWebhookExtensions
23
+ } catch {
24
+ return {}
25
+ }
26
+ }
27
+
20
28
  export const POST = withRateLimitTier(
21
29
  async (request: NextRequest) => {
22
- return handleStripeWebhook(request, stripeWebhookExtensions)
30
+ const extensions = await loadExtensions()
31
+ return handleStripeWebhook(request, extensions)
23
32
  },
24
33
  'webhook'
25
34
  )