gavaengine 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@ import { Editor, NodeViewProps } from '@tiptap/react';
3
3
  import * as _tiptap_core from '@tiptap/core';
4
4
  import { Node } from '@tiptap/core';
5
5
  import * as _tiptap_extension_youtube from '@tiptap/extension-youtube';
6
- import { g as GEMedia } from './types-X07o_zKf.js';
6
+ import { m as GEMedia } from './registry-Do5nzO7_.js';
7
7
  import { LucideIcon } from 'lucide-react';
8
8
 
9
9
  interface ArticleData {
@@ -1,9 +1,10 @@
1
1
  "use client";
2
2
  import {
3
3
  ActionsProvider,
4
+ ComponentRegistryProvider,
4
5
  ConfigProvider,
5
6
  SplashProvider
6
- } from "./chunk-MC3FBYWV.js";
7
+ } from "./chunk-PHT76VW6.js";
7
8
 
8
9
  // src/providers/GavaEngineProvider.tsx
9
10
  import { useRouter } from "next/navigation";
@@ -30,7 +31,7 @@ function GavaEngineProvider({
30
31
  children
31
32
  }) {
32
33
  const router = useRouter();
33
- return /* @__PURE__ */ jsx3(SessionProvider, { children: /* @__PURE__ */ jsx3(ThemeProvider, { children: /* @__PURE__ */ jsx3(ConfigProvider, { config, children: /* @__PURE__ */ jsx3(ActionsProvider, { actions, children: /* @__PURE__ */ jsx3(SplashProvider, { navigate: (url) => router.push(url), children }) }) }) }) });
34
+ return /* @__PURE__ */ jsx3(SessionProvider, { children: /* @__PURE__ */ jsx3(ThemeProvider, { children: /* @__PURE__ */ jsx3(ConfigProvider, { config, children: /* @__PURE__ */ jsx3(ActionsProvider, { actions, children: /* @__PURE__ */ jsx3(ComponentRegistryProvider, { overrides: config.components ?? {}, children: /* @__PURE__ */ jsx3(SplashProvider, { navigate: (url) => router.push(url), children }) }) }) }) }) });
34
35
  }
35
36
 
36
37
  // src/providers/ThemeToggle.tsx
@@ -64,4 +65,4 @@ export {
64
65
  GavaEngineProvider,
65
66
  ThemeToggle
66
67
  };
67
- //# sourceMappingURL=chunk-4LM22T36.js.map
68
+ //# sourceMappingURL=chunk-3ZYJ4C6R.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/providers/GavaEngineProvider.tsx","../src/providers/SessionProvider.tsx","../src/providers/ThemeProvider.tsx","../src/providers/ThemeToggle.tsx"],"sourcesContent":["\"use client\";\n\nimport { type ReactNode } from \"react\";\nimport { useRouter } from \"next/navigation\";\nimport { type GavaEngineConfig } from \"../config.js\";\nimport type { GEActions } from \"../types.js\";\nimport { ConfigProvider } from \"./ConfigContext.js\";\nimport { ActionsProvider } from \"./ActionsContext.js\";\nimport { SplashProvider } from \"./SplashContext.js\";\nimport { SessionProvider } from \"./SessionProvider.js\";\nimport { ThemeProvider } from \"./ThemeProvider.js\";\nimport { ComponentRegistryProvider } from \"../components/registry.js\";\n\ninterface GavaEngineProviderProps {\n config: GavaEngineConfig;\n actions: GEActions;\n children: ReactNode;\n}\n\nexport function GavaEngineProvider({\n config,\n actions,\n children,\n}: GavaEngineProviderProps) {\n const router = useRouter();\n\n return (\n <SessionProvider>\n <ThemeProvider>\n <ConfigProvider config={config}>\n <ActionsProvider actions={actions}>\n <ComponentRegistryProvider overrides={config.components ?? {}}>\n <SplashProvider navigate={(url) => router.push(url)}>\n {children}\n </SplashProvider>\n </ComponentRegistryProvider>\n </ActionsProvider>\n </ConfigProvider>\n </ThemeProvider>\n </SessionProvider>\n );\n}\n","\"use client\";\n\nimport { SessionProvider as NextAuthSessionProvider } from \"next-auth/react\";\nimport { type ReactNode } from \"react\";\n\nexport function SessionProvider({ children }: { children: ReactNode }) {\n return <NextAuthSessionProvider>{children}</NextAuthSessionProvider>;\n}\n","\"use client\";\n\nimport { ThemeProvider as NextThemesProvider } from \"next-themes\";\nimport { type ReactNode } from \"react\";\n\nexport function ThemeProvider({ children }: { children: ReactNode }) {\n return (\n <NextThemesProvider attribute=\"class\" defaultTheme=\"system\" enableSystem>\n {children}\n </NextThemesProvider>\n );\n}\n","\"use client\";\n\nimport { useTheme } from \"next-themes\";\nimport { useEffect, useState } from \"react\";\nimport { Sun, Moon } from \"lucide-react\";\n\nexport function ThemeToggle() {\n const [mounted, setMounted] = useState(false);\n const { theme, setTheme } = useTheme();\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n if (!mounted) {\n return (\n <button className=\"p-2 rounded-lg bg-card border border-card-border\">\n <div className=\"w-5 h-5\" />\n </button>\n );\n }\n\n return (\n <button\n onClick={() => setTheme(theme === \"dark\" ? \"light\" : \"dark\")}\n className=\"p-2 rounded-lg bg-card border border-card-border hover:bg-card-border transition-colors\"\n aria-label=\"Toggle theme\"\n >\n {theme === \"dark\" ? (\n <Sun className=\"w-5 h-5 text-foreground\" />\n ) : (\n <Moon className=\"w-5 h-5 text-foreground\" />\n )}\n </button>\n );\n}\n"],"mappings":";;;;;;;;;AAGA,SAAS,iBAAiB;;;ACD1B,SAAS,mBAAmB,+BAA+B;AAIlD;AADF,SAAS,gBAAgB,EAAE,SAAS,GAA4B;AACrE,SAAO,oBAAC,2BAAyB,UAAS;AAC5C;;;ACLA,SAAS,iBAAiB,0BAA0B;AAKhD,gBAAAA,YAAA;AAFG,SAAS,cAAc,EAAE,SAAS,GAA4B;AACnE,SACE,gBAAAA,KAAC,sBAAmB,WAAU,SAAQ,cAAa,UAAS,cAAY,MACrE,UACH;AAEJ;;;AFqBc,gBAAAC,YAAA;AAbP,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AACF,GAA4B;AAC1B,QAAM,SAAS,UAAU;AAEzB,SACE,gBAAAA,KAAC,mBACC,0BAAAA,KAAC,iBACC,0BAAAA,KAAC,kBAAe,QACd,0BAAAA,KAAC,mBAAgB,SACf,0BAAAA,KAAC,6BAA0B,WAAW,OAAO,cAAc,CAAC,GAC1D,0BAAAA,KAAC,kBAAe,UAAU,CAAC,QAAQ,OAAO,KAAK,GAAG,GAC/C,UACH,GACF,GACF,GACF,GACF,GACF;AAEJ;;;AGvCA,SAAS,gBAAgB;AACzB,SAAS,WAAW,gBAAgB;AACpC,SAAS,KAAK,YAAY;AAalB,gBAAAC,YAAA;AAXD,SAAS,cAAc;AAC5B,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,EAAE,OAAO,SAAS,IAAI,SAAS;AAErC,YAAU,MAAM;AACd,eAAW,IAAI;AAAA,EACjB,GAAG,CAAC,CAAC;AAEL,MAAI,CAAC,SAAS;AACZ,WACE,gBAAAA,KAAC,YAAO,WAAU,oDAChB,0BAAAA,KAAC,SAAI,WAAU,WAAU,GAC3B;AAAA,EAEJ;AAEA,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,MAAM,SAAS,UAAU,SAAS,UAAU,MAAM;AAAA,MAC3D,WAAU;AAAA,MACV,cAAW;AAAA,MAEV,oBAAU,SACT,gBAAAA,KAAC,OAAI,WAAU,2BAA0B,IAEzC,gBAAAA,KAAC,QAAK,WAAU,2BAA0B;AAAA;AAAA,EAE9C;AAEJ;","names":["jsx","jsx","jsx"]}
@@ -514,6 +514,27 @@ function SplashProvider({
514
514
  return /* @__PURE__ */ jsx3(SplashContext.Provider, { value: { phase, navigateWithSplash, openSplash }, children });
515
515
  }
516
516
 
517
+ // src/components/registry.tsx
518
+ import {
519
+ createContext as createContext4,
520
+ useContext as useContext4
521
+ } from "react";
522
+ import { jsx as jsx4 } from "react/jsx-runtime";
523
+ var RegistryContext = createContext4({});
524
+ function ComponentRegistryProvider({
525
+ overrides,
526
+ children
527
+ }) {
528
+ return /* @__PURE__ */ jsx4(RegistryContext.Provider, { value: overrides, children });
529
+ }
530
+ function useRegisteredComponent(name, fallback) {
531
+ const registry = useContext4(RegistryContext);
532
+ return registry[name] ?? fallback;
533
+ }
534
+ function useComponentRegistry() {
535
+ return useContext4(RegistryContext);
536
+ }
537
+
517
538
  export {
518
539
  it,
519
540
  en,
@@ -529,6 +550,9 @@ export {
529
550
  useGavaActions,
530
551
  ActionsProvider,
531
552
  useSplash,
532
- SplashProvider
553
+ SplashProvider,
554
+ ComponentRegistryProvider,
555
+ useRegisteredComponent,
556
+ useComponentRegistry
533
557
  };
534
- //# sourceMappingURL=chunk-MC3FBYWV.js.map
558
+ //# sourceMappingURL=chunk-PHT76VW6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/i18n/it.ts","../src/i18n/en.ts","../src/i18n/index.ts","../src/config.ts","../src/providers/ConfigContext.tsx","../src/providers/ActionsContext.tsx","../src/providers/SplashContext.tsx","../src/components/registry.tsx"],"sourcesContent":["import type { GELocale } from \"./types.js\";\n\nexport const it: GELocale = {\n content: {\n articles: \"Articoli\",\n newArticle: \"Nuovo articolo\",\n titlePlaceholder: \"Titolo dell'articolo\",\n excerptPlaceholder: \"Breve descrizione dell'articolo...\",\n slugPlaceholder: \"slug-articolo\",\n authorPlaceholder: \"Nome dell'autore\",\n category: \"Categoria\",\n selectCategory: \"Seleziona categoria\",\n excerpt: \"Estratto\",\n author: \"Autore\",\n slugUrl: \"Slug URL\",\n noArticles: \"Nessun articolo.\",\n noArticlesSearch: \"Nessun articolo trovato.\",\n searchArticles: \"Cerca articoli...\",\n coverImageLabel: \"Immagine di copertina\",\n coverImageHint: \"Scegli dalla libreria o carica un nuovo file\",\n viewArticle: \"Vedi articolo pubblicato\",\n untitled: \"Senza titolo\",\n },\n editor: {\n publish: \"Pubblica\",\n unpublish: \"Ritira\",\n saveDraft: \"Salva bozza\",\n revisions: \"Cronologia\",\n saving: \"Salvando...\",\n saved: \"Salvato\",\n saveError: \"Errore nel salvataggio\",\n noRevisions: \"Nessuna revisione salvata.\",\n restore: \"Ripristina\",\n restoreConfirm:\n \"Ripristinare questa revisione? Lo stato attuale verrà salvato prima del ripristino.\",\n beforeRestore: \"Prima del ripristino\",\n publishedNote: \"Pubblicato\",\n preview: \"Anteprima\",\n placeholder: \"Inizia a scrivere il tuo articolo...\",\n },\n media: {\n media: \"Media\",\n noMedia: \"Nessun file caricato.\",\n noMediaSearch: \"Nessun file trovato.\",\n chooseFile: \"Scegli file\",\n dragHint: \"Trascina un'immagine qui oppure\",\n uploadHint: \"JPEG, PNG, WebP, GIF (max 5MB)\",\n mediaLibrary: \"Libreria media\",\n uploadNew: \"Carica nuovo\",\n searchFiles: \"Cerca file...\",\n selectImage: \"Seleziona immagine\",\n noImages: \"Nessuna immagine nella libreria.\",\n noImagesSearch: \"Nessuna immagine trovata.\",\n copyUrl: \"Copia URL\",\n editImage: \"Modifica immagine\",\n restoreOriginal: \"Ripristina originale\",\n freeAspect: \"Libero\",\n },\n users: {\n users: \"Utenti\",\n name: \"Nome\",\n email: \"Email\",\n password: \"Password\",\n passwordEditHint: \" (lascia vuoto per non modificarla)\",\n role: \"Ruolo\",\n createdAt: \"Creato il\",\n actions: \"Azioni\",\n createUser: \"Crea utente\",\n unauthorized: \"Non autorizzato\",\n notAuthenticated: \"Non autenticato\",\n allFieldsRequired: \"Tutti i campi sono obbligatori.\",\n passwordMinLength: \"La password deve avere almeno 6 caratteri.\",\n emailExists: \"Esiste già un utente con questa email.\",\n invalidRole: \"Ruolo non valido.\",\n cannotDeleteSelf: \"Non puoi eliminare il tuo stesso account.\",\n },\n common: {\n statistics: \"Statistiche\",\n settings: \"Impostazioni\",\n delete: \"Elimina\",\n edit: \"Modifica\",\n search: \"Cerca\",\n draft: \"Bozza\",\n published: \"Pubblicato\",\n all: \"Tutti\",\n drafts: \"Bozze\",\n loading: \"Caricamento...\",\n confirm: \"Conferma\",\n cancel: \"Annulla\",\n apply: \"Applica\",\n change: \"Cambia\",\n logout: \"Esci\",\n saveChanges: \"Salva modifiche\",\n updated: \"Aggiornato\",\n status: \"Stato\",\n title: \"Titolo\",\n deleteConfirm: (title) => `Eliminare \"${title || \"Senza titolo\"}\"?`,\n unpublishConfirm: (title) =>\n `Ritirare \"${title || \"Senza titolo\"}\"? L'articolo tornerà in bozza.`,\n deleteUserConfirm: (name) =>\n `Sei sicuro di voler eliminare l'utente \"${name}\"?`,\n totalArticles: (count) =>\n `${count} articol${count === 1 ? \"o\" : \"i\"} totali`,\n totalFiles: (count) => `${count} file caricati`,\n },\n};\n","import type { GELocale } from \"./types.js\";\n\nexport const en: GELocale = {\n content: {\n articles: \"Articles\",\n newArticle: \"New article\",\n titlePlaceholder: \"Article title\",\n excerptPlaceholder: \"Brief description of the article...\",\n slugPlaceholder: \"article-slug\",\n authorPlaceholder: \"Author name\",\n category: \"Category\",\n selectCategory: \"Select category\",\n excerpt: \"Excerpt\",\n author: \"Author\",\n slugUrl: \"URL Slug\",\n noArticles: \"No articles.\",\n noArticlesSearch: \"No articles found.\",\n searchArticles: \"Search articles...\",\n coverImageLabel: \"Cover image\",\n coverImageHint: \"Choose from library or upload a new file\",\n viewArticle: \"View published article\",\n untitled: \"Untitled\",\n },\n editor: {\n publish: \"Publish\",\n unpublish: \"Unpublish\",\n saveDraft: \"Save draft\",\n revisions: \"History\",\n saving: \"Saving...\",\n saved: \"Saved\",\n saveError: \"Error saving\",\n noRevisions: \"No revisions saved.\",\n restore: \"Restore\",\n restoreConfirm:\n \"Restore this revision? The current state will be saved before restoring.\",\n beforeRestore: \"Before restore\",\n publishedNote: \"Published\",\n preview: \"Preview\",\n placeholder: \"Start writing your article...\",\n },\n media: {\n media: \"Media\",\n noMedia: \"No files uploaded.\",\n noMediaSearch: \"No files found.\",\n chooseFile: \"Choose file\",\n dragHint: \"Drag an image here or\",\n uploadHint: \"JPEG, PNG, WebP, GIF (max 5MB)\",\n mediaLibrary: \"Media library\",\n uploadNew: \"Upload new\",\n searchFiles: \"Search files...\",\n selectImage: \"Select image\",\n noImages: \"No images in library.\",\n noImagesSearch: \"No images found.\",\n copyUrl: \"Copy URL\",\n editImage: \"Edit image\",\n restoreOriginal: \"Restore original\",\n freeAspect: \"Free\",\n },\n users: {\n users: \"Users\",\n name: \"Name\",\n email: \"Email\",\n password: \"Password\",\n passwordEditHint: \" (leave blank to keep current)\",\n role: \"Role\",\n createdAt: \"Created at\",\n actions: \"Actions\",\n createUser: \"Create user\",\n unauthorized: \"Unauthorized\",\n notAuthenticated: \"Not authenticated\",\n allFieldsRequired: \"All fields are required.\",\n passwordMinLength: \"Password must be at least 6 characters.\",\n emailExists: \"A user with this email already exists.\",\n invalidRole: \"Invalid role.\",\n cannotDeleteSelf: \"You cannot delete your own account.\",\n },\n common: {\n statistics: \"Statistics\",\n settings: \"Settings\",\n delete: \"Delete\",\n edit: \"Edit\",\n search: \"Search\",\n draft: \"Draft\",\n published: \"Published\",\n all: \"All\",\n drafts: \"Drafts\",\n loading: \"Loading...\",\n confirm: \"Confirm\",\n cancel: \"Cancel\",\n apply: \"Apply\",\n change: \"Change\",\n logout: \"Logout\",\n saveChanges: \"Save changes\",\n updated: \"Updated\",\n status: \"Status\",\n title: \"Title\",\n deleteConfirm: (title) => `Delete \"${title || \"Untitled\"}\"?`,\n unpublishConfirm: (title) =>\n `Unpublish \"${title || \"Untitled\"}\"? The article will go back to draft.`,\n deleteUserConfirm: (name) =>\n `Are you sure you want to delete user \"${name}\"?`,\n totalArticles: (count) =>\n `${count} total article${count === 1 ? \"\" : \"s\"}`,\n totalFiles: (count) => `${count} uploaded file${count === 1 ? \"\" : \"s\"}`,\n },\n};\n","import type { GELocale } from \"./types.js\";\nimport { it } from \"./it.js\";\nimport { en } from \"./en.js\";\n\nexport type { GELocale } from \"./types.js\";\nexport { it } from \"./it.js\";\nexport { en } from \"./en.js\";\n\nconst builtinLocales: Record<string, GELocale> = { it, en };\n\nexport function loadLocale(locale: string): GELocale {\n const found = builtinLocales[locale];\n if (!found) {\n throw new Error(\n `Locale \"${locale}\" not found. Available: ${Object.keys(builtinLocales).join(\", \")}`\n );\n }\n return found;\n}\n\nexport function defineLocale(locale: GELocale): GELocale {\n return locale;\n}\n\nexport function mergeLocales(\n base: GELocale,\n overrides: DeepPartial<GELocale>\n): GELocale {\n return deepMergeLocale(base, overrides);\n}\n\nexport function registerLocale(key: string, locale: GELocale): void {\n builtinLocales[key] = locale;\n}\n\ntype DeepPartial<T> = {\n [P in keyof T]?: T[P] extends (...args: any[]) => any\n ? T[P]\n : T[P] extends object\n ? DeepPartial<T[P]>\n : T[P];\n};\n\nfunction deepMergeLocale<T extends Record<string, any>>(\n target: T,\n source: DeepPartial<T>\n): T {\n const result = { ...target };\n for (const key of Object.keys(source) as (keyof T)[]) {\n const sourceVal = source[key];\n const targetVal = target[key];\n if (\n sourceVal &&\n typeof sourceVal === \"object\" &&\n !Array.isArray(sourceVal) &&\n typeof targetVal === \"object\" &&\n !Array.isArray(targetVal) &&\n typeof sourceVal !== \"function\"\n ) {\n (result as any)[key] = deepMergeLocale(\n targetVal as Record<string, any>,\n sourceVal as Record<string, any>\n );\n } else if (sourceVal !== undefined) {\n (result as any)[key] = sourceVal;\n }\n }\n return result;\n}\n","import { loadLocale } from \"./i18n/index.js\";\nimport type { GELocale } from \"./i18n/types.js\";\nimport type { GEAuthAdapter } from \"./auth/types.js\";\nimport type { GEContentType } from \"./content/types.js\";\nimport type { GEComponentOverrides } from \"./components/registry.js\";\n\nexport interface GavaEngineConfig {\n branding: {\n name: string;\n logo?: string;\n };\n roles: {\n list: string[];\n labels: Record<string, string>;\n canEdit: (role: string) => boolean;\n canPublish: (role: string) => boolean;\n adminRole: string;\n };\n statuses: {\n draft: string;\n published: string;\n };\n locale: string;\n models: {\n article: string;\n articleRevision: string;\n articleView: string;\n media: string;\n user: string;\n };\n auth?: GEAuthAdapter;\n contentTypes?: GEContentType[];\n components?: GEComponentOverrides;\n categories: string[];\n upload: {\n endpoint: string;\n imageTypes: string[];\n videoTypes: string[];\n maxImageSize: number;\n maxVideoSize: number;\n };\n editor: {\n placeholder: string;\n autoSaveDelay: number;\n revisionThrottleMinutes: number;\n headingLevels: number[];\n };\n routes: {\n articles: string;\n articleEdit: (id: string) => string;\n articleNew: string;\n articleView: (slug: string) => string;\n articlePreview: (id: string) => string;\n users: string;\n userEdit: (id: string) => string;\n userNew: string;\n media: string;\n dashboard: string;\n login: string;\n home: string;\n };\n strings: {\n articles: string;\n newArticle: string;\n media: string;\n users: string;\n statistics: string;\n settings: string;\n revisions: string;\n publish: string;\n unpublish: string;\n saveDraft: string;\n delete: string;\n edit: string;\n search: string;\n titlePlaceholder: string;\n excerptPlaceholder: string;\n slugPlaceholder: string;\n authorPlaceholder: string;\n category: string;\n selectCategory: string;\n excerpt: string;\n author: string;\n slugUrl: string;\n draft: string;\n published: string;\n all: string;\n drafts: string;\n saving: string;\n saved: string;\n saveError: string;\n noArticles: string;\n noArticlesSearch: string;\n noMedia: string;\n noMediaSearch: string;\n noRevisions: string;\n loading: string;\n confirm: string;\n cancel: string;\n apply: string;\n change: string;\n logout: string;\n viewArticle: string;\n preview: string;\n restore: string;\n restoreConfirm: string;\n beforeRestore: string;\n publishedNote: string;\n deleteConfirm: (title: string) => string;\n unpublishConfirm: (title: string) => string;\n deleteUserConfirm: (name: string) => string;\n totalArticles: (count: number) => string;\n totalFiles: (count: number) => string;\n coverImageLabel: string;\n coverImageHint: string;\n chooseFile: string;\n dragHint: string;\n uploadHint: string;\n mediaLibrary: string;\n uploadNew: string;\n searchFiles: string;\n searchArticles: string;\n selectImage: string;\n noImages: string;\n noImagesSearch: string;\n copyUrl: string;\n editImage: string;\n restoreOriginal: string;\n freeAspect: string;\n unauthorized: string;\n notAuthenticated: string;\n allFieldsRequired: string;\n passwordMinLength: string;\n emailExists: string;\n invalidRole: string;\n cannotDeleteSelf: string;\n name: string;\n email: string;\n password: string;\n passwordEditHint: string;\n role: string;\n createdAt: string;\n actions: string;\n createUser: string;\n saveChanges: string;\n updated: string;\n status: string;\n title: string;\n untitled: string;\n };\n}\n\nfunction localeToStrings(locale: GELocale): GavaEngineConfig[\"strings\"] {\n return {\n // content\n articles: locale.content.articles,\n newArticle: locale.content.newArticle,\n titlePlaceholder: locale.content.titlePlaceholder,\n excerptPlaceholder: locale.content.excerptPlaceholder,\n slugPlaceholder: locale.content.slugPlaceholder,\n authorPlaceholder: locale.content.authorPlaceholder,\n category: locale.content.category,\n selectCategory: locale.content.selectCategory,\n excerpt: locale.content.excerpt,\n author: locale.content.author,\n slugUrl: locale.content.slugUrl,\n noArticles: locale.content.noArticles,\n noArticlesSearch: locale.content.noArticlesSearch,\n searchArticles: locale.content.searchArticles,\n coverImageLabel: locale.content.coverImageLabel,\n coverImageHint: locale.content.coverImageHint,\n viewArticle: locale.content.viewArticle,\n untitled: locale.content.untitled,\n // editor\n publish: locale.editor.publish,\n unpublish: locale.editor.unpublish,\n saveDraft: locale.editor.saveDraft,\n revisions: locale.editor.revisions,\n saving: locale.editor.saving,\n saved: locale.editor.saved,\n saveError: locale.editor.saveError,\n noRevisions: locale.editor.noRevisions,\n restore: locale.editor.restore,\n restoreConfirm: locale.editor.restoreConfirm,\n beforeRestore: locale.editor.beforeRestore,\n publishedNote: locale.editor.publishedNote,\n preview: locale.editor.preview,\n // media\n media: locale.media.media,\n noMedia: locale.media.noMedia,\n noMediaSearch: locale.media.noMediaSearch,\n chooseFile: locale.media.chooseFile,\n dragHint: locale.media.dragHint,\n uploadHint: locale.media.uploadHint,\n mediaLibrary: locale.media.mediaLibrary,\n uploadNew: locale.media.uploadNew,\n searchFiles: locale.media.searchFiles,\n selectImage: locale.media.selectImage,\n noImages: locale.media.noImages,\n noImagesSearch: locale.media.noImagesSearch,\n copyUrl: locale.media.copyUrl,\n editImage: locale.media.editImage,\n restoreOriginal: locale.media.restoreOriginal,\n freeAspect: locale.media.freeAspect,\n // users\n users: locale.users.users,\n name: locale.users.name,\n email: locale.users.email,\n password: locale.users.password,\n passwordEditHint: locale.users.passwordEditHint,\n role: locale.users.role,\n createdAt: locale.users.createdAt,\n actions: locale.users.actions,\n createUser: locale.users.createUser,\n unauthorized: locale.users.unauthorized,\n notAuthenticated: locale.users.notAuthenticated,\n allFieldsRequired: locale.users.allFieldsRequired,\n passwordMinLength: locale.users.passwordMinLength,\n emailExists: locale.users.emailExists,\n invalidRole: locale.users.invalidRole,\n cannotDeleteSelf: locale.users.cannotDeleteSelf,\n // common\n statistics: locale.common.statistics,\n settings: locale.common.settings,\n delete: locale.common.delete,\n edit: locale.common.edit,\n search: locale.common.search,\n draft: locale.common.draft,\n published: locale.common.published,\n all: locale.common.all,\n drafts: locale.common.drafts,\n loading: locale.common.loading,\n confirm: locale.common.confirm,\n cancel: locale.common.cancel,\n apply: locale.common.apply,\n change: locale.common.change,\n logout: locale.common.logout,\n saveChanges: locale.common.saveChanges,\n updated: locale.common.updated,\n status: locale.common.status,\n title: locale.common.title,\n deleteConfirm: locale.common.deleteConfirm,\n unpublishConfirm: locale.common.unpublishConfirm,\n deleteUserConfirm: locale.common.deleteUserConfirm,\n totalArticles: locale.common.totalArticles,\n totalFiles: locale.common.totalFiles,\n };\n}\n\nconst DEFAULT_STRINGS = localeToStrings(loadLocale(\"it\"));\n\nconst DEFAULT_CONFIG: GavaEngineConfig = {\n branding: {\n name: \"GavaEngine\",\n },\n roles: {\n list: [\"admin\", \"redattore\", \"scrittore\", \"lettore\"],\n labels: {\n admin: \"Amministratore\",\n redattore: \"Redattore\",\n scrittore: \"Scrittore\",\n lettore: \"Lettore\",\n },\n canEdit: (role: string) => role !== \"lettore\",\n canPublish: (role: string) => role === \"admin\" || role === \"redattore\",\n adminRole: \"admin\",\n },\n statuses: {\n draft: \"bozza\",\n published: \"pubblicato\",\n },\n locale: \"it\",\n models: {\n article: \"article\",\n articleRevision: \"articleRevision\",\n articleView: \"articleView\",\n media: \"media\",\n user: \"user\",\n },\n categories: [\n \"Cultura ed Intercultura\",\n \"Fatti ed Eventi\",\n \"Poeti e Prosatori\",\n \"Famiglia, Istituzioni e Territorio\",\n \"Amici del Meucci\",\n ],\n upload: {\n endpoint: \"/api/upload\",\n imageTypes: [\"image/jpeg\", \"image/png\", \"image/webp\", \"image/gif\"],\n videoTypes: [\"video/mp4\", \"video/webm\", \"video/quicktime\"],\n maxImageSize: 5 * 1024 * 1024,\n maxVideoSize: 50 * 1024 * 1024,\n },\n editor: {\n placeholder: \"Inizia a scrivere il tuo articolo...\",\n autoSaveDelay: 2000,\n revisionThrottleMinutes: 5,\n headingLevels: [2, 3],\n },\n routes: {\n articles: \"/dashboard/articoli\",\n articleEdit: (id) => `/dashboard/articoli/${id}`,\n articleNew: \"/dashboard/articoli/nuovo\",\n articleView: (slug) => `/articoli/${slug}`,\n articlePreview: (id) => `/anteprima/${id}`,\n users: \"/dashboard/utenti\",\n userEdit: (id) => `/dashboard/utenti/${id}`,\n userNew: \"/dashboard/utenti/nuovo\",\n media: \"/dashboard/media\",\n dashboard: \"/dashboard\",\n login: \"/login\",\n home: \"/\",\n },\n strings: DEFAULT_STRINGS,\n};\n\nfunction deepMerge<T extends Record<string, any>>(\n target: T,\n source: Partial<T>\n): T {\n const result = { ...target };\n for (const key of Object.keys(source) as (keyof T)[]) {\n const sourceVal = source[key];\n const targetVal = target[key];\n if (\n sourceVal &&\n typeof sourceVal === \"object\" &&\n !Array.isArray(sourceVal) &&\n typeof targetVal === \"object\" &&\n !Array.isArray(targetVal) &&\n typeof sourceVal !== \"function\"\n ) {\n (result as any)[key] = deepMerge(\n targetVal as Record<string, any>,\n sourceVal as Record<string, any>\n );\n } else if (sourceVal !== undefined) {\n (result as any)[key] = sourceVal;\n }\n }\n return result;\n}\n\nexport function defineConfig(\n overrides: Partial<GavaEngineConfig> = {}\n): GavaEngineConfig {\n // If a different locale is specified, load it as base strings\n const locale = overrides.locale ?? DEFAULT_CONFIG.locale;\n const baseStrings = localeToStrings(loadLocale(locale));\n\n // Build config with locale-based strings as default\n const configWithLocale = {\n ...DEFAULT_CONFIG,\n strings: baseStrings,\n };\n\n // Also update editor.placeholder from locale if not overridden\n if (!overrides.editor?.placeholder) {\n const localeData = loadLocale(locale);\n configWithLocale.editor = {\n ...configWithLocale.editor,\n placeholder: localeData.editor.placeholder,\n };\n }\n\n return deepMerge(configWithLocale, overrides);\n}\n\nexport { DEFAULT_CONFIG, localeToStrings };\n","\"use client\";\n\nimport { createContext, useContext, type ReactNode } from \"react\";\nimport { type GavaEngineConfig, DEFAULT_CONFIG } from \"../config.js\";\n\nconst ConfigContext = createContext<GavaEngineConfig>(DEFAULT_CONFIG);\n\nexport function useGavaConfig() {\n return useContext(ConfigContext);\n}\n\nexport function ConfigProvider({\n config,\n children,\n}: {\n config: GavaEngineConfig;\n children: ReactNode;\n}) {\n return (\n <ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>\n );\n}\n","\"use client\";\n\nimport { createContext, useContext, type ReactNode } from \"react\";\nimport type { GEActions } from \"../types.js\";\n\nconst ActionsContext = createContext<GEActions | null>(null);\n\nexport function useGavaActions(): GEActions {\n const ctx = useContext(ActionsContext);\n if (!ctx) {\n throw new Error(\n \"useGavaActions must be used within a <GavaEngineProvider> with actions provided.\"\n );\n }\n return ctx;\n}\n\nexport function ActionsProvider({\n actions,\n children,\n}: {\n actions: GEActions;\n children: ReactNode;\n}) {\n return (\n <ActionsContext.Provider value={actions}>{children}</ActionsContext.Provider>\n );\n}\n","\"use client\";\n\nimport {\n createContext,\n useContext,\n useState,\n useCallback,\n type ReactNode,\n} from \"react\";\n\ntype Phase = \"idle\" | \"closing\" | \"closed\" | \"opening\";\n\ninterface SplashContextValue {\n phase: Phase;\n navigateWithSplash: (url: string) => void;\n openSplash: () => void;\n}\n\nconst SplashContext = createContext<SplashContextValue>({\n phase: \"idle\",\n navigateWithSplash: () => {},\n openSplash: () => {},\n});\n\nexport function useSplash() {\n return useContext(SplashContext);\n}\n\nexport function SplashProvider({\n children,\n navigate,\n}: {\n children: ReactNode;\n navigate: (url: string) => void;\n}) {\n const [phase, setPhase] = useState<Phase>(\"idle\");\n\n const navigateWithSplash = useCallback(\n (url: string) => {\n if (phase !== \"idle\") return;\n setPhase(\"closing\");\n\n setTimeout(() => {\n setPhase(\"closed\");\n navigate(url);\n }, 700);\n },\n [phase, navigate]\n );\n\n const openSplash = useCallback(() => {\n if (phase !== \"closed\") return;\n requestAnimationFrame(() => {\n setPhase(\"opening\");\n setTimeout(() => setPhase(\"idle\"), 900);\n });\n }, [phase]);\n\n return (\n <SplashContext.Provider value={{ phase, navigateWithSplash, openSplash }}>\n {children}\n </SplashContext.Provider>\n );\n}\n","\"use client\";\n\nimport {\n createContext,\n useContext,\n type ComponentType,\n type ReactNode,\n} from \"react\";\nimport type { ContentEditorProps } from \"./content/ContentEditor.js\";\nimport type { ContentListProps } from \"./content/ContentList.js\";\n\nexport interface GEComponentOverrides {\n DashboardNavbar?: ComponentType<any>;\n DashboardLayout?: ComponentType<{ children: ReactNode }>;\n EditorToolbar?: ComponentType<{ editor: any }>;\n ContentEditor?: ComponentType<ContentEditorProps>;\n ContentList?: ComponentType<ContentListProps>;\n MediaGrid?: ComponentType<any>;\n UserTable?: ComponentType<any>;\n LoginPage?: ComponentType<any>;\n StatCard?: ComponentType<any>;\n}\n\nconst RegistryContext = createContext<GEComponentOverrides>({});\n\nexport function ComponentRegistryProvider({\n overrides,\n children,\n}: {\n overrides: GEComponentOverrides;\n children: ReactNode;\n}) {\n return (\n <RegistryContext.Provider value={overrides}>\n {children}\n </RegistryContext.Provider>\n );\n}\n\nexport function useRegisteredComponent<K extends keyof GEComponentOverrides>(\n name: K,\n fallback: NonNullable<GEComponentOverrides[K]>\n): NonNullable<GEComponentOverrides[K]> {\n const registry = useContext(RegistryContext);\n return (registry[name] as NonNullable<GEComponentOverrides[K]>) ?? fallback;\n}\n\nexport function useComponentRegistry(): GEComponentOverrides {\n return useContext(RegistryContext);\n}\n"],"mappings":"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","names":["createContext","useContext","jsx","createContext","useContext","jsx","createContext","useContext","jsx"]}
@@ -3,7 +3,7 @@ import {
3
3
  useGavaActions,
4
4
  useGavaConfig,
5
5
  useSplash
6
- } from "./chunk-MC3FBYWV.js";
6
+ } from "./chunk-PHT76VW6.js";
7
7
 
8
8
  // src/components/editor/ArticleEditor.tsx
9
9
  import { useState as useState6, useEffect as useEffect4, useCallback as useCallback4, useRef as useRef3 } from "react";
@@ -3258,4 +3258,4 @@ export {
3258
3258
  SplashScreen,
3259
3259
  DashboardSplashTrigger
3260
3260
  };
3261
- //# sourceMappingURL=chunk-5X5LEDAN.js.map
3261
+ //# sourceMappingURL=chunk-XUWBLDOW.js.map
@@ -1,30 +1,13 @@
1
- export { A as ArticleEditor, a as ArticleList, C as CoverImageUpload, D as DashboardNavbar, b as DashboardSplashTrigger, c as DraggableYoutube, d as DraggableYoutubeView, E as EditorToolbar, I as ImageEditModal, M as MediaGrid, e as MediaPickerModal, R as ResizableImage, f as ResizableImageView, g as RevisionPanel, S as SplashScreen, h as StatCard, U as UserForm, i as UserTable, V as VideoExtension, j as VideoView } from '../DashboardSplashTrigger-CRpueuUi.js';
1
+ import { G as GEFieldDef } from '../registry-Do5nzO7_.js';
2
+ export { C as ComponentRegistryProvider, a as ContentEditor, b as ContentEditorProps, c as ContentList, d as ContentListProps, e as GEComponentOverrides, u as useComponentRegistry, f as useRegisteredComponent } from '../registry-Do5nzO7_.js';
3
+ export { A as ArticleEditor, a as ArticleList, C as CoverImageUpload, D as DashboardNavbar, b as DashboardSplashTrigger, c as DraggableYoutube, d as DraggableYoutubeView, E as EditorToolbar, I as ImageEditModal, M as MediaGrid, e as MediaPickerModal, R as ResizableImage, f as ResizableImageView, g as RevisionPanel, S as SplashScreen, h as StatCard, U as UserForm, i as UserTable, V as VideoExtension, j as VideoView } from '../DashboardSplashTrigger-Bz4Z4edN.js';
2
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
- import { G as GEContentType, a as GEContentActions, b as GEFieldDef } from '../types-X07o_zKf.js';
5
+ import 'react';
4
6
  import '@tiptap/react';
5
7
  import '@tiptap/core';
6
8
  import '@tiptap/extension-youtube';
7
9
  import 'lucide-react';
8
10
 
9
- interface ContentEditorProps {
10
- contentType: GEContentType;
11
- actions: GEContentActions;
12
- initialData?: Record<string, any>;
13
- id?: string;
14
- categories?: string[];
15
- onSave?: () => void;
16
- onPublish?: () => void;
17
- }
18
- declare function ContentEditor({ contentType, actions, initialData, id, categories, onSave, onPublish, }: ContentEditorProps): react_jsx_runtime.JSX.Element;
19
-
20
- interface ContentListProps {
21
- contentType: GEContentType;
22
- actions: GEContentActions;
23
- onEdit?: (id: string) => void;
24
- onCreate?: () => void;
25
- }
26
- declare function ContentList({ contentType, actions, onEdit, onCreate, }: ContentListProps): react_jsx_runtime.JSX.Element;
27
-
28
11
  interface TextRendererProps {
29
12
  field: GEFieldDef;
30
13
  value: string;
@@ -102,4 +85,4 @@ interface CategoryManagerProps {
102
85
  }
103
86
  declare function CategoryManager({ getCategories, createCategory, updateCategory, deleteCategory, }: CategoryManagerProps): react_jsx_runtime.JSX.Element;
104
87
 
105
- export { BooleanRenderer, CategoryManager, ContentEditor, type ContentEditorProps, ContentList, type ContentListProps, DateRenderer, ImageRenderer, JsonRenderer, NumberRenderer, SelectRenderer, SlugRenderer, TextRenderer };
88
+ export { BooleanRenderer, CategoryManager, DateRenderer, ImageRenderer, JsonRenderer, NumberRenderer, SelectRenderer, SlugRenderer, TextRenderer };
@@ -31,13 +31,18 @@ import {
31
31
  UserTable,
32
32
  VideoExtension,
33
33
  VideoView
34
- } from "../chunk-5X5LEDAN.js";
35
- import "../chunk-MC3FBYWV.js";
34
+ } from "../chunk-XUWBLDOW.js";
35
+ import {
36
+ ComponentRegistryProvider,
37
+ useComponentRegistry,
38
+ useRegisteredComponent
39
+ } from "../chunk-PHT76VW6.js";
36
40
  export {
37
41
  ArticleEditor,
38
42
  ArticleList,
39
43
  BooleanRenderer,
40
44
  CategoryManager,
45
+ ComponentRegistryProvider,
41
46
  ContentEditor,
42
47
  ContentList,
43
48
  CoverImageUpload,
@@ -64,6 +69,8 @@ export {
64
69
  UserForm,
65
70
  UserTable,
66
71
  VideoExtension,
67
- VideoView
72
+ VideoView,
73
+ useComponentRegistry,
74
+ useRegisteredComponent
68
75
  };
69
76
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,5 @@
1
1
  import { GEContentType } from '../content/index.js';
2
+ import { ComponentType, ReactNode } from 'react';
2
3
 
3
4
  interface GEUser {
4
5
  id: string;
@@ -18,6 +19,60 @@ interface GEAuthAdapter {
18
19
  signOut?(): Promise<void>;
19
20
  }
20
21
 
22
+ interface GEContentActions {
23
+ getAll(options?: {
24
+ search?: string;
25
+ status?: string;
26
+ }): Promise<any[]>;
27
+ getById(id: string): Promise<any | null>;
28
+ create(data?: Record<string, any>): Promise<string>;
29
+ update(id: string, data: Record<string, any>): Promise<{
30
+ success: boolean;
31
+ }>;
32
+ delete(id: string): Promise<{
33
+ success: boolean;
34
+ }>;
35
+ publish?(id: string): Promise<{
36
+ success: boolean;
37
+ }>;
38
+ unpublish?(id: string): Promise<{
39
+ success: boolean;
40
+ }>;
41
+ }
42
+
43
+ interface ContentEditorProps {
44
+ contentType: GEContentType;
45
+ actions: GEContentActions;
46
+ initialData?: Record<string, any>;
47
+ id?: string;
48
+ categories?: string[];
49
+ onSave?: () => void;
50
+ onPublish?: () => void;
51
+ }
52
+
53
+ interface ContentListProps {
54
+ contentType: GEContentType;
55
+ actions: GEContentActions;
56
+ onEdit?: (id: string) => void;
57
+ onCreate?: () => void;
58
+ }
59
+
60
+ interface GEComponentOverrides {
61
+ DashboardNavbar?: ComponentType<any>;
62
+ DashboardLayout?: ComponentType<{
63
+ children: ReactNode;
64
+ }>;
65
+ EditorToolbar?: ComponentType<{
66
+ editor: any;
67
+ }>;
68
+ ContentEditor?: ComponentType<ContentEditorProps>;
69
+ ContentList?: ComponentType<ContentListProps>;
70
+ MediaGrid?: ComponentType<any>;
71
+ UserTable?: ComponentType<any>;
72
+ LoginPage?: ComponentType<any>;
73
+ StatCard?: ComponentType<any>;
74
+ }
75
+
21
76
  interface GavaEngineConfig {
22
77
  branding: {
23
78
  name: string;
@@ -44,6 +99,7 @@ interface GavaEngineConfig {
44
99
  };
45
100
  auth?: GEAuthAdapter;
46
101
  contentTypes?: GEContentType[];
102
+ components?: GEComponentOverrides;
47
103
  categories: string[];
48
104
  upload: {
49
105
  endpoint: string;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/i18n/it.ts","../../src/i18n/en.ts","../../src/i18n/index.ts","../../src/config.ts","../../src/handlers/revisions.ts","../../src/handlers/articles.ts","../../src/handlers/users.ts","../../src/handlers/media.ts","../../src/handlers/upload.ts","../../src/handlers/auth.ts","../../src/handlers/auth-utils.ts","../../src/handlers/content.ts","../../src/handlers/categories.ts"],"sourcesContent":["import type { GELocale } from \"./types.js\";\n\nexport const it: GELocale = {\n content: {\n articles: \"Articoli\",\n newArticle: \"Nuovo articolo\",\n titlePlaceholder: \"Titolo dell'articolo\",\n excerptPlaceholder: \"Breve descrizione dell'articolo...\",\n slugPlaceholder: \"slug-articolo\",\n authorPlaceholder: \"Nome dell'autore\",\n category: \"Categoria\",\n selectCategory: \"Seleziona categoria\",\n excerpt: \"Estratto\",\n author: \"Autore\",\n slugUrl: \"Slug URL\",\n noArticles: \"Nessun articolo.\",\n noArticlesSearch: \"Nessun articolo trovato.\",\n searchArticles: \"Cerca articoli...\",\n coverImageLabel: \"Immagine di copertina\",\n coverImageHint: \"Scegli dalla libreria o carica un nuovo file\",\n viewArticle: \"Vedi articolo pubblicato\",\n untitled: \"Senza titolo\",\n },\n editor: {\n publish: \"Pubblica\",\n unpublish: \"Ritira\",\n saveDraft: \"Salva bozza\",\n revisions: \"Cronologia\",\n saving: \"Salvando...\",\n saved: \"Salvato\",\n saveError: \"Errore nel salvataggio\",\n noRevisions: \"Nessuna revisione salvata.\",\n restore: \"Ripristina\",\n restoreConfirm:\n \"Ripristinare questa revisione? Lo stato attuale verrà salvato prima del ripristino.\",\n beforeRestore: \"Prima del ripristino\",\n publishedNote: \"Pubblicato\",\n preview: \"Anteprima\",\n placeholder: \"Inizia a scrivere il tuo articolo...\",\n },\n media: {\n media: \"Media\",\n noMedia: \"Nessun file caricato.\",\n noMediaSearch: \"Nessun file trovato.\",\n chooseFile: \"Scegli file\",\n dragHint: \"Trascina un'immagine qui oppure\",\n uploadHint: \"JPEG, PNG, WebP, GIF (max 5MB)\",\n mediaLibrary: \"Libreria media\",\n uploadNew: \"Carica nuovo\",\n searchFiles: \"Cerca file...\",\n selectImage: \"Seleziona immagine\",\n noImages: \"Nessuna immagine nella libreria.\",\n noImagesSearch: \"Nessuna immagine trovata.\",\n copyUrl: \"Copia URL\",\n editImage: \"Modifica immagine\",\n restoreOriginal: \"Ripristina originale\",\n freeAspect: \"Libero\",\n },\n users: {\n users: \"Utenti\",\n name: \"Nome\",\n email: \"Email\",\n password: \"Password\",\n passwordEditHint: \" (lascia vuoto per non modificarla)\",\n role: \"Ruolo\",\n createdAt: \"Creato il\",\n actions: \"Azioni\",\n createUser: \"Crea utente\",\n unauthorized: \"Non autorizzato\",\n notAuthenticated: \"Non autenticato\",\n allFieldsRequired: \"Tutti i campi sono obbligatori.\",\n passwordMinLength: \"La password deve avere almeno 6 caratteri.\",\n emailExists: \"Esiste già un utente con questa email.\",\n invalidRole: \"Ruolo non valido.\",\n cannotDeleteSelf: \"Non puoi eliminare il tuo stesso account.\",\n },\n common: {\n statistics: \"Statistiche\",\n settings: \"Impostazioni\",\n delete: \"Elimina\",\n edit: \"Modifica\",\n search: \"Cerca\",\n draft: \"Bozza\",\n published: \"Pubblicato\",\n all: \"Tutti\",\n drafts: \"Bozze\",\n loading: \"Caricamento...\",\n confirm: \"Conferma\",\n cancel: \"Annulla\",\n apply: \"Applica\",\n change: \"Cambia\",\n logout: \"Esci\",\n saveChanges: \"Salva modifiche\",\n updated: \"Aggiornato\",\n status: \"Stato\",\n title: \"Titolo\",\n deleteConfirm: (title) => `Eliminare \"${title || \"Senza titolo\"}\"?`,\n unpublishConfirm: (title) =>\n `Ritirare \"${title || \"Senza titolo\"}\"? L'articolo tornerà in bozza.`,\n deleteUserConfirm: (name) =>\n `Sei sicuro di voler eliminare l'utente \"${name}\"?`,\n totalArticles: (count) =>\n `${count} articol${count === 1 ? \"o\" : \"i\"} totali`,\n totalFiles: (count) => `${count} file caricati`,\n },\n};\n","import type { GELocale } from \"./types.js\";\n\nexport const en: GELocale = {\n content: {\n articles: \"Articles\",\n newArticle: \"New article\",\n titlePlaceholder: \"Article title\",\n excerptPlaceholder: \"Brief description of the article...\",\n slugPlaceholder: \"article-slug\",\n authorPlaceholder: \"Author name\",\n category: \"Category\",\n selectCategory: \"Select category\",\n excerpt: \"Excerpt\",\n author: \"Author\",\n slugUrl: \"URL Slug\",\n noArticles: \"No articles.\",\n noArticlesSearch: \"No articles found.\",\n searchArticles: \"Search articles...\",\n coverImageLabel: \"Cover image\",\n coverImageHint: \"Choose from library or upload a new file\",\n viewArticle: \"View published article\",\n untitled: \"Untitled\",\n },\n editor: {\n publish: \"Publish\",\n unpublish: \"Unpublish\",\n saveDraft: \"Save draft\",\n revisions: \"History\",\n saving: \"Saving...\",\n saved: \"Saved\",\n saveError: \"Error saving\",\n noRevisions: \"No revisions saved.\",\n restore: \"Restore\",\n restoreConfirm:\n \"Restore this revision? The current state will be saved before restoring.\",\n beforeRestore: \"Before restore\",\n publishedNote: \"Published\",\n preview: \"Preview\",\n placeholder: \"Start writing your article...\",\n },\n media: {\n media: \"Media\",\n noMedia: \"No files uploaded.\",\n noMediaSearch: \"No files found.\",\n chooseFile: \"Choose file\",\n dragHint: \"Drag an image here or\",\n uploadHint: \"JPEG, PNG, WebP, GIF (max 5MB)\",\n mediaLibrary: \"Media library\",\n uploadNew: \"Upload new\",\n searchFiles: \"Search files...\",\n selectImage: \"Select image\",\n noImages: \"No images in library.\",\n noImagesSearch: \"No images found.\",\n copyUrl: \"Copy URL\",\n editImage: \"Edit image\",\n restoreOriginal: \"Restore original\",\n freeAspect: \"Free\",\n },\n users: {\n users: \"Users\",\n name: \"Name\",\n email: \"Email\",\n password: \"Password\",\n passwordEditHint: \" (leave blank to keep current)\",\n role: \"Role\",\n createdAt: \"Created at\",\n actions: \"Actions\",\n createUser: \"Create user\",\n unauthorized: \"Unauthorized\",\n notAuthenticated: \"Not authenticated\",\n allFieldsRequired: \"All fields are required.\",\n passwordMinLength: \"Password must be at least 6 characters.\",\n emailExists: \"A user with this email already exists.\",\n invalidRole: \"Invalid role.\",\n cannotDeleteSelf: \"You cannot delete your own account.\",\n },\n common: {\n statistics: \"Statistics\",\n settings: \"Settings\",\n delete: \"Delete\",\n edit: \"Edit\",\n search: \"Search\",\n draft: \"Draft\",\n published: \"Published\",\n all: \"All\",\n drafts: \"Drafts\",\n loading: \"Loading...\",\n confirm: \"Confirm\",\n cancel: \"Cancel\",\n apply: \"Apply\",\n change: \"Change\",\n logout: \"Logout\",\n saveChanges: \"Save changes\",\n updated: \"Updated\",\n status: \"Status\",\n title: \"Title\",\n deleteConfirm: (title) => `Delete \"${title || \"Untitled\"}\"?`,\n unpublishConfirm: (title) =>\n `Unpublish \"${title || \"Untitled\"}\"? The article will go back to draft.`,\n deleteUserConfirm: (name) =>\n `Are you sure you want to delete user \"${name}\"?`,\n totalArticles: (count) =>\n `${count} total article${count === 1 ? \"\" : \"s\"}`,\n totalFiles: (count) => `${count} uploaded file${count === 1 ? \"\" : \"s\"}`,\n },\n};\n","import type { GELocale } from \"./types.js\";\nimport { it } from \"./it.js\";\nimport { en } from \"./en.js\";\n\nexport type { GELocale } from \"./types.js\";\nexport { it } from \"./it.js\";\nexport { en } from \"./en.js\";\n\nconst builtinLocales: Record<string, GELocale> = { it, en };\n\nexport function loadLocale(locale: string): GELocale {\n const found = builtinLocales[locale];\n if (!found) {\n throw new Error(\n `Locale \"${locale}\" not found. Available: ${Object.keys(builtinLocales).join(\", \")}`\n );\n }\n return found;\n}\n\nexport function defineLocale(locale: GELocale): GELocale {\n return locale;\n}\n\nexport function mergeLocales(\n base: GELocale,\n overrides: DeepPartial<GELocale>\n): GELocale {\n return deepMergeLocale(base, overrides);\n}\n\nexport function registerLocale(key: string, locale: GELocale): void {\n builtinLocales[key] = locale;\n}\n\ntype DeepPartial<T> = {\n [P in keyof T]?: T[P] extends (...args: any[]) => any\n ? T[P]\n : T[P] extends object\n ? DeepPartial<T[P]>\n : T[P];\n};\n\nfunction deepMergeLocale<T extends Record<string, any>>(\n target: T,\n source: DeepPartial<T>\n): T {\n const result = { ...target };\n for (const key of Object.keys(source) as (keyof T)[]) {\n const sourceVal = source[key];\n const targetVal = target[key];\n if (\n sourceVal &&\n typeof sourceVal === \"object\" &&\n !Array.isArray(sourceVal) &&\n typeof targetVal === \"object\" &&\n !Array.isArray(targetVal) &&\n typeof sourceVal !== \"function\"\n ) {\n (result as any)[key] = deepMergeLocale(\n targetVal as Record<string, any>,\n sourceVal as Record<string, any>\n );\n } else if (sourceVal !== undefined) {\n (result as any)[key] = sourceVal;\n }\n }\n return result;\n}\n","import { loadLocale } from \"./i18n/index.js\";\nimport type { GELocale } from \"./i18n/types.js\";\nimport type { GEAuthAdapter } from \"./auth/types.js\";\nimport type { GEContentType } from \"./content/types.js\";\n\nexport interface GavaEngineConfig {\n branding: {\n name: string;\n logo?: string;\n };\n roles: {\n list: string[];\n labels: Record<string, string>;\n canEdit: (role: string) => boolean;\n canPublish: (role: string) => boolean;\n adminRole: string;\n };\n statuses: {\n draft: string;\n published: string;\n };\n locale: string;\n models: {\n article: string;\n articleRevision: string;\n articleView: string;\n media: string;\n user: string;\n };\n auth?: GEAuthAdapter;\n contentTypes?: GEContentType[];\n categories: string[];\n upload: {\n endpoint: string;\n imageTypes: string[];\n videoTypes: string[];\n maxImageSize: number;\n maxVideoSize: number;\n };\n editor: {\n placeholder: string;\n autoSaveDelay: number;\n revisionThrottleMinutes: number;\n headingLevels: number[];\n };\n routes: {\n articles: string;\n articleEdit: (id: string) => string;\n articleNew: string;\n articleView: (slug: string) => string;\n articlePreview: (id: string) => string;\n users: string;\n userEdit: (id: string) => string;\n userNew: string;\n media: string;\n dashboard: string;\n login: string;\n home: string;\n };\n strings: {\n articles: string;\n newArticle: string;\n media: string;\n users: string;\n statistics: string;\n settings: string;\n revisions: string;\n publish: string;\n unpublish: string;\n saveDraft: string;\n delete: string;\n edit: string;\n search: string;\n titlePlaceholder: string;\n excerptPlaceholder: string;\n slugPlaceholder: string;\n authorPlaceholder: string;\n category: string;\n selectCategory: string;\n excerpt: string;\n author: string;\n slugUrl: string;\n draft: string;\n published: string;\n all: string;\n drafts: string;\n saving: string;\n saved: string;\n saveError: string;\n noArticles: string;\n noArticlesSearch: string;\n noMedia: string;\n noMediaSearch: string;\n noRevisions: string;\n loading: string;\n confirm: string;\n cancel: string;\n apply: string;\n change: string;\n logout: string;\n viewArticle: string;\n preview: string;\n restore: string;\n restoreConfirm: string;\n beforeRestore: string;\n publishedNote: string;\n deleteConfirm: (title: string) => string;\n unpublishConfirm: (title: string) => string;\n deleteUserConfirm: (name: string) => string;\n totalArticles: (count: number) => string;\n totalFiles: (count: number) => string;\n coverImageLabel: string;\n coverImageHint: string;\n chooseFile: string;\n dragHint: string;\n uploadHint: string;\n mediaLibrary: string;\n uploadNew: string;\n searchFiles: string;\n searchArticles: string;\n selectImage: string;\n noImages: string;\n noImagesSearch: string;\n copyUrl: string;\n editImage: string;\n restoreOriginal: string;\n freeAspect: string;\n unauthorized: string;\n notAuthenticated: string;\n allFieldsRequired: string;\n passwordMinLength: string;\n emailExists: string;\n invalidRole: string;\n cannotDeleteSelf: string;\n name: string;\n email: string;\n password: string;\n passwordEditHint: string;\n role: string;\n createdAt: string;\n actions: string;\n createUser: string;\n saveChanges: string;\n updated: string;\n status: string;\n title: string;\n untitled: string;\n };\n}\n\nfunction localeToStrings(locale: GELocale): GavaEngineConfig[\"strings\"] {\n return {\n // content\n articles: locale.content.articles,\n newArticle: locale.content.newArticle,\n titlePlaceholder: locale.content.titlePlaceholder,\n excerptPlaceholder: locale.content.excerptPlaceholder,\n slugPlaceholder: locale.content.slugPlaceholder,\n authorPlaceholder: locale.content.authorPlaceholder,\n category: locale.content.category,\n selectCategory: locale.content.selectCategory,\n excerpt: locale.content.excerpt,\n author: locale.content.author,\n slugUrl: locale.content.slugUrl,\n noArticles: locale.content.noArticles,\n noArticlesSearch: locale.content.noArticlesSearch,\n searchArticles: locale.content.searchArticles,\n coverImageLabel: locale.content.coverImageLabel,\n coverImageHint: locale.content.coverImageHint,\n viewArticle: locale.content.viewArticle,\n untitled: locale.content.untitled,\n // editor\n publish: locale.editor.publish,\n unpublish: locale.editor.unpublish,\n saveDraft: locale.editor.saveDraft,\n revisions: locale.editor.revisions,\n saving: locale.editor.saving,\n saved: locale.editor.saved,\n saveError: locale.editor.saveError,\n noRevisions: locale.editor.noRevisions,\n restore: locale.editor.restore,\n restoreConfirm: locale.editor.restoreConfirm,\n beforeRestore: locale.editor.beforeRestore,\n publishedNote: locale.editor.publishedNote,\n preview: locale.editor.preview,\n // media\n media: locale.media.media,\n noMedia: locale.media.noMedia,\n noMediaSearch: locale.media.noMediaSearch,\n chooseFile: locale.media.chooseFile,\n dragHint: locale.media.dragHint,\n uploadHint: locale.media.uploadHint,\n mediaLibrary: locale.media.mediaLibrary,\n uploadNew: locale.media.uploadNew,\n searchFiles: locale.media.searchFiles,\n selectImage: locale.media.selectImage,\n noImages: locale.media.noImages,\n noImagesSearch: locale.media.noImagesSearch,\n copyUrl: locale.media.copyUrl,\n editImage: locale.media.editImage,\n restoreOriginal: locale.media.restoreOriginal,\n freeAspect: locale.media.freeAspect,\n // users\n users: locale.users.users,\n name: locale.users.name,\n email: locale.users.email,\n password: locale.users.password,\n passwordEditHint: locale.users.passwordEditHint,\n role: locale.users.role,\n createdAt: locale.users.createdAt,\n actions: locale.users.actions,\n createUser: locale.users.createUser,\n unauthorized: locale.users.unauthorized,\n notAuthenticated: locale.users.notAuthenticated,\n allFieldsRequired: locale.users.allFieldsRequired,\n passwordMinLength: locale.users.passwordMinLength,\n emailExists: locale.users.emailExists,\n invalidRole: locale.users.invalidRole,\n cannotDeleteSelf: locale.users.cannotDeleteSelf,\n // common\n statistics: locale.common.statistics,\n settings: locale.common.settings,\n delete: locale.common.delete,\n edit: locale.common.edit,\n search: locale.common.search,\n draft: locale.common.draft,\n published: locale.common.published,\n all: locale.common.all,\n drafts: locale.common.drafts,\n loading: locale.common.loading,\n confirm: locale.common.confirm,\n cancel: locale.common.cancel,\n apply: locale.common.apply,\n change: locale.common.change,\n logout: locale.common.logout,\n saveChanges: locale.common.saveChanges,\n updated: locale.common.updated,\n status: locale.common.status,\n title: locale.common.title,\n deleteConfirm: locale.common.deleteConfirm,\n unpublishConfirm: locale.common.unpublishConfirm,\n deleteUserConfirm: locale.common.deleteUserConfirm,\n totalArticles: locale.common.totalArticles,\n totalFiles: locale.common.totalFiles,\n };\n}\n\nconst DEFAULT_STRINGS = localeToStrings(loadLocale(\"it\"));\n\nconst DEFAULT_CONFIG: GavaEngineConfig = {\n branding: {\n name: \"GavaEngine\",\n },\n roles: {\n list: [\"admin\", \"redattore\", \"scrittore\", \"lettore\"],\n labels: {\n admin: \"Amministratore\",\n redattore: \"Redattore\",\n scrittore: \"Scrittore\",\n lettore: \"Lettore\",\n },\n canEdit: (role: string) => role !== \"lettore\",\n canPublish: (role: string) => role === \"admin\" || role === \"redattore\",\n adminRole: \"admin\",\n },\n statuses: {\n draft: \"bozza\",\n published: \"pubblicato\",\n },\n locale: \"it\",\n models: {\n article: \"article\",\n articleRevision: \"articleRevision\",\n articleView: \"articleView\",\n media: \"media\",\n user: \"user\",\n },\n categories: [\n \"Cultura ed Intercultura\",\n \"Fatti ed Eventi\",\n \"Poeti e Prosatori\",\n \"Famiglia, Istituzioni e Territorio\",\n \"Amici del Meucci\",\n ],\n upload: {\n endpoint: \"/api/upload\",\n imageTypes: [\"image/jpeg\", \"image/png\", \"image/webp\", \"image/gif\"],\n videoTypes: [\"video/mp4\", \"video/webm\", \"video/quicktime\"],\n maxImageSize: 5 * 1024 * 1024,\n maxVideoSize: 50 * 1024 * 1024,\n },\n editor: {\n placeholder: \"Inizia a scrivere il tuo articolo...\",\n autoSaveDelay: 2000,\n revisionThrottleMinutes: 5,\n headingLevels: [2, 3],\n },\n routes: {\n articles: \"/dashboard/articoli\",\n articleEdit: (id) => `/dashboard/articoli/${id}`,\n articleNew: \"/dashboard/articoli/nuovo\",\n articleView: (slug) => `/articoli/${slug}`,\n articlePreview: (id) => `/anteprima/${id}`,\n users: \"/dashboard/utenti\",\n userEdit: (id) => `/dashboard/utenti/${id}`,\n userNew: \"/dashboard/utenti/nuovo\",\n media: \"/dashboard/media\",\n dashboard: \"/dashboard\",\n login: \"/login\",\n home: \"/\",\n },\n strings: DEFAULT_STRINGS,\n};\n\nfunction deepMerge<T extends Record<string, any>>(\n target: T,\n source: Partial<T>\n): T {\n const result = { ...target };\n for (const key of Object.keys(source) as (keyof T)[]) {\n const sourceVal = source[key];\n const targetVal = target[key];\n if (\n sourceVal &&\n typeof sourceVal === \"object\" &&\n !Array.isArray(sourceVal) &&\n typeof targetVal === \"object\" &&\n !Array.isArray(targetVal) &&\n typeof sourceVal !== \"function\"\n ) {\n (result as any)[key] = deepMerge(\n targetVal as Record<string, any>,\n sourceVal as Record<string, any>\n );\n } else if (sourceVal !== undefined) {\n (result as any)[key] = sourceVal;\n }\n }\n return result;\n}\n\nexport function defineConfig(\n overrides: Partial<GavaEngineConfig> = {}\n): GavaEngineConfig {\n // If a different locale is specified, load it as base strings\n const locale = overrides.locale ?? DEFAULT_CONFIG.locale;\n const baseStrings = localeToStrings(loadLocale(locale));\n\n // Build config with locale-based strings as default\n const configWithLocale = {\n ...DEFAULT_CONFIG,\n strings: baseStrings,\n };\n\n // Also update editor.placeholder from locale if not overridden\n if (!overrides.editor?.placeholder) {\n const localeData = loadLocale(locale);\n configWithLocale.editor = {\n ...configWithLocale.editor,\n placeholder: localeData.editor.placeholder,\n };\n }\n\n return deepMerge(configWithLocale, overrides);\n}\n\nexport { DEFAULT_CONFIG, localeToStrings };\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport function createRevisionHandlers(prisma: any, config: GavaEngineConfig) {\n const throttleMs = config.editor.revisionThrottleMinutes * 60 * 1000;\n const articleModel = config.models.article;\n const revisionModel = config.models.articleRevision;\n\n return {\n async getRevisions(articleId: string) {\n return prisma[revisionModel].findMany({\n where: { articleId },\n include: { editor: { select: { name: true } } },\n orderBy: { createdAt: \"desc\" },\n });\n },\n\n async restoreRevision(\n articleId: string,\n revisionId: string,\n editorId: string\n ) {\n const article = await prisma[articleModel].findUnique({\n where: { id: articleId },\n });\n if (!article) throw new Error(\"Article not found\");\n\n const revision = await prisma[revisionModel].findUnique({\n where: { id: revisionId },\n });\n if (!revision || revision.articleId !== articleId) {\n throw new Error(\"Revision not found\");\n }\n\n // Save current state before restoring\n await prisma[revisionModel].create({\n data: {\n articleId,\n title: article.title,\n content: article.content,\n excerpt: article.excerpt,\n coverImage: article.coverImage,\n category: article.category,\n editorId,\n note: config.strings.beforeRestore,\n },\n });\n\n // Restore\n await prisma[articleModel].update({\n where: { id: articleId },\n data: {\n title: revision.title,\n content: revision.content,\n excerpt: revision.excerpt,\n coverImage: revision.coverImage,\n category: revision.category,\n updatedAt: new Date(),\n },\n });\n\n return { success: true };\n },\n\n async createRevisionSnapshot(\n articleId: string,\n editorId: string,\n note: string = \"\"\n ) {\n const article = await prisma[articleModel].findUnique({\n where: { id: articleId },\n });\n if (!article) return;\n\n // Throttle: only create if last revision was > threshold ago\n const threshold = new Date(Date.now() - throttleMs);\n const recent = await prisma[revisionModel].findFirst({\n where: { articleId, createdAt: { gte: threshold } },\n orderBy: { createdAt: \"desc\" },\n });\n\n if (recent && !note) return;\n\n await prisma[revisionModel].create({\n data: {\n articleId,\n title: article.title,\n content: article.content,\n excerpt: article.excerpt,\n coverImage: article.coverImage,\n category: article.category,\n editorId,\n note,\n },\n });\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\nimport { createRevisionHandlers } from \"./revisions.js\";\n\nexport function createArticleHandlers(prisma: any, config: GavaEngineConfig) {\n const revisionHandlers = createRevisionHandlers(prisma, config);\n const articleModel = config.models.article;\n\n return {\n async getArticles() {\n return prisma[articleModel].findMany({\n orderBy: { updatedAt: \"desc\" },\n });\n },\n\n async getArticleById(id: string) {\n return prisma[articleModel].findUnique({\n where: { id },\n });\n },\n\n async createArticle(authorName: string) {\n const article = await prisma[articleModel].create({\n data: {\n authorName,\n },\n });\n return article.id;\n },\n\n async updateArticle(\n userId: string,\n id: string,\n data: {\n title?: string;\n slug?: string;\n excerpt?: string;\n content?: string;\n coverImage?: string;\n category?: string;\n authorName?: string;\n }\n ) {\n const article = await prisma[articleModel].findUnique({ where: { id } });\n if (!article) throw new Error(\"Article not found\");\n\n await revisionHandlers.createRevisionSnapshot(id, userId);\n\n await prisma[articleModel].update({\n where: { id },\n data: { ...data, updatedAt: new Date() },\n });\n\n return { success: true };\n },\n\n async deleteArticle(id: string) {\n const article = await prisma[articleModel].findUnique({ where: { id } });\n if (!article) throw new Error(\"Article not found\");\n\n await prisma[articleModel].delete({ where: { id } });\n return { success: true };\n },\n\n async publishArticle(userId: string, id: string) {\n const article = await prisma[articleModel].findUnique({ where: { id } });\n if (!article) throw new Error(\"Article not found\");\n\n if (!article.title || !article.slug) {\n throw new Error(\n \"Title and slug are required for publishing\"\n );\n }\n\n await revisionHandlers.createRevisionSnapshot(\n id,\n userId,\n config.strings.publishedNote\n );\n\n await prisma[articleModel].update({\n where: { id },\n data: {\n status: config.statuses.published,\n publishedAt: new Date(),\n },\n });\n\n return { success: true };\n },\n\n async unpublishArticle(id: string) {\n const article = await prisma[articleModel].findUnique({ where: { id } });\n if (!article) throw new Error(\"Article not found\");\n\n await prisma[articleModel].update({\n where: { id },\n data: {\n status: config.statuses.draft,\n publishedAt: null,\n },\n });\n\n return { success: true };\n },\n };\n}\n","import bcrypt from \"bcryptjs\";\nimport type { GavaEngineConfig } from \"../config.js\";\n\nexport function createUserHandlers(prisma: any, config: GavaEngineConfig) {\n const userModel = config.models.user;\n\n return {\n async getUsers() {\n return prisma[userModel].findMany({\n select: {\n id: true,\n name: true,\n email: true,\n role: true,\n createdAt: true,\n },\n orderBy: { createdAt: \"desc\" },\n });\n },\n\n async getUserById(id: string) {\n return prisma[userModel].findUnique({\n where: { id },\n select: {\n id: true,\n name: true,\n email: true,\n role: true,\n },\n });\n },\n\n async createUser(formData: FormData) {\n const name = formData.get(\"name\") as string;\n const email = formData.get(\"email\") as string;\n const password = formData.get(\"password\") as string;\n const role = formData.get(\"role\") as string;\n\n if (!name || !email || !password || !role) {\n return { error: config.strings.allFieldsRequired };\n }\n\n if (!config.roles.list.includes(role)) {\n return { error: config.strings.invalidRole };\n }\n\n if (password.length < 6) {\n return { error: config.strings.passwordMinLength };\n }\n\n const existing = await prisma[userModel].findUnique({ where: { email } });\n if (existing) {\n return { error: config.strings.emailExists };\n }\n\n const hashedPassword = await bcrypt.hash(password, 10);\n\n await prisma[userModel].create({\n data: {\n name,\n email,\n password: hashedPassword,\n role,\n },\n });\n\n return { success: true };\n },\n\n async updateUser(id: string, formData: FormData) {\n const name = formData.get(\"name\") as string;\n const email = formData.get(\"email\") as string;\n const password = formData.get(\"password\") as string;\n const role = formData.get(\"role\") as string;\n\n if (!name || !email || !role) {\n return { error: config.strings.allFieldsRequired };\n }\n\n if (!config.roles.list.includes(role)) {\n return { error: config.strings.invalidRole };\n }\n\n const existing = await prisma[userModel].findUnique({ where: { email } });\n if (existing && existing.id !== id) {\n return { error: config.strings.emailExists };\n }\n\n const data: {\n name: string;\n email: string;\n role: string;\n password?: string;\n } = {\n name,\n email,\n role,\n };\n\n if (password && password.length > 0) {\n if (password.length < 6) {\n return { error: config.strings.passwordMinLength };\n }\n data.password = await bcrypt.hash(password, 10);\n }\n\n await prisma[userModel].update({\n where: { id },\n data,\n });\n\n return { success: true };\n },\n\n async deleteUser(currentUserId: string, id: string) {\n if (currentUserId === id) {\n return { error: config.strings.cannotDeleteSelf };\n }\n\n await prisma[userModel].delete({ where: { id } });\n return { success: true };\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport function createMediaHandlers(prisma: any, config: GavaEngineConfig) {\n const mediaModel = config.models.media;\n const articleModel = config.models.article;\n\n return {\n async getMedia(search?: string) {\n return prisma[mediaModel].findMany({\n where: search ? { filename: { contains: search } } : undefined,\n include: { uploader: { select: { name: true } } },\n orderBy: { createdAt: \"desc\" },\n });\n },\n\n async deleteMedia(\n userId: string,\n userRole: string,\n id: string,\n deleteFileFromDisk?: (path: string) => Promise<void>\n ) {\n const media = await prisma[mediaModel].findUnique({ where: { id } });\n if (!media) throw new Error(\"File not found\");\n\n // Writers can only delete their own media\n if (userRole === \"scrittore\" && media.uploaderId !== userId) {\n throw new Error(\"Unauthorized\");\n }\n\n // Check if image is used in articles\n const usedInArticles = await prisma[articleModel].findMany({\n where: {\n OR: [\n { coverImage: media.path },\n { content: { contains: media.path } },\n ],\n },\n select: { id: true, title: true },\n });\n\n if (usedInArticles.length > 0) {\n const titles = usedInArticles\n .map((a: { title: string }) => a.title || \"Untitled\")\n .join(\", \");\n throw new Error(\n `Cannot delete: image is used in ${usedInArticles.length} article(s) (${titles})`\n );\n }\n\n // Delete file from disk if handler provided\n if (deleteFileFromDisk) {\n try {\n await deleteFileFromDisk(media.path);\n } catch {\n // File may already be missing\n }\n }\n\n await prisma[mediaModel].delete({ where: { id } });\n return { success: true };\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport interface UploadResult {\n url?: string;\n error?: string;\n}\n\nexport interface FileStorage {\n save(filename: string, buffer: Buffer, mimeType: string): Promise<string>;\n}\n\nexport function createUploadHandler(\n prisma: any,\n config: GavaEngineConfig,\n storage: FileStorage\n) {\n const allowedTypes = [\n ...config.upload.imageTypes,\n ...config.upload.videoTypes,\n ];\n\n const mediaModel = config.models.media;\n\n return {\n async handleUpload(\n file: {\n name: string;\n type: string;\n size: number;\n arrayBuffer: () => Promise<ArrayBuffer>;\n },\n uploaderId: string\n ): Promise<UploadResult> {\n if (!allowedTypes.includes(file.type)) {\n return { error: \"Unsupported file type\" };\n }\n\n const isVideo = config.upload.videoTypes.includes(file.type);\n const maxSize = isVideo\n ? config.upload.maxVideoSize\n : config.upload.maxImageSize;\n\n if (file.size > maxSize) {\n return {\n error: `File too large. Max ${isVideo ? config.upload.maxVideoSize / (1024 * 1024) : config.upload.maxImageSize / (1024 * 1024)}MB.`,\n };\n }\n\n const buffer = Buffer.from(await file.arrayBuffer());\n const url = await storage.save(file.name, buffer, file.type);\n\n await prisma[mediaModel].create({\n data: {\n filename: file.name,\n path: url,\n mimeType: file.type,\n size: file.size,\n uploaderId,\n },\n });\n\n return { url };\n },\n };\n}\n","import bcrypt from \"bcryptjs\";\nimport type { GavaEngineConfig } from \"../config.js\";\n\nexport function buildCredentialsProvider(prisma: any, config?: GavaEngineConfig) {\n const userModel = config?.models?.user ?? \"user\";\n\n return {\n credentials: {\n email: {},\n password: {},\n },\n async authorize(credentials: Record<string, unknown>) {\n const email = credentials.email as string;\n const password = credentials.password as string;\n\n if (!email || !password) return null;\n\n const user = await prisma[userModel].findUnique({\n where: { email },\n });\n\n if (!user) return null;\n\n const isValid = await bcrypt.compare(password, user.password);\n if (!isValid) return null;\n\n return {\n id: user.id,\n name: user.name,\n email: user.email,\n role: user.role,\n };\n },\n };\n}\n\nexport function buildAuthCallbacks(config: GavaEngineConfig) {\n return {\n async jwt({\n token,\n user,\n }: {\n token: Record<string, unknown>;\n user?: Record<string, unknown>;\n }) {\n if (user) {\n token.id = user.id as string;\n token.role = user.role as string;\n }\n return token;\n },\n async session({\n session,\n token,\n }: {\n session: Record<string, any>;\n token: Record<string, unknown>;\n }) {\n if (session.user) {\n session.user.id = token.id as string;\n session.user.role = token.role as string;\n }\n return session;\n },\n authorized({\n auth,\n request: { nextUrl },\n }: {\n auth: Record<string, any> | null;\n request: { nextUrl: URL };\n }) {\n const isLoggedIn = !!auth;\n const role = auth?.user?.role;\n const pathname = nextUrl.pathname;\n\n if (pathname === config.routes.login && isLoggedIn) {\n return Response.redirect(new URL(config.routes.articles, nextUrl));\n }\n\n if (pathname.startsWith(config.routes.dashboard)) {\n if (!isLoggedIn) {\n return Response.redirect(new URL(config.routes.login, nextUrl));\n }\n\n if (\n pathname.startsWith(config.routes.users) &&\n role !== config.roles.adminRole\n ) {\n return Response.redirect(\n new URL(config.routes.articles, nextUrl)\n );\n }\n }\n\n return true;\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport function createAuthUtils(config: GavaEngineConfig) {\n return {\n canEdit(role: string): boolean {\n return config.roles.canEdit(role);\n },\n canPublish(role: string): boolean {\n return config.roles.canPublish(role);\n },\n isAdmin(role: string): boolean {\n return role === config.roles.adminRole;\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\nimport type { GEContentType } from \"../content/types.js\";\n\nexport interface ContentHandlers {\n getAll(options?: {\n search?: string;\n status?: string;\n orderBy?: Record<string, \"asc\" | \"desc\">;\n }): Promise<any[]>;\n getById(id: string): Promise<any | null>;\n create(data?: Record<string, any>): Promise<string>;\n update(id: string, data: Record<string, any>): Promise<{ success: boolean }>;\n delete(id: string): Promise<{ success: boolean }>;\n publish?(userId: string, id: string): Promise<{ success: boolean }>;\n unpublish?(id: string): Promise<{ success: boolean }>;\n}\n\nexport function createContentHandlers(\n prisma: any,\n contentType: GEContentType,\n config: GavaEngineConfig\n): ContentHandlers {\n const modelName = contentType.slug.replace(/s$/, \"\").replace(/(^|\\-)(\\w)/g, (_m, _p1, p2) => p2.toUpperCase());\n // Try to find the Prisma model — fallback to slug\n const model = prisma[modelName] ?? prisma[contentType.slug];\n\n if (!model) {\n throw new Error(\n `Prisma model \"${modelName}\" not found for content type \"${contentType.slug}\"`\n );\n }\n\n const defaultSort = contentType.admin?.defaultSort\n ? { [contentType.admin.defaultSort.field]: contentType.admin.defaultSort.direction }\n : { updatedAt: \"desc\" };\n\n const searchableFields = contentType.admin?.searchableFields ?? [\"title\"];\n\n return {\n async getAll(options) {\n const where: Record<string, any> = {};\n\n if (options?.search) {\n where.OR = searchableFields.map((field) => ({\n [field]: { contains: options.search },\n }));\n }\n\n if (options?.status) {\n where.status = options.status;\n }\n\n return model.findMany({\n where: Object.keys(where).length > 0 ? where : undefined,\n orderBy: options?.orderBy ?? defaultSort,\n });\n },\n\n async getById(id: string) {\n return model.findUnique({ where: { id } });\n },\n\n async create(data?: Record<string, any>) {\n const createData: Record<string, any> = {};\n\n // Set default values from field definitions\n for (const field of contentType.fields) {\n if (field.defaultValue !== undefined) {\n createData[field.name] = field.defaultValue;\n }\n }\n\n // Set default status\n if (contentType.defaultStatus) {\n createData.status = contentType.defaultStatus;\n }\n\n // Merge provided data\n if (data) {\n Object.assign(createData, data);\n }\n\n const record = await model.create({\n data: createData,\n });\n\n return record.id;\n },\n\n async update(id: string, data: Record<string, any>) {\n const record = await model.findUnique({ where: { id } });\n if (!record) throw new Error(`${contentType.labels.singular} not found`);\n\n await model.update({\n where: { id },\n data: { ...data, updatedAt: new Date() },\n });\n\n return { success: true };\n },\n\n async delete(id: string) {\n const record = await model.findUnique({ where: { id } });\n if (!record) throw new Error(`${contentType.labels.singular} not found`);\n\n await model.delete({ where: { id } });\n return { success: true };\n },\n\n async publish(userId: string, id: string) {\n if (!contentType.publishedStatus) return { success: false };\n\n const record = await model.findUnique({ where: { id } });\n if (!record) throw new Error(`${contentType.labels.singular} not found`);\n\n await model.update({\n where: { id },\n data: {\n status: contentType.publishedStatus,\n publishedAt: new Date(),\n },\n });\n\n return { success: true };\n },\n\n async unpublish(id: string) {\n if (!contentType.defaultStatus) return { success: false };\n\n const record = await model.findUnique({ where: { id } });\n if (!record) throw new Error(`${contentType.labels.singular} not found`);\n\n await model.update({\n where: { id },\n data: {\n status: contentType.defaultStatus,\n publishedAt: null,\n },\n });\n\n return { success: true };\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport function createCategoryHandlers(prisma: any, config: GavaEngineConfig) {\n const categoryModel = prisma.category;\n\n return {\n async getCategories() {\n if (!categoryModel) {\n // Fallback: return config categories as static list\n return config.categories.map((name, i) => ({\n id: `static-${i}`,\n name,\n slug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n sortOrder: i,\n }));\n }\n\n return categoryModel.findMany({\n orderBy: { sortOrder: \"asc\" },\n });\n },\n\n async createCategory(data: { name: string; slug?: string; sortOrder?: number }) {\n if (!categoryModel) {\n throw new Error(\"Category model not available — categories are static from config\");\n }\n\n const slug =\n data.slug ??\n data.name\n .toLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .replace(/[^a-z0-9\\s-]/g, \"\")\n .replace(/\\s+/g, \"-\");\n\n return categoryModel.create({\n data: {\n name: data.name,\n slug,\n sortOrder: data.sortOrder ?? 0,\n },\n });\n },\n\n async updateCategory(\n id: string,\n data: { name?: string; slug?: string; sortOrder?: number }\n ) {\n if (!categoryModel) {\n throw new Error(\"Category model not available — categories are static from config\");\n }\n\n return categoryModel.update({\n where: { id },\n data,\n });\n },\n\n async deleteCategory(id: string) {\n if (!categoryModel) {\n throw new Error(\"Category model not available — categories are static from config\");\n }\n\n await categoryModel.delete({ where: { id } });\n return { success: true };\n },\n\n async seedCategories() {\n if (!categoryModel) return;\n\n const existing = await categoryModel.count();\n if (existing > 0) return;\n\n for (let i = 0; i < config.categories.length; i++) {\n const name = config.categories[i];\n const slug = name\n .toLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .replace(/[^a-z0-9\\s-]/g, \"\")\n .replace(/\\s+/g, \"-\");\n\n await categoryModel.create({\n data: {\n name,\n slug,\n sortOrder: i,\n },\n });\n }\n },\n };\n}\n"],"mappings":"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","names":["bcrypt"]}
1
+ {"version":3,"sources":["../../src/i18n/it.ts","../../src/i18n/en.ts","../../src/i18n/index.ts","../../src/config.ts","../../src/handlers/revisions.ts","../../src/handlers/articles.ts","../../src/handlers/users.ts","../../src/handlers/media.ts","../../src/handlers/upload.ts","../../src/handlers/auth.ts","../../src/handlers/auth-utils.ts","../../src/handlers/content.ts","../../src/handlers/categories.ts"],"sourcesContent":["import type { GELocale } from \"./types.js\";\n\nexport const it: GELocale = {\n content: {\n articles: \"Articoli\",\n newArticle: \"Nuovo articolo\",\n titlePlaceholder: \"Titolo dell'articolo\",\n excerptPlaceholder: \"Breve descrizione dell'articolo...\",\n slugPlaceholder: \"slug-articolo\",\n authorPlaceholder: \"Nome dell'autore\",\n category: \"Categoria\",\n selectCategory: \"Seleziona categoria\",\n excerpt: \"Estratto\",\n author: \"Autore\",\n slugUrl: \"Slug URL\",\n noArticles: \"Nessun articolo.\",\n noArticlesSearch: \"Nessun articolo trovato.\",\n searchArticles: \"Cerca articoli...\",\n coverImageLabel: \"Immagine di copertina\",\n coverImageHint: \"Scegli dalla libreria o carica un nuovo file\",\n viewArticle: \"Vedi articolo pubblicato\",\n untitled: \"Senza titolo\",\n },\n editor: {\n publish: \"Pubblica\",\n unpublish: \"Ritira\",\n saveDraft: \"Salva bozza\",\n revisions: \"Cronologia\",\n saving: \"Salvando...\",\n saved: \"Salvato\",\n saveError: \"Errore nel salvataggio\",\n noRevisions: \"Nessuna revisione salvata.\",\n restore: \"Ripristina\",\n restoreConfirm:\n \"Ripristinare questa revisione? Lo stato attuale verrà salvato prima del ripristino.\",\n beforeRestore: \"Prima del ripristino\",\n publishedNote: \"Pubblicato\",\n preview: \"Anteprima\",\n placeholder: \"Inizia a scrivere il tuo articolo...\",\n },\n media: {\n media: \"Media\",\n noMedia: \"Nessun file caricato.\",\n noMediaSearch: \"Nessun file trovato.\",\n chooseFile: \"Scegli file\",\n dragHint: \"Trascina un'immagine qui oppure\",\n uploadHint: \"JPEG, PNG, WebP, GIF (max 5MB)\",\n mediaLibrary: \"Libreria media\",\n uploadNew: \"Carica nuovo\",\n searchFiles: \"Cerca file...\",\n selectImage: \"Seleziona immagine\",\n noImages: \"Nessuna immagine nella libreria.\",\n noImagesSearch: \"Nessuna immagine trovata.\",\n copyUrl: \"Copia URL\",\n editImage: \"Modifica immagine\",\n restoreOriginal: \"Ripristina originale\",\n freeAspect: \"Libero\",\n },\n users: {\n users: \"Utenti\",\n name: \"Nome\",\n email: \"Email\",\n password: \"Password\",\n passwordEditHint: \" (lascia vuoto per non modificarla)\",\n role: \"Ruolo\",\n createdAt: \"Creato il\",\n actions: \"Azioni\",\n createUser: \"Crea utente\",\n unauthorized: \"Non autorizzato\",\n notAuthenticated: \"Non autenticato\",\n allFieldsRequired: \"Tutti i campi sono obbligatori.\",\n passwordMinLength: \"La password deve avere almeno 6 caratteri.\",\n emailExists: \"Esiste già un utente con questa email.\",\n invalidRole: \"Ruolo non valido.\",\n cannotDeleteSelf: \"Non puoi eliminare il tuo stesso account.\",\n },\n common: {\n statistics: \"Statistiche\",\n settings: \"Impostazioni\",\n delete: \"Elimina\",\n edit: \"Modifica\",\n search: \"Cerca\",\n draft: \"Bozza\",\n published: \"Pubblicato\",\n all: \"Tutti\",\n drafts: \"Bozze\",\n loading: \"Caricamento...\",\n confirm: \"Conferma\",\n cancel: \"Annulla\",\n apply: \"Applica\",\n change: \"Cambia\",\n logout: \"Esci\",\n saveChanges: \"Salva modifiche\",\n updated: \"Aggiornato\",\n status: \"Stato\",\n title: \"Titolo\",\n deleteConfirm: (title) => `Eliminare \"${title || \"Senza titolo\"}\"?`,\n unpublishConfirm: (title) =>\n `Ritirare \"${title || \"Senza titolo\"}\"? L'articolo tornerà in bozza.`,\n deleteUserConfirm: (name) =>\n `Sei sicuro di voler eliminare l'utente \"${name}\"?`,\n totalArticles: (count) =>\n `${count} articol${count === 1 ? \"o\" : \"i\"} totali`,\n totalFiles: (count) => `${count} file caricati`,\n },\n};\n","import type { GELocale } from \"./types.js\";\n\nexport const en: GELocale = {\n content: {\n articles: \"Articles\",\n newArticle: \"New article\",\n titlePlaceholder: \"Article title\",\n excerptPlaceholder: \"Brief description of the article...\",\n slugPlaceholder: \"article-slug\",\n authorPlaceholder: \"Author name\",\n category: \"Category\",\n selectCategory: \"Select category\",\n excerpt: \"Excerpt\",\n author: \"Author\",\n slugUrl: \"URL Slug\",\n noArticles: \"No articles.\",\n noArticlesSearch: \"No articles found.\",\n searchArticles: \"Search articles...\",\n coverImageLabel: \"Cover image\",\n coverImageHint: \"Choose from library or upload a new file\",\n viewArticle: \"View published article\",\n untitled: \"Untitled\",\n },\n editor: {\n publish: \"Publish\",\n unpublish: \"Unpublish\",\n saveDraft: \"Save draft\",\n revisions: \"History\",\n saving: \"Saving...\",\n saved: \"Saved\",\n saveError: \"Error saving\",\n noRevisions: \"No revisions saved.\",\n restore: \"Restore\",\n restoreConfirm:\n \"Restore this revision? The current state will be saved before restoring.\",\n beforeRestore: \"Before restore\",\n publishedNote: \"Published\",\n preview: \"Preview\",\n placeholder: \"Start writing your article...\",\n },\n media: {\n media: \"Media\",\n noMedia: \"No files uploaded.\",\n noMediaSearch: \"No files found.\",\n chooseFile: \"Choose file\",\n dragHint: \"Drag an image here or\",\n uploadHint: \"JPEG, PNG, WebP, GIF (max 5MB)\",\n mediaLibrary: \"Media library\",\n uploadNew: \"Upload new\",\n searchFiles: \"Search files...\",\n selectImage: \"Select image\",\n noImages: \"No images in library.\",\n noImagesSearch: \"No images found.\",\n copyUrl: \"Copy URL\",\n editImage: \"Edit image\",\n restoreOriginal: \"Restore original\",\n freeAspect: \"Free\",\n },\n users: {\n users: \"Users\",\n name: \"Name\",\n email: \"Email\",\n password: \"Password\",\n passwordEditHint: \" (leave blank to keep current)\",\n role: \"Role\",\n createdAt: \"Created at\",\n actions: \"Actions\",\n createUser: \"Create user\",\n unauthorized: \"Unauthorized\",\n notAuthenticated: \"Not authenticated\",\n allFieldsRequired: \"All fields are required.\",\n passwordMinLength: \"Password must be at least 6 characters.\",\n emailExists: \"A user with this email already exists.\",\n invalidRole: \"Invalid role.\",\n cannotDeleteSelf: \"You cannot delete your own account.\",\n },\n common: {\n statistics: \"Statistics\",\n settings: \"Settings\",\n delete: \"Delete\",\n edit: \"Edit\",\n search: \"Search\",\n draft: \"Draft\",\n published: \"Published\",\n all: \"All\",\n drafts: \"Drafts\",\n loading: \"Loading...\",\n confirm: \"Confirm\",\n cancel: \"Cancel\",\n apply: \"Apply\",\n change: \"Change\",\n logout: \"Logout\",\n saveChanges: \"Save changes\",\n updated: \"Updated\",\n status: \"Status\",\n title: \"Title\",\n deleteConfirm: (title) => `Delete \"${title || \"Untitled\"}\"?`,\n unpublishConfirm: (title) =>\n `Unpublish \"${title || \"Untitled\"}\"? The article will go back to draft.`,\n deleteUserConfirm: (name) =>\n `Are you sure you want to delete user \"${name}\"?`,\n totalArticles: (count) =>\n `${count} total article${count === 1 ? \"\" : \"s\"}`,\n totalFiles: (count) => `${count} uploaded file${count === 1 ? \"\" : \"s\"}`,\n },\n};\n","import type { GELocale } from \"./types.js\";\nimport { it } from \"./it.js\";\nimport { en } from \"./en.js\";\n\nexport type { GELocale } from \"./types.js\";\nexport { it } from \"./it.js\";\nexport { en } from \"./en.js\";\n\nconst builtinLocales: Record<string, GELocale> = { it, en };\n\nexport function loadLocale(locale: string): GELocale {\n const found = builtinLocales[locale];\n if (!found) {\n throw new Error(\n `Locale \"${locale}\" not found. Available: ${Object.keys(builtinLocales).join(\", \")}`\n );\n }\n return found;\n}\n\nexport function defineLocale(locale: GELocale): GELocale {\n return locale;\n}\n\nexport function mergeLocales(\n base: GELocale,\n overrides: DeepPartial<GELocale>\n): GELocale {\n return deepMergeLocale(base, overrides);\n}\n\nexport function registerLocale(key: string, locale: GELocale): void {\n builtinLocales[key] = locale;\n}\n\ntype DeepPartial<T> = {\n [P in keyof T]?: T[P] extends (...args: any[]) => any\n ? T[P]\n : T[P] extends object\n ? DeepPartial<T[P]>\n : T[P];\n};\n\nfunction deepMergeLocale<T extends Record<string, any>>(\n target: T,\n source: DeepPartial<T>\n): T {\n const result = { ...target };\n for (const key of Object.keys(source) as (keyof T)[]) {\n const sourceVal = source[key];\n const targetVal = target[key];\n if (\n sourceVal &&\n typeof sourceVal === \"object\" &&\n !Array.isArray(sourceVal) &&\n typeof targetVal === \"object\" &&\n !Array.isArray(targetVal) &&\n typeof sourceVal !== \"function\"\n ) {\n (result as any)[key] = deepMergeLocale(\n targetVal as Record<string, any>,\n sourceVal as Record<string, any>\n );\n } else if (sourceVal !== undefined) {\n (result as any)[key] = sourceVal;\n }\n }\n return result;\n}\n","import { loadLocale } from \"./i18n/index.js\";\nimport type { GELocale } from \"./i18n/types.js\";\nimport type { GEAuthAdapter } from \"./auth/types.js\";\nimport type { GEContentType } from \"./content/types.js\";\nimport type { GEComponentOverrides } from \"./components/registry.js\";\n\nexport interface GavaEngineConfig {\n branding: {\n name: string;\n logo?: string;\n };\n roles: {\n list: string[];\n labels: Record<string, string>;\n canEdit: (role: string) => boolean;\n canPublish: (role: string) => boolean;\n adminRole: string;\n };\n statuses: {\n draft: string;\n published: string;\n };\n locale: string;\n models: {\n article: string;\n articleRevision: string;\n articleView: string;\n media: string;\n user: string;\n };\n auth?: GEAuthAdapter;\n contentTypes?: GEContentType[];\n components?: GEComponentOverrides;\n categories: string[];\n upload: {\n endpoint: string;\n imageTypes: string[];\n videoTypes: string[];\n maxImageSize: number;\n maxVideoSize: number;\n };\n editor: {\n placeholder: string;\n autoSaveDelay: number;\n revisionThrottleMinutes: number;\n headingLevels: number[];\n };\n routes: {\n articles: string;\n articleEdit: (id: string) => string;\n articleNew: string;\n articleView: (slug: string) => string;\n articlePreview: (id: string) => string;\n users: string;\n userEdit: (id: string) => string;\n userNew: string;\n media: string;\n dashboard: string;\n login: string;\n home: string;\n };\n strings: {\n articles: string;\n newArticle: string;\n media: string;\n users: string;\n statistics: string;\n settings: string;\n revisions: string;\n publish: string;\n unpublish: string;\n saveDraft: string;\n delete: string;\n edit: string;\n search: string;\n titlePlaceholder: string;\n excerptPlaceholder: string;\n slugPlaceholder: string;\n authorPlaceholder: string;\n category: string;\n selectCategory: string;\n excerpt: string;\n author: string;\n slugUrl: string;\n draft: string;\n published: string;\n all: string;\n drafts: string;\n saving: string;\n saved: string;\n saveError: string;\n noArticles: string;\n noArticlesSearch: string;\n noMedia: string;\n noMediaSearch: string;\n noRevisions: string;\n loading: string;\n confirm: string;\n cancel: string;\n apply: string;\n change: string;\n logout: string;\n viewArticle: string;\n preview: string;\n restore: string;\n restoreConfirm: string;\n beforeRestore: string;\n publishedNote: string;\n deleteConfirm: (title: string) => string;\n unpublishConfirm: (title: string) => string;\n deleteUserConfirm: (name: string) => string;\n totalArticles: (count: number) => string;\n totalFiles: (count: number) => string;\n coverImageLabel: string;\n coverImageHint: string;\n chooseFile: string;\n dragHint: string;\n uploadHint: string;\n mediaLibrary: string;\n uploadNew: string;\n searchFiles: string;\n searchArticles: string;\n selectImage: string;\n noImages: string;\n noImagesSearch: string;\n copyUrl: string;\n editImage: string;\n restoreOriginal: string;\n freeAspect: string;\n unauthorized: string;\n notAuthenticated: string;\n allFieldsRequired: string;\n passwordMinLength: string;\n emailExists: string;\n invalidRole: string;\n cannotDeleteSelf: string;\n name: string;\n email: string;\n password: string;\n passwordEditHint: string;\n role: string;\n createdAt: string;\n actions: string;\n createUser: string;\n saveChanges: string;\n updated: string;\n status: string;\n title: string;\n untitled: string;\n };\n}\n\nfunction localeToStrings(locale: GELocale): GavaEngineConfig[\"strings\"] {\n return {\n // content\n articles: locale.content.articles,\n newArticle: locale.content.newArticle,\n titlePlaceholder: locale.content.titlePlaceholder,\n excerptPlaceholder: locale.content.excerptPlaceholder,\n slugPlaceholder: locale.content.slugPlaceholder,\n authorPlaceholder: locale.content.authorPlaceholder,\n category: locale.content.category,\n selectCategory: locale.content.selectCategory,\n excerpt: locale.content.excerpt,\n author: locale.content.author,\n slugUrl: locale.content.slugUrl,\n noArticles: locale.content.noArticles,\n noArticlesSearch: locale.content.noArticlesSearch,\n searchArticles: locale.content.searchArticles,\n coverImageLabel: locale.content.coverImageLabel,\n coverImageHint: locale.content.coverImageHint,\n viewArticle: locale.content.viewArticle,\n untitled: locale.content.untitled,\n // editor\n publish: locale.editor.publish,\n unpublish: locale.editor.unpublish,\n saveDraft: locale.editor.saveDraft,\n revisions: locale.editor.revisions,\n saving: locale.editor.saving,\n saved: locale.editor.saved,\n saveError: locale.editor.saveError,\n noRevisions: locale.editor.noRevisions,\n restore: locale.editor.restore,\n restoreConfirm: locale.editor.restoreConfirm,\n beforeRestore: locale.editor.beforeRestore,\n publishedNote: locale.editor.publishedNote,\n preview: locale.editor.preview,\n // media\n media: locale.media.media,\n noMedia: locale.media.noMedia,\n noMediaSearch: locale.media.noMediaSearch,\n chooseFile: locale.media.chooseFile,\n dragHint: locale.media.dragHint,\n uploadHint: locale.media.uploadHint,\n mediaLibrary: locale.media.mediaLibrary,\n uploadNew: locale.media.uploadNew,\n searchFiles: locale.media.searchFiles,\n selectImage: locale.media.selectImage,\n noImages: locale.media.noImages,\n noImagesSearch: locale.media.noImagesSearch,\n copyUrl: locale.media.copyUrl,\n editImage: locale.media.editImage,\n restoreOriginal: locale.media.restoreOriginal,\n freeAspect: locale.media.freeAspect,\n // users\n users: locale.users.users,\n name: locale.users.name,\n email: locale.users.email,\n password: locale.users.password,\n passwordEditHint: locale.users.passwordEditHint,\n role: locale.users.role,\n createdAt: locale.users.createdAt,\n actions: locale.users.actions,\n createUser: locale.users.createUser,\n unauthorized: locale.users.unauthorized,\n notAuthenticated: locale.users.notAuthenticated,\n allFieldsRequired: locale.users.allFieldsRequired,\n passwordMinLength: locale.users.passwordMinLength,\n emailExists: locale.users.emailExists,\n invalidRole: locale.users.invalidRole,\n cannotDeleteSelf: locale.users.cannotDeleteSelf,\n // common\n statistics: locale.common.statistics,\n settings: locale.common.settings,\n delete: locale.common.delete,\n edit: locale.common.edit,\n search: locale.common.search,\n draft: locale.common.draft,\n published: locale.common.published,\n all: locale.common.all,\n drafts: locale.common.drafts,\n loading: locale.common.loading,\n confirm: locale.common.confirm,\n cancel: locale.common.cancel,\n apply: locale.common.apply,\n change: locale.common.change,\n logout: locale.common.logout,\n saveChanges: locale.common.saveChanges,\n updated: locale.common.updated,\n status: locale.common.status,\n title: locale.common.title,\n deleteConfirm: locale.common.deleteConfirm,\n unpublishConfirm: locale.common.unpublishConfirm,\n deleteUserConfirm: locale.common.deleteUserConfirm,\n totalArticles: locale.common.totalArticles,\n totalFiles: locale.common.totalFiles,\n };\n}\n\nconst DEFAULT_STRINGS = localeToStrings(loadLocale(\"it\"));\n\nconst DEFAULT_CONFIG: GavaEngineConfig = {\n branding: {\n name: \"GavaEngine\",\n },\n roles: {\n list: [\"admin\", \"redattore\", \"scrittore\", \"lettore\"],\n labels: {\n admin: \"Amministratore\",\n redattore: \"Redattore\",\n scrittore: \"Scrittore\",\n lettore: \"Lettore\",\n },\n canEdit: (role: string) => role !== \"lettore\",\n canPublish: (role: string) => role === \"admin\" || role === \"redattore\",\n adminRole: \"admin\",\n },\n statuses: {\n draft: \"bozza\",\n published: \"pubblicato\",\n },\n locale: \"it\",\n models: {\n article: \"article\",\n articleRevision: \"articleRevision\",\n articleView: \"articleView\",\n media: \"media\",\n user: \"user\",\n },\n categories: [\n \"Cultura ed Intercultura\",\n \"Fatti ed Eventi\",\n \"Poeti e Prosatori\",\n \"Famiglia, Istituzioni e Territorio\",\n \"Amici del Meucci\",\n ],\n upload: {\n endpoint: \"/api/upload\",\n imageTypes: [\"image/jpeg\", \"image/png\", \"image/webp\", \"image/gif\"],\n videoTypes: [\"video/mp4\", \"video/webm\", \"video/quicktime\"],\n maxImageSize: 5 * 1024 * 1024,\n maxVideoSize: 50 * 1024 * 1024,\n },\n editor: {\n placeholder: \"Inizia a scrivere il tuo articolo...\",\n autoSaveDelay: 2000,\n revisionThrottleMinutes: 5,\n headingLevels: [2, 3],\n },\n routes: {\n articles: \"/dashboard/articoli\",\n articleEdit: (id) => `/dashboard/articoli/${id}`,\n articleNew: \"/dashboard/articoli/nuovo\",\n articleView: (slug) => `/articoli/${slug}`,\n articlePreview: (id) => `/anteprima/${id}`,\n users: \"/dashboard/utenti\",\n userEdit: (id) => `/dashboard/utenti/${id}`,\n userNew: \"/dashboard/utenti/nuovo\",\n media: \"/dashboard/media\",\n dashboard: \"/dashboard\",\n login: \"/login\",\n home: \"/\",\n },\n strings: DEFAULT_STRINGS,\n};\n\nfunction deepMerge<T extends Record<string, any>>(\n target: T,\n source: Partial<T>\n): T {\n const result = { ...target };\n for (const key of Object.keys(source) as (keyof T)[]) {\n const sourceVal = source[key];\n const targetVal = target[key];\n if (\n sourceVal &&\n typeof sourceVal === \"object\" &&\n !Array.isArray(sourceVal) &&\n typeof targetVal === \"object\" &&\n !Array.isArray(targetVal) &&\n typeof sourceVal !== \"function\"\n ) {\n (result as any)[key] = deepMerge(\n targetVal as Record<string, any>,\n sourceVal as Record<string, any>\n );\n } else if (sourceVal !== undefined) {\n (result as any)[key] = sourceVal;\n }\n }\n return result;\n}\n\nexport function defineConfig(\n overrides: Partial<GavaEngineConfig> = {}\n): GavaEngineConfig {\n // If a different locale is specified, load it as base strings\n const locale = overrides.locale ?? DEFAULT_CONFIG.locale;\n const baseStrings = localeToStrings(loadLocale(locale));\n\n // Build config with locale-based strings as default\n const configWithLocale = {\n ...DEFAULT_CONFIG,\n strings: baseStrings,\n };\n\n // Also update editor.placeholder from locale if not overridden\n if (!overrides.editor?.placeholder) {\n const localeData = loadLocale(locale);\n configWithLocale.editor = {\n ...configWithLocale.editor,\n placeholder: localeData.editor.placeholder,\n };\n }\n\n return deepMerge(configWithLocale, overrides);\n}\n\nexport { DEFAULT_CONFIG, localeToStrings };\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport function createRevisionHandlers(prisma: any, config: GavaEngineConfig) {\n const throttleMs = config.editor.revisionThrottleMinutes * 60 * 1000;\n const articleModel = config.models.article;\n const revisionModel = config.models.articleRevision;\n\n return {\n async getRevisions(articleId: string) {\n return prisma[revisionModel].findMany({\n where: { articleId },\n include: { editor: { select: { name: true } } },\n orderBy: { createdAt: \"desc\" },\n });\n },\n\n async restoreRevision(\n articleId: string,\n revisionId: string,\n editorId: string\n ) {\n const article = await prisma[articleModel].findUnique({\n where: { id: articleId },\n });\n if (!article) throw new Error(\"Article not found\");\n\n const revision = await prisma[revisionModel].findUnique({\n where: { id: revisionId },\n });\n if (!revision || revision.articleId !== articleId) {\n throw new Error(\"Revision not found\");\n }\n\n // Save current state before restoring\n await prisma[revisionModel].create({\n data: {\n articleId,\n title: article.title,\n content: article.content,\n excerpt: article.excerpt,\n coverImage: article.coverImage,\n category: article.category,\n editorId,\n note: config.strings.beforeRestore,\n },\n });\n\n // Restore\n await prisma[articleModel].update({\n where: { id: articleId },\n data: {\n title: revision.title,\n content: revision.content,\n excerpt: revision.excerpt,\n coverImage: revision.coverImage,\n category: revision.category,\n updatedAt: new Date(),\n },\n });\n\n return { success: true };\n },\n\n async createRevisionSnapshot(\n articleId: string,\n editorId: string,\n note: string = \"\"\n ) {\n const article = await prisma[articleModel].findUnique({\n where: { id: articleId },\n });\n if (!article) return;\n\n // Throttle: only create if last revision was > threshold ago\n const threshold = new Date(Date.now() - throttleMs);\n const recent = await prisma[revisionModel].findFirst({\n where: { articleId, createdAt: { gte: threshold } },\n orderBy: { createdAt: \"desc\" },\n });\n\n if (recent && !note) return;\n\n await prisma[revisionModel].create({\n data: {\n articleId,\n title: article.title,\n content: article.content,\n excerpt: article.excerpt,\n coverImage: article.coverImage,\n category: article.category,\n editorId,\n note,\n },\n });\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\nimport { createRevisionHandlers } from \"./revisions.js\";\n\nexport function createArticleHandlers(prisma: any, config: GavaEngineConfig) {\n const revisionHandlers = createRevisionHandlers(prisma, config);\n const articleModel = config.models.article;\n\n return {\n async getArticles() {\n return prisma[articleModel].findMany({\n orderBy: { updatedAt: \"desc\" },\n });\n },\n\n async getArticleById(id: string) {\n return prisma[articleModel].findUnique({\n where: { id },\n });\n },\n\n async createArticle(authorName: string) {\n const article = await prisma[articleModel].create({\n data: {\n authorName,\n },\n });\n return article.id;\n },\n\n async updateArticle(\n userId: string,\n id: string,\n data: {\n title?: string;\n slug?: string;\n excerpt?: string;\n content?: string;\n coverImage?: string;\n category?: string;\n authorName?: string;\n }\n ) {\n const article = await prisma[articleModel].findUnique({ where: { id } });\n if (!article) throw new Error(\"Article not found\");\n\n await revisionHandlers.createRevisionSnapshot(id, userId);\n\n await prisma[articleModel].update({\n where: { id },\n data: { ...data, updatedAt: new Date() },\n });\n\n return { success: true };\n },\n\n async deleteArticle(id: string) {\n const article = await prisma[articleModel].findUnique({ where: { id } });\n if (!article) throw new Error(\"Article not found\");\n\n await prisma[articleModel].delete({ where: { id } });\n return { success: true };\n },\n\n async publishArticle(userId: string, id: string) {\n const article = await prisma[articleModel].findUnique({ where: { id } });\n if (!article) throw new Error(\"Article not found\");\n\n if (!article.title || !article.slug) {\n throw new Error(\n \"Title and slug are required for publishing\"\n );\n }\n\n await revisionHandlers.createRevisionSnapshot(\n id,\n userId,\n config.strings.publishedNote\n );\n\n await prisma[articleModel].update({\n where: { id },\n data: {\n status: config.statuses.published,\n publishedAt: new Date(),\n },\n });\n\n return { success: true };\n },\n\n async unpublishArticle(id: string) {\n const article = await prisma[articleModel].findUnique({ where: { id } });\n if (!article) throw new Error(\"Article not found\");\n\n await prisma[articleModel].update({\n where: { id },\n data: {\n status: config.statuses.draft,\n publishedAt: null,\n },\n });\n\n return { success: true };\n },\n };\n}\n","import bcrypt from \"bcryptjs\";\nimport type { GavaEngineConfig } from \"../config.js\";\n\nexport function createUserHandlers(prisma: any, config: GavaEngineConfig) {\n const userModel = config.models.user;\n\n return {\n async getUsers() {\n return prisma[userModel].findMany({\n select: {\n id: true,\n name: true,\n email: true,\n role: true,\n createdAt: true,\n },\n orderBy: { createdAt: \"desc\" },\n });\n },\n\n async getUserById(id: string) {\n return prisma[userModel].findUnique({\n where: { id },\n select: {\n id: true,\n name: true,\n email: true,\n role: true,\n },\n });\n },\n\n async createUser(formData: FormData) {\n const name = formData.get(\"name\") as string;\n const email = formData.get(\"email\") as string;\n const password = formData.get(\"password\") as string;\n const role = formData.get(\"role\") as string;\n\n if (!name || !email || !password || !role) {\n return { error: config.strings.allFieldsRequired };\n }\n\n if (!config.roles.list.includes(role)) {\n return { error: config.strings.invalidRole };\n }\n\n if (password.length < 6) {\n return { error: config.strings.passwordMinLength };\n }\n\n const existing = await prisma[userModel].findUnique({ where: { email } });\n if (existing) {\n return { error: config.strings.emailExists };\n }\n\n const hashedPassword = await bcrypt.hash(password, 10);\n\n await prisma[userModel].create({\n data: {\n name,\n email,\n password: hashedPassword,\n role,\n },\n });\n\n return { success: true };\n },\n\n async updateUser(id: string, formData: FormData) {\n const name = formData.get(\"name\") as string;\n const email = formData.get(\"email\") as string;\n const password = formData.get(\"password\") as string;\n const role = formData.get(\"role\") as string;\n\n if (!name || !email || !role) {\n return { error: config.strings.allFieldsRequired };\n }\n\n if (!config.roles.list.includes(role)) {\n return { error: config.strings.invalidRole };\n }\n\n const existing = await prisma[userModel].findUnique({ where: { email } });\n if (existing && existing.id !== id) {\n return { error: config.strings.emailExists };\n }\n\n const data: {\n name: string;\n email: string;\n role: string;\n password?: string;\n } = {\n name,\n email,\n role,\n };\n\n if (password && password.length > 0) {\n if (password.length < 6) {\n return { error: config.strings.passwordMinLength };\n }\n data.password = await bcrypt.hash(password, 10);\n }\n\n await prisma[userModel].update({\n where: { id },\n data,\n });\n\n return { success: true };\n },\n\n async deleteUser(currentUserId: string, id: string) {\n if (currentUserId === id) {\n return { error: config.strings.cannotDeleteSelf };\n }\n\n await prisma[userModel].delete({ where: { id } });\n return { success: true };\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport function createMediaHandlers(prisma: any, config: GavaEngineConfig) {\n const mediaModel = config.models.media;\n const articleModel = config.models.article;\n\n return {\n async getMedia(search?: string) {\n return prisma[mediaModel].findMany({\n where: search ? { filename: { contains: search } } : undefined,\n include: { uploader: { select: { name: true } } },\n orderBy: { createdAt: \"desc\" },\n });\n },\n\n async deleteMedia(\n userId: string,\n userRole: string,\n id: string,\n deleteFileFromDisk?: (path: string) => Promise<void>\n ) {\n const media = await prisma[mediaModel].findUnique({ where: { id } });\n if (!media) throw new Error(\"File not found\");\n\n // Writers can only delete their own media\n if (userRole === \"scrittore\" && media.uploaderId !== userId) {\n throw new Error(\"Unauthorized\");\n }\n\n // Check if image is used in articles\n const usedInArticles = await prisma[articleModel].findMany({\n where: {\n OR: [\n { coverImage: media.path },\n { content: { contains: media.path } },\n ],\n },\n select: { id: true, title: true },\n });\n\n if (usedInArticles.length > 0) {\n const titles = usedInArticles\n .map((a: { title: string }) => a.title || \"Untitled\")\n .join(\", \");\n throw new Error(\n `Cannot delete: image is used in ${usedInArticles.length} article(s) (${titles})`\n );\n }\n\n // Delete file from disk if handler provided\n if (deleteFileFromDisk) {\n try {\n await deleteFileFromDisk(media.path);\n } catch {\n // File may already be missing\n }\n }\n\n await prisma[mediaModel].delete({ where: { id } });\n return { success: true };\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport interface UploadResult {\n url?: string;\n error?: string;\n}\n\nexport interface FileStorage {\n save(filename: string, buffer: Buffer, mimeType: string): Promise<string>;\n}\n\nexport function createUploadHandler(\n prisma: any,\n config: GavaEngineConfig,\n storage: FileStorage\n) {\n const allowedTypes = [\n ...config.upload.imageTypes,\n ...config.upload.videoTypes,\n ];\n\n const mediaModel = config.models.media;\n\n return {\n async handleUpload(\n file: {\n name: string;\n type: string;\n size: number;\n arrayBuffer: () => Promise<ArrayBuffer>;\n },\n uploaderId: string\n ): Promise<UploadResult> {\n if (!allowedTypes.includes(file.type)) {\n return { error: \"Unsupported file type\" };\n }\n\n const isVideo = config.upload.videoTypes.includes(file.type);\n const maxSize = isVideo\n ? config.upload.maxVideoSize\n : config.upload.maxImageSize;\n\n if (file.size > maxSize) {\n return {\n error: `File too large. Max ${isVideo ? config.upload.maxVideoSize / (1024 * 1024) : config.upload.maxImageSize / (1024 * 1024)}MB.`,\n };\n }\n\n const buffer = Buffer.from(await file.arrayBuffer());\n const url = await storage.save(file.name, buffer, file.type);\n\n await prisma[mediaModel].create({\n data: {\n filename: file.name,\n path: url,\n mimeType: file.type,\n size: file.size,\n uploaderId,\n },\n });\n\n return { url };\n },\n };\n}\n","import bcrypt from \"bcryptjs\";\nimport type { GavaEngineConfig } from \"../config.js\";\n\nexport function buildCredentialsProvider(prisma: any, config?: GavaEngineConfig) {\n const userModel = config?.models?.user ?? \"user\";\n\n return {\n credentials: {\n email: {},\n password: {},\n },\n async authorize(credentials: Record<string, unknown>) {\n const email = credentials.email as string;\n const password = credentials.password as string;\n\n if (!email || !password) return null;\n\n const user = await prisma[userModel].findUnique({\n where: { email },\n });\n\n if (!user) return null;\n\n const isValid = await bcrypt.compare(password, user.password);\n if (!isValid) return null;\n\n return {\n id: user.id,\n name: user.name,\n email: user.email,\n role: user.role,\n };\n },\n };\n}\n\nexport function buildAuthCallbacks(config: GavaEngineConfig) {\n return {\n async jwt({\n token,\n user,\n }: {\n token: Record<string, unknown>;\n user?: Record<string, unknown>;\n }) {\n if (user) {\n token.id = user.id as string;\n token.role = user.role as string;\n }\n return token;\n },\n async session({\n session,\n token,\n }: {\n session: Record<string, any>;\n token: Record<string, unknown>;\n }) {\n if (session.user) {\n session.user.id = token.id as string;\n session.user.role = token.role as string;\n }\n return session;\n },\n authorized({\n auth,\n request: { nextUrl },\n }: {\n auth: Record<string, any> | null;\n request: { nextUrl: URL };\n }) {\n const isLoggedIn = !!auth;\n const role = auth?.user?.role;\n const pathname = nextUrl.pathname;\n\n if (pathname === config.routes.login && isLoggedIn) {\n return Response.redirect(new URL(config.routes.articles, nextUrl));\n }\n\n if (pathname.startsWith(config.routes.dashboard)) {\n if (!isLoggedIn) {\n return Response.redirect(new URL(config.routes.login, nextUrl));\n }\n\n if (\n pathname.startsWith(config.routes.users) &&\n role !== config.roles.adminRole\n ) {\n return Response.redirect(\n new URL(config.routes.articles, nextUrl)\n );\n }\n }\n\n return true;\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport function createAuthUtils(config: GavaEngineConfig) {\n return {\n canEdit(role: string): boolean {\n return config.roles.canEdit(role);\n },\n canPublish(role: string): boolean {\n return config.roles.canPublish(role);\n },\n isAdmin(role: string): boolean {\n return role === config.roles.adminRole;\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\nimport type { GEContentType } from \"../content/types.js\";\n\nexport interface ContentHandlers {\n getAll(options?: {\n search?: string;\n status?: string;\n orderBy?: Record<string, \"asc\" | \"desc\">;\n }): Promise<any[]>;\n getById(id: string): Promise<any | null>;\n create(data?: Record<string, any>): Promise<string>;\n update(id: string, data: Record<string, any>): Promise<{ success: boolean }>;\n delete(id: string): Promise<{ success: boolean }>;\n publish?(userId: string, id: string): Promise<{ success: boolean }>;\n unpublish?(id: string): Promise<{ success: boolean }>;\n}\n\nexport function createContentHandlers(\n prisma: any,\n contentType: GEContentType,\n config: GavaEngineConfig\n): ContentHandlers {\n const modelName = contentType.slug.replace(/s$/, \"\").replace(/(^|\\-)(\\w)/g, (_m, _p1, p2) => p2.toUpperCase());\n // Try to find the Prisma model — fallback to slug\n const model = prisma[modelName] ?? prisma[contentType.slug];\n\n if (!model) {\n throw new Error(\n `Prisma model \"${modelName}\" not found for content type \"${contentType.slug}\"`\n );\n }\n\n const defaultSort = contentType.admin?.defaultSort\n ? { [contentType.admin.defaultSort.field]: contentType.admin.defaultSort.direction }\n : { updatedAt: \"desc\" };\n\n const searchableFields = contentType.admin?.searchableFields ?? [\"title\"];\n\n return {\n async getAll(options) {\n const where: Record<string, any> = {};\n\n if (options?.search) {\n where.OR = searchableFields.map((field) => ({\n [field]: { contains: options.search },\n }));\n }\n\n if (options?.status) {\n where.status = options.status;\n }\n\n return model.findMany({\n where: Object.keys(where).length > 0 ? where : undefined,\n orderBy: options?.orderBy ?? defaultSort,\n });\n },\n\n async getById(id: string) {\n return model.findUnique({ where: { id } });\n },\n\n async create(data?: Record<string, any>) {\n const createData: Record<string, any> = {};\n\n // Set default values from field definitions\n for (const field of contentType.fields) {\n if (field.defaultValue !== undefined) {\n createData[field.name] = field.defaultValue;\n }\n }\n\n // Set default status\n if (contentType.defaultStatus) {\n createData.status = contentType.defaultStatus;\n }\n\n // Merge provided data\n if (data) {\n Object.assign(createData, data);\n }\n\n const record = await model.create({\n data: createData,\n });\n\n return record.id;\n },\n\n async update(id: string, data: Record<string, any>) {\n const record = await model.findUnique({ where: { id } });\n if (!record) throw new Error(`${contentType.labels.singular} not found`);\n\n await model.update({\n where: { id },\n data: { ...data, updatedAt: new Date() },\n });\n\n return { success: true };\n },\n\n async delete(id: string) {\n const record = await model.findUnique({ where: { id } });\n if (!record) throw new Error(`${contentType.labels.singular} not found`);\n\n await model.delete({ where: { id } });\n return { success: true };\n },\n\n async publish(userId: string, id: string) {\n if (!contentType.publishedStatus) return { success: false };\n\n const record = await model.findUnique({ where: { id } });\n if (!record) throw new Error(`${contentType.labels.singular} not found`);\n\n await model.update({\n where: { id },\n data: {\n status: contentType.publishedStatus,\n publishedAt: new Date(),\n },\n });\n\n return { success: true };\n },\n\n async unpublish(id: string) {\n if (!contentType.defaultStatus) return { success: false };\n\n const record = await model.findUnique({ where: { id } });\n if (!record) throw new Error(`${contentType.labels.singular} not found`);\n\n await model.update({\n where: { id },\n data: {\n status: contentType.defaultStatus,\n publishedAt: null,\n },\n });\n\n return { success: true };\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport function createCategoryHandlers(prisma: any, config: GavaEngineConfig) {\n const categoryModel = prisma.category;\n\n return {\n async getCategories() {\n if (!categoryModel) {\n // Fallback: return config categories as static list\n return config.categories.map((name, i) => ({\n id: `static-${i}`,\n name,\n slug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n sortOrder: i,\n }));\n }\n\n return categoryModel.findMany({\n orderBy: { sortOrder: \"asc\" },\n });\n },\n\n async createCategory(data: { name: string; slug?: string; sortOrder?: number }) {\n if (!categoryModel) {\n throw new Error(\"Category model not available — categories are static from config\");\n }\n\n const slug =\n data.slug ??\n data.name\n .toLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .replace(/[^a-z0-9\\s-]/g, \"\")\n .replace(/\\s+/g, \"-\");\n\n return categoryModel.create({\n data: {\n name: data.name,\n slug,\n sortOrder: data.sortOrder ?? 0,\n },\n });\n },\n\n async updateCategory(\n id: string,\n data: { name?: string; slug?: string; sortOrder?: number }\n ) {\n if (!categoryModel) {\n throw new Error(\"Category model not available — categories are static from config\");\n }\n\n return categoryModel.update({\n where: { id },\n data,\n });\n },\n\n async deleteCategory(id: string) {\n if (!categoryModel) {\n throw new Error(\"Category model not available — categories are static from config\");\n }\n\n await categoryModel.delete({ where: { id } });\n return { success: true };\n },\n\n async seedCategories() {\n if (!categoryModel) return;\n\n const existing = await categoryModel.count();\n if (existing > 0) return;\n\n for (let i = 0; i < config.categories.length; i++) {\n const name = config.categories[i];\n const slug = name\n .toLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .replace(/[^a-z0-9\\s-]/g, \"\")\n .replace(/\\s+/g, \"-\");\n\n await categoryModel.create({\n data: {\n name,\n slug,\n sortOrder: i,\n },\n });\n }\n },\n };\n}\n"],"mappings":";AAEO,IAAM,KAAe;AAAA,EAC1B,SAAS;AAAA,IACP,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,mBAAmB;AAAA,IACnB,UAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,WAAW;AAAA,IACX,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,WAAW;AAAA,IACX,aAAa;AAAA,IACb,SAAS;AAAA,IACT,gBACE;AAAA,IACF,eAAe;AAAA,IACf,eAAe;AAAA,IACf,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA,OAAO;AAAA,IACL,OAAO;AAAA,IACP,SAAS;AAAA,IACT,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,WAAW;AAAA,IACX,aAAa;AAAA,IACb,aAAa;AAAA,IACb,UAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,SAAS;AAAA,IACT,WAAW;AAAA,IACX,iBAAiB;AAAA,IACjB,YAAY;AAAA,EACd;AAAA,EACA,OAAO;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,kBAAkB;AAAA,IAClB,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,mBAAmB;AAAA,IACnB,mBAAmB;AAAA,IACnB,aAAa;AAAA,IACb,aAAa;AAAA,IACb,kBAAkB;AAAA,EACpB;AAAA,EACA,QAAQ;AAAA,IACN,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,WAAW;AAAA,IACX,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,eAAe,CAAC,UAAU,cAAc,SAAS,cAAc;AAAA,IAC/D,kBAAkB,CAAC,UACjB,aAAa,SAAS,cAAc;AAAA,IACtC,mBAAmB,CAAC,SAClB,2CAA2C,IAAI;AAAA,IACjD,eAAe,CAAC,UACd,GAAG,KAAK,WAAW,UAAU,IAAI,MAAM,GAAG;AAAA,IAC5C,YAAY,CAAC,UAAU,GAAG,KAAK;AAAA,EACjC;AACF;;;ACvGO,IAAM,KAAe;AAAA,EAC1B,SAAS;AAAA,IACP,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,mBAAmB;AAAA,IACnB,UAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,WAAW;AAAA,IACX,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,WAAW;AAAA,IACX,aAAa;AAAA,IACb,SAAS;AAAA,IACT,gBACE;AAAA,IACF,eAAe;AAAA,IACf,eAAe;AAAA,IACf,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA,OAAO;AAAA,IACL,OAAO;AAAA,IACP,SAAS;AAAA,IACT,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,WAAW;AAAA,IACX,aAAa;AAAA,IACb,aAAa;AAAA,IACb,UAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,SAAS;AAAA,IACT,WAAW;AAAA,IACX,iBAAiB;AAAA,IACjB,YAAY;AAAA,EACd;AAAA,EACA,OAAO;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,kBAAkB;AAAA,IAClB,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,mBAAmB;AAAA,IACnB,mBAAmB;AAAA,IACnB,aAAa;AAAA,IACb,aAAa;AAAA,IACb,kBAAkB;AAAA,EACpB;AAAA,EACA,QAAQ;AAAA,IACN,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,WAAW;AAAA,IACX,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,eAAe,CAAC,UAAU,WAAW,SAAS,UAAU;AAAA,IACxD,kBAAkB,CAAC,UACjB,cAAc,SAAS,UAAU;AAAA,IACnC,mBAAmB,CAAC,SAClB,yCAAyC,IAAI;AAAA,IAC/C,eAAe,CAAC,UACd,GAAG,KAAK,iBAAiB,UAAU,IAAI,KAAK,GAAG;AAAA,IACjD,YAAY,CAAC,UAAU,GAAG,KAAK,iBAAiB,UAAU,IAAI,KAAK,GAAG;AAAA,EACxE;AACF;;;ACjGA,IAAM,iBAA2C,EAAE,IAAI,GAAG;AAEnD,SAAS,WAAW,QAA0B;AACnD,QAAM,QAAQ,eAAe,MAAM;AACnC,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR,WAAW,MAAM,2BAA2B,OAAO,KAAK,cAAc,EAAE,KAAK,IAAI,CAAC;AAAA,IACpF;AAAA,EACF;AACA,SAAO;AACT;;;ACsIA,SAAS,gBAAgB,QAA+C;AACtE,SAAO;AAAA;AAAA,IAEL,UAAU,OAAO,QAAQ;AAAA,IACzB,YAAY,OAAO,QAAQ;AAAA,IAC3B,kBAAkB,OAAO,QAAQ;AAAA,IACjC,oBAAoB,OAAO,QAAQ;AAAA,IACnC,iBAAiB,OAAO,QAAQ;AAAA,IAChC,mBAAmB,OAAO,QAAQ;AAAA,IAClC,UAAU,OAAO,QAAQ;AAAA,IACzB,gBAAgB,OAAO,QAAQ;AAAA,IAC/B,SAAS,OAAO,QAAQ;AAAA,IACxB,QAAQ,OAAO,QAAQ;AAAA,IACvB,SAAS,OAAO,QAAQ;AAAA,IACxB,YAAY,OAAO,QAAQ;AAAA,IAC3B,kBAAkB,OAAO,QAAQ;AAAA,IACjC,gBAAgB,OAAO,QAAQ;AAAA,IAC/B,iBAAiB,OAAO,QAAQ;AAAA,IAChC,gBAAgB,OAAO,QAAQ;AAAA,IAC/B,aAAa,OAAO,QAAQ;AAAA,IAC5B,UAAU,OAAO,QAAQ;AAAA;AAAA,IAEzB,SAAS,OAAO,OAAO;AAAA,IACvB,WAAW,OAAO,OAAO;AAAA,IACzB,WAAW,OAAO,OAAO;AAAA,IACzB,WAAW,OAAO,OAAO;AAAA,IACzB,QAAQ,OAAO,OAAO;AAAA,IACtB,OAAO,OAAO,OAAO;AAAA,IACrB,WAAW,OAAO,OAAO;AAAA,IACzB,aAAa,OAAO,OAAO;AAAA,IAC3B,SAAS,OAAO,OAAO;AAAA,IACvB,gBAAgB,OAAO,OAAO;AAAA,IAC9B,eAAe,OAAO,OAAO;AAAA,IAC7B,eAAe,OAAO,OAAO;AAAA,IAC7B,SAAS,OAAO,OAAO;AAAA;AAAA,IAEvB,OAAO,OAAO,MAAM;AAAA,IACpB,SAAS,OAAO,MAAM;AAAA,IACtB,eAAe,OAAO,MAAM;AAAA,IAC5B,YAAY,OAAO,MAAM;AAAA,IACzB,UAAU,OAAO,MAAM;AAAA,IACvB,YAAY,OAAO,MAAM;AAAA,IACzB,cAAc,OAAO,MAAM;AAAA,IAC3B,WAAW,OAAO,MAAM;AAAA,IACxB,aAAa,OAAO,MAAM;AAAA,IAC1B,aAAa,OAAO,MAAM;AAAA,IAC1B,UAAU,OAAO,MAAM;AAAA,IACvB,gBAAgB,OAAO,MAAM;AAAA,IAC7B,SAAS,OAAO,MAAM;AAAA,IACtB,WAAW,OAAO,MAAM;AAAA,IACxB,iBAAiB,OAAO,MAAM;AAAA,IAC9B,YAAY,OAAO,MAAM;AAAA;AAAA,IAEzB,OAAO,OAAO,MAAM;AAAA,IACpB,MAAM,OAAO,MAAM;AAAA,IACnB,OAAO,OAAO,MAAM;AAAA,IACpB,UAAU,OAAO,MAAM;AAAA,IACvB,kBAAkB,OAAO,MAAM;AAAA,IAC/B,MAAM,OAAO,MAAM;AAAA,IACnB,WAAW,OAAO,MAAM;AAAA,IACxB,SAAS,OAAO,MAAM;AAAA,IACtB,YAAY,OAAO,MAAM;AAAA,IACzB,cAAc,OAAO,MAAM;AAAA,IAC3B,kBAAkB,OAAO,MAAM;AAAA,IAC/B,mBAAmB,OAAO,MAAM;AAAA,IAChC,mBAAmB,OAAO,MAAM;AAAA,IAChC,aAAa,OAAO,MAAM;AAAA,IAC1B,aAAa,OAAO,MAAM;AAAA,IAC1B,kBAAkB,OAAO,MAAM;AAAA;AAAA,IAE/B,YAAY,OAAO,OAAO;AAAA,IAC1B,UAAU,OAAO,OAAO;AAAA,IACxB,QAAQ,OAAO,OAAO;AAAA,IACtB,MAAM,OAAO,OAAO;AAAA,IACpB,QAAQ,OAAO,OAAO;AAAA,IACtB,OAAO,OAAO,OAAO;AAAA,IACrB,WAAW,OAAO,OAAO;AAAA,IACzB,KAAK,OAAO,OAAO;AAAA,IACnB,QAAQ,OAAO,OAAO;AAAA,IACtB,SAAS,OAAO,OAAO;AAAA,IACvB,SAAS,OAAO,OAAO;AAAA,IACvB,QAAQ,OAAO,OAAO;AAAA,IACtB,OAAO,OAAO,OAAO;AAAA,IACrB,QAAQ,OAAO,OAAO;AAAA,IACtB,QAAQ,OAAO,OAAO;AAAA,IACtB,aAAa,OAAO,OAAO;AAAA,IAC3B,SAAS,OAAO,OAAO;AAAA,IACvB,QAAQ,OAAO,OAAO;AAAA,IACtB,OAAO,OAAO,OAAO;AAAA,IACrB,eAAe,OAAO,OAAO;AAAA,IAC7B,kBAAkB,OAAO,OAAO;AAAA,IAChC,mBAAmB,OAAO,OAAO;AAAA,IACjC,eAAe,OAAO,OAAO;AAAA,IAC7B,YAAY,OAAO,OAAO;AAAA,EAC5B;AACF;AAEA,IAAM,kBAAkB,gBAAgB,WAAW,IAAI,CAAC;AAExD,IAAM,iBAAmC;AAAA,EACvC,UAAU;AAAA,IACR,MAAM;AAAA,EACR;AAAA,EACA,OAAO;AAAA,IACL,MAAM,CAAC,SAAS,aAAa,aAAa,SAAS;AAAA,IACnD,QAAQ;AAAA,MACN,OAAO;AAAA,MACP,WAAW;AAAA,MACX,WAAW;AAAA,MACX,SAAS;AAAA,IACX;AAAA,IACA,SAAS,CAAC,SAAiB,SAAS;AAAA,IACpC,YAAY,CAAC,SAAiB,SAAS,WAAW,SAAS;AAAA,IAC3D,WAAW;AAAA,EACb;AAAA,EACA,UAAU;AAAA,IACR,OAAO;AAAA,IACP,WAAW;AAAA,EACb;AAAA,EACA,QAAQ;AAAA,EACR,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN,UAAU;AAAA,IACV,YAAY,CAAC,cAAc,aAAa,cAAc,WAAW;AAAA,IACjE,YAAY,CAAC,aAAa,cAAc,iBAAiB;AAAA,IACzD,cAAc,IAAI,OAAO;AAAA,IACzB,cAAc,KAAK,OAAO;AAAA,EAC5B;AAAA,EACA,QAAQ;AAAA,IACN,aAAa;AAAA,IACb,eAAe;AAAA,IACf,yBAAyB;AAAA,IACzB,eAAe,CAAC,GAAG,CAAC;AAAA,EACtB;AAAA,EACA,QAAQ;AAAA,IACN,UAAU;AAAA,IACV,aAAa,CAAC,OAAO,uBAAuB,EAAE;AAAA,IAC9C,YAAY;AAAA,IACZ,aAAa,CAAC,SAAS,aAAa,IAAI;AAAA,IACxC,gBAAgB,CAAC,OAAO,cAAc,EAAE;AAAA,IACxC,OAAO;AAAA,IACP,UAAU,CAAC,OAAO,qBAAqB,EAAE;AAAA,IACzC,SAAS;AAAA,IACT,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA,SAAS;AACX;AAEA,SAAS,UACP,QACA,QACG;AACH,QAAM,SAAS,EAAE,GAAG,OAAO;AAC3B,aAAW,OAAO,OAAO,KAAK,MAAM,GAAkB;AACpD,UAAM,YAAY,OAAO,GAAG;AAC5B,UAAM,YAAY,OAAO,GAAG;AAC5B,QACE,aACA,OAAO,cAAc,YACrB,CAAC,MAAM,QAAQ,SAAS,KACxB,OAAO,cAAc,YACrB,CAAC,MAAM,QAAQ,SAAS,KACxB,OAAO,cAAc,YACrB;AACA,MAAC,OAAe,GAAG,IAAI;AAAA,QACrB;AAAA,QACA;AAAA,MACF;AAAA,IACF,WAAW,cAAc,QAAW;AAClC,MAAC,OAAe,GAAG,IAAI;AAAA,IACzB;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,aACd,YAAuC,CAAC,GACtB;AAElB,QAAM,SAAS,UAAU,UAAU,eAAe;AAClD,QAAM,cAAc,gBAAgB,WAAW,MAAM,CAAC;AAGtD,QAAM,mBAAmB;AAAA,IACvB,GAAG;AAAA,IACH,SAAS;AAAA,EACX;AAGA,MAAI,CAAC,UAAU,QAAQ,aAAa;AAClC,UAAM,aAAa,WAAW,MAAM;AACpC,qBAAiB,SAAS;AAAA,MACxB,GAAG,iBAAiB;AAAA,MACpB,aAAa,WAAW,OAAO;AAAA,IACjC;AAAA,EACF;AAEA,SAAO,UAAU,kBAAkB,SAAS;AAC9C;;;AC5WO,SAAS,uBAAuB,QAAa,QAA0B;AAC5E,QAAM,aAAa,OAAO,OAAO,0BAA0B,KAAK;AAChE,QAAM,eAAe,OAAO,OAAO;AACnC,QAAM,gBAAgB,OAAO,OAAO;AAEpC,SAAO;AAAA,IACL,MAAM,aAAa,WAAmB;AACpC,aAAO,OAAO,aAAa,EAAE,SAAS;AAAA,QACpC,OAAO,EAAE,UAAU;AAAA,QACnB,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,KAAK,EAAE,EAAE;AAAA,QAC9C,SAAS,EAAE,WAAW,OAAO;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,gBACJ,WACA,YACA,UACA;AACA,YAAM,UAAU,MAAM,OAAO,YAAY,EAAE,WAAW;AAAA,QACpD,OAAO,EAAE,IAAI,UAAU;AAAA,MACzB,CAAC;AACD,UAAI,CAAC,QAAS,OAAM,IAAI,MAAM,mBAAmB;AAEjD,YAAM,WAAW,MAAM,OAAO,aAAa,EAAE,WAAW;AAAA,QACtD,OAAO,EAAE,IAAI,WAAW;AAAA,MAC1B,CAAC;AACD,UAAI,CAAC,YAAY,SAAS,cAAc,WAAW;AACjD,cAAM,IAAI,MAAM,oBAAoB;AAAA,MACtC;AAGA,YAAM,OAAO,aAAa,EAAE,OAAO;AAAA,QACjC,MAAM;AAAA,UACJ;AAAA,UACA,OAAO,QAAQ;AAAA,UACf,SAAS,QAAQ;AAAA,UACjB,SAAS,QAAQ;AAAA,UACjB,YAAY,QAAQ;AAAA,UACpB,UAAU,QAAQ;AAAA,UAClB;AAAA,UACA,MAAM,OAAO,QAAQ;AAAA,QACvB;AAAA,MACF,CAAC;AAGD,YAAM,OAAO,YAAY,EAAE,OAAO;AAAA,QAChC,OAAO,EAAE,IAAI,UAAU;AAAA,QACvB,MAAM;AAAA,UACJ,OAAO,SAAS;AAAA,UAChB,SAAS,SAAS;AAAA,UAClB,SAAS,SAAS;AAAA,UAClB,YAAY,SAAS;AAAA,UACrB,UAAU,SAAS;AAAA,UACnB,WAAW,oBAAI,KAAK;AAAA,QACtB;AAAA,MACF,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,uBACJ,WACA,UACA,OAAe,IACf;AACA,YAAM,UAAU,MAAM,OAAO,YAAY,EAAE,WAAW;AAAA,QACpD,OAAO,EAAE,IAAI,UAAU;AAAA,MACzB,CAAC;AACD,UAAI,CAAC,QAAS;AAGd,YAAM,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,UAAU;AAClD,YAAM,SAAS,MAAM,OAAO,aAAa,EAAE,UAAU;AAAA,QACnD,OAAO,EAAE,WAAW,WAAW,EAAE,KAAK,UAAU,EAAE;AAAA,QAClD,SAAS,EAAE,WAAW,OAAO;AAAA,MAC/B,CAAC;AAED,UAAI,UAAU,CAAC,KAAM;AAErB,YAAM,OAAO,aAAa,EAAE,OAAO;AAAA,QACjC,MAAM;AAAA,UACJ;AAAA,UACA,OAAO,QAAQ;AAAA,UACf,SAAS,QAAQ;AAAA,UACjB,SAAS,QAAQ;AAAA,UACjB,YAAY,QAAQ;AAAA,UACpB,UAAU,QAAQ;AAAA,UAClB;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;AC7FO,SAAS,sBAAsB,QAAa,QAA0B;AAC3E,QAAM,mBAAmB,uBAAuB,QAAQ,MAAM;AAC9D,QAAM,eAAe,OAAO,OAAO;AAEnC,SAAO;AAAA,IACL,MAAM,cAAc;AAClB,aAAO,OAAO,YAAY,EAAE,SAAS;AAAA,QACnC,SAAS,EAAE,WAAW,OAAO;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,eAAe,IAAY;AAC/B,aAAO,OAAO,YAAY,EAAE,WAAW;AAAA,QACrC,OAAO,EAAE,GAAG;AAAA,MACd,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,cAAc,YAAoB;AACtC,YAAM,UAAU,MAAM,OAAO,YAAY,EAAE,OAAO;AAAA,QAChD,MAAM;AAAA,UACJ;AAAA,QACF;AAAA,MACF,CAAC;AACD,aAAO,QAAQ;AAAA,IACjB;AAAA,IAEA,MAAM,cACJ,QACA,IACA,MASA;AACA,YAAM,UAAU,MAAM,OAAO,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACvE,UAAI,CAAC,QAAS,OAAM,IAAI,MAAM,mBAAmB;AAEjD,YAAM,iBAAiB,uBAAuB,IAAI,MAAM;AAExD,YAAM,OAAO,YAAY,EAAE,OAAO;AAAA,QAChC,OAAO,EAAE,GAAG;AAAA,QACZ,MAAM,EAAE,GAAG,MAAM,WAAW,oBAAI,KAAK,EAAE;AAAA,MACzC,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,cAAc,IAAY;AAC9B,YAAM,UAAU,MAAM,OAAO,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACvE,UAAI,CAAC,QAAS,OAAM,IAAI,MAAM,mBAAmB;AAEjD,YAAM,OAAO,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACnD,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,eAAe,QAAgB,IAAY;AAC/C,YAAM,UAAU,MAAM,OAAO,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACvE,UAAI,CAAC,QAAS,OAAM,IAAI,MAAM,mBAAmB;AAEjD,UAAI,CAAC,QAAQ,SAAS,CAAC,QAAQ,MAAM;AACnC,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAEA,YAAM,iBAAiB;AAAA,QACrB;AAAA,QACA;AAAA,QACA,OAAO,QAAQ;AAAA,MACjB;AAEA,YAAM,OAAO,YAAY,EAAE,OAAO;AAAA,QAChC,OAAO,EAAE,GAAG;AAAA,QACZ,MAAM;AAAA,UACJ,QAAQ,OAAO,SAAS;AAAA,UACxB,aAAa,oBAAI,KAAK;AAAA,QACxB;AAAA,MACF,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,iBAAiB,IAAY;AACjC,YAAM,UAAU,MAAM,OAAO,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACvE,UAAI,CAAC,QAAS,OAAM,IAAI,MAAM,mBAAmB;AAEjD,YAAM,OAAO,YAAY,EAAE,OAAO;AAAA,QAChC,OAAO,EAAE,GAAG;AAAA,QACZ,MAAM;AAAA,UACJ,QAAQ,OAAO,SAAS;AAAA,UACxB,aAAa;AAAA,QACf;AAAA,MACF,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,EACF;AACF;;;ACzGA,OAAO,YAAY;AAGZ,SAAS,mBAAmB,QAAa,QAA0B;AACxE,QAAM,YAAY,OAAO,OAAO;AAEhC,SAAO;AAAA,IACL,MAAM,WAAW;AACf,aAAO,OAAO,SAAS,EAAE,SAAS;AAAA,QAChC,QAAQ;AAAA,UACN,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,OAAO;AAAA,UACP,MAAM;AAAA,UACN,WAAW;AAAA,QACb;AAAA,QACA,SAAS,EAAE,WAAW,OAAO;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,YAAY,IAAY;AAC5B,aAAO,OAAO,SAAS,EAAE,WAAW;AAAA,QAClC,OAAO,EAAE,GAAG;AAAA,QACZ,QAAQ;AAAA,UACN,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,OAAO;AAAA,UACP,MAAM;AAAA,QACR;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,WAAW,UAAoB;AACnC,YAAM,OAAO,SAAS,IAAI,MAAM;AAChC,YAAM,QAAQ,SAAS,IAAI,OAAO;AAClC,YAAM,WAAW,SAAS,IAAI,UAAU;AACxC,YAAM,OAAO,SAAS,IAAI,MAAM;AAEhC,UAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,YAAY,CAAC,MAAM;AACzC,eAAO,EAAE,OAAO,OAAO,QAAQ,kBAAkB;AAAA,MACnD;AAEA,UAAI,CAAC,OAAO,MAAM,KAAK,SAAS,IAAI,GAAG;AACrC,eAAO,EAAE,OAAO,OAAO,QAAQ,YAAY;AAAA,MAC7C;AAEA,UAAI,SAAS,SAAS,GAAG;AACvB,eAAO,EAAE,OAAO,OAAO,QAAQ,kBAAkB;AAAA,MACnD;AAEA,YAAM,WAAW,MAAM,OAAO,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AACxE,UAAI,UAAU;AACZ,eAAO,EAAE,OAAO,OAAO,QAAQ,YAAY;AAAA,MAC7C;AAEA,YAAM,iBAAiB,MAAM,OAAO,KAAK,UAAU,EAAE;AAErD,YAAM,OAAO,SAAS,EAAE,OAAO;AAAA,QAC7B,MAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA,UAAU;AAAA,UACV;AAAA,QACF;AAAA,MACF,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,WAAW,IAAY,UAAoB;AAC/C,YAAM,OAAO,SAAS,IAAI,MAAM;AAChC,YAAM,QAAQ,SAAS,IAAI,OAAO;AAClC,YAAM,WAAW,SAAS,IAAI,UAAU;AACxC,YAAM,OAAO,SAAS,IAAI,MAAM;AAEhC,UAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM;AAC5B,eAAO,EAAE,OAAO,OAAO,QAAQ,kBAAkB;AAAA,MACnD;AAEA,UAAI,CAAC,OAAO,MAAM,KAAK,SAAS,IAAI,GAAG;AACrC,eAAO,EAAE,OAAO,OAAO,QAAQ,YAAY;AAAA,MAC7C;AAEA,YAAM,WAAW,MAAM,OAAO,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AACxE,UAAI,YAAY,SAAS,OAAO,IAAI;AAClC,eAAO,EAAE,OAAO,OAAO,QAAQ,YAAY;AAAA,MAC7C;AAEA,YAAM,OAKF;AAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,UAAI,YAAY,SAAS,SAAS,GAAG;AACnC,YAAI,SAAS,SAAS,GAAG;AACvB,iBAAO,EAAE,OAAO,OAAO,QAAQ,kBAAkB;AAAA,QACnD;AACA,aAAK,WAAW,MAAM,OAAO,KAAK,UAAU,EAAE;AAAA,MAChD;AAEA,YAAM,OAAO,SAAS,EAAE,OAAO;AAAA,QAC7B,OAAO,EAAE,GAAG;AAAA,QACZ;AAAA,MACF,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,WAAW,eAAuB,IAAY;AAClD,UAAI,kBAAkB,IAAI;AACxB,eAAO,EAAE,OAAO,OAAO,QAAQ,iBAAiB;AAAA,MAClD;AAEA,YAAM,OAAO,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AAChD,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,EACF;AACF;;;ACzHO,SAAS,oBAAoB,QAAa,QAA0B;AACzE,QAAM,aAAa,OAAO,OAAO;AACjC,QAAM,eAAe,OAAO,OAAO;AAEnC,SAAO;AAAA,IACL,MAAM,SAAS,QAAiB;AAC9B,aAAO,OAAO,UAAU,EAAE,SAAS;AAAA,QACjC,OAAO,SAAS,EAAE,UAAU,EAAE,UAAU,OAAO,EAAE,IAAI;AAAA,QACrD,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,KAAK,EAAE,EAAE;AAAA,QAChD,SAAS,EAAE,WAAW,OAAO;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,YACJ,QACA,UACA,IACA,oBACA;AACA,YAAM,QAAQ,MAAM,OAAO,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACnE,UAAI,CAAC,MAAO,OAAM,IAAI,MAAM,gBAAgB;AAG5C,UAAI,aAAa,eAAe,MAAM,eAAe,QAAQ;AAC3D,cAAM,IAAI,MAAM,cAAc;AAAA,MAChC;AAGA,YAAM,iBAAiB,MAAM,OAAO,YAAY,EAAE,SAAS;AAAA,QACzD,OAAO;AAAA,UACL,IAAI;AAAA,YACF,EAAE,YAAY,MAAM,KAAK;AAAA,YACzB,EAAE,SAAS,EAAE,UAAU,MAAM,KAAK,EAAE;AAAA,UACtC;AAAA,QACF;AAAA,QACA,QAAQ,EAAE,IAAI,MAAM,OAAO,KAAK;AAAA,MAClC,CAAC;AAED,UAAI,eAAe,SAAS,GAAG;AAC7B,cAAM,SAAS,eACZ,IAAI,CAAC,MAAyB,EAAE,SAAS,UAAU,EACnD,KAAK,IAAI;AACZ,cAAM,IAAI;AAAA,UACR,mCAAmC,eAAe,MAAM,gBAAgB,MAAM;AAAA,QAChF;AAAA,MACF;AAGA,UAAI,oBAAoB;AACtB,YAAI;AACF,gBAAM,mBAAmB,MAAM,IAAI;AAAA,QACrC,QAAQ;AAAA,QAER;AAAA,MACF;AAEA,YAAM,OAAO,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACjD,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,EACF;AACF;;;ACnDO,SAAS,oBACd,QACA,QACA,SACA;AACA,QAAM,eAAe;AAAA,IACnB,GAAG,OAAO,OAAO;AAAA,IACjB,GAAG,OAAO,OAAO;AAAA,EACnB;AAEA,QAAM,aAAa,OAAO,OAAO;AAEjC,SAAO;AAAA,IACL,MAAM,aACJ,MAMA,YACuB;AACvB,UAAI,CAAC,aAAa,SAAS,KAAK,IAAI,GAAG;AACrC,eAAO,EAAE,OAAO,wBAAwB;AAAA,MAC1C;AAEA,YAAM,UAAU,OAAO,OAAO,WAAW,SAAS,KAAK,IAAI;AAC3D,YAAM,UAAU,UACZ,OAAO,OAAO,eACd,OAAO,OAAO;AAElB,UAAI,KAAK,OAAO,SAAS;AACvB,eAAO;AAAA,UACL,OAAO,uBAAuB,UAAU,OAAO,OAAO,gBAAgB,OAAO,QAAQ,OAAO,OAAO,gBAAgB,OAAO,KAAK;AAAA,QACjI;AAAA,MACF;AAEA,YAAM,SAAS,OAAO,KAAK,MAAM,KAAK,YAAY,CAAC;AACnD,YAAM,MAAM,MAAM,QAAQ,KAAK,KAAK,MAAM,QAAQ,KAAK,IAAI;AAE3D,YAAM,OAAO,UAAU,EAAE,OAAO;AAAA,QAC9B,MAAM;AAAA,UACJ,UAAU,KAAK;AAAA,UACf,MAAM;AAAA,UACN,UAAU,KAAK;AAAA,UACf,MAAM,KAAK;AAAA,UACX;AAAA,QACF;AAAA,MACF,CAAC;AAED,aAAO,EAAE,IAAI;AAAA,IACf;AAAA,EACF;AACF;;;AChEA,OAAOA,aAAY;AAGZ,SAAS,yBAAyB,QAAa,QAA2B;AAC/E,QAAM,YAAY,QAAQ,QAAQ,QAAQ;AAE1C,SAAO;AAAA,IACL,aAAa;AAAA,MACX,OAAO,CAAC;AAAA,MACR,UAAU,CAAC;AAAA,IACb;AAAA,IACA,MAAM,UAAU,aAAsC;AACpD,YAAM,QAAQ,YAAY;AAC1B,YAAM,WAAW,YAAY;AAE7B,UAAI,CAAC,SAAS,CAAC,SAAU,QAAO;AAEhC,YAAM,OAAO,MAAM,OAAO,SAAS,EAAE,WAAW;AAAA,QAC9C,OAAO,EAAE,MAAM;AAAA,MACjB,CAAC;AAED,UAAI,CAAC,KAAM,QAAO;AAElB,YAAM,UAAU,MAAMA,QAAO,QAAQ,UAAU,KAAK,QAAQ;AAC5D,UAAI,CAAC,QAAS,QAAO;AAErB,aAAO;AAAA,QACL,IAAI,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,QACX,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK;AAAA,MACb;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,mBAAmB,QAA0B;AAC3D,SAAO;AAAA,IACL,MAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF,GAGG;AACD,UAAI,MAAM;AACR,cAAM,KAAK,KAAK;AAChB,cAAM,OAAO,KAAK;AAAA,MACpB;AACA,aAAO;AAAA,IACT;AAAA,IACA,MAAM,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,IACF,GAGG;AACD,UAAI,QAAQ,MAAM;AAChB,gBAAQ,KAAK,KAAK,MAAM;AACxB,gBAAQ,KAAK,OAAO,MAAM;AAAA,MAC5B;AACA,aAAO;AAAA,IACT;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA,SAAS,EAAE,QAAQ;AAAA,IACrB,GAGG;AACD,YAAM,aAAa,CAAC,CAAC;AACrB,YAAM,OAAO,MAAM,MAAM;AACzB,YAAM,WAAW,QAAQ;AAEzB,UAAI,aAAa,OAAO,OAAO,SAAS,YAAY;AAClD,eAAO,SAAS,SAAS,IAAI,IAAI,OAAO,OAAO,UAAU,OAAO,CAAC;AAAA,MACnE;AAEA,UAAI,SAAS,WAAW,OAAO,OAAO,SAAS,GAAG;AAChD,YAAI,CAAC,YAAY;AACf,iBAAO,SAAS,SAAS,IAAI,IAAI,OAAO,OAAO,OAAO,OAAO,CAAC;AAAA,QAChE;AAEA,YACE,SAAS,WAAW,OAAO,OAAO,KAAK,KACvC,SAAS,OAAO,MAAM,WACtB;AACA,iBAAO,SAAS;AAAA,YACd,IAAI,IAAI,OAAO,OAAO,UAAU,OAAO;AAAA,UACzC;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC/FO,SAAS,gBAAgB,QAA0B;AACxD,SAAO;AAAA,IACL,QAAQ,MAAuB;AAC7B,aAAO,OAAO,MAAM,QAAQ,IAAI;AAAA,IAClC;AAAA,IACA,WAAW,MAAuB;AAChC,aAAO,OAAO,MAAM,WAAW,IAAI;AAAA,IACrC;AAAA,IACA,QAAQ,MAAuB;AAC7B,aAAO,SAAS,OAAO,MAAM;AAAA,IAC/B;AAAA,EACF;AACF;;;ACGO,SAAS,sBACd,QACA,aACA,QACiB;AACjB,QAAM,YAAY,YAAY,KAAK,QAAQ,MAAM,EAAE,EAAE,QAAQ,eAAe,CAAC,IAAI,KAAK,OAAO,GAAG,YAAY,CAAC;AAE7G,QAAM,QAAQ,OAAO,SAAS,KAAK,OAAO,YAAY,IAAI;AAE1D,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR,iBAAiB,SAAS,iCAAiC,YAAY,IAAI;AAAA,IAC7E;AAAA,EACF;AAEA,QAAM,cAAc,YAAY,OAAO,cACnC,EAAE,CAAC,YAAY,MAAM,YAAY,KAAK,GAAG,YAAY,MAAM,YAAY,UAAU,IACjF,EAAE,WAAW,OAAO;AAExB,QAAM,mBAAmB,YAAY,OAAO,oBAAoB,CAAC,OAAO;AAExE,SAAO;AAAA,IACL,MAAM,OAAO,SAAS;AACpB,YAAM,QAA6B,CAAC;AAEpC,UAAI,SAAS,QAAQ;AACnB,cAAM,KAAK,iBAAiB,IAAI,CAAC,WAAW;AAAA,UAC1C,CAAC,KAAK,GAAG,EAAE,UAAU,QAAQ,OAAO;AAAA,QACtC,EAAE;AAAA,MACJ;AAEA,UAAI,SAAS,QAAQ;AACnB,cAAM,SAAS,QAAQ;AAAA,MACzB;AAEA,aAAO,MAAM,SAAS;AAAA,QACpB,OAAO,OAAO,KAAK,KAAK,EAAE,SAAS,IAAI,QAAQ;AAAA,QAC/C,SAAS,SAAS,WAAW;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,QAAQ,IAAY;AACxB,aAAO,MAAM,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AAAA,IAC3C;AAAA,IAEA,MAAM,OAAO,MAA4B;AACvC,YAAM,aAAkC,CAAC;AAGzC,iBAAW,SAAS,YAAY,QAAQ;AACtC,YAAI,MAAM,iBAAiB,QAAW;AACpC,qBAAW,MAAM,IAAI,IAAI,MAAM;AAAA,QACjC;AAAA,MACF;AAGA,UAAI,YAAY,eAAe;AAC7B,mBAAW,SAAS,YAAY;AAAA,MAClC;AAGA,UAAI,MAAM;AACR,eAAO,OAAO,YAAY,IAAI;AAAA,MAChC;AAEA,YAAM,SAAS,MAAM,MAAM,OAAO;AAAA,QAChC,MAAM;AAAA,MACR,CAAC;AAED,aAAO,OAAO;AAAA,IAChB;AAAA,IAEA,MAAM,OAAO,IAAY,MAA2B;AAClD,YAAM,SAAS,MAAM,MAAM,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACvD,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,GAAG,YAAY,OAAO,QAAQ,YAAY;AAEvE,YAAM,MAAM,OAAO;AAAA,QACjB,OAAO,EAAE,GAAG;AAAA,QACZ,MAAM,EAAE,GAAG,MAAM,WAAW,oBAAI,KAAK,EAAE;AAAA,MACzC,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,OAAO,IAAY;AACvB,YAAM,SAAS,MAAM,MAAM,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACvD,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,GAAG,YAAY,OAAO,QAAQ,YAAY;AAEvE,YAAM,MAAM,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACpC,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,QAAQ,QAAgB,IAAY;AACxC,UAAI,CAAC,YAAY,gBAAiB,QAAO,EAAE,SAAS,MAAM;AAE1D,YAAM,SAAS,MAAM,MAAM,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACvD,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,GAAG,YAAY,OAAO,QAAQ,YAAY;AAEvE,YAAM,MAAM,OAAO;AAAA,QACjB,OAAO,EAAE,GAAG;AAAA,QACZ,MAAM;AAAA,UACJ,QAAQ,YAAY;AAAA,UACpB,aAAa,oBAAI,KAAK;AAAA,QACxB;AAAA,MACF,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,UAAU,IAAY;AAC1B,UAAI,CAAC,YAAY,cAAe,QAAO,EAAE,SAAS,MAAM;AAExD,YAAM,SAAS,MAAM,MAAM,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACvD,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,GAAG,YAAY,OAAO,QAAQ,YAAY;AAEvE,YAAM,MAAM,OAAO;AAAA,QACjB,OAAO,EAAE,GAAG;AAAA,QACZ,MAAM;AAAA,UACJ,QAAQ,YAAY;AAAA,UACpB,aAAa;AAAA,QACf;AAAA,MACF,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,EACF;AACF;;;AC7IO,SAAS,uBAAuB,QAAa,QAA0B;AAC5E,QAAM,gBAAgB,OAAO;AAE7B,SAAO;AAAA,IACL,MAAM,gBAAgB;AACpB,UAAI,CAAC,eAAe;AAElB,eAAO,OAAO,WAAW,IAAI,CAAC,MAAM,OAAO;AAAA,UACzC,IAAI,UAAU,CAAC;AAAA,UACf;AAAA,UACA,MAAM,KAAK,YAAY,EAAE,QAAQ,QAAQ,GAAG;AAAA,UAC5C,WAAW;AAAA,QACb,EAAE;AAAA,MACJ;AAEA,aAAO,cAAc,SAAS;AAAA,QAC5B,SAAS,EAAE,WAAW,MAAM;AAAA,MAC9B,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,eAAe,MAA2D;AAC9E,UAAI,CAAC,eAAe;AAClB,cAAM,IAAI,MAAM,uEAAkE;AAAA,MACpF;AAEA,YAAM,OACJ,KAAK,QACL,KAAK,KACF,YAAY,EACZ,UAAU,KAAK,EACf,QAAQ,oBAAoB,EAAE,EAC9B,QAAQ,iBAAiB,EAAE,EAC3B,QAAQ,QAAQ,GAAG;AAExB,aAAO,cAAc,OAAO;AAAA,QAC1B,MAAM;AAAA,UACJ,MAAM,KAAK;AAAA,UACX;AAAA,UACA,WAAW,KAAK,aAAa;AAAA,QAC/B;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,eACJ,IACA,MACA;AACA,UAAI,CAAC,eAAe;AAClB,cAAM,IAAI,MAAM,uEAAkE;AAAA,MACpF;AAEA,aAAO,cAAc,OAAO;AAAA,QAC1B,OAAO,EAAE,GAAG;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,eAAe,IAAY;AAC/B,UAAI,CAAC,eAAe;AAClB,cAAM,IAAI,MAAM,uEAAkE;AAAA,MACpF;AAEA,YAAM,cAAc,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AAC5C,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,iBAAiB;AACrB,UAAI,CAAC,cAAe;AAEpB,YAAM,WAAW,MAAM,cAAc,MAAM;AAC3C,UAAI,WAAW,EAAG;AAElB,eAAS,IAAI,GAAG,IAAI,OAAO,WAAW,QAAQ,KAAK;AACjD,cAAM,OAAO,OAAO,WAAW,CAAC;AAChC,cAAM,OAAO,KACV,YAAY,EACZ,UAAU,KAAK,EACf,QAAQ,oBAAoB,EAAE,EAC9B,QAAQ,iBAAiB,EAAE,EAC3B,QAAQ,QAAQ,GAAG;AAEtB,cAAM,cAAc,OAAO;AAAA,UACzB,MAAM;AAAA,YACJ;AAAA,YACA;AAAA,YACA,WAAW;AAAA,UACb;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;","names":["bcrypt"]}
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
3
  import { G as GEAuthAdapter } from './types-d8-k_4dN.js';
4
- import { G as GEContentType, c as GEActions } from './types-X07o_zKf.js';
4
+ import { g as GEContentType, e as GEComponentOverrides, h as GEActions } from './registry-Do5nzO7_.js';
5
5
 
6
6
  interface GELocale {
7
7
  content: {
@@ -130,6 +130,7 @@ interface GavaEngineConfig {
130
130
  };
131
131
  auth?: GEAuthAdapter;
132
132
  contentTypes?: GEContentType[];
133
+ components?: GEComponentOverrides;
133
134
  categories: string[];
134
135
  upload: {
135
136
  endpoint: string;
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { G as GELocale, a as GavaEngineConfig } from './index-CCsSC4nF.js';
2
- export { A as ActionsProvider, C as ConfigProvider, D as DEFAULT_CONFIG, b as GavaEngineProvider, S as SessionProvider, c as SplashProvider, T as ThemeProvider, d as ThemeToggle, e as defineConfig, l as localeToStrings, u as useGavaActions, f as useGavaConfig, g as useSplash } from './index-CCsSC4nF.js';
3
- import { G as GEContentType } from './types-X07o_zKf.js';
4
- export { c as GEActions, d as GEActionsV2, e as GEArticle, a as GEContentActions, b as GEFieldDef, f as GEFieldType, g as GEMedia, h as GERevision, i as GESession, j as GEUser, k as articlesContentType, l as createLegacyActions, m as defineContentType } from './types-X07o_zKf.js';
5
- export { A as ArticleEditor, a as ArticleList, C as CoverImageUpload, D as DashboardNavbar, b as DashboardSplashTrigger, c as DraggableYoutube, d as DraggableYoutubeView, E as EditorToolbar, I as ImageEditModal, M as MediaGrid, e as MediaPickerModal, R as ResizableImage, f as ResizableImageView, g as RevisionPanel, S as SplashScreen, h as StatCard, U as UserForm, i as UserTable, V as VideoExtension, j as VideoView } from './DashboardSplashTrigger-CRpueuUi.js';
1
+ import { G as GELocale, a as GavaEngineConfig } from './index-ByyETmJM.js';
2
+ export { A as ActionsProvider, C as ConfigProvider, D as DEFAULT_CONFIG, b as GavaEngineProvider, S as SessionProvider, c as SplashProvider, T as ThemeProvider, d as ThemeToggle, e as defineConfig, l as localeToStrings, u as useGavaActions, f as useGavaConfig, g as useSplash } from './index-ByyETmJM.js';
3
+ import { g as GEContentType } from './registry-Do5nzO7_.js';
4
+ export { C as ComponentRegistryProvider, h as GEActions, i as GEActionsV2, j as GEArticle, e as GEComponentOverrides, k as GEContentActions, G as GEFieldDef, l as GEFieldType, m as GEMedia, n as GERevision, o as GESession, p as GEUser, q as articlesContentType, r as createLegacyActions, s as defineContentType, u as useComponentRegistry, f as useRegisteredComponent } from './registry-Do5nzO7_.js';
5
+ export { A as ArticleEditor, a as ArticleList, C as CoverImageUpload, D as DashboardNavbar, b as DashboardSplashTrigger, c as DraggableYoutube, d as DraggableYoutubeView, E as EditorToolbar, I as ImageEditModal, M as MediaGrid, e as MediaPickerModal, R as ResizableImage, f as ResizableImageView, g as RevisionPanel, S as SplashScreen, h as StatCard, U as UserForm, i as UserTable, V as VideoExtension, j as VideoView } from './DashboardSplashTrigger-Bz4Z4edN.js';
6
6
  export { G as GEAuthAdapter, a as GEAuthSession, b as GEAuthUser } from './types-d8-k_4dN.js';
7
7
  export { AuthProvider, createNextAuthAdapter, useGavaAuth } from './auth/index.js';
8
8
  import 'react/jsx-runtime';
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  SessionProvider,
5
5
  ThemeProvider,
6
6
  ThemeToggle
7
- } from "./chunk-4LM22T36.js";
7
+ } from "./chunk-3ZYJ4C6R.js";
8
8
  import {
9
9
  ArticleEditor,
10
10
  ArticleList,
@@ -26,9 +26,10 @@ import {
26
26
  UserTable,
27
27
  VideoExtension,
28
28
  VideoView
29
- } from "./chunk-5X5LEDAN.js";
29
+ } from "./chunk-XUWBLDOW.js";
30
30
  import {
31
31
  ActionsProvider,
32
+ ComponentRegistryProvider,
32
33
  ConfigProvider,
33
34
  DEFAULT_CONFIG,
34
35
  SplashProvider,
@@ -40,10 +41,12 @@ import {
40
41
  localeToStrings,
41
42
  mergeLocales,
42
43
  registerLocale,
44
+ useComponentRegistry,
43
45
  useGavaActions,
44
46
  useGavaConfig,
47
+ useRegisteredComponent,
45
48
  useSplash
46
- } from "./chunk-MC3FBYWV.js";
49
+ } from "./chunk-PHT76VW6.js";
47
50
  import {
48
51
  AuthProvider,
49
52
  createNextAuthAdapter,
@@ -693,6 +696,7 @@ export {
693
696
  ArticleEditor,
694
697
  ArticleList,
695
698
  AuthProvider,
699
+ ComponentRegistryProvider,
696
700
  ConfigProvider,
697
701
  CoverImageUpload,
698
702
  DEFAULT_CONFIG,
@@ -740,9 +744,11 @@ export {
740
744
  localeToStrings,
741
745
  mergeLocales,
742
746
  registerLocale,
747
+ useComponentRegistry,
743
748
  useGavaActions,
744
749
  useGavaAuth,
745
750
  useGavaConfig,
751
+ useRegisteredComponent,
746
752
  useSplash
747
753
  };
748
754
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/content/types.ts","../src/types.ts","../src/handlers/revisions.ts","../src/handlers/articles.ts","../src/handlers/users.ts","../src/handlers/media.ts","../src/handlers/upload.ts","../src/handlers/auth.ts","../src/handlers/auth-utils.ts","../src/handlers/content.ts","../src/handlers/categories.ts"],"sourcesContent":["export type GEFieldType =\n | \"text\"\n | \"richtext\"\n | \"number\"\n | \"boolean\"\n | \"date\"\n | \"image\"\n | \"select\"\n | \"slug\"\n | \"relationship\"\n | \"json\";\n\nexport interface GEFieldDef {\n name: string;\n type: GEFieldType;\n label: string;\n required?: boolean;\n defaultValue?: any;\n placeholder?: string;\n options?: string[]; // for 'select' type\n generateFrom?: string; // for 'slug' type — field name to auto-generate from\n relationTo?: string; // for 'relationship' type — content type slug\n hidden?: boolean; // hide from editor\n admin?: {\n width?: \"full\" | \"half\";\n position?: \"main\" | \"sidebar\";\n };\n}\n\nexport interface GEContentType {\n slug: string; // 'articles', 'pages', 'events'\n labels: {\n singular: string;\n plural: string;\n };\n fields: GEFieldDef[];\n statuses?: string[]; // ['draft', 'published'] — custom statuses\n defaultStatus?: string;\n publishedStatus?: string;\n features?: {\n revisions?: boolean;\n views?: boolean;\n search?: boolean;\n };\n admin?: {\n listColumns?: string[];\n searchableFields?: string[];\n defaultSort?: {\n field: string;\n direction: \"asc\" | \"desc\";\n };\n };\n}\n\n// Helper to define a content type with full type safety\nexport function defineContentType(contentType: GEContentType): GEContentType {\n return {\n statuses: [\"draft\", \"published\"],\n defaultStatus: \"draft\",\n publishedStatus: \"published\",\n features: {\n revisions: true,\n views: false,\n search: true,\n },\n ...contentType,\n };\n}\n\n// Built-in \"articles\" content type matching the legacy v0.x schema\nexport const articlesContentType: GEContentType = defineContentType({\n slug: \"articles\",\n labels: { singular: \"Article\", plural: \"Articles\" },\n fields: [\n { name: \"title\", type: \"text\", label: \"Title\", placeholder: \"Article title\" },\n { name: \"slug\", type: \"slug\", label: \"Slug\", generateFrom: \"title\", admin: { position: \"sidebar\" } },\n { name: \"excerpt\", type: \"text\", label: \"Excerpt\", placeholder: \"Brief description...\", admin: { position: \"sidebar\" } },\n { name: \"content\", type: \"richtext\", label: \"Content\" },\n { name: \"coverImage\", type: \"image\", label: \"Cover image\", admin: { position: \"sidebar\" } },\n { name: \"category\", type: \"select\", label: \"Category\", admin: { position: \"sidebar\" } },\n { name: \"authorName\", type: \"text\", label: \"Author\", admin: { position: \"sidebar\" } },\n ],\n features: { revisions: true, views: true, search: true },\n admin: {\n listColumns: [\"title\", \"category\", \"status\", \"updatedAt\"],\n searchableFields: [\"title\", \"excerpt\", \"authorName\"],\n defaultSort: { field: \"updatedAt\", direction: \"desc\" },\n },\n});\n","export interface GEArticle {\n id: string;\n title: string;\n slug: string;\n excerpt: string;\n content: string;\n coverImage: string;\n category: string;\n status: string;\n authorName: string;\n viewCount?: number;\n createdAt: Date;\n updatedAt: Date;\n publishedAt: Date | null;\n}\n\nexport interface GEUser {\n id: string;\n name: string;\n email: string;\n role: string;\n createdAt: Date;\n}\n\nexport interface GEMedia {\n id: string;\n filename: string;\n path: string;\n mimeType: string;\n size: number;\n createdAt: Date;\n uploader: { name: string };\n}\n\nexport interface GERevision {\n id: string;\n title: string;\n content: string;\n excerpt: string;\n coverImage: string;\n category: string;\n note: string;\n createdAt: Date;\n editor: { name: string };\n}\n\nexport interface GESession {\n user: {\n id: string;\n name?: string | null;\n email?: string | null;\n role: string;\n };\n}\n\n// v2.0 content-based actions interface\nexport interface GEContentActions {\n getAll(options?: {\n search?: string;\n status?: string;\n }): Promise<any[]>;\n getById(id: string): Promise<any | null>;\n create(data?: Record<string, any>): Promise<string>;\n update(\n id: string,\n data: Record<string, any>\n ): Promise<{ success: boolean }>;\n delete(id: string): Promise<{ success: boolean }>;\n publish?(id: string): Promise<{ success: boolean }>;\n unpublish?(id: string): Promise<{ success: boolean }>;\n}\n\n// v2.0 actions interface with content-based structure\nexport interface GEActionsV2 {\n content: Record<string, GEContentActions>;\n media: {\n getMedia: (search?: string) => Promise<GEMedia[]>;\n deleteMedia: (id: string) => Promise<{ success: boolean }>;\n };\n users: {\n getUsers: () => Promise<GEUser[]>;\n getUserById: (id: string) => Promise<GEUser | null>;\n createUser: (formData: FormData) => Promise<{ error?: string } | void>;\n updateUser: (\n id: string,\n formData: FormData\n ) => Promise<{ error?: string } | void>;\n deleteUser: (id: string) => Promise<{ error?: string } | void>;\n };\n revisions: {\n getRevisions: (contentId: string) => Promise<GERevision[]>;\n restoreRevision: (\n contentId: string,\n revisionId: string\n ) => Promise<{ success: boolean }>;\n };\n uploadUrl: string;\n}\n\n// Legacy v1.x flat actions interface (backward compat)\nexport interface GEActions {\n // Articles\n getArticles: () => Promise<GEArticle[]>;\n getArticleById: (id: string) => Promise<GEArticle | null>;\n createArticle: () => Promise<string>;\n updateArticle: (\n id: string,\n data: {\n title?: string;\n slug?: string;\n excerpt?: string;\n content?: string;\n coverImage?: string;\n category?: string;\n authorName?: string;\n }\n ) => Promise<{ success: boolean }>;\n deleteArticle: (id: string) => Promise<{ success: boolean }>;\n publishArticle: (id: string) => Promise<{ success: boolean }>;\n unpublishArticle: (id: string) => Promise<{ success: boolean }>;\n\n // Media\n getMedia: (search?: string) => Promise<GEMedia[]>;\n deleteMedia: (id: string) => Promise<{ success: boolean }>;\n uploadUrl: string;\n\n // Revisions\n getRevisions: (articleId: string) => Promise<GERevision[]>;\n restoreRevision: (\n articleId: string,\n revisionId: string\n ) => Promise<{ success: boolean }>;\n\n // Users\n getUsers: () => Promise<GEUser[]>;\n getUserById: (id: string) => Promise<GEUser | null>;\n createUser: (formData: FormData) => Promise<{ error?: string } | void>;\n updateUser: (\n id: string,\n formData: FormData\n ) => Promise<{ error?: string } | void>;\n deleteUser: (id: string) => Promise<{ error?: string } | void>;\n}\n\n/**\n * @deprecated Use GEActionsV2 instead. This helper maps v1.x flat actions to v2.x structure.\n */\nexport function createLegacyActions(v2Actions: GEActionsV2, contentSlug: string = \"articles\"): GEActions {\n const content = v2Actions.content[contentSlug];\n if (!content) {\n throw new Error(`Content type \"${contentSlug}\" not found in actions`);\n }\n\n return {\n getArticles: () => content.getAll(),\n getArticleById: (id) => content.getById(id),\n createArticle: () => content.create(),\n updateArticle: (id, data) => content.update(id, data),\n deleteArticle: (id) => content.delete(id),\n publishArticle: (id) => content.publish?.(id) ?? Promise.resolve({ success: false }),\n unpublishArticle: (id) => content.unpublish?.(id) ?? Promise.resolve({ success: false }),\n getMedia: v2Actions.media.getMedia,\n deleteMedia: v2Actions.media.deleteMedia,\n uploadUrl: v2Actions.uploadUrl,\n getRevisions: v2Actions.revisions.getRevisions,\n restoreRevision: v2Actions.revisions.restoreRevision,\n getUsers: v2Actions.users.getUsers,\n getUserById: v2Actions.users.getUserById,\n createUser: v2Actions.users.createUser,\n updateUser: v2Actions.users.updateUser,\n deleteUser: v2Actions.users.deleteUser,\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport function createRevisionHandlers(prisma: any, config: GavaEngineConfig) {\n const throttleMs = config.editor.revisionThrottleMinutes * 60 * 1000;\n const articleModel = config.models.article;\n const revisionModel = config.models.articleRevision;\n\n return {\n async getRevisions(articleId: string) {\n return prisma[revisionModel].findMany({\n where: { articleId },\n include: { editor: { select: { name: true } } },\n orderBy: { createdAt: \"desc\" },\n });\n },\n\n async restoreRevision(\n articleId: string,\n revisionId: string,\n editorId: string\n ) {\n const article = await prisma[articleModel].findUnique({\n where: { id: articleId },\n });\n if (!article) throw new Error(\"Article not found\");\n\n const revision = await prisma[revisionModel].findUnique({\n where: { id: revisionId },\n });\n if (!revision || revision.articleId !== articleId) {\n throw new Error(\"Revision not found\");\n }\n\n // Save current state before restoring\n await prisma[revisionModel].create({\n data: {\n articleId,\n title: article.title,\n content: article.content,\n excerpt: article.excerpt,\n coverImage: article.coverImage,\n category: article.category,\n editorId,\n note: config.strings.beforeRestore,\n },\n });\n\n // Restore\n await prisma[articleModel].update({\n where: { id: articleId },\n data: {\n title: revision.title,\n content: revision.content,\n excerpt: revision.excerpt,\n coverImage: revision.coverImage,\n category: revision.category,\n updatedAt: new Date(),\n },\n });\n\n return { success: true };\n },\n\n async createRevisionSnapshot(\n articleId: string,\n editorId: string,\n note: string = \"\"\n ) {\n const article = await prisma[articleModel].findUnique({\n where: { id: articleId },\n });\n if (!article) return;\n\n // Throttle: only create if last revision was > threshold ago\n const threshold = new Date(Date.now() - throttleMs);\n const recent = await prisma[revisionModel].findFirst({\n where: { articleId, createdAt: { gte: threshold } },\n orderBy: { createdAt: \"desc\" },\n });\n\n if (recent && !note) return;\n\n await prisma[revisionModel].create({\n data: {\n articleId,\n title: article.title,\n content: article.content,\n excerpt: article.excerpt,\n coverImage: article.coverImage,\n category: article.category,\n editorId,\n note,\n },\n });\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\nimport { createRevisionHandlers } from \"./revisions.js\";\n\nexport function createArticleHandlers(prisma: any, config: GavaEngineConfig) {\n const revisionHandlers = createRevisionHandlers(prisma, config);\n const articleModel = config.models.article;\n\n return {\n async getArticles() {\n return prisma[articleModel].findMany({\n orderBy: { updatedAt: \"desc\" },\n });\n },\n\n async getArticleById(id: string) {\n return prisma[articleModel].findUnique({\n where: { id },\n });\n },\n\n async createArticle(authorName: string) {\n const article = await prisma[articleModel].create({\n data: {\n authorName,\n },\n });\n return article.id;\n },\n\n async updateArticle(\n userId: string,\n id: string,\n data: {\n title?: string;\n slug?: string;\n excerpt?: string;\n content?: string;\n coverImage?: string;\n category?: string;\n authorName?: string;\n }\n ) {\n const article = await prisma[articleModel].findUnique({ where: { id } });\n if (!article) throw new Error(\"Article not found\");\n\n await revisionHandlers.createRevisionSnapshot(id, userId);\n\n await prisma[articleModel].update({\n where: { id },\n data: { ...data, updatedAt: new Date() },\n });\n\n return { success: true };\n },\n\n async deleteArticle(id: string) {\n const article = await prisma[articleModel].findUnique({ where: { id } });\n if (!article) throw new Error(\"Article not found\");\n\n await prisma[articleModel].delete({ where: { id } });\n return { success: true };\n },\n\n async publishArticle(userId: string, id: string) {\n const article = await prisma[articleModel].findUnique({ where: { id } });\n if (!article) throw new Error(\"Article not found\");\n\n if (!article.title || !article.slug) {\n throw new Error(\n \"Title and slug are required for publishing\"\n );\n }\n\n await revisionHandlers.createRevisionSnapshot(\n id,\n userId,\n config.strings.publishedNote\n );\n\n await prisma[articleModel].update({\n where: { id },\n data: {\n status: config.statuses.published,\n publishedAt: new Date(),\n },\n });\n\n return { success: true };\n },\n\n async unpublishArticle(id: string) {\n const article = await prisma[articleModel].findUnique({ where: { id } });\n if (!article) throw new Error(\"Article not found\");\n\n await prisma[articleModel].update({\n where: { id },\n data: {\n status: config.statuses.draft,\n publishedAt: null,\n },\n });\n\n return { success: true };\n },\n };\n}\n","import bcrypt from \"bcryptjs\";\nimport type { GavaEngineConfig } from \"../config.js\";\n\nexport function createUserHandlers(prisma: any, config: GavaEngineConfig) {\n const userModel = config.models.user;\n\n return {\n async getUsers() {\n return prisma[userModel].findMany({\n select: {\n id: true,\n name: true,\n email: true,\n role: true,\n createdAt: true,\n },\n orderBy: { createdAt: \"desc\" },\n });\n },\n\n async getUserById(id: string) {\n return prisma[userModel].findUnique({\n where: { id },\n select: {\n id: true,\n name: true,\n email: true,\n role: true,\n },\n });\n },\n\n async createUser(formData: FormData) {\n const name = formData.get(\"name\") as string;\n const email = formData.get(\"email\") as string;\n const password = formData.get(\"password\") as string;\n const role = formData.get(\"role\") as string;\n\n if (!name || !email || !password || !role) {\n return { error: config.strings.allFieldsRequired };\n }\n\n if (!config.roles.list.includes(role)) {\n return { error: config.strings.invalidRole };\n }\n\n if (password.length < 6) {\n return { error: config.strings.passwordMinLength };\n }\n\n const existing = await prisma[userModel].findUnique({ where: { email } });\n if (existing) {\n return { error: config.strings.emailExists };\n }\n\n const hashedPassword = await bcrypt.hash(password, 10);\n\n await prisma[userModel].create({\n data: {\n name,\n email,\n password: hashedPassword,\n role,\n },\n });\n\n return { success: true };\n },\n\n async updateUser(id: string, formData: FormData) {\n const name = formData.get(\"name\") as string;\n const email = formData.get(\"email\") as string;\n const password = formData.get(\"password\") as string;\n const role = formData.get(\"role\") as string;\n\n if (!name || !email || !role) {\n return { error: config.strings.allFieldsRequired };\n }\n\n if (!config.roles.list.includes(role)) {\n return { error: config.strings.invalidRole };\n }\n\n const existing = await prisma[userModel].findUnique({ where: { email } });\n if (existing && existing.id !== id) {\n return { error: config.strings.emailExists };\n }\n\n const data: {\n name: string;\n email: string;\n role: string;\n password?: string;\n } = {\n name,\n email,\n role,\n };\n\n if (password && password.length > 0) {\n if (password.length < 6) {\n return { error: config.strings.passwordMinLength };\n }\n data.password = await bcrypt.hash(password, 10);\n }\n\n await prisma[userModel].update({\n where: { id },\n data,\n });\n\n return { success: true };\n },\n\n async deleteUser(currentUserId: string, id: string) {\n if (currentUserId === id) {\n return { error: config.strings.cannotDeleteSelf };\n }\n\n await prisma[userModel].delete({ where: { id } });\n return { success: true };\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport function createMediaHandlers(prisma: any, config: GavaEngineConfig) {\n const mediaModel = config.models.media;\n const articleModel = config.models.article;\n\n return {\n async getMedia(search?: string) {\n return prisma[mediaModel].findMany({\n where: search ? { filename: { contains: search } } : undefined,\n include: { uploader: { select: { name: true } } },\n orderBy: { createdAt: \"desc\" },\n });\n },\n\n async deleteMedia(\n userId: string,\n userRole: string,\n id: string,\n deleteFileFromDisk?: (path: string) => Promise<void>\n ) {\n const media = await prisma[mediaModel].findUnique({ where: { id } });\n if (!media) throw new Error(\"File not found\");\n\n // Writers can only delete their own media\n if (userRole === \"scrittore\" && media.uploaderId !== userId) {\n throw new Error(\"Unauthorized\");\n }\n\n // Check if image is used in articles\n const usedInArticles = await prisma[articleModel].findMany({\n where: {\n OR: [\n { coverImage: media.path },\n { content: { contains: media.path } },\n ],\n },\n select: { id: true, title: true },\n });\n\n if (usedInArticles.length > 0) {\n const titles = usedInArticles\n .map((a: { title: string }) => a.title || \"Untitled\")\n .join(\", \");\n throw new Error(\n `Cannot delete: image is used in ${usedInArticles.length} article(s) (${titles})`\n );\n }\n\n // Delete file from disk if handler provided\n if (deleteFileFromDisk) {\n try {\n await deleteFileFromDisk(media.path);\n } catch {\n // File may already be missing\n }\n }\n\n await prisma[mediaModel].delete({ where: { id } });\n return { success: true };\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport interface UploadResult {\n url?: string;\n error?: string;\n}\n\nexport interface FileStorage {\n save(filename: string, buffer: Buffer, mimeType: string): Promise<string>;\n}\n\nexport function createUploadHandler(\n prisma: any,\n config: GavaEngineConfig,\n storage: FileStorage\n) {\n const allowedTypes = [\n ...config.upload.imageTypes,\n ...config.upload.videoTypes,\n ];\n\n const mediaModel = config.models.media;\n\n return {\n async handleUpload(\n file: {\n name: string;\n type: string;\n size: number;\n arrayBuffer: () => Promise<ArrayBuffer>;\n },\n uploaderId: string\n ): Promise<UploadResult> {\n if (!allowedTypes.includes(file.type)) {\n return { error: \"Unsupported file type\" };\n }\n\n const isVideo = config.upload.videoTypes.includes(file.type);\n const maxSize = isVideo\n ? config.upload.maxVideoSize\n : config.upload.maxImageSize;\n\n if (file.size > maxSize) {\n return {\n error: `File too large. Max ${isVideo ? config.upload.maxVideoSize / (1024 * 1024) : config.upload.maxImageSize / (1024 * 1024)}MB.`,\n };\n }\n\n const buffer = Buffer.from(await file.arrayBuffer());\n const url = await storage.save(file.name, buffer, file.type);\n\n await prisma[mediaModel].create({\n data: {\n filename: file.name,\n path: url,\n mimeType: file.type,\n size: file.size,\n uploaderId,\n },\n });\n\n return { url };\n },\n };\n}\n","import bcrypt from \"bcryptjs\";\nimport type { GavaEngineConfig } from \"../config.js\";\n\nexport function buildCredentialsProvider(prisma: any, config?: GavaEngineConfig) {\n const userModel = config?.models?.user ?? \"user\";\n\n return {\n credentials: {\n email: {},\n password: {},\n },\n async authorize(credentials: Record<string, unknown>) {\n const email = credentials.email as string;\n const password = credentials.password as string;\n\n if (!email || !password) return null;\n\n const user = await prisma[userModel].findUnique({\n where: { email },\n });\n\n if (!user) return null;\n\n const isValid = await bcrypt.compare(password, user.password);\n if (!isValid) return null;\n\n return {\n id: user.id,\n name: user.name,\n email: user.email,\n role: user.role,\n };\n },\n };\n}\n\nexport function buildAuthCallbacks(config: GavaEngineConfig) {\n return {\n async jwt({\n token,\n user,\n }: {\n token: Record<string, unknown>;\n user?: Record<string, unknown>;\n }) {\n if (user) {\n token.id = user.id as string;\n token.role = user.role as string;\n }\n return token;\n },\n async session({\n session,\n token,\n }: {\n session: Record<string, any>;\n token: Record<string, unknown>;\n }) {\n if (session.user) {\n session.user.id = token.id as string;\n session.user.role = token.role as string;\n }\n return session;\n },\n authorized({\n auth,\n request: { nextUrl },\n }: {\n auth: Record<string, any> | null;\n request: { nextUrl: URL };\n }) {\n const isLoggedIn = !!auth;\n const role = auth?.user?.role;\n const pathname = nextUrl.pathname;\n\n if (pathname === config.routes.login && isLoggedIn) {\n return Response.redirect(new URL(config.routes.articles, nextUrl));\n }\n\n if (pathname.startsWith(config.routes.dashboard)) {\n if (!isLoggedIn) {\n return Response.redirect(new URL(config.routes.login, nextUrl));\n }\n\n if (\n pathname.startsWith(config.routes.users) &&\n role !== config.roles.adminRole\n ) {\n return Response.redirect(\n new URL(config.routes.articles, nextUrl)\n );\n }\n }\n\n return true;\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport function createAuthUtils(config: GavaEngineConfig) {\n return {\n canEdit(role: string): boolean {\n return config.roles.canEdit(role);\n },\n canPublish(role: string): boolean {\n return config.roles.canPublish(role);\n },\n isAdmin(role: string): boolean {\n return role === config.roles.adminRole;\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\nimport type { GEContentType } from \"../content/types.js\";\n\nexport interface ContentHandlers {\n getAll(options?: {\n search?: string;\n status?: string;\n orderBy?: Record<string, \"asc\" | \"desc\">;\n }): Promise<any[]>;\n getById(id: string): Promise<any | null>;\n create(data?: Record<string, any>): Promise<string>;\n update(id: string, data: Record<string, any>): Promise<{ success: boolean }>;\n delete(id: string): Promise<{ success: boolean }>;\n publish?(userId: string, id: string): Promise<{ success: boolean }>;\n unpublish?(id: string): Promise<{ success: boolean }>;\n}\n\nexport function createContentHandlers(\n prisma: any,\n contentType: GEContentType,\n config: GavaEngineConfig\n): ContentHandlers {\n const modelName = contentType.slug.replace(/s$/, \"\").replace(/(^|\\-)(\\w)/g, (_m, _p1, p2) => p2.toUpperCase());\n // Try to find the Prisma model — fallback to slug\n const model = prisma[modelName] ?? prisma[contentType.slug];\n\n if (!model) {\n throw new Error(\n `Prisma model \"${modelName}\" not found for content type \"${contentType.slug}\"`\n );\n }\n\n const defaultSort = contentType.admin?.defaultSort\n ? { [contentType.admin.defaultSort.field]: contentType.admin.defaultSort.direction }\n : { updatedAt: \"desc\" };\n\n const searchableFields = contentType.admin?.searchableFields ?? [\"title\"];\n\n return {\n async getAll(options) {\n const where: Record<string, any> = {};\n\n if (options?.search) {\n where.OR = searchableFields.map((field) => ({\n [field]: { contains: options.search },\n }));\n }\n\n if (options?.status) {\n where.status = options.status;\n }\n\n return model.findMany({\n where: Object.keys(where).length > 0 ? where : undefined,\n orderBy: options?.orderBy ?? defaultSort,\n });\n },\n\n async getById(id: string) {\n return model.findUnique({ where: { id } });\n },\n\n async create(data?: Record<string, any>) {\n const createData: Record<string, any> = {};\n\n // Set default values from field definitions\n for (const field of contentType.fields) {\n if (field.defaultValue !== undefined) {\n createData[field.name] = field.defaultValue;\n }\n }\n\n // Set default status\n if (contentType.defaultStatus) {\n createData.status = contentType.defaultStatus;\n }\n\n // Merge provided data\n if (data) {\n Object.assign(createData, data);\n }\n\n const record = await model.create({\n data: createData,\n });\n\n return record.id;\n },\n\n async update(id: string, data: Record<string, any>) {\n const record = await model.findUnique({ where: { id } });\n if (!record) throw new Error(`${contentType.labels.singular} not found`);\n\n await model.update({\n where: { id },\n data: { ...data, updatedAt: new Date() },\n });\n\n return { success: true };\n },\n\n async delete(id: string) {\n const record = await model.findUnique({ where: { id } });\n if (!record) throw new Error(`${contentType.labels.singular} not found`);\n\n await model.delete({ where: { id } });\n return { success: true };\n },\n\n async publish(userId: string, id: string) {\n if (!contentType.publishedStatus) return { success: false };\n\n const record = await model.findUnique({ where: { id } });\n if (!record) throw new Error(`${contentType.labels.singular} not found`);\n\n await model.update({\n where: { id },\n data: {\n status: contentType.publishedStatus,\n publishedAt: new Date(),\n },\n });\n\n return { success: true };\n },\n\n async unpublish(id: string) {\n if (!contentType.defaultStatus) return { success: false };\n\n const record = await model.findUnique({ where: { id } });\n if (!record) throw new Error(`${contentType.labels.singular} not found`);\n\n await model.update({\n where: { id },\n data: {\n status: contentType.defaultStatus,\n publishedAt: null,\n },\n });\n\n return { success: true };\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport function createCategoryHandlers(prisma: any, config: GavaEngineConfig) {\n const categoryModel = prisma.category;\n\n return {\n async getCategories() {\n if (!categoryModel) {\n // Fallback: return config categories as static list\n return config.categories.map((name, i) => ({\n id: `static-${i}`,\n name,\n slug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n sortOrder: i,\n }));\n }\n\n return categoryModel.findMany({\n orderBy: { sortOrder: \"asc\" },\n });\n },\n\n async createCategory(data: { name: string; slug?: string; sortOrder?: number }) {\n if (!categoryModel) {\n throw new Error(\"Category model not available — categories are static from config\");\n }\n\n const slug =\n data.slug ??\n data.name\n .toLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .replace(/[^a-z0-9\\s-]/g, \"\")\n .replace(/\\s+/g, \"-\");\n\n return categoryModel.create({\n data: {\n name: data.name,\n slug,\n sortOrder: data.sortOrder ?? 0,\n },\n });\n },\n\n async updateCategory(\n id: string,\n data: { name?: string; slug?: string; sortOrder?: number }\n ) {\n if (!categoryModel) {\n throw new Error(\"Category model not available — categories are static from config\");\n }\n\n return categoryModel.update({\n where: { id },\n data,\n });\n },\n\n async deleteCategory(id: string) {\n if (!categoryModel) {\n throw new Error(\"Category model not available — categories are static from config\");\n }\n\n await categoryModel.delete({ where: { id } });\n return { success: true };\n },\n\n async seedCategories() {\n if (!categoryModel) return;\n\n const existing = await categoryModel.count();\n if (existing > 0) return;\n\n for (let i = 0; i < config.categories.length; i++) {\n const name = config.categories[i];\n const slug = name\n .toLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .replace(/[^a-z0-9\\s-]/g, \"\")\n .replace(/\\s+/g, \"-\");\n\n await categoryModel.create({\n data: {\n name,\n slug,\n sortOrder: i,\n },\n });\n }\n },\n };\n}\n"],"mappings":"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","names":["bcrypt"]}
1
+ {"version":3,"sources":["../src/content/types.ts","../src/types.ts","../src/handlers/revisions.ts","../src/handlers/articles.ts","../src/handlers/users.ts","../src/handlers/media.ts","../src/handlers/upload.ts","../src/handlers/auth.ts","../src/handlers/auth-utils.ts","../src/handlers/content.ts","../src/handlers/categories.ts"],"sourcesContent":["export type GEFieldType =\n | \"text\"\n | \"richtext\"\n | \"number\"\n | \"boolean\"\n | \"date\"\n | \"image\"\n | \"select\"\n | \"slug\"\n | \"relationship\"\n | \"json\";\n\nexport interface GEFieldDef {\n name: string;\n type: GEFieldType;\n label: string;\n required?: boolean;\n defaultValue?: any;\n placeholder?: string;\n options?: string[]; // for 'select' type\n generateFrom?: string; // for 'slug' type — field name to auto-generate from\n relationTo?: string; // for 'relationship' type — content type slug\n hidden?: boolean; // hide from editor\n admin?: {\n width?: \"full\" | \"half\";\n position?: \"main\" | \"sidebar\";\n };\n}\n\nexport interface GEContentType {\n slug: string; // 'articles', 'pages', 'events'\n labels: {\n singular: string;\n plural: string;\n };\n fields: GEFieldDef[];\n statuses?: string[]; // ['draft', 'published'] — custom statuses\n defaultStatus?: string;\n publishedStatus?: string;\n features?: {\n revisions?: boolean;\n views?: boolean;\n search?: boolean;\n };\n admin?: {\n listColumns?: string[];\n searchableFields?: string[];\n defaultSort?: {\n field: string;\n direction: \"asc\" | \"desc\";\n };\n };\n}\n\n// Helper to define a content type with full type safety\nexport function defineContentType(contentType: GEContentType): GEContentType {\n return {\n statuses: [\"draft\", \"published\"],\n defaultStatus: \"draft\",\n publishedStatus: \"published\",\n features: {\n revisions: true,\n views: false,\n search: true,\n },\n ...contentType,\n };\n}\n\n// Built-in \"articles\" content type matching the legacy v0.x schema\nexport const articlesContentType: GEContentType = defineContentType({\n slug: \"articles\",\n labels: { singular: \"Article\", plural: \"Articles\" },\n fields: [\n { name: \"title\", type: \"text\", label: \"Title\", placeholder: \"Article title\" },\n { name: \"slug\", type: \"slug\", label: \"Slug\", generateFrom: \"title\", admin: { position: \"sidebar\" } },\n { name: \"excerpt\", type: \"text\", label: \"Excerpt\", placeholder: \"Brief description...\", admin: { position: \"sidebar\" } },\n { name: \"content\", type: \"richtext\", label: \"Content\" },\n { name: \"coverImage\", type: \"image\", label: \"Cover image\", admin: { position: \"sidebar\" } },\n { name: \"category\", type: \"select\", label: \"Category\", admin: { position: \"sidebar\" } },\n { name: \"authorName\", type: \"text\", label: \"Author\", admin: { position: \"sidebar\" } },\n ],\n features: { revisions: true, views: true, search: true },\n admin: {\n listColumns: [\"title\", \"category\", \"status\", \"updatedAt\"],\n searchableFields: [\"title\", \"excerpt\", \"authorName\"],\n defaultSort: { field: \"updatedAt\", direction: \"desc\" },\n },\n});\n","export interface GEArticle {\n id: string;\n title: string;\n slug: string;\n excerpt: string;\n content: string;\n coverImage: string;\n category: string;\n status: string;\n authorName: string;\n viewCount?: number;\n createdAt: Date;\n updatedAt: Date;\n publishedAt: Date | null;\n}\n\nexport interface GEUser {\n id: string;\n name: string;\n email: string;\n role: string;\n createdAt: Date;\n}\n\nexport interface GEMedia {\n id: string;\n filename: string;\n path: string;\n mimeType: string;\n size: number;\n createdAt: Date;\n uploader: { name: string };\n}\n\nexport interface GERevision {\n id: string;\n title: string;\n content: string;\n excerpt: string;\n coverImage: string;\n category: string;\n note: string;\n createdAt: Date;\n editor: { name: string };\n}\n\nexport interface GESession {\n user: {\n id: string;\n name?: string | null;\n email?: string | null;\n role: string;\n };\n}\n\n// v2.0 content-based actions interface\nexport interface GEContentActions {\n getAll(options?: {\n search?: string;\n status?: string;\n }): Promise<any[]>;\n getById(id: string): Promise<any | null>;\n create(data?: Record<string, any>): Promise<string>;\n update(\n id: string,\n data: Record<string, any>\n ): Promise<{ success: boolean }>;\n delete(id: string): Promise<{ success: boolean }>;\n publish?(id: string): Promise<{ success: boolean }>;\n unpublish?(id: string): Promise<{ success: boolean }>;\n}\n\n// v2.0 actions interface with content-based structure\nexport interface GEActionsV2 {\n content: Record<string, GEContentActions>;\n media: {\n getMedia: (search?: string) => Promise<GEMedia[]>;\n deleteMedia: (id: string) => Promise<{ success: boolean }>;\n };\n users: {\n getUsers: () => Promise<GEUser[]>;\n getUserById: (id: string) => Promise<GEUser | null>;\n createUser: (formData: FormData) => Promise<{ error?: string } | void>;\n updateUser: (\n id: string,\n formData: FormData\n ) => Promise<{ error?: string } | void>;\n deleteUser: (id: string) => Promise<{ error?: string } | void>;\n };\n revisions: {\n getRevisions: (contentId: string) => Promise<GERevision[]>;\n restoreRevision: (\n contentId: string,\n revisionId: string\n ) => Promise<{ success: boolean }>;\n };\n uploadUrl: string;\n}\n\n// Legacy v1.x flat actions interface (backward compat)\nexport interface GEActions {\n // Articles\n getArticles: () => Promise<GEArticle[]>;\n getArticleById: (id: string) => Promise<GEArticle | null>;\n createArticle: () => Promise<string>;\n updateArticle: (\n id: string,\n data: {\n title?: string;\n slug?: string;\n excerpt?: string;\n content?: string;\n coverImage?: string;\n category?: string;\n authorName?: string;\n }\n ) => Promise<{ success: boolean }>;\n deleteArticle: (id: string) => Promise<{ success: boolean }>;\n publishArticle: (id: string) => Promise<{ success: boolean }>;\n unpublishArticle: (id: string) => Promise<{ success: boolean }>;\n\n // Media\n getMedia: (search?: string) => Promise<GEMedia[]>;\n deleteMedia: (id: string) => Promise<{ success: boolean }>;\n uploadUrl: string;\n\n // Revisions\n getRevisions: (articleId: string) => Promise<GERevision[]>;\n restoreRevision: (\n articleId: string,\n revisionId: string\n ) => Promise<{ success: boolean }>;\n\n // Users\n getUsers: () => Promise<GEUser[]>;\n getUserById: (id: string) => Promise<GEUser | null>;\n createUser: (formData: FormData) => Promise<{ error?: string } | void>;\n updateUser: (\n id: string,\n formData: FormData\n ) => Promise<{ error?: string } | void>;\n deleteUser: (id: string) => Promise<{ error?: string } | void>;\n}\n\n/**\n * @deprecated Use GEActionsV2 instead. This helper maps v1.x flat actions to v2.x structure.\n */\nexport function createLegacyActions(v2Actions: GEActionsV2, contentSlug: string = \"articles\"): GEActions {\n const content = v2Actions.content[contentSlug];\n if (!content) {\n throw new Error(`Content type \"${contentSlug}\" not found in actions`);\n }\n\n return {\n getArticles: () => content.getAll(),\n getArticleById: (id) => content.getById(id),\n createArticle: () => content.create(),\n updateArticle: (id, data) => content.update(id, data),\n deleteArticle: (id) => content.delete(id),\n publishArticle: (id) => content.publish?.(id) ?? Promise.resolve({ success: false }),\n unpublishArticle: (id) => content.unpublish?.(id) ?? Promise.resolve({ success: false }),\n getMedia: v2Actions.media.getMedia,\n deleteMedia: v2Actions.media.deleteMedia,\n uploadUrl: v2Actions.uploadUrl,\n getRevisions: v2Actions.revisions.getRevisions,\n restoreRevision: v2Actions.revisions.restoreRevision,\n getUsers: v2Actions.users.getUsers,\n getUserById: v2Actions.users.getUserById,\n createUser: v2Actions.users.createUser,\n updateUser: v2Actions.users.updateUser,\n deleteUser: v2Actions.users.deleteUser,\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport function createRevisionHandlers(prisma: any, config: GavaEngineConfig) {\n const throttleMs = config.editor.revisionThrottleMinutes * 60 * 1000;\n const articleModel = config.models.article;\n const revisionModel = config.models.articleRevision;\n\n return {\n async getRevisions(articleId: string) {\n return prisma[revisionModel].findMany({\n where: { articleId },\n include: { editor: { select: { name: true } } },\n orderBy: { createdAt: \"desc\" },\n });\n },\n\n async restoreRevision(\n articleId: string,\n revisionId: string,\n editorId: string\n ) {\n const article = await prisma[articleModel].findUnique({\n where: { id: articleId },\n });\n if (!article) throw new Error(\"Article not found\");\n\n const revision = await prisma[revisionModel].findUnique({\n where: { id: revisionId },\n });\n if (!revision || revision.articleId !== articleId) {\n throw new Error(\"Revision not found\");\n }\n\n // Save current state before restoring\n await prisma[revisionModel].create({\n data: {\n articleId,\n title: article.title,\n content: article.content,\n excerpt: article.excerpt,\n coverImage: article.coverImage,\n category: article.category,\n editorId,\n note: config.strings.beforeRestore,\n },\n });\n\n // Restore\n await prisma[articleModel].update({\n where: { id: articleId },\n data: {\n title: revision.title,\n content: revision.content,\n excerpt: revision.excerpt,\n coverImage: revision.coverImage,\n category: revision.category,\n updatedAt: new Date(),\n },\n });\n\n return { success: true };\n },\n\n async createRevisionSnapshot(\n articleId: string,\n editorId: string,\n note: string = \"\"\n ) {\n const article = await prisma[articleModel].findUnique({\n where: { id: articleId },\n });\n if (!article) return;\n\n // Throttle: only create if last revision was > threshold ago\n const threshold = new Date(Date.now() - throttleMs);\n const recent = await prisma[revisionModel].findFirst({\n where: { articleId, createdAt: { gte: threshold } },\n orderBy: { createdAt: \"desc\" },\n });\n\n if (recent && !note) return;\n\n await prisma[revisionModel].create({\n data: {\n articleId,\n title: article.title,\n content: article.content,\n excerpt: article.excerpt,\n coverImage: article.coverImage,\n category: article.category,\n editorId,\n note,\n },\n });\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\nimport { createRevisionHandlers } from \"./revisions.js\";\n\nexport function createArticleHandlers(prisma: any, config: GavaEngineConfig) {\n const revisionHandlers = createRevisionHandlers(prisma, config);\n const articleModel = config.models.article;\n\n return {\n async getArticles() {\n return prisma[articleModel].findMany({\n orderBy: { updatedAt: \"desc\" },\n });\n },\n\n async getArticleById(id: string) {\n return prisma[articleModel].findUnique({\n where: { id },\n });\n },\n\n async createArticle(authorName: string) {\n const article = await prisma[articleModel].create({\n data: {\n authorName,\n },\n });\n return article.id;\n },\n\n async updateArticle(\n userId: string,\n id: string,\n data: {\n title?: string;\n slug?: string;\n excerpt?: string;\n content?: string;\n coverImage?: string;\n category?: string;\n authorName?: string;\n }\n ) {\n const article = await prisma[articleModel].findUnique({ where: { id } });\n if (!article) throw new Error(\"Article not found\");\n\n await revisionHandlers.createRevisionSnapshot(id, userId);\n\n await prisma[articleModel].update({\n where: { id },\n data: { ...data, updatedAt: new Date() },\n });\n\n return { success: true };\n },\n\n async deleteArticle(id: string) {\n const article = await prisma[articleModel].findUnique({ where: { id } });\n if (!article) throw new Error(\"Article not found\");\n\n await prisma[articleModel].delete({ where: { id } });\n return { success: true };\n },\n\n async publishArticle(userId: string, id: string) {\n const article = await prisma[articleModel].findUnique({ where: { id } });\n if (!article) throw new Error(\"Article not found\");\n\n if (!article.title || !article.slug) {\n throw new Error(\n \"Title and slug are required for publishing\"\n );\n }\n\n await revisionHandlers.createRevisionSnapshot(\n id,\n userId,\n config.strings.publishedNote\n );\n\n await prisma[articleModel].update({\n where: { id },\n data: {\n status: config.statuses.published,\n publishedAt: new Date(),\n },\n });\n\n return { success: true };\n },\n\n async unpublishArticle(id: string) {\n const article = await prisma[articleModel].findUnique({ where: { id } });\n if (!article) throw new Error(\"Article not found\");\n\n await prisma[articleModel].update({\n where: { id },\n data: {\n status: config.statuses.draft,\n publishedAt: null,\n },\n });\n\n return { success: true };\n },\n };\n}\n","import bcrypt from \"bcryptjs\";\nimport type { GavaEngineConfig } from \"../config.js\";\n\nexport function createUserHandlers(prisma: any, config: GavaEngineConfig) {\n const userModel = config.models.user;\n\n return {\n async getUsers() {\n return prisma[userModel].findMany({\n select: {\n id: true,\n name: true,\n email: true,\n role: true,\n createdAt: true,\n },\n orderBy: { createdAt: \"desc\" },\n });\n },\n\n async getUserById(id: string) {\n return prisma[userModel].findUnique({\n where: { id },\n select: {\n id: true,\n name: true,\n email: true,\n role: true,\n },\n });\n },\n\n async createUser(formData: FormData) {\n const name = formData.get(\"name\") as string;\n const email = formData.get(\"email\") as string;\n const password = formData.get(\"password\") as string;\n const role = formData.get(\"role\") as string;\n\n if (!name || !email || !password || !role) {\n return { error: config.strings.allFieldsRequired };\n }\n\n if (!config.roles.list.includes(role)) {\n return { error: config.strings.invalidRole };\n }\n\n if (password.length < 6) {\n return { error: config.strings.passwordMinLength };\n }\n\n const existing = await prisma[userModel].findUnique({ where: { email } });\n if (existing) {\n return { error: config.strings.emailExists };\n }\n\n const hashedPassword = await bcrypt.hash(password, 10);\n\n await prisma[userModel].create({\n data: {\n name,\n email,\n password: hashedPassword,\n role,\n },\n });\n\n return { success: true };\n },\n\n async updateUser(id: string, formData: FormData) {\n const name = formData.get(\"name\") as string;\n const email = formData.get(\"email\") as string;\n const password = formData.get(\"password\") as string;\n const role = formData.get(\"role\") as string;\n\n if (!name || !email || !role) {\n return { error: config.strings.allFieldsRequired };\n }\n\n if (!config.roles.list.includes(role)) {\n return { error: config.strings.invalidRole };\n }\n\n const existing = await prisma[userModel].findUnique({ where: { email } });\n if (existing && existing.id !== id) {\n return { error: config.strings.emailExists };\n }\n\n const data: {\n name: string;\n email: string;\n role: string;\n password?: string;\n } = {\n name,\n email,\n role,\n };\n\n if (password && password.length > 0) {\n if (password.length < 6) {\n return { error: config.strings.passwordMinLength };\n }\n data.password = await bcrypt.hash(password, 10);\n }\n\n await prisma[userModel].update({\n where: { id },\n data,\n });\n\n return { success: true };\n },\n\n async deleteUser(currentUserId: string, id: string) {\n if (currentUserId === id) {\n return { error: config.strings.cannotDeleteSelf };\n }\n\n await prisma[userModel].delete({ where: { id } });\n return { success: true };\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport function createMediaHandlers(prisma: any, config: GavaEngineConfig) {\n const mediaModel = config.models.media;\n const articleModel = config.models.article;\n\n return {\n async getMedia(search?: string) {\n return prisma[mediaModel].findMany({\n where: search ? { filename: { contains: search } } : undefined,\n include: { uploader: { select: { name: true } } },\n orderBy: { createdAt: \"desc\" },\n });\n },\n\n async deleteMedia(\n userId: string,\n userRole: string,\n id: string,\n deleteFileFromDisk?: (path: string) => Promise<void>\n ) {\n const media = await prisma[mediaModel].findUnique({ where: { id } });\n if (!media) throw new Error(\"File not found\");\n\n // Writers can only delete their own media\n if (userRole === \"scrittore\" && media.uploaderId !== userId) {\n throw new Error(\"Unauthorized\");\n }\n\n // Check if image is used in articles\n const usedInArticles = await prisma[articleModel].findMany({\n where: {\n OR: [\n { coverImage: media.path },\n { content: { contains: media.path } },\n ],\n },\n select: { id: true, title: true },\n });\n\n if (usedInArticles.length > 0) {\n const titles = usedInArticles\n .map((a: { title: string }) => a.title || \"Untitled\")\n .join(\", \");\n throw new Error(\n `Cannot delete: image is used in ${usedInArticles.length} article(s) (${titles})`\n );\n }\n\n // Delete file from disk if handler provided\n if (deleteFileFromDisk) {\n try {\n await deleteFileFromDisk(media.path);\n } catch {\n // File may already be missing\n }\n }\n\n await prisma[mediaModel].delete({ where: { id } });\n return { success: true };\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport interface UploadResult {\n url?: string;\n error?: string;\n}\n\nexport interface FileStorage {\n save(filename: string, buffer: Buffer, mimeType: string): Promise<string>;\n}\n\nexport function createUploadHandler(\n prisma: any,\n config: GavaEngineConfig,\n storage: FileStorage\n) {\n const allowedTypes = [\n ...config.upload.imageTypes,\n ...config.upload.videoTypes,\n ];\n\n const mediaModel = config.models.media;\n\n return {\n async handleUpload(\n file: {\n name: string;\n type: string;\n size: number;\n arrayBuffer: () => Promise<ArrayBuffer>;\n },\n uploaderId: string\n ): Promise<UploadResult> {\n if (!allowedTypes.includes(file.type)) {\n return { error: \"Unsupported file type\" };\n }\n\n const isVideo = config.upload.videoTypes.includes(file.type);\n const maxSize = isVideo\n ? config.upload.maxVideoSize\n : config.upload.maxImageSize;\n\n if (file.size > maxSize) {\n return {\n error: `File too large. Max ${isVideo ? config.upload.maxVideoSize / (1024 * 1024) : config.upload.maxImageSize / (1024 * 1024)}MB.`,\n };\n }\n\n const buffer = Buffer.from(await file.arrayBuffer());\n const url = await storage.save(file.name, buffer, file.type);\n\n await prisma[mediaModel].create({\n data: {\n filename: file.name,\n path: url,\n mimeType: file.type,\n size: file.size,\n uploaderId,\n },\n });\n\n return { url };\n },\n };\n}\n","import bcrypt from \"bcryptjs\";\nimport type { GavaEngineConfig } from \"../config.js\";\n\nexport function buildCredentialsProvider(prisma: any, config?: GavaEngineConfig) {\n const userModel = config?.models?.user ?? \"user\";\n\n return {\n credentials: {\n email: {},\n password: {},\n },\n async authorize(credentials: Record<string, unknown>) {\n const email = credentials.email as string;\n const password = credentials.password as string;\n\n if (!email || !password) return null;\n\n const user = await prisma[userModel].findUnique({\n where: { email },\n });\n\n if (!user) return null;\n\n const isValid = await bcrypt.compare(password, user.password);\n if (!isValid) return null;\n\n return {\n id: user.id,\n name: user.name,\n email: user.email,\n role: user.role,\n };\n },\n };\n}\n\nexport function buildAuthCallbacks(config: GavaEngineConfig) {\n return {\n async jwt({\n token,\n user,\n }: {\n token: Record<string, unknown>;\n user?: Record<string, unknown>;\n }) {\n if (user) {\n token.id = user.id as string;\n token.role = user.role as string;\n }\n return token;\n },\n async session({\n session,\n token,\n }: {\n session: Record<string, any>;\n token: Record<string, unknown>;\n }) {\n if (session.user) {\n session.user.id = token.id as string;\n session.user.role = token.role as string;\n }\n return session;\n },\n authorized({\n auth,\n request: { nextUrl },\n }: {\n auth: Record<string, any> | null;\n request: { nextUrl: URL };\n }) {\n const isLoggedIn = !!auth;\n const role = auth?.user?.role;\n const pathname = nextUrl.pathname;\n\n if (pathname === config.routes.login && isLoggedIn) {\n return Response.redirect(new URL(config.routes.articles, nextUrl));\n }\n\n if (pathname.startsWith(config.routes.dashboard)) {\n if (!isLoggedIn) {\n return Response.redirect(new URL(config.routes.login, nextUrl));\n }\n\n if (\n pathname.startsWith(config.routes.users) &&\n role !== config.roles.adminRole\n ) {\n return Response.redirect(\n new URL(config.routes.articles, nextUrl)\n );\n }\n }\n\n return true;\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport function createAuthUtils(config: GavaEngineConfig) {\n return {\n canEdit(role: string): boolean {\n return config.roles.canEdit(role);\n },\n canPublish(role: string): boolean {\n return config.roles.canPublish(role);\n },\n isAdmin(role: string): boolean {\n return role === config.roles.adminRole;\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\nimport type { GEContentType } from \"../content/types.js\";\n\nexport interface ContentHandlers {\n getAll(options?: {\n search?: string;\n status?: string;\n orderBy?: Record<string, \"asc\" | \"desc\">;\n }): Promise<any[]>;\n getById(id: string): Promise<any | null>;\n create(data?: Record<string, any>): Promise<string>;\n update(id: string, data: Record<string, any>): Promise<{ success: boolean }>;\n delete(id: string): Promise<{ success: boolean }>;\n publish?(userId: string, id: string): Promise<{ success: boolean }>;\n unpublish?(id: string): Promise<{ success: boolean }>;\n}\n\nexport function createContentHandlers(\n prisma: any,\n contentType: GEContentType,\n config: GavaEngineConfig\n): ContentHandlers {\n const modelName = contentType.slug.replace(/s$/, \"\").replace(/(^|\\-)(\\w)/g, (_m, _p1, p2) => p2.toUpperCase());\n // Try to find the Prisma model — fallback to slug\n const model = prisma[modelName] ?? prisma[contentType.slug];\n\n if (!model) {\n throw new Error(\n `Prisma model \"${modelName}\" not found for content type \"${contentType.slug}\"`\n );\n }\n\n const defaultSort = contentType.admin?.defaultSort\n ? { [contentType.admin.defaultSort.field]: contentType.admin.defaultSort.direction }\n : { updatedAt: \"desc\" };\n\n const searchableFields = contentType.admin?.searchableFields ?? [\"title\"];\n\n return {\n async getAll(options) {\n const where: Record<string, any> = {};\n\n if (options?.search) {\n where.OR = searchableFields.map((field) => ({\n [field]: { contains: options.search },\n }));\n }\n\n if (options?.status) {\n where.status = options.status;\n }\n\n return model.findMany({\n where: Object.keys(where).length > 0 ? where : undefined,\n orderBy: options?.orderBy ?? defaultSort,\n });\n },\n\n async getById(id: string) {\n return model.findUnique({ where: { id } });\n },\n\n async create(data?: Record<string, any>) {\n const createData: Record<string, any> = {};\n\n // Set default values from field definitions\n for (const field of contentType.fields) {\n if (field.defaultValue !== undefined) {\n createData[field.name] = field.defaultValue;\n }\n }\n\n // Set default status\n if (contentType.defaultStatus) {\n createData.status = contentType.defaultStatus;\n }\n\n // Merge provided data\n if (data) {\n Object.assign(createData, data);\n }\n\n const record = await model.create({\n data: createData,\n });\n\n return record.id;\n },\n\n async update(id: string, data: Record<string, any>) {\n const record = await model.findUnique({ where: { id } });\n if (!record) throw new Error(`${contentType.labels.singular} not found`);\n\n await model.update({\n where: { id },\n data: { ...data, updatedAt: new Date() },\n });\n\n return { success: true };\n },\n\n async delete(id: string) {\n const record = await model.findUnique({ where: { id } });\n if (!record) throw new Error(`${contentType.labels.singular} not found`);\n\n await model.delete({ where: { id } });\n return { success: true };\n },\n\n async publish(userId: string, id: string) {\n if (!contentType.publishedStatus) return { success: false };\n\n const record = await model.findUnique({ where: { id } });\n if (!record) throw new Error(`${contentType.labels.singular} not found`);\n\n await model.update({\n where: { id },\n data: {\n status: contentType.publishedStatus,\n publishedAt: new Date(),\n },\n });\n\n return { success: true };\n },\n\n async unpublish(id: string) {\n if (!contentType.defaultStatus) return { success: false };\n\n const record = await model.findUnique({ where: { id } });\n if (!record) throw new Error(`${contentType.labels.singular} not found`);\n\n await model.update({\n where: { id },\n data: {\n status: contentType.defaultStatus,\n publishedAt: null,\n },\n });\n\n return { success: true };\n },\n };\n}\n","import type { GavaEngineConfig } from \"../config.js\";\n\nexport function createCategoryHandlers(prisma: any, config: GavaEngineConfig) {\n const categoryModel = prisma.category;\n\n return {\n async getCategories() {\n if (!categoryModel) {\n // Fallback: return config categories as static list\n return config.categories.map((name, i) => ({\n id: `static-${i}`,\n name,\n slug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n sortOrder: i,\n }));\n }\n\n return categoryModel.findMany({\n orderBy: { sortOrder: \"asc\" },\n });\n },\n\n async createCategory(data: { name: string; slug?: string; sortOrder?: number }) {\n if (!categoryModel) {\n throw new Error(\"Category model not available — categories are static from config\");\n }\n\n const slug =\n data.slug ??\n data.name\n .toLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .replace(/[^a-z0-9\\s-]/g, \"\")\n .replace(/\\s+/g, \"-\");\n\n return categoryModel.create({\n data: {\n name: data.name,\n slug,\n sortOrder: data.sortOrder ?? 0,\n },\n });\n },\n\n async updateCategory(\n id: string,\n data: { name?: string; slug?: string; sortOrder?: number }\n ) {\n if (!categoryModel) {\n throw new Error(\"Category model not available — categories are static from config\");\n }\n\n return categoryModel.update({\n where: { id },\n data,\n });\n },\n\n async deleteCategory(id: string) {\n if (!categoryModel) {\n throw new Error(\"Category model not available — categories are static from config\");\n }\n\n await categoryModel.delete({ where: { id } });\n return { success: true };\n },\n\n async seedCategories() {\n if (!categoryModel) return;\n\n const existing = await categoryModel.count();\n if (existing > 0) return;\n\n for (let i = 0; i < config.categories.length; i++) {\n const name = config.categories[i];\n const slug = name\n .toLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .replace(/[^a-z0-9\\s-]/g, \"\")\n .replace(/\\s+/g, \"-\");\n\n await categoryModel.create({\n data: {\n name,\n slug,\n sortOrder: i,\n },\n });\n }\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuDO,SAAS,kBAAkB,aAA2C;AAC3E,SAAO;AAAA,IACL,UAAU,CAAC,SAAS,WAAW;AAAA,IAC/B,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,UAAU;AAAA,MACR,WAAW;AAAA,MACX,OAAO;AAAA,MACP,QAAQ;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EACL;AACF;AAGO,IAAM,sBAAqC,kBAAkB;AAAA,EAClE,MAAM;AAAA,EACN,QAAQ,EAAE,UAAU,WAAW,QAAQ,WAAW;AAAA,EAClD,QAAQ;AAAA,IACN,EAAE,MAAM,SAAS,MAAM,QAAQ,OAAO,SAAS,aAAa,gBAAgB;AAAA,IAC5E,EAAE,MAAM,QAAQ,MAAM,QAAQ,OAAO,QAAQ,cAAc,SAAS,OAAO,EAAE,UAAU,UAAU,EAAE;AAAA,IACnG,EAAE,MAAM,WAAW,MAAM,QAAQ,OAAO,WAAW,aAAa,wBAAwB,OAAO,EAAE,UAAU,UAAU,EAAE;AAAA,IACvH,EAAE,MAAM,WAAW,MAAM,YAAY,OAAO,UAAU;AAAA,IACtD,EAAE,MAAM,cAAc,MAAM,SAAS,OAAO,eAAe,OAAO,EAAE,UAAU,UAAU,EAAE;AAAA,IAC1F,EAAE,MAAM,YAAY,MAAM,UAAU,OAAO,YAAY,OAAO,EAAE,UAAU,UAAU,EAAE;AAAA,IACtF,EAAE,MAAM,cAAc,MAAM,QAAQ,OAAO,UAAU,OAAO,EAAE,UAAU,UAAU,EAAE;AAAA,EACtF;AAAA,EACA,UAAU,EAAE,WAAW,MAAM,OAAO,MAAM,QAAQ,KAAK;AAAA,EACvD,OAAO;AAAA,IACL,aAAa,CAAC,SAAS,YAAY,UAAU,WAAW;AAAA,IACxD,kBAAkB,CAAC,SAAS,WAAW,YAAY;AAAA,IACnD,aAAa,EAAE,OAAO,aAAa,WAAW,OAAO;AAAA,EACvD;AACF,CAAC;;;AC2DM,SAAS,oBAAoB,WAAwB,cAAsB,YAAuB;AACvG,QAAM,UAAU,UAAU,QAAQ,WAAW;AAC7C,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,iBAAiB,WAAW,wBAAwB;AAAA,EACtE;AAEA,SAAO;AAAA,IACL,aAAa,MAAM,QAAQ,OAAO;AAAA,IAClC,gBAAgB,CAAC,OAAO,QAAQ,QAAQ,EAAE;AAAA,IAC1C,eAAe,MAAM,QAAQ,OAAO;AAAA,IACpC,eAAe,CAAC,IAAI,SAAS,QAAQ,OAAO,IAAI,IAAI;AAAA,IACpD,eAAe,CAAC,OAAO,QAAQ,OAAO,EAAE;AAAA,IACxC,gBAAgB,CAAC,OAAO,QAAQ,UAAU,EAAE,KAAK,QAAQ,QAAQ,EAAE,SAAS,MAAM,CAAC;AAAA,IACnF,kBAAkB,CAAC,OAAO,QAAQ,YAAY,EAAE,KAAK,QAAQ,QAAQ,EAAE,SAAS,MAAM,CAAC;AAAA,IACvF,UAAU,UAAU,MAAM;AAAA,IAC1B,aAAa,UAAU,MAAM;AAAA,IAC7B,WAAW,UAAU;AAAA,IACrB,cAAc,UAAU,UAAU;AAAA,IAClC,iBAAiB,UAAU,UAAU;AAAA,IACrC,UAAU,UAAU,MAAM;AAAA,IAC1B,aAAa,UAAU,MAAM;AAAA,IAC7B,YAAY,UAAU,MAAM;AAAA,IAC5B,YAAY,UAAU,MAAM;AAAA,IAC5B,YAAY,UAAU,MAAM;AAAA,EAC9B;AACF;;;AC1KO,SAAS,uBAAuB,QAAa,QAA0B;AAC5E,QAAM,aAAa,OAAO,OAAO,0BAA0B,KAAK;AAChE,QAAM,eAAe,OAAO,OAAO;AACnC,QAAM,gBAAgB,OAAO,OAAO;AAEpC,SAAO;AAAA,IACL,MAAM,aAAa,WAAmB;AACpC,aAAO,OAAO,aAAa,EAAE,SAAS;AAAA,QACpC,OAAO,EAAE,UAAU;AAAA,QACnB,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,KAAK,EAAE,EAAE;AAAA,QAC9C,SAAS,EAAE,WAAW,OAAO;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,gBACJ,WACA,YACA,UACA;AACA,YAAM,UAAU,MAAM,OAAO,YAAY,EAAE,WAAW;AAAA,QACpD,OAAO,EAAE,IAAI,UAAU;AAAA,MACzB,CAAC;AACD,UAAI,CAAC,QAAS,OAAM,IAAI,MAAM,mBAAmB;AAEjD,YAAM,WAAW,MAAM,OAAO,aAAa,EAAE,WAAW;AAAA,QACtD,OAAO,EAAE,IAAI,WAAW;AAAA,MAC1B,CAAC;AACD,UAAI,CAAC,YAAY,SAAS,cAAc,WAAW;AACjD,cAAM,IAAI,MAAM,oBAAoB;AAAA,MACtC;AAGA,YAAM,OAAO,aAAa,EAAE,OAAO;AAAA,QACjC,MAAM;AAAA,UACJ;AAAA,UACA,OAAO,QAAQ;AAAA,UACf,SAAS,QAAQ;AAAA,UACjB,SAAS,QAAQ;AAAA,UACjB,YAAY,QAAQ;AAAA,UACpB,UAAU,QAAQ;AAAA,UAClB;AAAA,UACA,MAAM,OAAO,QAAQ;AAAA,QACvB;AAAA,MACF,CAAC;AAGD,YAAM,OAAO,YAAY,EAAE,OAAO;AAAA,QAChC,OAAO,EAAE,IAAI,UAAU;AAAA,QACvB,MAAM;AAAA,UACJ,OAAO,SAAS;AAAA,UAChB,SAAS,SAAS;AAAA,UAClB,SAAS,SAAS;AAAA,UAClB,YAAY,SAAS;AAAA,UACrB,UAAU,SAAS;AAAA,UACnB,WAAW,oBAAI,KAAK;AAAA,QACtB;AAAA,MACF,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,uBACJ,WACA,UACA,OAAe,IACf;AACA,YAAM,UAAU,MAAM,OAAO,YAAY,EAAE,WAAW;AAAA,QACpD,OAAO,EAAE,IAAI,UAAU;AAAA,MACzB,CAAC;AACD,UAAI,CAAC,QAAS;AAGd,YAAM,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,UAAU;AAClD,YAAM,SAAS,MAAM,OAAO,aAAa,EAAE,UAAU;AAAA,QACnD,OAAO,EAAE,WAAW,WAAW,EAAE,KAAK,UAAU,EAAE;AAAA,QAClD,SAAS,EAAE,WAAW,OAAO;AAAA,MAC/B,CAAC;AAED,UAAI,UAAU,CAAC,KAAM;AAErB,YAAM,OAAO,aAAa,EAAE,OAAO;AAAA,QACjC,MAAM;AAAA,UACJ;AAAA,UACA,OAAO,QAAQ;AAAA,UACf,SAAS,QAAQ;AAAA,UACjB,SAAS,QAAQ;AAAA,UACjB,YAAY,QAAQ;AAAA,UACpB,UAAU,QAAQ;AAAA,UAClB;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;AC7FO,SAAS,sBAAsB,QAAa,QAA0B;AAC3E,QAAM,mBAAmB,uBAAuB,QAAQ,MAAM;AAC9D,QAAM,eAAe,OAAO,OAAO;AAEnC,SAAO;AAAA,IACL,MAAM,cAAc;AAClB,aAAO,OAAO,YAAY,EAAE,SAAS;AAAA,QACnC,SAAS,EAAE,WAAW,OAAO;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,eAAe,IAAY;AAC/B,aAAO,OAAO,YAAY,EAAE,WAAW;AAAA,QACrC,OAAO,EAAE,GAAG;AAAA,MACd,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,cAAc,YAAoB;AACtC,YAAM,UAAU,MAAM,OAAO,YAAY,EAAE,OAAO;AAAA,QAChD,MAAM;AAAA,UACJ;AAAA,QACF;AAAA,MACF,CAAC;AACD,aAAO,QAAQ;AAAA,IACjB;AAAA,IAEA,MAAM,cACJ,QACA,IACA,MASA;AACA,YAAM,UAAU,MAAM,OAAO,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACvE,UAAI,CAAC,QAAS,OAAM,IAAI,MAAM,mBAAmB;AAEjD,YAAM,iBAAiB,uBAAuB,IAAI,MAAM;AAExD,YAAM,OAAO,YAAY,EAAE,OAAO;AAAA,QAChC,OAAO,EAAE,GAAG;AAAA,QACZ,MAAM,EAAE,GAAG,MAAM,WAAW,oBAAI,KAAK,EAAE;AAAA,MACzC,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,cAAc,IAAY;AAC9B,YAAM,UAAU,MAAM,OAAO,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACvE,UAAI,CAAC,QAAS,OAAM,IAAI,MAAM,mBAAmB;AAEjD,YAAM,OAAO,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACnD,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,eAAe,QAAgB,IAAY;AAC/C,YAAM,UAAU,MAAM,OAAO,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACvE,UAAI,CAAC,QAAS,OAAM,IAAI,MAAM,mBAAmB;AAEjD,UAAI,CAAC,QAAQ,SAAS,CAAC,QAAQ,MAAM;AACnC,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAEA,YAAM,iBAAiB;AAAA,QACrB;AAAA,QACA;AAAA,QACA,OAAO,QAAQ;AAAA,MACjB;AAEA,YAAM,OAAO,YAAY,EAAE,OAAO;AAAA,QAChC,OAAO,EAAE,GAAG;AAAA,QACZ,MAAM;AAAA,UACJ,QAAQ,OAAO,SAAS;AAAA,UACxB,aAAa,oBAAI,KAAK;AAAA,QACxB;AAAA,MACF,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,iBAAiB,IAAY;AACjC,YAAM,UAAU,MAAM,OAAO,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACvE,UAAI,CAAC,QAAS,OAAM,IAAI,MAAM,mBAAmB;AAEjD,YAAM,OAAO,YAAY,EAAE,OAAO;AAAA,QAChC,OAAO,EAAE,GAAG;AAAA,QACZ,MAAM;AAAA,UACJ,QAAQ,OAAO,SAAS;AAAA,UACxB,aAAa;AAAA,QACf;AAAA,MACF,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,EACF;AACF;;;ACzGA,OAAO,YAAY;AAGZ,SAAS,mBAAmB,QAAa,QAA0B;AACxE,QAAM,YAAY,OAAO,OAAO;AAEhC,SAAO;AAAA,IACL,MAAM,WAAW;AACf,aAAO,OAAO,SAAS,EAAE,SAAS;AAAA,QAChC,QAAQ;AAAA,UACN,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,OAAO;AAAA,UACP,MAAM;AAAA,UACN,WAAW;AAAA,QACb;AAAA,QACA,SAAS,EAAE,WAAW,OAAO;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,YAAY,IAAY;AAC5B,aAAO,OAAO,SAAS,EAAE,WAAW;AAAA,QAClC,OAAO,EAAE,GAAG;AAAA,QACZ,QAAQ;AAAA,UACN,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,OAAO;AAAA,UACP,MAAM;AAAA,QACR;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,WAAW,UAAoB;AACnC,YAAM,OAAO,SAAS,IAAI,MAAM;AAChC,YAAM,QAAQ,SAAS,IAAI,OAAO;AAClC,YAAM,WAAW,SAAS,IAAI,UAAU;AACxC,YAAM,OAAO,SAAS,IAAI,MAAM;AAEhC,UAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,YAAY,CAAC,MAAM;AACzC,eAAO,EAAE,OAAO,OAAO,QAAQ,kBAAkB;AAAA,MACnD;AAEA,UAAI,CAAC,OAAO,MAAM,KAAK,SAAS,IAAI,GAAG;AACrC,eAAO,EAAE,OAAO,OAAO,QAAQ,YAAY;AAAA,MAC7C;AAEA,UAAI,SAAS,SAAS,GAAG;AACvB,eAAO,EAAE,OAAO,OAAO,QAAQ,kBAAkB;AAAA,MACnD;AAEA,YAAM,WAAW,MAAM,OAAO,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AACxE,UAAI,UAAU;AACZ,eAAO,EAAE,OAAO,OAAO,QAAQ,YAAY;AAAA,MAC7C;AAEA,YAAM,iBAAiB,MAAM,OAAO,KAAK,UAAU,EAAE;AAErD,YAAM,OAAO,SAAS,EAAE,OAAO;AAAA,QAC7B,MAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA,UAAU;AAAA,UACV;AAAA,QACF;AAAA,MACF,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,WAAW,IAAY,UAAoB;AAC/C,YAAM,OAAO,SAAS,IAAI,MAAM;AAChC,YAAM,QAAQ,SAAS,IAAI,OAAO;AAClC,YAAM,WAAW,SAAS,IAAI,UAAU;AACxC,YAAM,OAAO,SAAS,IAAI,MAAM;AAEhC,UAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM;AAC5B,eAAO,EAAE,OAAO,OAAO,QAAQ,kBAAkB;AAAA,MACnD;AAEA,UAAI,CAAC,OAAO,MAAM,KAAK,SAAS,IAAI,GAAG;AACrC,eAAO,EAAE,OAAO,OAAO,QAAQ,YAAY;AAAA,MAC7C;AAEA,YAAM,WAAW,MAAM,OAAO,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AACxE,UAAI,YAAY,SAAS,OAAO,IAAI;AAClC,eAAO,EAAE,OAAO,OAAO,QAAQ,YAAY;AAAA,MAC7C;AAEA,YAAM,OAKF;AAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,UAAI,YAAY,SAAS,SAAS,GAAG;AACnC,YAAI,SAAS,SAAS,GAAG;AACvB,iBAAO,EAAE,OAAO,OAAO,QAAQ,kBAAkB;AAAA,QACnD;AACA,aAAK,WAAW,MAAM,OAAO,KAAK,UAAU,EAAE;AAAA,MAChD;AAEA,YAAM,OAAO,SAAS,EAAE,OAAO;AAAA,QAC7B,OAAO,EAAE,GAAG;AAAA,QACZ;AAAA,MACF,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,WAAW,eAAuB,IAAY;AAClD,UAAI,kBAAkB,IAAI;AACxB,eAAO,EAAE,OAAO,OAAO,QAAQ,iBAAiB;AAAA,MAClD;AAEA,YAAM,OAAO,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AAChD,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,EACF;AACF;;;ACzHO,SAAS,oBAAoB,QAAa,QAA0B;AACzE,QAAM,aAAa,OAAO,OAAO;AACjC,QAAM,eAAe,OAAO,OAAO;AAEnC,SAAO;AAAA,IACL,MAAM,SAAS,QAAiB;AAC9B,aAAO,OAAO,UAAU,EAAE,SAAS;AAAA,QACjC,OAAO,SAAS,EAAE,UAAU,EAAE,UAAU,OAAO,EAAE,IAAI;AAAA,QACrD,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,KAAK,EAAE,EAAE;AAAA,QAChD,SAAS,EAAE,WAAW,OAAO;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,YACJ,QACA,UACA,IACA,oBACA;AACA,YAAM,QAAQ,MAAM,OAAO,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACnE,UAAI,CAAC,MAAO,OAAM,IAAI,MAAM,gBAAgB;AAG5C,UAAI,aAAa,eAAe,MAAM,eAAe,QAAQ;AAC3D,cAAM,IAAI,MAAM,cAAc;AAAA,MAChC;AAGA,YAAM,iBAAiB,MAAM,OAAO,YAAY,EAAE,SAAS;AAAA,QACzD,OAAO;AAAA,UACL,IAAI;AAAA,YACF,EAAE,YAAY,MAAM,KAAK;AAAA,YACzB,EAAE,SAAS,EAAE,UAAU,MAAM,KAAK,EAAE;AAAA,UACtC;AAAA,QACF;AAAA,QACA,QAAQ,EAAE,IAAI,MAAM,OAAO,KAAK;AAAA,MAClC,CAAC;AAED,UAAI,eAAe,SAAS,GAAG;AAC7B,cAAM,SAAS,eACZ,IAAI,CAAC,MAAyB,EAAE,SAAS,UAAU,EACnD,KAAK,IAAI;AACZ,cAAM,IAAI;AAAA,UACR,mCAAmC,eAAe,MAAM,gBAAgB,MAAM;AAAA,QAChF;AAAA,MACF;AAGA,UAAI,oBAAoB;AACtB,YAAI;AACF,gBAAM,mBAAmB,MAAM,IAAI;AAAA,QACrC,QAAQ;AAAA,QAER;AAAA,MACF;AAEA,YAAM,OAAO,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACjD,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,EACF;AACF;;;ACnDO,SAAS,oBACd,QACA,QACA,SACA;AACA,QAAM,eAAe;AAAA,IACnB,GAAG,OAAO,OAAO;AAAA,IACjB,GAAG,OAAO,OAAO;AAAA,EACnB;AAEA,QAAM,aAAa,OAAO,OAAO;AAEjC,SAAO;AAAA,IACL,MAAM,aACJ,MAMA,YACuB;AACvB,UAAI,CAAC,aAAa,SAAS,KAAK,IAAI,GAAG;AACrC,eAAO,EAAE,OAAO,wBAAwB;AAAA,MAC1C;AAEA,YAAM,UAAU,OAAO,OAAO,WAAW,SAAS,KAAK,IAAI;AAC3D,YAAM,UAAU,UACZ,OAAO,OAAO,eACd,OAAO,OAAO;AAElB,UAAI,KAAK,OAAO,SAAS;AACvB,eAAO;AAAA,UACL,OAAO,uBAAuB,UAAU,OAAO,OAAO,gBAAgB,OAAO,QAAQ,OAAO,OAAO,gBAAgB,OAAO,KAAK;AAAA,QACjI;AAAA,MACF;AAEA,YAAM,SAAS,OAAO,KAAK,MAAM,KAAK,YAAY,CAAC;AACnD,YAAM,MAAM,MAAM,QAAQ,KAAK,KAAK,MAAM,QAAQ,KAAK,IAAI;AAE3D,YAAM,OAAO,UAAU,EAAE,OAAO;AAAA,QAC9B,MAAM;AAAA,UACJ,UAAU,KAAK;AAAA,UACf,MAAM;AAAA,UACN,UAAU,KAAK;AAAA,UACf,MAAM,KAAK;AAAA,UACX;AAAA,QACF;AAAA,MACF,CAAC;AAED,aAAO,EAAE,IAAI;AAAA,IACf;AAAA,EACF;AACF;;;AChEA,OAAOA,aAAY;AAGZ,SAAS,yBAAyB,QAAa,QAA2B;AAC/E,QAAM,YAAY,QAAQ,QAAQ,QAAQ;AAE1C,SAAO;AAAA,IACL,aAAa;AAAA,MACX,OAAO,CAAC;AAAA,MACR,UAAU,CAAC;AAAA,IACb;AAAA,IACA,MAAM,UAAU,aAAsC;AACpD,YAAM,QAAQ,YAAY;AAC1B,YAAM,WAAW,YAAY;AAE7B,UAAI,CAAC,SAAS,CAAC,SAAU,QAAO;AAEhC,YAAM,OAAO,MAAM,OAAO,SAAS,EAAE,WAAW;AAAA,QAC9C,OAAO,EAAE,MAAM;AAAA,MACjB,CAAC;AAED,UAAI,CAAC,KAAM,QAAO;AAElB,YAAM,UAAU,MAAMA,QAAO,QAAQ,UAAU,KAAK,QAAQ;AAC5D,UAAI,CAAC,QAAS,QAAO;AAErB,aAAO;AAAA,QACL,IAAI,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,QACX,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK;AAAA,MACb;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,mBAAmB,QAA0B;AAC3D,SAAO;AAAA,IACL,MAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF,GAGG;AACD,UAAI,MAAM;AACR,cAAM,KAAK,KAAK;AAChB,cAAM,OAAO,KAAK;AAAA,MACpB;AACA,aAAO;AAAA,IACT;AAAA,IACA,MAAM,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,IACF,GAGG;AACD,UAAI,QAAQ,MAAM;AAChB,gBAAQ,KAAK,KAAK,MAAM;AACxB,gBAAQ,KAAK,OAAO,MAAM;AAAA,MAC5B;AACA,aAAO;AAAA,IACT;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA,SAAS,EAAE,QAAQ;AAAA,IACrB,GAGG;AACD,YAAM,aAAa,CAAC,CAAC;AACrB,YAAM,OAAO,MAAM,MAAM;AACzB,YAAM,WAAW,QAAQ;AAEzB,UAAI,aAAa,OAAO,OAAO,SAAS,YAAY;AAClD,eAAO,SAAS,SAAS,IAAI,IAAI,OAAO,OAAO,UAAU,OAAO,CAAC;AAAA,MACnE;AAEA,UAAI,SAAS,WAAW,OAAO,OAAO,SAAS,GAAG;AAChD,YAAI,CAAC,YAAY;AACf,iBAAO,SAAS,SAAS,IAAI,IAAI,OAAO,OAAO,OAAO,OAAO,CAAC;AAAA,QAChE;AAEA,YACE,SAAS,WAAW,OAAO,OAAO,KAAK,KACvC,SAAS,OAAO,MAAM,WACtB;AACA,iBAAO,SAAS;AAAA,YACd,IAAI,IAAI,OAAO,OAAO,UAAU,OAAO;AAAA,UACzC;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC/FO,SAAS,gBAAgB,QAA0B;AACxD,SAAO;AAAA,IACL,QAAQ,MAAuB;AAC7B,aAAO,OAAO,MAAM,QAAQ,IAAI;AAAA,IAClC;AAAA,IACA,WAAW,MAAuB;AAChC,aAAO,OAAO,MAAM,WAAW,IAAI;AAAA,IACrC;AAAA,IACA,QAAQ,MAAuB;AAC7B,aAAO,SAAS,OAAO,MAAM;AAAA,IAC/B;AAAA,EACF;AACF;;;ACGO,SAAS,sBACd,QACA,aACA,QACiB;AACjB,QAAM,YAAY,YAAY,KAAK,QAAQ,MAAM,EAAE,EAAE,QAAQ,eAAe,CAAC,IAAI,KAAK,OAAO,GAAG,YAAY,CAAC;AAE7G,QAAM,QAAQ,OAAO,SAAS,KAAK,OAAO,YAAY,IAAI;AAE1D,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR,iBAAiB,SAAS,iCAAiC,YAAY,IAAI;AAAA,IAC7E;AAAA,EACF;AAEA,QAAM,cAAc,YAAY,OAAO,cACnC,EAAE,CAAC,YAAY,MAAM,YAAY,KAAK,GAAG,YAAY,MAAM,YAAY,UAAU,IACjF,EAAE,WAAW,OAAO;AAExB,QAAM,mBAAmB,YAAY,OAAO,oBAAoB,CAAC,OAAO;AAExE,SAAO;AAAA,IACL,MAAM,OAAO,SAAS;AACpB,YAAM,QAA6B,CAAC;AAEpC,UAAI,SAAS,QAAQ;AACnB,cAAM,KAAK,iBAAiB,IAAI,CAAC,WAAW;AAAA,UAC1C,CAAC,KAAK,GAAG,EAAE,UAAU,QAAQ,OAAO;AAAA,QACtC,EAAE;AAAA,MACJ;AAEA,UAAI,SAAS,QAAQ;AACnB,cAAM,SAAS,QAAQ;AAAA,MACzB;AAEA,aAAO,MAAM,SAAS;AAAA,QACpB,OAAO,OAAO,KAAK,KAAK,EAAE,SAAS,IAAI,QAAQ;AAAA,QAC/C,SAAS,SAAS,WAAW;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,QAAQ,IAAY;AACxB,aAAO,MAAM,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AAAA,IAC3C;AAAA,IAEA,MAAM,OAAO,MAA4B;AACvC,YAAM,aAAkC,CAAC;AAGzC,iBAAW,SAAS,YAAY,QAAQ;AACtC,YAAI,MAAM,iBAAiB,QAAW;AACpC,qBAAW,MAAM,IAAI,IAAI,MAAM;AAAA,QACjC;AAAA,MACF;AAGA,UAAI,YAAY,eAAe;AAC7B,mBAAW,SAAS,YAAY;AAAA,MAClC;AAGA,UAAI,MAAM;AACR,eAAO,OAAO,YAAY,IAAI;AAAA,MAChC;AAEA,YAAM,SAAS,MAAM,MAAM,OAAO;AAAA,QAChC,MAAM;AAAA,MACR,CAAC;AAED,aAAO,OAAO;AAAA,IAChB;AAAA,IAEA,MAAM,OAAO,IAAY,MAA2B;AAClD,YAAM,SAAS,MAAM,MAAM,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACvD,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,GAAG,YAAY,OAAO,QAAQ,YAAY;AAEvE,YAAM,MAAM,OAAO;AAAA,QACjB,OAAO,EAAE,GAAG;AAAA,QACZ,MAAM,EAAE,GAAG,MAAM,WAAW,oBAAI,KAAK,EAAE;AAAA,MACzC,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,OAAO,IAAY;AACvB,YAAM,SAAS,MAAM,MAAM,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACvD,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,GAAG,YAAY,OAAO,QAAQ,YAAY;AAEvE,YAAM,MAAM,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACpC,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,QAAQ,QAAgB,IAAY;AACxC,UAAI,CAAC,YAAY,gBAAiB,QAAO,EAAE,SAAS,MAAM;AAE1D,YAAM,SAAS,MAAM,MAAM,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACvD,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,GAAG,YAAY,OAAO,QAAQ,YAAY;AAEvE,YAAM,MAAM,OAAO;AAAA,QACjB,OAAO,EAAE,GAAG;AAAA,QACZ,MAAM;AAAA,UACJ,QAAQ,YAAY;AAAA,UACpB,aAAa,oBAAI,KAAK;AAAA,QACxB;AAAA,MACF,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,UAAU,IAAY;AAC1B,UAAI,CAAC,YAAY,cAAe,QAAO,EAAE,SAAS,MAAM;AAExD,YAAM,SAAS,MAAM,MAAM,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACvD,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,GAAG,YAAY,OAAO,QAAQ,YAAY;AAEvE,YAAM,MAAM,OAAO;AAAA,QACjB,OAAO,EAAE,GAAG;AAAA,QACZ,MAAM;AAAA,UACJ,QAAQ,YAAY;AAAA,UACpB,aAAa;AAAA,QACf;AAAA,MACF,CAAC;AAED,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,EACF;AACF;;;AC7IO,SAAS,uBAAuB,QAAa,QAA0B;AAC5E,QAAM,gBAAgB,OAAO;AAE7B,SAAO;AAAA,IACL,MAAM,gBAAgB;AACpB,UAAI,CAAC,eAAe;AAElB,eAAO,OAAO,WAAW,IAAI,CAAC,MAAM,OAAO;AAAA,UACzC,IAAI,UAAU,CAAC;AAAA,UACf;AAAA,UACA,MAAM,KAAK,YAAY,EAAE,QAAQ,QAAQ,GAAG;AAAA,UAC5C,WAAW;AAAA,QACb,EAAE;AAAA,MACJ;AAEA,aAAO,cAAc,SAAS;AAAA,QAC5B,SAAS,EAAE,WAAW,MAAM;AAAA,MAC9B,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,eAAe,MAA2D;AAC9E,UAAI,CAAC,eAAe;AAClB,cAAM,IAAI,MAAM,uEAAkE;AAAA,MACpF;AAEA,YAAM,OACJ,KAAK,QACL,KAAK,KACF,YAAY,EACZ,UAAU,KAAK,EACf,QAAQ,oBAAoB,EAAE,EAC9B,QAAQ,iBAAiB,EAAE,EAC3B,QAAQ,QAAQ,GAAG;AAExB,aAAO,cAAc,OAAO;AAAA,QAC1B,MAAM;AAAA,UACJ,MAAM,KAAK;AAAA,UACX;AAAA,UACA,WAAW,KAAK,aAAa;AAAA,QAC/B;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,eACJ,IACA,MACA;AACA,UAAI,CAAC,eAAe;AAClB,cAAM,IAAI,MAAM,uEAAkE;AAAA,MACpF;AAEA,aAAO,cAAc,OAAO;AAAA,QAC1B,OAAO,EAAE,GAAG;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,eAAe,IAAY;AAC/B,UAAI,CAAC,eAAe;AAClB,cAAM,IAAI,MAAM,uEAAkE;AAAA,MACpF;AAEA,YAAM,cAAc,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AAC5C,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,iBAAiB;AACrB,UAAI,CAAC,cAAe;AAEpB,YAAM,WAAW,MAAM,cAAc,MAAM;AAC3C,UAAI,WAAW,EAAG;AAElB,eAAS,IAAI,GAAG,IAAI,OAAO,WAAW,QAAQ,KAAK;AACjD,cAAM,OAAO,OAAO,WAAW,CAAC;AAChC,cAAM,OAAO,KACV,YAAY,EACZ,UAAU,KAAK,EACf,QAAQ,oBAAoB,EAAE,EAC9B,QAAQ,iBAAiB,EAAE,EAC3B,QAAQ,QAAQ,GAAG;AAEtB,cAAM,cAAc,OAAO;AAAA,UACzB,MAAM;AAAA,YACJ;AAAA,YACA;AAAA,YACA,WAAW;AAAA,UACb;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;","names":["bcrypt"]}
@@ -1,5 +1,5 @@
1
- export { A as ActionsProvider, C as ConfigProvider, b as GavaEngineProvider, S as SessionProvider, c as SplashProvider, T as ThemeProvider, d as ThemeToggle, u as useGavaActions, f as useGavaConfig, g as useSplash } from '../index-CCsSC4nF.js';
1
+ export { A as ActionsProvider, C as ConfigProvider, b as GavaEngineProvider, S as SessionProvider, c as SplashProvider, T as ThemeProvider, d as ThemeToggle, u as useGavaActions, f as useGavaConfig, g as useSplash } from '../index-ByyETmJM.js';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
4
4
  import '../types-d8-k_4dN.js';
5
- import '../types-X07o_zKf.js';
5
+ import '../registry-Do5nzO7_.js';
@@ -4,7 +4,7 @@ import {
4
4
  SessionProvider,
5
5
  ThemeProvider,
6
6
  ThemeToggle
7
- } from "../chunk-4LM22T36.js";
7
+ } from "../chunk-3ZYJ4C6R.js";
8
8
  import {
9
9
  ActionsProvider,
10
10
  ConfigProvider,
@@ -12,7 +12,7 @@ import {
12
12
  useGavaActions,
13
13
  useGavaConfig,
14
14
  useSplash
15
- } from "../chunk-MC3FBYWV.js";
15
+ } from "../chunk-PHT76VW6.js";
16
16
  export {
17
17
  ActionsProvider,
18
18
  ConfigProvider,
@@ -1,3 +1,6 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ComponentType, ReactNode } from 'react';
3
+
1
4
  type GEFieldType = "text" | "richtext" | "number" | "boolean" | "date" | "image" | "select" | "slug" | "relationship" | "json";
2
5
  interface GEFieldDef {
3
6
  name: string;
@@ -195,4 +198,45 @@ interface GEActions {
195
198
  */
196
199
  declare function createLegacyActions(v2Actions: GEActionsV2, contentSlug?: string): GEActions;
197
200
 
198
- export { type GEContentType as G, type GEContentActions as a, type GEFieldDef as b, type GEActions as c, type GEActionsV2 as d, type GEArticle as e, type GEFieldType as f, type GEMedia as g, type GERevision as h, type GESession as i, type GEUser as j, articlesContentType as k, createLegacyActions as l, defineContentType as m };
201
+ interface ContentEditorProps {
202
+ contentType: GEContentType;
203
+ actions: GEContentActions;
204
+ initialData?: Record<string, any>;
205
+ id?: string;
206
+ categories?: string[];
207
+ onSave?: () => void;
208
+ onPublish?: () => void;
209
+ }
210
+ declare function ContentEditor({ contentType, actions, initialData, id, categories, onSave, onPublish, }: ContentEditorProps): react_jsx_runtime.JSX.Element;
211
+
212
+ interface ContentListProps {
213
+ contentType: GEContentType;
214
+ actions: GEContentActions;
215
+ onEdit?: (id: string) => void;
216
+ onCreate?: () => void;
217
+ }
218
+ declare function ContentList({ contentType, actions, onEdit, onCreate, }: ContentListProps): react_jsx_runtime.JSX.Element;
219
+
220
+ interface GEComponentOverrides {
221
+ DashboardNavbar?: ComponentType<any>;
222
+ DashboardLayout?: ComponentType<{
223
+ children: ReactNode;
224
+ }>;
225
+ EditorToolbar?: ComponentType<{
226
+ editor: any;
227
+ }>;
228
+ ContentEditor?: ComponentType<ContentEditorProps>;
229
+ ContentList?: ComponentType<ContentListProps>;
230
+ MediaGrid?: ComponentType<any>;
231
+ UserTable?: ComponentType<any>;
232
+ LoginPage?: ComponentType<any>;
233
+ StatCard?: ComponentType<any>;
234
+ }
235
+ declare function ComponentRegistryProvider({ overrides, children, }: {
236
+ overrides: GEComponentOverrides;
237
+ children: ReactNode;
238
+ }): react_jsx_runtime.JSX.Element;
239
+ declare function useRegisteredComponent<K extends keyof GEComponentOverrides>(name: K, fallback: NonNullable<GEComponentOverrides[K]>): NonNullable<GEComponentOverrides[K]>;
240
+ declare function useComponentRegistry(): GEComponentOverrides;
241
+
242
+ export { ComponentRegistryProvider as C, type GEFieldDef as G, ContentEditor as a, type ContentEditorProps as b, ContentList as c, type ContentListProps as d, type GEComponentOverrides as e, useRegisteredComponent as f, type GEContentType as g, type GEActions as h, type GEActionsV2 as i, type GEArticle as j, type GEContentActions as k, type GEFieldType as l, type GEMedia as m, type GERevision as n, type GESession as o, type GEUser as p, articlesContentType as q, createLegacyActions as r, defineContentType as s, useComponentRegistry as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gavaengine",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Modular CMS engine — editor, auth, media & user management as React components",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/providers/GavaEngineProvider.tsx","../src/providers/SessionProvider.tsx","../src/providers/ThemeProvider.tsx","../src/providers/ThemeToggle.tsx"],"sourcesContent":["\"use client\";\n\nimport { type ReactNode } from \"react\";\nimport { useRouter } from \"next/navigation\";\nimport { type GavaEngineConfig } from \"../config.js\";\nimport type { GEActions } from \"../types.js\";\nimport { ConfigProvider } from \"./ConfigContext.js\";\nimport { ActionsProvider } from \"./ActionsContext.js\";\nimport { SplashProvider } from \"./SplashContext.js\";\nimport { SessionProvider } from \"./SessionProvider.js\";\nimport { ThemeProvider } from \"./ThemeProvider.js\";\n\ninterface GavaEngineProviderProps {\n config: GavaEngineConfig;\n actions: GEActions;\n children: ReactNode;\n}\n\nexport function GavaEngineProvider({\n config,\n actions,\n children,\n}: GavaEngineProviderProps) {\n const router = useRouter();\n\n return (\n <SessionProvider>\n <ThemeProvider>\n <ConfigProvider config={config}>\n <ActionsProvider actions={actions}>\n <SplashProvider navigate={(url) => router.push(url)}>\n {children}\n </SplashProvider>\n </ActionsProvider>\n </ConfigProvider>\n </ThemeProvider>\n </SessionProvider>\n );\n}\n","\"use client\";\n\nimport { SessionProvider as NextAuthSessionProvider } from \"next-auth/react\";\nimport { type ReactNode } from \"react\";\n\nexport function SessionProvider({ children }: { children: ReactNode }) {\n return <NextAuthSessionProvider>{children}</NextAuthSessionProvider>;\n}\n","\"use client\";\n\nimport { ThemeProvider as NextThemesProvider } from \"next-themes\";\nimport { type ReactNode } from \"react\";\n\nexport function ThemeProvider({ children }: { children: ReactNode }) {\n return (\n <NextThemesProvider attribute=\"class\" defaultTheme=\"system\" enableSystem>\n {children}\n </NextThemesProvider>\n );\n}\n","\"use client\";\n\nimport { useTheme } from \"next-themes\";\nimport { useEffect, useState } from \"react\";\nimport { Sun, Moon } from \"lucide-react\";\n\nexport function ThemeToggle() {\n const [mounted, setMounted] = useState(false);\n const { theme, setTheme } = useTheme();\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n if (!mounted) {\n return (\n <button className=\"p-2 rounded-lg bg-card border border-card-border\">\n <div className=\"w-5 h-5\" />\n </button>\n );\n }\n\n return (\n <button\n onClick={() => setTheme(theme === \"dark\" ? \"light\" : \"dark\")}\n className=\"p-2 rounded-lg bg-card border border-card-border hover:bg-card-border transition-colors\"\n aria-label=\"Toggle theme\"\n >\n {theme === \"dark\" ? (\n <Sun className=\"w-5 h-5 text-foreground\" />\n ) : (\n <Moon className=\"w-5 h-5 text-foreground\" />\n )}\n </button>\n );\n}\n"],"mappings":";;;;;;;;AAGA,SAAS,iBAAiB;;;ACD1B,SAAS,mBAAmB,+BAA+B;AAIlD;AADF,SAAS,gBAAgB,EAAE,SAAS,GAA4B;AACrE,SAAO,oBAAC,2BAAyB,UAAS;AAC5C;;;ACLA,SAAS,iBAAiB,0BAA0B;AAKhD,gBAAAA,YAAA;AAFG,SAAS,cAAc,EAAE,SAAS,GAA4B;AACnE,SACE,gBAAAA,KAAC,sBAAmB,WAAU,SAAQ,cAAa,UAAS,cAAY,MACrE,UACH;AAEJ;;;AFmBY,gBAAAC,YAAA;AAZL,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AACF,GAA4B;AAC1B,QAAM,SAAS,UAAU;AAEzB,SACE,gBAAAA,KAAC,mBACC,0BAAAA,KAAC,iBACC,0BAAAA,KAAC,kBAAe,QACd,0BAAAA,KAAC,mBAAgB,SACf,0BAAAA,KAAC,kBAAe,UAAU,CAAC,QAAQ,OAAO,KAAK,GAAG,GAC/C,UACH,GACF,GACF,GACF,GACF;AAEJ;;;AGpCA,SAAS,gBAAgB;AACzB,SAAS,WAAW,gBAAgB;AACpC,SAAS,KAAK,YAAY;AAalB,gBAAAC,YAAA;AAXD,SAAS,cAAc;AAC5B,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,EAAE,OAAO,SAAS,IAAI,SAAS;AAErC,YAAU,MAAM;AACd,eAAW,IAAI;AAAA,EACjB,GAAG,CAAC,CAAC;AAEL,MAAI,CAAC,SAAS;AACZ,WACE,gBAAAA,KAAC,YAAO,WAAU,oDAChB,0BAAAA,KAAC,SAAI,WAAU,WAAU,GAC3B;AAAA,EAEJ;AAEA,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,MAAM,SAAS,UAAU,SAAS,UAAU,MAAM;AAAA,MAC3D,WAAU;AAAA,MACV,cAAW;AAAA,MAEV,oBAAU,SACT,gBAAAA,KAAC,OAAI,WAAU,2BAA0B,IAEzC,gBAAAA,KAAC,QAAK,WAAU,2BAA0B;AAAA;AAAA,EAE9C;AAEJ;","names":["jsx","jsx","jsx"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/i18n/it.ts","../src/i18n/en.ts","../src/i18n/index.ts","../src/config.ts","../src/providers/ConfigContext.tsx","../src/providers/ActionsContext.tsx","../src/providers/SplashContext.tsx"],"sourcesContent":["import type { GELocale } from \"./types.js\";\n\nexport const it: GELocale = {\n content: {\n articles: \"Articoli\",\n newArticle: \"Nuovo articolo\",\n titlePlaceholder: \"Titolo dell'articolo\",\n excerptPlaceholder: \"Breve descrizione dell'articolo...\",\n slugPlaceholder: \"slug-articolo\",\n authorPlaceholder: \"Nome dell'autore\",\n category: \"Categoria\",\n selectCategory: \"Seleziona categoria\",\n excerpt: \"Estratto\",\n author: \"Autore\",\n slugUrl: \"Slug URL\",\n noArticles: \"Nessun articolo.\",\n noArticlesSearch: \"Nessun articolo trovato.\",\n searchArticles: \"Cerca articoli...\",\n coverImageLabel: \"Immagine di copertina\",\n coverImageHint: \"Scegli dalla libreria o carica un nuovo file\",\n viewArticle: \"Vedi articolo pubblicato\",\n untitled: \"Senza titolo\",\n },\n editor: {\n publish: \"Pubblica\",\n unpublish: \"Ritira\",\n saveDraft: \"Salva bozza\",\n revisions: \"Cronologia\",\n saving: \"Salvando...\",\n saved: \"Salvato\",\n saveError: \"Errore nel salvataggio\",\n noRevisions: \"Nessuna revisione salvata.\",\n restore: \"Ripristina\",\n restoreConfirm:\n \"Ripristinare questa revisione? Lo stato attuale verrà salvato prima del ripristino.\",\n beforeRestore: \"Prima del ripristino\",\n publishedNote: \"Pubblicato\",\n preview: \"Anteprima\",\n placeholder: \"Inizia a scrivere il tuo articolo...\",\n },\n media: {\n media: \"Media\",\n noMedia: \"Nessun file caricato.\",\n noMediaSearch: \"Nessun file trovato.\",\n chooseFile: \"Scegli file\",\n dragHint: \"Trascina un'immagine qui oppure\",\n uploadHint: \"JPEG, PNG, WebP, GIF (max 5MB)\",\n mediaLibrary: \"Libreria media\",\n uploadNew: \"Carica nuovo\",\n searchFiles: \"Cerca file...\",\n selectImage: \"Seleziona immagine\",\n noImages: \"Nessuna immagine nella libreria.\",\n noImagesSearch: \"Nessuna immagine trovata.\",\n copyUrl: \"Copia URL\",\n editImage: \"Modifica immagine\",\n restoreOriginal: \"Ripristina originale\",\n freeAspect: \"Libero\",\n },\n users: {\n users: \"Utenti\",\n name: \"Nome\",\n email: \"Email\",\n password: \"Password\",\n passwordEditHint: \" (lascia vuoto per non modificarla)\",\n role: \"Ruolo\",\n createdAt: \"Creato il\",\n actions: \"Azioni\",\n createUser: \"Crea utente\",\n unauthorized: \"Non autorizzato\",\n notAuthenticated: \"Non autenticato\",\n allFieldsRequired: \"Tutti i campi sono obbligatori.\",\n passwordMinLength: \"La password deve avere almeno 6 caratteri.\",\n emailExists: \"Esiste già un utente con questa email.\",\n invalidRole: \"Ruolo non valido.\",\n cannotDeleteSelf: \"Non puoi eliminare il tuo stesso account.\",\n },\n common: {\n statistics: \"Statistiche\",\n settings: \"Impostazioni\",\n delete: \"Elimina\",\n edit: \"Modifica\",\n search: \"Cerca\",\n draft: \"Bozza\",\n published: \"Pubblicato\",\n all: \"Tutti\",\n drafts: \"Bozze\",\n loading: \"Caricamento...\",\n confirm: \"Conferma\",\n cancel: \"Annulla\",\n apply: \"Applica\",\n change: \"Cambia\",\n logout: \"Esci\",\n saveChanges: \"Salva modifiche\",\n updated: \"Aggiornato\",\n status: \"Stato\",\n title: \"Titolo\",\n deleteConfirm: (title) => `Eliminare \"${title || \"Senza titolo\"}\"?`,\n unpublishConfirm: (title) =>\n `Ritirare \"${title || \"Senza titolo\"}\"? L'articolo tornerà in bozza.`,\n deleteUserConfirm: (name) =>\n `Sei sicuro di voler eliminare l'utente \"${name}\"?`,\n totalArticles: (count) =>\n `${count} articol${count === 1 ? \"o\" : \"i\"} totali`,\n totalFiles: (count) => `${count} file caricati`,\n },\n};\n","import type { GELocale } from \"./types.js\";\n\nexport const en: GELocale = {\n content: {\n articles: \"Articles\",\n newArticle: \"New article\",\n titlePlaceholder: \"Article title\",\n excerptPlaceholder: \"Brief description of the article...\",\n slugPlaceholder: \"article-slug\",\n authorPlaceholder: \"Author name\",\n category: \"Category\",\n selectCategory: \"Select category\",\n excerpt: \"Excerpt\",\n author: \"Author\",\n slugUrl: \"URL Slug\",\n noArticles: \"No articles.\",\n noArticlesSearch: \"No articles found.\",\n searchArticles: \"Search articles...\",\n coverImageLabel: \"Cover image\",\n coverImageHint: \"Choose from library or upload a new file\",\n viewArticle: \"View published article\",\n untitled: \"Untitled\",\n },\n editor: {\n publish: \"Publish\",\n unpublish: \"Unpublish\",\n saveDraft: \"Save draft\",\n revisions: \"History\",\n saving: \"Saving...\",\n saved: \"Saved\",\n saveError: \"Error saving\",\n noRevisions: \"No revisions saved.\",\n restore: \"Restore\",\n restoreConfirm:\n \"Restore this revision? The current state will be saved before restoring.\",\n beforeRestore: \"Before restore\",\n publishedNote: \"Published\",\n preview: \"Preview\",\n placeholder: \"Start writing your article...\",\n },\n media: {\n media: \"Media\",\n noMedia: \"No files uploaded.\",\n noMediaSearch: \"No files found.\",\n chooseFile: \"Choose file\",\n dragHint: \"Drag an image here or\",\n uploadHint: \"JPEG, PNG, WebP, GIF (max 5MB)\",\n mediaLibrary: \"Media library\",\n uploadNew: \"Upload new\",\n searchFiles: \"Search files...\",\n selectImage: \"Select image\",\n noImages: \"No images in library.\",\n noImagesSearch: \"No images found.\",\n copyUrl: \"Copy URL\",\n editImage: \"Edit image\",\n restoreOriginal: \"Restore original\",\n freeAspect: \"Free\",\n },\n users: {\n users: \"Users\",\n name: \"Name\",\n email: \"Email\",\n password: \"Password\",\n passwordEditHint: \" (leave blank to keep current)\",\n role: \"Role\",\n createdAt: \"Created at\",\n actions: \"Actions\",\n createUser: \"Create user\",\n unauthorized: \"Unauthorized\",\n notAuthenticated: \"Not authenticated\",\n allFieldsRequired: \"All fields are required.\",\n passwordMinLength: \"Password must be at least 6 characters.\",\n emailExists: \"A user with this email already exists.\",\n invalidRole: \"Invalid role.\",\n cannotDeleteSelf: \"You cannot delete your own account.\",\n },\n common: {\n statistics: \"Statistics\",\n settings: \"Settings\",\n delete: \"Delete\",\n edit: \"Edit\",\n search: \"Search\",\n draft: \"Draft\",\n published: \"Published\",\n all: \"All\",\n drafts: \"Drafts\",\n loading: \"Loading...\",\n confirm: \"Confirm\",\n cancel: \"Cancel\",\n apply: \"Apply\",\n change: \"Change\",\n logout: \"Logout\",\n saveChanges: \"Save changes\",\n updated: \"Updated\",\n status: \"Status\",\n title: \"Title\",\n deleteConfirm: (title) => `Delete \"${title || \"Untitled\"}\"?`,\n unpublishConfirm: (title) =>\n `Unpublish \"${title || \"Untitled\"}\"? The article will go back to draft.`,\n deleteUserConfirm: (name) =>\n `Are you sure you want to delete user \"${name}\"?`,\n totalArticles: (count) =>\n `${count} total article${count === 1 ? \"\" : \"s\"}`,\n totalFiles: (count) => `${count} uploaded file${count === 1 ? \"\" : \"s\"}`,\n },\n};\n","import type { GELocale } from \"./types.js\";\nimport { it } from \"./it.js\";\nimport { en } from \"./en.js\";\n\nexport type { GELocale } from \"./types.js\";\nexport { it } from \"./it.js\";\nexport { en } from \"./en.js\";\n\nconst builtinLocales: Record<string, GELocale> = { it, en };\n\nexport function loadLocale(locale: string): GELocale {\n const found = builtinLocales[locale];\n if (!found) {\n throw new Error(\n `Locale \"${locale}\" not found. Available: ${Object.keys(builtinLocales).join(\", \")}`\n );\n }\n return found;\n}\n\nexport function defineLocale(locale: GELocale): GELocale {\n return locale;\n}\n\nexport function mergeLocales(\n base: GELocale,\n overrides: DeepPartial<GELocale>\n): GELocale {\n return deepMergeLocale(base, overrides);\n}\n\nexport function registerLocale(key: string, locale: GELocale): void {\n builtinLocales[key] = locale;\n}\n\ntype DeepPartial<T> = {\n [P in keyof T]?: T[P] extends (...args: any[]) => any\n ? T[P]\n : T[P] extends object\n ? DeepPartial<T[P]>\n : T[P];\n};\n\nfunction deepMergeLocale<T extends Record<string, any>>(\n target: T,\n source: DeepPartial<T>\n): T {\n const result = { ...target };\n for (const key of Object.keys(source) as (keyof T)[]) {\n const sourceVal = source[key];\n const targetVal = target[key];\n if (\n sourceVal &&\n typeof sourceVal === \"object\" &&\n !Array.isArray(sourceVal) &&\n typeof targetVal === \"object\" &&\n !Array.isArray(targetVal) &&\n typeof sourceVal !== \"function\"\n ) {\n (result as any)[key] = deepMergeLocale(\n targetVal as Record<string, any>,\n sourceVal as Record<string, any>\n );\n } else if (sourceVal !== undefined) {\n (result as any)[key] = sourceVal;\n }\n }\n return result;\n}\n","import { loadLocale } from \"./i18n/index.js\";\nimport type { GELocale } from \"./i18n/types.js\";\nimport type { GEAuthAdapter } from \"./auth/types.js\";\nimport type { GEContentType } from \"./content/types.js\";\n\nexport interface GavaEngineConfig {\n branding: {\n name: string;\n logo?: string;\n };\n roles: {\n list: string[];\n labels: Record<string, string>;\n canEdit: (role: string) => boolean;\n canPublish: (role: string) => boolean;\n adminRole: string;\n };\n statuses: {\n draft: string;\n published: string;\n };\n locale: string;\n models: {\n article: string;\n articleRevision: string;\n articleView: string;\n media: string;\n user: string;\n };\n auth?: GEAuthAdapter;\n contentTypes?: GEContentType[];\n categories: string[];\n upload: {\n endpoint: string;\n imageTypes: string[];\n videoTypes: string[];\n maxImageSize: number;\n maxVideoSize: number;\n };\n editor: {\n placeholder: string;\n autoSaveDelay: number;\n revisionThrottleMinutes: number;\n headingLevels: number[];\n };\n routes: {\n articles: string;\n articleEdit: (id: string) => string;\n articleNew: string;\n articleView: (slug: string) => string;\n articlePreview: (id: string) => string;\n users: string;\n userEdit: (id: string) => string;\n userNew: string;\n media: string;\n dashboard: string;\n login: string;\n home: string;\n };\n strings: {\n articles: string;\n newArticle: string;\n media: string;\n users: string;\n statistics: string;\n settings: string;\n revisions: string;\n publish: string;\n unpublish: string;\n saveDraft: string;\n delete: string;\n edit: string;\n search: string;\n titlePlaceholder: string;\n excerptPlaceholder: string;\n slugPlaceholder: string;\n authorPlaceholder: string;\n category: string;\n selectCategory: string;\n excerpt: string;\n author: string;\n slugUrl: string;\n draft: string;\n published: string;\n all: string;\n drafts: string;\n saving: string;\n saved: string;\n saveError: string;\n noArticles: string;\n noArticlesSearch: string;\n noMedia: string;\n noMediaSearch: string;\n noRevisions: string;\n loading: string;\n confirm: string;\n cancel: string;\n apply: string;\n change: string;\n logout: string;\n viewArticle: string;\n preview: string;\n restore: string;\n restoreConfirm: string;\n beforeRestore: string;\n publishedNote: string;\n deleteConfirm: (title: string) => string;\n unpublishConfirm: (title: string) => string;\n deleteUserConfirm: (name: string) => string;\n totalArticles: (count: number) => string;\n totalFiles: (count: number) => string;\n coverImageLabel: string;\n coverImageHint: string;\n chooseFile: string;\n dragHint: string;\n uploadHint: string;\n mediaLibrary: string;\n uploadNew: string;\n searchFiles: string;\n searchArticles: string;\n selectImage: string;\n noImages: string;\n noImagesSearch: string;\n copyUrl: string;\n editImage: string;\n restoreOriginal: string;\n freeAspect: string;\n unauthorized: string;\n notAuthenticated: string;\n allFieldsRequired: string;\n passwordMinLength: string;\n emailExists: string;\n invalidRole: string;\n cannotDeleteSelf: string;\n name: string;\n email: string;\n password: string;\n passwordEditHint: string;\n role: string;\n createdAt: string;\n actions: string;\n createUser: string;\n saveChanges: string;\n updated: string;\n status: string;\n title: string;\n untitled: string;\n };\n}\n\nfunction localeToStrings(locale: GELocale): GavaEngineConfig[\"strings\"] {\n return {\n // content\n articles: locale.content.articles,\n newArticle: locale.content.newArticle,\n titlePlaceholder: locale.content.titlePlaceholder,\n excerptPlaceholder: locale.content.excerptPlaceholder,\n slugPlaceholder: locale.content.slugPlaceholder,\n authorPlaceholder: locale.content.authorPlaceholder,\n category: locale.content.category,\n selectCategory: locale.content.selectCategory,\n excerpt: locale.content.excerpt,\n author: locale.content.author,\n slugUrl: locale.content.slugUrl,\n noArticles: locale.content.noArticles,\n noArticlesSearch: locale.content.noArticlesSearch,\n searchArticles: locale.content.searchArticles,\n coverImageLabel: locale.content.coverImageLabel,\n coverImageHint: locale.content.coverImageHint,\n viewArticle: locale.content.viewArticle,\n untitled: locale.content.untitled,\n // editor\n publish: locale.editor.publish,\n unpublish: locale.editor.unpublish,\n saveDraft: locale.editor.saveDraft,\n revisions: locale.editor.revisions,\n saving: locale.editor.saving,\n saved: locale.editor.saved,\n saveError: locale.editor.saveError,\n noRevisions: locale.editor.noRevisions,\n restore: locale.editor.restore,\n restoreConfirm: locale.editor.restoreConfirm,\n beforeRestore: locale.editor.beforeRestore,\n publishedNote: locale.editor.publishedNote,\n preview: locale.editor.preview,\n // media\n media: locale.media.media,\n noMedia: locale.media.noMedia,\n noMediaSearch: locale.media.noMediaSearch,\n chooseFile: locale.media.chooseFile,\n dragHint: locale.media.dragHint,\n uploadHint: locale.media.uploadHint,\n mediaLibrary: locale.media.mediaLibrary,\n uploadNew: locale.media.uploadNew,\n searchFiles: locale.media.searchFiles,\n selectImage: locale.media.selectImage,\n noImages: locale.media.noImages,\n noImagesSearch: locale.media.noImagesSearch,\n copyUrl: locale.media.copyUrl,\n editImage: locale.media.editImage,\n restoreOriginal: locale.media.restoreOriginal,\n freeAspect: locale.media.freeAspect,\n // users\n users: locale.users.users,\n name: locale.users.name,\n email: locale.users.email,\n password: locale.users.password,\n passwordEditHint: locale.users.passwordEditHint,\n role: locale.users.role,\n createdAt: locale.users.createdAt,\n actions: locale.users.actions,\n createUser: locale.users.createUser,\n unauthorized: locale.users.unauthorized,\n notAuthenticated: locale.users.notAuthenticated,\n allFieldsRequired: locale.users.allFieldsRequired,\n passwordMinLength: locale.users.passwordMinLength,\n emailExists: locale.users.emailExists,\n invalidRole: locale.users.invalidRole,\n cannotDeleteSelf: locale.users.cannotDeleteSelf,\n // common\n statistics: locale.common.statistics,\n settings: locale.common.settings,\n delete: locale.common.delete,\n edit: locale.common.edit,\n search: locale.common.search,\n draft: locale.common.draft,\n published: locale.common.published,\n all: locale.common.all,\n drafts: locale.common.drafts,\n loading: locale.common.loading,\n confirm: locale.common.confirm,\n cancel: locale.common.cancel,\n apply: locale.common.apply,\n change: locale.common.change,\n logout: locale.common.logout,\n saveChanges: locale.common.saveChanges,\n updated: locale.common.updated,\n status: locale.common.status,\n title: locale.common.title,\n deleteConfirm: locale.common.deleteConfirm,\n unpublishConfirm: locale.common.unpublishConfirm,\n deleteUserConfirm: locale.common.deleteUserConfirm,\n totalArticles: locale.common.totalArticles,\n totalFiles: locale.common.totalFiles,\n };\n}\n\nconst DEFAULT_STRINGS = localeToStrings(loadLocale(\"it\"));\n\nconst DEFAULT_CONFIG: GavaEngineConfig = {\n branding: {\n name: \"GavaEngine\",\n },\n roles: {\n list: [\"admin\", \"redattore\", \"scrittore\", \"lettore\"],\n labels: {\n admin: \"Amministratore\",\n redattore: \"Redattore\",\n scrittore: \"Scrittore\",\n lettore: \"Lettore\",\n },\n canEdit: (role: string) => role !== \"lettore\",\n canPublish: (role: string) => role === \"admin\" || role === \"redattore\",\n adminRole: \"admin\",\n },\n statuses: {\n draft: \"bozza\",\n published: \"pubblicato\",\n },\n locale: \"it\",\n models: {\n article: \"article\",\n articleRevision: \"articleRevision\",\n articleView: \"articleView\",\n media: \"media\",\n user: \"user\",\n },\n categories: [\n \"Cultura ed Intercultura\",\n \"Fatti ed Eventi\",\n \"Poeti e Prosatori\",\n \"Famiglia, Istituzioni e Territorio\",\n \"Amici del Meucci\",\n ],\n upload: {\n endpoint: \"/api/upload\",\n imageTypes: [\"image/jpeg\", \"image/png\", \"image/webp\", \"image/gif\"],\n videoTypes: [\"video/mp4\", \"video/webm\", \"video/quicktime\"],\n maxImageSize: 5 * 1024 * 1024,\n maxVideoSize: 50 * 1024 * 1024,\n },\n editor: {\n placeholder: \"Inizia a scrivere il tuo articolo...\",\n autoSaveDelay: 2000,\n revisionThrottleMinutes: 5,\n headingLevels: [2, 3],\n },\n routes: {\n articles: \"/dashboard/articoli\",\n articleEdit: (id) => `/dashboard/articoli/${id}`,\n articleNew: \"/dashboard/articoli/nuovo\",\n articleView: (slug) => `/articoli/${slug}`,\n articlePreview: (id) => `/anteprima/${id}`,\n users: \"/dashboard/utenti\",\n userEdit: (id) => `/dashboard/utenti/${id}`,\n userNew: \"/dashboard/utenti/nuovo\",\n media: \"/dashboard/media\",\n dashboard: \"/dashboard\",\n login: \"/login\",\n home: \"/\",\n },\n strings: DEFAULT_STRINGS,\n};\n\nfunction deepMerge<T extends Record<string, any>>(\n target: T,\n source: Partial<T>\n): T {\n const result = { ...target };\n for (const key of Object.keys(source) as (keyof T)[]) {\n const sourceVal = source[key];\n const targetVal = target[key];\n if (\n sourceVal &&\n typeof sourceVal === \"object\" &&\n !Array.isArray(sourceVal) &&\n typeof targetVal === \"object\" &&\n !Array.isArray(targetVal) &&\n typeof sourceVal !== \"function\"\n ) {\n (result as any)[key] = deepMerge(\n targetVal as Record<string, any>,\n sourceVal as Record<string, any>\n );\n } else if (sourceVal !== undefined) {\n (result as any)[key] = sourceVal;\n }\n }\n return result;\n}\n\nexport function defineConfig(\n overrides: Partial<GavaEngineConfig> = {}\n): GavaEngineConfig {\n // If a different locale is specified, load it as base strings\n const locale = overrides.locale ?? DEFAULT_CONFIG.locale;\n const baseStrings = localeToStrings(loadLocale(locale));\n\n // Build config with locale-based strings as default\n const configWithLocale = {\n ...DEFAULT_CONFIG,\n strings: baseStrings,\n };\n\n // Also update editor.placeholder from locale if not overridden\n if (!overrides.editor?.placeholder) {\n const localeData = loadLocale(locale);\n configWithLocale.editor = {\n ...configWithLocale.editor,\n placeholder: localeData.editor.placeholder,\n };\n }\n\n return deepMerge(configWithLocale, overrides);\n}\n\nexport { DEFAULT_CONFIG, localeToStrings };\n","\"use client\";\n\nimport { createContext, useContext, type ReactNode } from \"react\";\nimport { type GavaEngineConfig, DEFAULT_CONFIG } from \"../config.js\";\n\nconst ConfigContext = createContext<GavaEngineConfig>(DEFAULT_CONFIG);\n\nexport function useGavaConfig() {\n return useContext(ConfigContext);\n}\n\nexport function ConfigProvider({\n config,\n children,\n}: {\n config: GavaEngineConfig;\n children: ReactNode;\n}) {\n return (\n <ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>\n );\n}\n","\"use client\";\n\nimport { createContext, useContext, type ReactNode } from \"react\";\nimport type { GEActions } from \"../types.js\";\n\nconst ActionsContext = createContext<GEActions | null>(null);\n\nexport function useGavaActions(): GEActions {\n const ctx = useContext(ActionsContext);\n if (!ctx) {\n throw new Error(\n \"useGavaActions must be used within a <GavaEngineProvider> with actions provided.\"\n );\n }\n return ctx;\n}\n\nexport function ActionsProvider({\n actions,\n children,\n}: {\n actions: GEActions;\n children: ReactNode;\n}) {\n return (\n <ActionsContext.Provider value={actions}>{children}</ActionsContext.Provider>\n );\n}\n","\"use client\";\n\nimport {\n createContext,\n useContext,\n useState,\n useCallback,\n type ReactNode,\n} from \"react\";\n\ntype Phase = \"idle\" | \"closing\" | \"closed\" | \"opening\";\n\ninterface SplashContextValue {\n phase: Phase;\n navigateWithSplash: (url: string) => void;\n openSplash: () => void;\n}\n\nconst SplashContext = createContext<SplashContextValue>({\n phase: \"idle\",\n navigateWithSplash: () => {},\n openSplash: () => {},\n});\n\nexport function useSplash() {\n return useContext(SplashContext);\n}\n\nexport function SplashProvider({\n children,\n navigate,\n}: {\n children: ReactNode;\n navigate: (url: string) => void;\n}) {\n const [phase, setPhase] = useState<Phase>(\"idle\");\n\n const navigateWithSplash = useCallback(\n (url: string) => {\n if (phase !== \"idle\") return;\n setPhase(\"closing\");\n\n setTimeout(() => {\n setPhase(\"closed\");\n navigate(url);\n }, 700);\n },\n [phase, navigate]\n );\n\n const openSplash = useCallback(() => {\n if (phase !== \"closed\") return;\n requestAnimationFrame(() => {\n setPhase(\"opening\");\n setTimeout(() => setPhase(\"idle\"), 900);\n });\n }, [phase]);\n\n return (\n <SplashContext.Provider value={{ phase, navigateWithSplash, openSplash }}>\n {children}\n </SplashContext.Provider>\n );\n}\n"],"mappings":"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","names":["createContext","useContext","jsx","createContext","useContext","jsx"]}