@carlonicora/nextjs-jsonapi 0.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/BlockNoteEditor-VFWG6LXI.js.map +1 -1
  2. package/dist/JsonApiRequest-ZZLSP26T.js.map +1 -1
  3. package/dist/atoms/index.js.map +1 -1
  4. package/dist/chunk-2K3Q24UF.js.map +1 -1
  5. package/dist/chunk-3FBCC4G3.js.map +1 -1
  6. package/dist/chunk-4HCRAOS5.js.map +1 -1
  7. package/dist/chunk-6GKHCVF6.js.map +1 -1
  8. package/dist/chunk-7QVYU63E.js.map +1 -1
  9. package/dist/chunk-A5DDIABK.js.map +1 -1
  10. package/dist/chunk-AWONBQQP.js.map +1 -1
  11. package/dist/chunk-CXQOWQSY.js.map +1 -1
  12. package/dist/chunk-DO2HLAZO.js.map +1 -1
  13. package/dist/chunk-EFJEWLRL.js.map +1 -1
  14. package/dist/chunk-FY4SXJGU.js.map +1 -1
  15. package/dist/chunk-H6FMOA6B.js.map +1 -1
  16. package/dist/chunk-I2REI7OA.js.map +1 -1
  17. package/dist/chunk-IBS6NI7D.js.map +1 -1
  18. package/dist/chunk-J4Q36PMP.js.map +1 -1
  19. package/dist/chunk-JC3WJK65.js.map +1 -1
  20. package/dist/chunk-LXKSUWAV.js.map +1 -1
  21. package/dist/chunk-RAF7PNLG.js.map +1 -1
  22. package/dist/chunk-RUR22SVM.js.map +1 -1
  23. package/dist/chunk-TEGF6ZWG.js.map +1 -1
  24. package/dist/chunk-TMVHSY3Y.js.map +1 -1
  25. package/dist/chunk-V2JJPI7N.js.map +1 -1
  26. package/dist/client/index.js.map +1 -1
  27. package/dist/components/index.js.map +1 -1
  28. package/dist/contexts/index.js.map +1 -1
  29. package/dist/core/index.js.map +1 -1
  30. package/dist/features/index.js.map +1 -1
  31. package/dist/hooks/index.js.map +1 -1
  32. package/dist/index.js.map +1 -1
  33. package/dist/interfaces/index.js.map +1 -1
  34. package/dist/permissions/index.js.map +1 -1
  35. package/dist/request-QFS7NEIE.js.map +1 -1
  36. package/dist/request-ZYY6RI5X.js.map +1 -1
  37. package/dist/roles/index.js.map +1 -1
  38. package/dist/server/index.js.map +1 -1
  39. package/dist/shadcnui/index.js.map +1 -1
  40. package/dist/token-MJMC26ON.js.map +1 -1
  41. package/dist/token-UYE7CV6X.js.map +1 -1
  42. package/dist/utils/index.js.map +1 -1
  43. package/package.json +5 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-AWONBQQP.js","../src/features/user/components/widgets/UserAvatar.tsx","../src/features/user/components/lists/ContributorsList.tsx"],"names":["jsx"],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACA;ACoBQ,+CAAA;AAnBD,SAAS,UAAA,CAAW,EAAE,IAAA,EAAM,SAAA,EAAW,QAAA,EAAU,SAAS,CAAA,EAAoB;AACnF,EAAA,MAAM,YAAA,EAAc,kDAAA,CAAoB;AAExC,EAAA,MAAM,WAAA,kBAAa,qCAAA,CAAC,KAAA,EAAA,GAAmB;AACrC,IAAA,GAAA,CAAI,CAAC,KAAA,EAAO,OAAO,EAAA;AACnB,IAAA,OAAO,KAAA,CAAM,CAAC,CAAA,CAAE,WAAA,CAAY,CAAA;AAAA,EAC9B,CAAA,EAHmB,YAAA,CAAA;AAKnB,EAAA,MAAM,YAAA,kBAAc,qCAAA,CAAC,IAAA,EAAA,GAAiB;AACpC,IAAA,MAAM,MAAA,EAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC5B,IAAA,MAAM,SAAA,EACJ,KAAA,CAAM,OAAA,EAAS,EAAA,EAAI,UAAA,CAAW,KAAA,CAAM,CAAC,CAAA,CAAE,CAAC,CAAC,EAAA,EAAI,UAAA,CAAW,KAAA,CAAM,KAAA,CAAM,OAAA,EAAS,CAAC,CAAA,CAAE,CAAC,CAAC,EAAA,EAAI,UAAA,CAAW,KAAA,CAAM,CAAC,CAAA,CAAE,CAAC,CAAC,CAAA;AAE9G,IAAA,wBAAO,QAAA,UAAY,IAAA;AAAA,EACrB,CAAA,EANoB,aAAA,CAAA;AAQpB,EAAA,MAAM,UAAA,kBAAY,qCAAA,CAAA,EAAA,GAAM;AACtB,IAAA,uBACE,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,wBAAA,EACb,QAAA,kBAAA,8BAAA,uBAAC,EAAA,EAAO,SAAA,EAAW,CAAA,QAAA,EAAW,SAAS,CAAA,CAAA;AACoB,sBAAA;AACjB,sBAAA;AAE5C,IAAA;AAPc,EAAA;AAad,EAAA;AACgB,oBAAA;AAAA;AAIP,MAAA;AAAU,QAAA;AACL,QAAA;AAGE,MAAA;AAGZ,IAAA;AAAC,MAAA;AAAA,MAAA;AACsD,QAAA;AAC0C,QAAA;AAC7D,QAAA;AAG/B,QAAA;AAAU,UAAA;AACL,UAAA;AACR,QAAA;AAAA,MAAA;AAOF,IAAA;AAGuB,oBAAA;AAC7B,EAAA;AAEJ;AA9DgB;ADyCsI;AACA;AEhDlJ;AAJiE;AAC3B,EAAA;AAIpC,EAAA;AAAAA,oBAAAA;AAAC,MAAA;AAAA,MAAA;AAEgE,QAAA;AAC7B,QAAA;AAEyB,QAAA;AAAA,MAAA;AAJvC,MAAA;AAKtB,IAAA;AAGa,oBAAA;AAEN,MAAA;AAAA,MAAA;AAEwD,QAAA;AACrB,QAAA;AAEY,QAAA;AAAA,MAAA;AAJlC,MAAA;AAOpB,IAAA;AACF,EAAA;AAEJ;AA3BgB;AF8EsI;AACA;AACA;AACA;AACA","file":"/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-AWONBQQP.js","sourcesContent":[null,"\"use client\";\n\nimport { Modules } from \"../../../../core\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n Link,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../../../../shadcnui\";\nimport { cn } from \"../../../../utils\";\nimport { UserInterface } from \"../../data\";\n\ntype UserAvatarProps = {\n user: UserInterface;\n className?: string;\n showFull?: boolean;\n showLink?: boolean;\n};\n\nexport function UserAvatar({ user, className, showFull, showLink }: UserAvatarProps) {\n const generateUrl = usePageUrlGenerator();\n\n const getInitial = (param?: string) => {\n if (!param) return \"\";\n return param[0].toUpperCase();\n };\n\n const getInitials = (name: string) => {\n const words = name.split(\" \");\n const initials =\n words.length > 1 ? getInitial(words[0][0]) + getInitial(words[words.length - 1][0]) : getInitial(words[0][0]);\n\n return initials ?? \"\";\n };\n\n const getAvatar = () => {\n return (\n <div className=\"*:ring-border *:ring-1\">\n <Avatar className={`h-6 w-6 ${className}`}>\n <AvatarImage className=\"object-cover\" src={user?.avatar} />\n <AvatarFallback>{getInitials(user.name)}</AvatarFallback>\n </Avatar>\n </div>\n );\n };\n\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n {showLink === false ? (\n // If showLink is explicitly false, never show a link\n showFull ? (\n <div className={cn(`mb-2 flex w-full flex-row items-center justify-start gap-x-2 text-sm`, className)}>\n {getAvatar()}\n {user.name}\n </div>\n ) : (\n getAvatar()\n )\n ) : showFull ? (\n <Link\n href={generateUrl({ page: Modules.User, id: user.id })}\n className={cn(`mb-2 flex w-full flex-row items-center justify-start gap-x-2 text-sm`, className)}\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flex w-full flex-row items-center gap-x-2\">\n {getAvatar()}\n {user.name}\n </div>\n </Link>\n ) : showLink ? (\n <Link href={generateUrl({ page: Modules.User, id: user.id })} className={className}>\n {getAvatar()}\n </Link>\n ) : (\n getAvatar()\n )}\n </TooltipTrigger>\n <TooltipContent>{user.name}</TooltipContent>\n </Tooltip>\n );\n}\n","\"use client\";\n\nimport { Modules } from \"../../../../core\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport { Link } from \"../../../../shadcnui\";\nimport { ContentInterface } from \"../../../content\";\nimport { UserInterface } from \"../../data\";\nimport { UserAvatar } from \"../widgets\";\n\ntype ContributorsListProps = {\n content: ContentInterface;\n};\n\nexport function ContributorsList({ content }: ContributorsListProps) {\n const generateUrl = usePageUrlGenerator();\n\n return (\n <div className=\"flex flex-row items-center\">\n <Link\n key={content.author.id}\n href={generateUrl({ page: Modules.User, id: content.author.id })}\n onClick={(e) => e.stopPropagation()}\n >\n <UserAvatar user={content.author} className=\"mr-1 h-6 w-6\" />\n </Link>\n <div className=\"flex flex-row-reverse justify-end -space-x-1 space-x-reverse\">\n {content.editors\n .filter((editor: UserInterface) => editor.id !== content.author.id)\n .map((editor: UserInterface) => (\n <Link\n key={editor.id}\n href={generateUrl({ page: Modules.User, id: editor.id })}\n onClick={(e) => e.stopPropagation()}\n >\n <UserAvatar user={editor} className=\"h-5 w-5\" />\n </Link>\n ))}\n </div>\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-AWONBQQP.js","../src/features/user/components/widgets/UserAvatar.tsx","../src/features/user/components/lists/ContributorsList.tsx"],"names":["jsx"],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACA;ACoBQ,+CAAA;AAnBD,SAAS,UAAA,CAAW,EAAE,IAAA,EAAM,SAAA,EAAW,QAAA,EAAU,SAAS,CAAA,EAAoB;AACnF,EAAA,MAAM,YAAA,EAAc,kDAAA,CAAoB;AAExC,EAAA,MAAM,WAAA,kBAAa,qCAAA,CAAC,KAAA,EAAA,GAAmB;AACrC,IAAA,GAAA,CAAI,CAAC,KAAA,EAAO,OAAO,EAAA;AACnB,IAAA,OAAO,KAAA,CAAM,CAAC,CAAA,CAAE,WAAA,CAAY,CAAA;AAAA,EAC9B,CAAA,EAHmB,YAAA,CAAA;AAKnB,EAAA,MAAM,YAAA,kBAAc,qCAAA,CAAC,IAAA,EAAA,GAAiB;AACpC,IAAA,MAAM,MAAA,EAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC5B,IAAA,MAAM,SAAA,EACJ,KAAA,CAAM,OAAA,EAAS,EAAA,EAAI,UAAA,CAAW,KAAA,CAAM,CAAC,CAAA,CAAE,CAAC,CAAC,EAAA,EAAI,UAAA,CAAW,KAAA,CAAM,KAAA,CAAM,OAAA,EAAS,CAAC,CAAA,CAAE,CAAC,CAAC,EAAA,EAAI,UAAA,CAAW,KAAA,CAAM,CAAC,CAAA,CAAE,CAAC,CAAC,CAAA;AAE9G,IAAA,wBAAO,QAAA,UAAY,IAAA;AAAA,EACrB,CAAA,EANoB,aAAA,CAAA;AAQpB,EAAA,MAAM,UAAA,kBAAY,qCAAA,CAAA,EAAA,GAAM;AACtB,IAAA,uBACE,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,wBAAA,EACb,QAAA,kBAAA,8BAAA,uBAAC,EAAA,EAAO,SAAA,EAAW,CAAA,QAAA,EAAW,SAAS,CAAA,CAAA;AACoB,sBAAA;AACjB,sBAAA;AAE5C,IAAA;AAPc,EAAA;AAad,EAAA;AACgB,oBAAA;AAAA;AAIP,MAAA;AAAU,QAAA;AACL,QAAA;AAGE,MAAA;AAGZ,IAAA;AAAC,MAAA;AAAA,MAAA;AACsD,QAAA;AAC0C,QAAA;AAC7D,QAAA;AAG/B,QAAA;AAAU,UAAA;AACL,UAAA;AACR,QAAA;AAAA,MAAA;AAOF,IAAA;AAGuB,oBAAA;AAC7B,EAAA;AAEJ;AA9DgB;ADyCsI;AACA;AEhDlJ;AAJiE;AAC3B,EAAA;AAIpC,EAAA;AAAAA,oBAAAA;AAAC,MAAA;AAAA,MAAA;AAEgE,QAAA;AAC7B,QAAA;AAEyB,QAAA;AAAA,MAAA;AAJvC,MAAA;AAKtB,IAAA;AAGa,oBAAA;AAEN,MAAA;AAAA,MAAA;AAEwD,QAAA;AACrB,QAAA;AAEY,QAAA;AAAA,MAAA;AAJlC,MAAA;AAOpB,IAAA;AACF,EAAA;AAEJ;AA3BgB;AF8EsI;AACA;AACA;AACA;AACA","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-AWONBQQP.js","sourcesContent":[null,"\"use client\";\n\nimport { Modules } from \"../../../../core\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n Link,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../../../../shadcnui\";\nimport { cn } from \"../../../../utils\";\nimport { UserInterface } from \"../../data\";\n\ntype UserAvatarProps = {\n user: UserInterface;\n className?: string;\n showFull?: boolean;\n showLink?: boolean;\n};\n\nexport function UserAvatar({ user, className, showFull, showLink }: UserAvatarProps) {\n const generateUrl = usePageUrlGenerator();\n\n const getInitial = (param?: string) => {\n if (!param) return \"\";\n return param[0].toUpperCase();\n };\n\n const getInitials = (name: string) => {\n const words = name.split(\" \");\n const initials =\n words.length > 1 ? getInitial(words[0][0]) + getInitial(words[words.length - 1][0]) : getInitial(words[0][0]);\n\n return initials ?? \"\";\n };\n\n const getAvatar = () => {\n return (\n <div className=\"*:ring-border *:ring-1\">\n <Avatar className={`h-6 w-6 ${className}`}>\n <AvatarImage className=\"object-cover\" src={user?.avatar} />\n <AvatarFallback>{getInitials(user.name)}</AvatarFallback>\n </Avatar>\n </div>\n );\n };\n\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n {showLink === false ? (\n // If showLink is explicitly false, never show a link\n showFull ? (\n <div className={cn(`mb-2 flex w-full flex-row items-center justify-start gap-x-2 text-sm`, className)}>\n {getAvatar()}\n {user.name}\n </div>\n ) : (\n getAvatar()\n )\n ) : showFull ? (\n <Link\n href={generateUrl({ page: Modules.User, id: user.id })}\n className={cn(`mb-2 flex w-full flex-row items-center justify-start gap-x-2 text-sm`, className)}\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flex w-full flex-row items-center gap-x-2\">\n {getAvatar()}\n {user.name}\n </div>\n </Link>\n ) : showLink ? (\n <Link href={generateUrl({ page: Modules.User, id: user.id })} className={className}>\n {getAvatar()}\n </Link>\n ) : (\n getAvatar()\n )}\n </TooltipTrigger>\n <TooltipContent>{user.name}</TooltipContent>\n </Tooltip>\n );\n}\n","\"use client\";\n\nimport { Modules } from \"../../../../core\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport { Link } from \"../../../../shadcnui\";\nimport { ContentInterface } from \"../../../content\";\nimport { UserInterface } from \"../../data\";\nimport { UserAvatar } from \"../widgets\";\n\ntype ContributorsListProps = {\n content: ContentInterface;\n};\n\nexport function ContributorsList({ content }: ContributorsListProps) {\n const generateUrl = usePageUrlGenerator();\n\n return (\n <div className=\"flex flex-row items-center\">\n <Link\n key={content.author.id}\n href={generateUrl({ page: Modules.User, id: content.author.id })}\n onClick={(e) => e.stopPropagation()}\n >\n <UserAvatar user={content.author} className=\"mr-1 h-6 w-6\" />\n </Link>\n <div className=\"flex flex-row-reverse justify-end -space-x-1 space-x-reverse\">\n {content.editors\n .filter((editor: UserInterface) => editor.id !== content.author.id)\n .map((editor: UserInterface) => (\n <Link\n key={editor.id}\n href={generateUrl({ page: Modules.User, id: editor.id })}\n onClick={(e) => e.stopPropagation()}\n >\n <UserAvatar user={editor} className=\"h-5 w-5\" />\n </Link>\n ))}\n </div>\n </div>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-CXQOWQSY.js","../src/i18n/config.ts"],"names":[],"mappings":"AAAA;AACE;AACF,sDAA4B;AAC5B;AACA;ACwBA,IAAI,QAAA,EAA6B,IAAA;AAG1B,SAAS,aAAA,CAAc,MAAA,EAA0B;AACtD,EAAA,QAAA,EAAU,MAAA;AACZ;AAFgB,qCAAA,aAAA,EAAA,eAAA,CAAA;AAKT,SAAS,aAAA,CAAA,EAA4B;AAC1C,EAAA,GAAA,CAAI,iBAAC,OAAA,2BAAS,WAAA,EAAW;AACvB,IAAA,MAAM,IAAI,KAAA,CAAM,2DAA2D,CAAA;AAAA,EAC7E;AACA,EAAA,OAAO,OAAA,CAAQ,SAAA,CAAU,CAAA;AAC3B;AALgB,qCAAA,aAAA,EAAA,eAAA,CAAA;AAOT,SAAS,mBAAA,CAAoB,SAAA,EAA2E;AAC7G,EAAA,GAAA,CAAI,iBAAC,OAAA,6BAAS,iBAAA,EAAiB;AAE7B,IAAA,OAAO,CAAC,GAAA,EAAA,GAAgB,GAAA;AAAA,EAC1B;AACA,EAAA,OAAO,OAAA,CAAQ,eAAA,CAAgB,SAAS,CAAA;AAC1C;AANgB,qCAAA,mBAAA,EAAA,qBAAA,CAAA;AAQT,SAAS,WAAA,CAAA,EAA6B;AAC3C,EAAA,GAAA,CAAI,iBAAC,OAAA,6BAAS,MAAA,EAAM;AAClB,IAAA,MAAM,IAAI,KAAA,CAAM,2DAA2D,CAAA;AAAA,EAC7E;AACA,EAAA,OAAO,OAAA,CAAQ,IAAA;AACjB;AALgB,qCAAA,WAAA,EAAA,aAAA,CAAA;AAOT,SAAS,aAAA,CAAA,EAAwB;AACtC,EAAA,GAAA,iBAAI,OAAA,6BAAS,WAAA,EAAW;AACtB,IAAA,OAAO,OAAA,CAAQ,SAAA,CAAU,CAAA;AAAA,EAC3B;AAEA,EAAA,OAAO,IAAA;AACT;AANgB,qCAAA,aAAA,EAAA,eAAA,CAAA;AAQT,SAAS,oBAAA,CAAA,EAA4B;AAC1C,EAAA,GAAA,iBAAI,OAAA,6BAAS,kBAAA,EAAkB;AAC7B,IAAA,OAAO,OAAA,CAAQ,gBAAA,CAAiB,CAAA;AAAA,EAClC;AAEA,EAAA,OAAO,KAAA,CAAA;AACT;AANgB,qCAAA,oBAAA,EAAA,sBAAA,CAAA;ADrBhB;AACA;AACE;AACA;AACA;AACA;AACA;AACA;AACF,+PAAC","file":"/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-CXQOWQSY.js","sourcesContent":[null,"import { ComponentType } from \"react\";\n\n// Types for injected hooks\nexport interface I18nRouter {\n push: (href: string) => void;\n replace: (href: string) => void;\n back: () => void;\n forward: () => void;\n refresh: () => void;\n prefetch: (href: string) => void;\n}\n\nexport type UseRouterHook = () => I18nRouter;\nexport type UseTranslationsHook = (namespace?: string) => (key: string, values?: Record<string, any>) => string;\nexport type UseLocaleHook = () => string;\n\nexport type UseDateFnsLocaleHook = () => any; // date-fns Locale type\nexport type LinkComponent = ComponentType<{ href: string; children: React.ReactNode; [key: string]: any }>;\n\nexport interface I18nConfig {\n useRouter: UseRouterHook;\n useTranslations: UseTranslationsHook;\n useLocale?: UseLocaleHook;\n useDateFnsLocale?: UseDateFnsLocaleHook;\n Link: LinkComponent;\n}\n\n// Private storage\nlet _config: I18nConfig | null = null;\n\n// Configuration function (called by app at startup)\nexport function configureI18n(config: I18nConfig): void {\n _config = config;\n}\n\n// Hooks for library components to use\nexport function useI18nRouter(): I18nRouter {\n if (!_config?.useRouter) {\n throw new Error(\"i18n not configured. Call configureI18n() at app startup.\");\n }\n return _config.useRouter();\n}\n\nexport function useI18nTranslations(namespace?: string): (key: string, values?: Record<string, any>) => string {\n if (!_config?.useTranslations) {\n // Fallback: return key as-is (safe for server/client)\n return (key: string) => key;\n }\n return _config.useTranslations(namespace);\n}\n\nexport function getI18nLink(): LinkComponent {\n if (!_config?.Link) {\n throw new Error(\"i18n not configured. Call configureI18n() at app startup.\");\n }\n return _config.Link;\n}\n\nexport function useI18nLocale(): string {\n if (_config?.useLocale) {\n return _config.useLocale();\n }\n // Fallback to English (safe for server/client)\n return \"en\";\n}\n\nexport function useI18nDateFnsLocale(): any {\n if (_config?.useDateFnsLocale) {\n return _config.useDateFnsLocale();\n }\n // Fallback to undefined (Calendar will use default)\n return undefined;\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-CXQOWQSY.js","../src/i18n/config.ts"],"names":[],"mappings":"AAAA;AACE;AACF,sDAA4B;AAC5B;AACA;ACwBA,IAAI,QAAA,EAA6B,IAAA;AAG1B,SAAS,aAAA,CAAc,MAAA,EAA0B;AACtD,EAAA,QAAA,EAAU,MAAA;AACZ;AAFgB,qCAAA,aAAA,EAAA,eAAA,CAAA;AAKT,SAAS,aAAA,CAAA,EAA4B;AAC1C,EAAA,GAAA,CAAI,iBAAC,OAAA,2BAAS,WAAA,EAAW;AACvB,IAAA,MAAM,IAAI,KAAA,CAAM,2DAA2D,CAAA;AAAA,EAC7E;AACA,EAAA,OAAO,OAAA,CAAQ,SAAA,CAAU,CAAA;AAC3B;AALgB,qCAAA,aAAA,EAAA,eAAA,CAAA;AAOT,SAAS,mBAAA,CAAoB,SAAA,EAA2E;AAC7G,EAAA,GAAA,CAAI,iBAAC,OAAA,6BAAS,iBAAA,EAAiB;AAE7B,IAAA,OAAO,CAAC,GAAA,EAAA,GAAgB,GAAA;AAAA,EAC1B;AACA,EAAA,OAAO,OAAA,CAAQ,eAAA,CAAgB,SAAS,CAAA;AAC1C;AANgB,qCAAA,mBAAA,EAAA,qBAAA,CAAA;AAQT,SAAS,WAAA,CAAA,EAA6B;AAC3C,EAAA,GAAA,CAAI,iBAAC,OAAA,6BAAS,MAAA,EAAM;AAClB,IAAA,MAAM,IAAI,KAAA,CAAM,2DAA2D,CAAA;AAAA,EAC7E;AACA,EAAA,OAAO,OAAA,CAAQ,IAAA;AACjB;AALgB,qCAAA,WAAA,EAAA,aAAA,CAAA;AAOT,SAAS,aAAA,CAAA,EAAwB;AACtC,EAAA,GAAA,iBAAI,OAAA,6BAAS,WAAA,EAAW;AACtB,IAAA,OAAO,OAAA,CAAQ,SAAA,CAAU,CAAA;AAAA,EAC3B;AAEA,EAAA,OAAO,IAAA;AACT;AANgB,qCAAA,aAAA,EAAA,eAAA,CAAA;AAQT,SAAS,oBAAA,CAAA,EAA4B;AAC1C,EAAA,GAAA,iBAAI,OAAA,6BAAS,kBAAA,EAAkB;AAC7B,IAAA,OAAO,OAAA,CAAQ,gBAAA,CAAiB,CAAA;AAAA,EAClC;AAEA,EAAA,OAAO,KAAA,CAAA;AACT;AANgB,qCAAA,oBAAA,EAAA,sBAAA,CAAA;ADrBhB;AACA;AACE;AACA;AACA;AACA;AACA;AACA;AACF,+PAAC","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-CXQOWQSY.js","sourcesContent":[null,"import { ComponentType } from \"react\";\n\n// Types for injected hooks\nexport interface I18nRouter {\n push: (href: string) => void;\n replace: (href: string) => void;\n back: () => void;\n forward: () => void;\n refresh: () => void;\n prefetch: (href: string) => void;\n}\n\nexport type UseRouterHook = () => I18nRouter;\nexport type UseTranslationsHook = (namespace?: string) => (key: string, values?: Record<string, any>) => string;\nexport type UseLocaleHook = () => string;\n\nexport type UseDateFnsLocaleHook = () => any; // date-fns Locale type\nexport type LinkComponent = ComponentType<{ href: string; children: React.ReactNode; [key: string]: any }>;\n\nexport interface I18nConfig {\n useRouter: UseRouterHook;\n useTranslations: UseTranslationsHook;\n useLocale?: UseLocaleHook;\n useDateFnsLocale?: UseDateFnsLocaleHook;\n Link: LinkComponent;\n}\n\n// Private storage\nlet _config: I18nConfig | null = null;\n\n// Configuration function (called by app at startup)\nexport function configureI18n(config: I18nConfig): void {\n _config = config;\n}\n\n// Hooks for library components to use\nexport function useI18nRouter(): I18nRouter {\n if (!_config?.useRouter) {\n throw new Error(\"i18n not configured. Call configureI18n() at app startup.\");\n }\n return _config.useRouter();\n}\n\nexport function useI18nTranslations(namespace?: string): (key: string, values?: Record<string, any>) => string {\n if (!_config?.useTranslations) {\n // Fallback: return key as-is (safe for server/client)\n return (key: string) => key;\n }\n return _config.useTranslations(namespace);\n}\n\nexport function getI18nLink(): LinkComponent {\n if (!_config?.Link) {\n throw new Error(\"i18n not configured. Call configureI18n() at app startup.\");\n }\n return _config.Link;\n}\n\nexport function useI18nLocale(): string {\n if (_config?.useLocale) {\n return _config.useLocale();\n }\n // Fallback to English (safe for server/client)\n return \"en\";\n}\n\nexport function useI18nDateFnsLocale(): any {\n if (_config?.useDateFnsLocale) {\n return _config.useDateFnsLocale();\n }\n // Fallback to undefined (Calendar will use default)\n return undefined;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-DO2HLAZO.js","../src/core/registry/DataClassRegistry.ts"],"names":[],"mappings":"AAAA;AACE;AACF,sDAA4B;AAC5B;AACA;ACDO,IAAM,kBAAA,YAAN,MAAwB;AAAA,EAH/B,OAG+B;AAAA,IAAA,qCAAA,IAAA,EAAA,mBAAA,CAAA;AAAA,EAAA;AAAA,EAC7B,4BAAe,KAAA,kBAAO,IAAI,GAAA,CAA0C,EAAA;AAAA,EAEpE,OAAc,mBAAA,CACZ,GAAA,EACA,gBAAA,EACM;AACN,IAAA,MAAM,SAAA,EAAW,GAAA,CAAI,IAAA;AACrB,IAAA,GAAA,CAAI,CAAC,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,QAAQ,CAAA,EAAG;AAC5B,MAAA,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,QAAA,EAAU,gBAAgB,CAAA;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,OAAc,GAAA,CAAI,QAAA,EAEhB;AACA,IAAA,MAAM,SAAA,EAAW,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,QAAA,CAAS,IAAI,CAAA;AAC5C,IAAA,GAAA,CAAI,CAAC,QAAA,EAAU;AACb,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,8BAAA,EAAiC,OAAO,SAAA,IAAa,SAAA,EAAW,SAAA,EAAW,QAAA,CAAS,IAAI,CAAA,CAAA;AAC1G,IAAA;AAEO,IAAA;AACT,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQoF,EAAA;AACvC,IAAA;AACb,MAAA;AACmB,QAAA;AAC/C,MAAA;AACD,IAAA;AACH,EAAA;AAAA;AAAA;AAAA;AAK4B,EAAA;AACV,IAAA;AAClB,EAAA;AACF;ADJ+G;AACA;AACA;AACA","file":"/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-DO2HLAZO.js","sourcesContent":[null,"import { ApiDataInterface } from \"../interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\n\nexport class DataClassRegistry {\n private static _map = new Map<string, { new (): ApiDataInterface }>();\n\n public static registerObjectClass(\n key: ApiRequestDataTypeInterface,\n classConstructor: { new (): ApiDataInterface },\n ): void {\n const classKey = key.name;\n if (!this._map.has(classKey)) {\n this._map.set(classKey, classConstructor);\n }\n }\n\n public static get(classKey: ApiRequestDataTypeInterface): {\n new (): ApiDataInterface;\n } {\n const response = this._map.get(classKey.name);\n if (!response) {\n throw new Error(`Class not registered for key: ${typeof classKey === \"string\" ? classKey : classKey.name}`);\n }\n\n return response;\n }\n\n /**\n * Bootstrap the registry with all modules.\n * This is a convenience method for apps to register all their modules at once.\n *\n * @param modules - An object with module definitions (like the app's Modules class)\n */\n public static bootstrap(modules: Record<string, ApiRequestDataTypeInterface>): void {\n Object.values(modules).forEach((module) => {\n if (module && module.model) {\n this.registerObjectClass(module, module.model);\n }\n });\n }\n\n /**\n * Clear all registered classes. Useful for testing.\n */\n public static clear(): void {\n this._map.clear();\n }\n}\n\n// Export alias for backward compatibility\nexport { DataClassRegistry as DataClass };\n"]}
1
+ {"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-DO2HLAZO.js","../src/core/registry/DataClassRegistry.ts"],"names":[],"mappings":"AAAA;AACE;AACF,sDAA4B;AAC5B;AACA;ACDO,IAAM,kBAAA,YAAN,MAAwB;AAAA,EAH/B,OAG+B;AAAA,IAAA,qCAAA,IAAA,EAAA,mBAAA,CAAA;AAAA,EAAA;AAAA,EAC7B,4BAAe,KAAA,kBAAO,IAAI,GAAA,CAA0C,EAAA;AAAA,EAEpE,OAAc,mBAAA,CACZ,GAAA,EACA,gBAAA,EACM;AACN,IAAA,MAAM,SAAA,EAAW,GAAA,CAAI,IAAA;AACrB,IAAA,GAAA,CAAI,CAAC,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,QAAQ,CAAA,EAAG;AAC5B,MAAA,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,QAAA,EAAU,gBAAgB,CAAA;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,OAAc,GAAA,CAAI,QAAA,EAEhB;AACA,IAAA,MAAM,SAAA,EAAW,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,QAAA,CAAS,IAAI,CAAA;AAC5C,IAAA,GAAA,CAAI,CAAC,QAAA,EAAU;AACb,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,8BAAA,EAAiC,OAAO,SAAA,IAAa,SAAA,EAAW,SAAA,EAAW,QAAA,CAAS,IAAI,CAAA,CAAA;AAC1G,IAAA;AAEO,IAAA;AACT,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQoF,EAAA;AACvC,IAAA;AACb,MAAA;AACmB,QAAA;AAC/C,MAAA;AACD,IAAA;AACH,EAAA;AAAA;AAAA;AAAA;AAK4B,EAAA;AACV,IAAA;AAClB,EAAA;AACF;ADJ+G;AACA;AACA;AACA","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-DO2HLAZO.js","sourcesContent":[null,"import { ApiDataInterface } from \"../interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\n\nexport class DataClassRegistry {\n private static _map = new Map<string, { new (): ApiDataInterface }>();\n\n public static registerObjectClass(\n key: ApiRequestDataTypeInterface,\n classConstructor: { new (): ApiDataInterface },\n ): void {\n const classKey = key.name;\n if (!this._map.has(classKey)) {\n this._map.set(classKey, classConstructor);\n }\n }\n\n public static get(classKey: ApiRequestDataTypeInterface): {\n new (): ApiDataInterface;\n } {\n const response = this._map.get(classKey.name);\n if (!response) {\n throw new Error(`Class not registered for key: ${typeof classKey === \"string\" ? classKey : classKey.name}`);\n }\n\n return response;\n }\n\n /**\n * Bootstrap the registry with all modules.\n * This is a convenience method for apps to register all their modules at once.\n *\n * @param modules - An object with module definitions (like the app's Modules class)\n */\n public static bootstrap(modules: Record<string, ApiRequestDataTypeInterface>): void {\n Object.values(modules).forEach((module) => {\n if (module && module.model) {\n this.registerObjectClass(module, module.model);\n }\n });\n }\n\n /**\n * Clear all registered classes. Useful for testing.\n */\n public static clear(): void {\n this._map.clear();\n }\n}\n\n// Export alias for backward compatibility\nexport { DataClassRegistry as DataClass };\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-EFJEWLRL.js","../src/server/token.ts"],"names":[],"mappings":"AAAA;AACE;AACF,sDAA4B;AAC5B;AACA;ACCA,MAAA,SAAsB,cAAA,CAAA,EAA8C;AAClE,EAAA,MAAM,EAAE,QAAQ,EAAA,EAAI,MAAM,4DAAA,CAAO,cAAc,GAAA;AAC/C,EAAA,MAAM,YAAA,EAAc,MAAM,OAAA,CAAQ,CAAA;AAClC,EAAA,uBAAO,WAAA,mBAAY,GAAA,mBAAI,OAAO,CAAA,6BAAG,OAAA;AACnC;AAJsB,qCAAA,cAAA,EAAA,gBAAA,CAAA;ADMtB;AACA;AACE;AACF,wCAAC","file":"/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-EFJEWLRL.js","sourcesContent":[null,"\"use server\";\n\n/**\n * Get the authentication token from cookies (server-side)\n */\nexport async function getServerToken(): Promise<string | undefined> {\n const { cookies } = await import(\"next/headers\");\n const cookieStore = await cookies();\n return cookieStore.get(\"token\")?.value;\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-EFJEWLRL.js","../src/server/token.ts"],"names":[],"mappings":"AAAA;AACE;AACF,sDAA4B;AAC5B;AACA;ACCA,MAAA,SAAsB,cAAA,CAAA,EAA8C;AAClE,EAAA,MAAM,EAAE,QAAQ,EAAA,EAAI,MAAM,4DAAA,CAAO,cAAc,GAAA;AAC/C,EAAA,MAAM,YAAA,EAAc,MAAM,OAAA,CAAQ,CAAA;AAClC,EAAA,uBAAO,WAAA,mBAAY,GAAA,mBAAI,OAAO,CAAA,6BAAG,OAAA;AACnC;AAJsB,qCAAA,cAAA,EAAA,gBAAA,CAAA;ADMtB;AACA;AACE;AACF,wCAAC","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-EFJEWLRL.js","sourcesContent":[null,"\"use server\";\n\n/**\n * Get the authentication token from cookies (server-side)\n */\nexport async function getServerToken(): Promise<string | undefined> {\n const { cookies } = await import(\"next/headers\");\n const cookieStore = await cookies();\n return cookieStore.get(\"token\")?.value;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-FY4SXJGU.js","../src/hooks/TableGeneratorRegistry.ts","../src/hooks/url.rewriter.ts","../src/hooks/usePageUrlGenerator.ts","../src/hooks/useDataListRetriever.ts","../src/hooks/useDebounce.ts","../src/hooks/useTableGenerator.ts","../src/hooks/useCustomD3Graph.tsx"],"names":[],"mappings":"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","file":"/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-FY4SXJGU.js","sourcesContent":[null,"\"use client\";\n\nimport { UseTableStructureHook, UseTableStructureHookParams, UseTableStructureHookReturn } from \"./types\";\n\ntype TableGeneratorHook = UseTableStructureHook<any, any>;\n\nexport class TableGeneratorRegistry {\n private static instance: TableGeneratorRegistry;\n private registry = new Map<string, TableGeneratorHook>();\n\n private constructor() {}\n\n public static getInstance(): TableGeneratorRegistry {\n if (!TableGeneratorRegistry.instance) {\n TableGeneratorRegistry.instance = new TableGeneratorRegistry();\n }\n return TableGeneratorRegistry.instance;\n }\n\n public register<T, U>(type: string, hook: UseTableStructureHook<T, U>): void {\n if (!this.registry.has(type)) this.registry.set(type, hook as TableGeneratorHook);\n }\n\n public get<T, U>(type: string, params: UseTableStructureHookParams<T, U>): UseTableStructureHookReturn<T> {\n const hook = this.registry.get(type);\n if (!hook) {\n throw new Error(\n `Table generator for type \"${type}\" is not registered. Available types: ${Array.from(this.registry.keys()).join(\n \", \",\n )}`,\n );\n }\n return hook(params);\n }\n\n public isRegistered(type: string): boolean {\n return this.registry.has(type);\n }\n\n public getRegisteredTypes(): string[] {\n return Array.from(this.registry.keys());\n }\n\n public unregister(type: string): boolean {\n return this.registry.delete(type);\n }\n\n public clear(): void {\n this.registry.clear();\n }\n}\n\nexport const tableGeneratorRegistry = TableGeneratorRegistry.getInstance();\n","\"use client\";\n\nimport { useLocale } from \"next-intl\";\nimport { useCallback } from \"react\";\nimport { ModuleWithPermissions } from \"../permissions\";\nimport { usePageUrlGenerator } from \"./usePageUrlGenerator\";\n\nexport function useUrlRewriter() {\n const locale = useLocale();\n const generateUrl = usePageUrlGenerator();\n\n return useCallback(\n (params: { page: ModuleWithPermissions | string; id?: string; childPage?: string }): void => {\n window.history.replaceState(\n null,\n \"\",\n generateUrl({ page: params.page, id: params.id, childPage: params.childPage, language: locale }),\n );\n },\n [locale, generateUrl],\n );\n}\n","import { PageUrl } from \"../permissions/types\";\n\nexport function usePageUrlGenerator(): (params: {\n page?: PageUrl | string;\n id?: string;\n childPage?: PageUrl | string;\n childId?: string;\n additionalParameters?: { [key: string]: string | string[] | undefined };\n language?: string;\n}) => string {\n const generateUrl = (params: {\n page?: PageUrl | string;\n id?: string;\n childPage?: PageUrl | string;\n childId?: string;\n additionalParameters?: { [key: string]: string | string[] | undefined };\n language?: string;\n }): string => {\n if (!params.page) return \"/\";\n\n const pathParams: string[] = [\n `${params.language ? `/${params.language}` : \"\"}${typeof params.page === \"string\" ? params.page : params.page.pageUrl}`,\n ];\n\n if (params.id) {\n pathParams.push(params.id);\n if (params.childPage) {\n pathParams.push(typeof params.childPage === \"string\" ? params.childPage : (params.childPage.pageUrl ?? \"\"));\n if (params.childId) {\n pathParams.push(params.childId);\n }\n }\n }\n const response = pathParams.join(`/`);\n\n if (params.additionalParameters) {\n const searchParams = new URLSearchParams();\n for (const key in params.additionalParameters) {\n if (params.additionalParameters[key]) {\n searchParams.append(key, params.additionalParameters[key] as string);\n }\n }\n return `${response}?${searchParams.toString()}`;\n }\n\n return response;\n };\n\n return generateUrl;\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { AbstractService } from \"../core\";\n\nexport type PageInfo = {\n startItem: number;\n endItem: number;\n pageSize: number;\n};\n\nexport type DataListRetriever<T> = {\n ready?: boolean;\n setReady: (state: boolean) => void;\n isLoaded: boolean;\n data: T[] | undefined;\n next?: (onlyNewRecords?: boolean) => Promise<void>;\n previous?: (onlyNewRecords?: boolean) => Promise<void>;\n search: (search: string) => Promise<void>;\n refresh: () => Promise<void>;\n addAdditionalParameter: (key: string, value: any | null) => void;\n removeAdditionalParameter: (key: string) => void;\n setRefreshedElement: (element: T) => void;\n removeElement: (element: T) => void;\n isSearch: boolean;\n pageInfo?: PageInfo;\n};\n\nexport function useDataListRetriever<T>(params: {\n ready?: boolean;\n retriever: (params: any) => Promise<T[]>;\n retrieverParams?: any;\n search?: string;\n addAdditionalParameter?: (key: string, value: any | null) => void;\n requiresSearch?: boolean;\n module: any;\n}): DataListRetriever<T> {\n const [data, setData] = useState<T[] | undefined>(undefined);\n const [nextPage, setNextPage] = useState<string | undefined>(undefined);\n const [previousPage, setPreviousPage] = useState<string | undefined>(undefined);\n const [isLoaded, setIsLoaded] = useState(false);\n const [ready, setReady] = useState<boolean>(params.ready ?? true);\n const searchTermRef = useRef<string>(\"\");\n const additionalParamsRef = useRef<any>({});\n const requestIdRef = useRef(0);\n const abortControllerRef = useRef<AbortController | null>(null);\n const isFetchingRef = useRef(false);\n\n const resolvedType = params.module;\n const resolvedService = AbstractService; // We'll just use AbstractService directly for pagination\n\n // Helper to parse page params from pagination URLs\n const parsePageParams = useCallback((url: string | undefined): { offset: number; size: number } | null => {\n if (!url) return null;\n try {\n const urlObj = new URL(url);\n const offset = parseInt(urlObj.searchParams.get(\"page[offset]\") || \"0\", 10);\n const size = parseInt(urlObj.searchParams.get(\"page[size]\") || \"25\", 10);\n return { offset, size };\n } catch {\n return null;\n }\n }, []);\n\n // Helper to adjust pagination URL offset (used when removing elements)\n const adjustPaginationUrl = useCallback((url: string | undefined, delta: number): string | undefined => {\n if (!url) return undefined;\n try {\n const urlObj = new URL(url);\n const currentOffset = parseInt(urlObj.searchParams.get(\"page[offset]\") || \"0\", 10);\n const newOffset = Math.max(0, currentOffset + delta);\n urlObj.searchParams.set(\"page[offset]\", String(newOffset));\n return urlObj.toString();\n } catch {\n return url;\n }\n }, []);\n\n // Calculate pageInfo from pagination URLs and current data\n const pageInfo = useMemo((): PageInfo | undefined => {\n if (!data || data.length === 0) return undefined;\n\n // Try to determine current offset and page size from pagination URLs\n const nextParams = parsePageParams(nextPage);\n const prevParams = parsePageParams(previousPage);\n\n let currentOffset = 0;\n let pageSize = 25; // default\n\n if (nextParams) {\n // If we have a next page, current offset = next offset - page size\n pageSize = nextParams.size;\n currentOffset = Math.max(0, nextParams.offset - pageSize);\n } else if (prevParams) {\n // If we only have a previous page (we're on the last page)\n pageSize = prevParams.size;\n currentOffset = prevParams.offset + pageSize;\n }\n\n const startItem = currentOffset + 1;\n const endItem = currentOffset + data.length;\n\n return { startItem, endItem, pageSize };\n }, [data, nextPage, previousPage, parsePageParams]);\n\n const stableParams = useMemo(\n () => ({\n service: resolvedService,\n type: resolvedType,\n retriever: params.retriever,\n retrieverParams: params.retrieverParams,\n requiresSearch: params.requiresSearch,\n }),\n [resolvedService, resolvedType, params.retriever, params.retrieverParams, params.requiresSearch],\n );\n\n const fetchData = useCallback(\n async (fetchParams?: { isRefine?: boolean; isRefresh?: boolean; callNext?: boolean; callPrevious?: boolean }) => {\n if (ready === false) {\n return;\n }\n\n // Prevent concurrent fetches (unless it's a pagination call)\n if (isFetchingRef.current && !fetchParams?.callNext && !fetchParams?.callPrevious) {\n return;\n }\n\n const thisRequestId = ++requestIdRef.current;\n isFetchingRef.current = true;\n\n if (stableParams.requiresSearch === true && fetchParams?.isRefine !== true && fetchParams?.isRefresh !== true)\n return;\n\n if (\n !nextPage &&\n !previousPage &&\n isLoaded &&\n fetchParams?.callNext !== true &&\n fetchParams?.callPrevious !== true &&\n params.search === searchTermRef.current\n )\n return;\n\n const currentSearchTerm = searchTermRef.current;\n\n setIsLoaded(false);\n\n try {\n let response: T[];\n const nextRef = { next: undefined };\n const previousRef = { previous: undefined };\n const selfRef = { self: undefined };\n\n if (nextPage && fetchParams?.callNext && fetchParams?.isRefine !== true) {\n const ServiceClass = stableParams.service as typeof AbstractService;\n\n response = await ServiceClass.next<T[]>({\n type: stableParams.type,\n endpoint: nextPage,\n next: nextRef,\n previous: previousRef,\n self: selfRef,\n });\n } else if (previousPage && fetchParams?.callPrevious && fetchParams?.isRefine !== true) {\n const ServiceClass = stableParams.service as typeof AbstractService;\n\n response = await ServiceClass.previous<T[]>({\n type: stableParams.type,\n endpoint: previousPage,\n next: nextRef,\n previous: previousRef,\n self: selfRef,\n });\n } else {\n let retrieverParams = stableParams.retrieverParams ? { ...stableParams.retrieverParams } : {};\n\n retrieverParams = {\n ...retrieverParams,\n ...additionalParamsRef.current,\n };\n\n retrieverParams.search = currentSearchTerm;\n retrieverParams.next = nextRef;\n retrieverParams.previous = previousRef;\n retrieverParams.self = selfRef;\n\n response = await stableParams.retriever(retrieverParams);\n }\n\n // Only update state if this is still the latest request and wasn't aborted\n if (thisRequestId === requestIdRef.current && !abortControllerRef.current?.signal.aborted) {\n if (fetchParams?.isRefresh === true) {\n setData(response);\n } else {\n setData((prevData) => [...(prevData ? (prevData as T[]) : []), ...response]);\n }\n setIsLoaded(true);\n setNextPage(nextRef.next ? nextRef.next : undefined);\n setPreviousPage(previousRef.previous ? previousRef.previous : undefined);\n }\n } catch (error) {\n // Don't update state if request was aborted (AbortController disabled)\n if (thisRequestId === requestIdRef.current) {\n setIsLoaded(true);\n console.error(\"Error fetching data:\", error);\n }\n } finally {\n // Always reset fetching flag when done\n if (thisRequestId === requestIdRef.current) {\n isFetchingRef.current = false;\n }\n }\n },\n [stableParams, ready, params.search],\n );\n\n const setRefreshedElement = useCallback(\n (element: T) => {\n setData((prevData) => {\n if (!prevData) return prevData;\n\n const index = prevData.findIndex((data) => (data as any).id === (element as any).id);\n if (index === -1) return prevData;\n\n // Use immutable update pattern instead of mutation\n return prevData.map((item, i) => (i === index ? element : item));\n });\n },\n [setData],\n );\n\n const removeElement = useCallback(\n (element: T) => {\n setData((prevData) => {\n if (!prevData) return prevData;\n\n const index = prevData.findIndex((data) => (data as any).id === (element as any).id);\n\n if (index === -1) return prevData;\n\n // Adjust nextPage offset since we're removing an item\n setNextPage((prev) => adjustPaginationUrl(prev, -1));\n\n const newData = [...prevData];\n newData.splice(index, 1);\n return newData;\n });\n },\n [adjustPaginationUrl],\n );\n\n // Consolidated effect: Only fetch once when ready and not loaded\n // This prevents the duplicate API calls that occurred when both the mount effect\n // and ready effect fired simultaneously on initial render\n useEffect(() => {\n // Only fetch if ready and haven't loaded yet\n if (ready && !isLoaded) {\n fetchData({ isRefresh: true });\n }\n }, [ready, fetchData]);\n\n const loadNext = useCallback(\n async (onlyNewRecords?: boolean) => {\n if (nextPage) fetchData({ isRefresh: onlyNewRecords, callNext: true });\n },\n [fetchData, nextPage],\n );\n\n const loadPrevious = useCallback(\n async (onlyNewRecords?: boolean) => {\n if (previousPage) fetchData({ isRefresh: onlyNewRecords, callPrevious: true });\n },\n [fetchData, previousPage],\n );\n\n const addAdditionalParameter = useCallback(\n (key: string, value: any | null) => {\n if (value === null) {\n delete additionalParamsRef.current[key];\n } else {\n additionalParamsRef.current[key] = value;\n }\n\n setReady(true);\n setNextPage(undefined);\n setPreviousPage(undefined);\n fetchData({ isRefine: true, isRefresh: true });\n },\n [fetchData],\n );\n\n const removeAdditionalParameter = useCallback(\n (key: string) => {\n if (additionalParamsRef.current[key] !== undefined) {\n delete additionalParamsRef.current[key];\n setNextPage(undefined);\n setPreviousPage(undefined);\n fetchData({ isRefine: true, isRefresh: true });\n }\n },\n [fetchData],\n );\n\n const search = useCallback(\n async (search: string) => {\n if (search === searchTermRef.current) return;\n\n setNextPage(undefined);\n setPreviousPage(undefined);\n searchTermRef.current = search;\n fetchData({ isRefine: true, isRefresh: true });\n },\n [fetchData],\n );\n\n const isSearch = !!searchTermRef.current;\n\n const refresh = useCallback(async () => {\n setNextPage(undefined);\n setPreviousPage(undefined);\n fetchData({ isRefresh: true });\n }, [fetchData]);\n\n // Cleanup abort controller on unmount\n useEffect(() => {\n return () => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n };\n }, []);\n\n return {\n ready,\n setReady,\n isLoaded: isLoaded,\n data: data as T[],\n next: nextPage ? loadNext : undefined,\n previous: previousPage ? loadPrevious : undefined,\n search: search,\n addAdditionalParameter: addAdditionalParameter,\n removeAdditionalParameter: removeAdditionalParameter,\n refresh: refresh,\n setRefreshedElement: setRefreshedElement,\n isSearch: isSearch,\n removeElement: removeElement,\n pageInfo: pageInfo,\n };\n}\n","import { useCallback, useEffect, useRef } from \"react\";\n\nexport function useDebounce<T extends (...args: any[]) => any>(callback: T, delay: number): T & { cancel: () => void } {\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n const callbackRef = useRef(callback);\n\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n const debouncedFunction = useCallback(\n (...args: Parameters<T>) => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n timeoutRef.current = setTimeout(() => {\n callbackRef.current(...args);\n }, delay);\n },\n [delay],\n );\n\n // Attach a cancel method to clear pending timeout\n const cancel = () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n };\n\n return Object.assign(debouncedFunction, { cancel }) as T & { cancel: () => void };\n}\n\nexport default useDebounce;\n","\"use client\";\n\nimport { UseTableStructureHook, UseTableStructureHookParams, UseTableStructureHookReturn } from \"./types\";\nimport { ModuleWithPermissions } from \"../permissions\";\nimport { tableGeneratorRegistry } from \"./TableGeneratorRegistry\";\n\nexport function registerTableGenerator<T, U>(type: ModuleWithPermissions, hook: UseTableStructureHook<T, U>): void {\n tableGeneratorRegistry.register(type.name, hook);\n}\n\nexport function useTableGenerator<T, U>(\n type: ModuleWithPermissions,\n params: UseTableStructureHookParams<T, U>,\n): UseTableStructureHookReturn<T> {\n return tableGeneratorRegistry.get(type.name, params);\n}\n","import * as d3 from \"d3\";\nimport { Loader2 } from \"lucide-react\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { renderToStaticMarkup } from \"react-dom/server\";\nimport { D3Link, D3Node } from \"../interfaces\";\n\n/**\n * Custom hook for D3 graph visualization with larger circles and more interactive features\n */\nexport function useCustomD3Graph(\n nodes: D3Node[],\n links: D3Link[],\n onNodeClick: (nodeId: string) => void,\n visibleNodeIds?: Set<string>,\n loadingNodeIds?: Set<string>,\n containerKey?: string | number,\n) {\n const svgRef = useRef<SVGSVGElement | null>(null);\n const zoomRef = useRef<d3.ZoomTransform | null>(null);\n const zoomBehaviorRef = useRef<d3.ZoomBehavior<SVGSVGElement, unknown> | null>(null);\n const nodePositionsRef = useRef<Map<string, { x: number; y: number }>>(new Map());\n const prevContainerKeyRef = useRef<string | number | undefined>(containerKey);\n\n const zoomToNode = useCallback(\n (nodeId: string, childIds: string[] = []) => {\n if (!svgRef.current || !zoomBehaviorRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const zoom = zoomBehaviorRef.current;\n\n const targetNode = nodes.find((n) => n.id === nodeId);\n const childNodes = nodes.filter((n) => childIds.includes(n.id));\n\n if (!targetNode) return;\n\n const positions: { x: number; y: number }[] = [];\n\n if (\n targetNode.fx !== undefined &&\n targetNode.fy !== undefined &&\n targetNode.fx !== null &&\n targetNode.fy !== null\n ) {\n positions.push({ x: targetNode.fx, y: targetNode.fy });\n } else if (\n targetNode.x !== undefined &&\n targetNode.y !== undefined &&\n targetNode.x !== null &&\n targetNode.y !== null\n ) {\n positions.push({ x: targetNode.x, y: targetNode.y });\n }\n\n childNodes.forEach((child) => {\n if (child.fx !== undefined && child.fy !== undefined && child.fx !== null && child.fy !== null) {\n positions.push({ x: child.fx, y: child.fy });\n } else if (child.x !== undefined && child.y !== undefined && child.x !== null && child.y !== null) {\n positions.push({ x: child.x, y: child.y });\n }\n });\n\n if (positions.length === 0) return;\n\n const bounds = {\n xMin: Math.min(...positions.map((p) => p.x)),\n xMax: Math.max(...positions.map((p) => p.x)),\n yMin: Math.min(...positions.map((p) => p.y)),\n yMax: Math.max(...positions.map((p) => p.y)),\n };\n\n const padding = 150;\n bounds.xMin -= padding;\n bounds.xMax += padding;\n bounds.yMin -= padding;\n bounds.yMax += padding;\n\n const width = svgRef.current.clientWidth;\n const height = svgRef.current.clientHeight;\n\n const contentWidth = bounds.xMax - bounds.xMin;\n const contentHeight = bounds.yMax - bounds.yMin;\n\n const scaleX = width / contentWidth;\n const scaleY = height / contentHeight;\n\n let scale = Math.min(scaleX, scaleY);\n\n scale = Math.min(Math.max(scale, 0.2), 1.5);\n\n const centerX = (bounds.xMin + bounds.xMax) / 2;\n const centerY = (bounds.yMin + bounds.yMax) / 2;\n\n const translateX = width / 2 - centerX * scale;\n const translateY = height / 2 - centerY * scale;\n\n svg\n .transition()\n .duration(750)\n .call(zoom.transform, d3.zoomIdentity.translate(translateX, translateY).scale(scale));\n },\n [nodes],\n );\n\n const colorScale = useMemo(() => {\n const accentColor = \"var(--accent)\";\n\n // Define unified color for all content types\n const contentColor = \"hsl(30, 80%, 55%)\"; // Orange for all content\n\n const groupTypes = new Set<string>();\n nodes.forEach((node) => {\n groupTypes.add(node.instanceType);\n });\n\n const typeColorMap = new Map<string, string>();\n\n Array.from(groupTypes).forEach((type, index) => {\n if (type === nodes[0]?.instanceType) {\n // Root node\n typeColorMap.set(type, accentColor);\n } else if (type === \"documents\" || type === \"articles\" || type === \"hyperlinks\") {\n // All content types get the same orange color\n typeColorMap.set(type, contentColor);\n } else {\n // Topics, Expertises, etc. - use golden angle\n const hueShift = (index * 137.508) % 360;\n typeColorMap.set(type, `hsl(${hueShift}, 32%, 52%)`);\n }\n });\n\n return typeColorMap;\n }, [nodes]);\n\n const washOutColor = useCallback((color: string): string => {\n // Parse HSL color and make it lighter and more desaturated\n const hslMatch = color.match(/hsl\\((\\d+\\.?\\d*),\\s*(\\d+\\.?\\d*)%,\\s*(\\d+\\.?\\d*)%\\)/);\n if (hslMatch) {\n const hue = parseFloat(hslMatch[1]);\n\n // Reduce saturation to 15% and increase lightness to 80%\n return `hsl(${hue}, 15%, 80%)`;\n }\n\n // For var(--accent), return a lighter version\n if (color.includes(\"var(--accent)\")) {\n return \"hsl(0, 0%, 80%)\"; // Light gray for washed out accent\n }\n\n // Fallback\n return \"hsl(0, 0%, 80%)\";\n }, []);\n\n const getNodeColor = useCallback(\n (node: D3Node) => {\n const baseColor = colorScale.get(node.instanceType) || \"gray\";\n if (node.washedOut) {\n return washOutColor(baseColor);\n }\n return baseColor;\n },\n [colorScale, washOutColor],\n );\n\n useEffect(() => {\n if (!nodes.length || !svgRef.current) return;\n\n const visibleNodes = visibleNodeIds\n ? nodes.filter((node) => visibleNodeIds.has(node.id))\n : nodes.filter((node) => node.visible !== false);\n\n const visibleNodeIdSet = new Set(visibleNodes.map((node) => node.id));\n const visibleLinks = links.filter((link) => {\n const sourceId = typeof link.source === \"string\" ? link.source : link.source.id;\n const targetId = typeof link.target === \"string\" ? link.target : link.target.id;\n return visibleNodeIdSet.has(sourceId) && visibleNodeIdSet.has(targetId);\n });\n\n const svg = d3.select<SVGSVGElement, unknown>(svgRef.current);\n svg.selectAll(\"*\").remove();\n\n const container = svgRef.current?.parentElement;\n if (!container) return;\n\n const width = container.clientWidth;\n const height = container.clientHeight;\n\n svg.attr(\"width\", width).attr(\"height\", height).attr(\"viewBox\", `0 0 ${width} ${height}`);\n\n const graphGroup = svg.append(\"g\").attr(\"class\", \"graph-content\");\n\n const zoom = d3\n .zoom<SVGSVGElement, unknown>()\n .scaleExtent([0.1, 4])\n .on(\"zoom\", (event) => {\n const transform = event.transform;\n graphGroup.attr(\"transform\", transform.toString());\n zoomRef.current = transform;\n });\n\n zoomBehaviorRef.current = zoom;\n\n svg\n .call(zoom as any)\n .on(\"wheel.zoom\", null)\n .on(\"dblclick.zoom\", null);\n\n const nodeRadius = 40;\n\n const childDistanceFromRoot = Math.min(width, height) * 0.4;\n const grandchildDistanceFromChild = nodeRadius * 10;\n\n const centralNodeId = nodes[0].id;\n\n const nodeHierarchy = new Map<\n string,\n {\n depth: number;\n parent: string | null;\n children: string[];\n angle?: number;\n x?: number;\n y?: number;\n }\n >();\n\n nodeHierarchy.set(centralNodeId, {\n depth: 0,\n parent: null,\n children: [],\n });\n\n visibleLinks.forEach((link) => {\n const sourceId = typeof link.source === \"string\" ? link.source : link.source.id;\n const targetId = typeof link.target === \"string\" ? link.target : link.target.id;\n\n if (sourceId === centralNodeId) {\n nodeHierarchy.set(targetId, { depth: 1, parent: centralNodeId, children: [] });\n const rootNode = nodeHierarchy.get(centralNodeId);\n if (rootNode) {\n rootNode.children.push(targetId);\n }\n }\n });\n\n visibleLinks.forEach((link) => {\n const sourceId = typeof link.source === \"string\" ? link.source : link.source.id;\n const targetId = typeof link.target === \"string\" ? link.target : link.target.id;\n\n const sourceNode = nodeHierarchy.get(sourceId);\n if (sourceNode && sourceNode.depth === 1 && !nodeHierarchy.has(targetId)) {\n nodeHierarchy.set(targetId, { depth: 2, parent: sourceId, children: [] });\n sourceNode.children.push(targetId);\n }\n });\n\n const rootChildren = nodeHierarchy.get(centralNodeId)?.children || [];\n\n const childAngleStep = (2 * Math.PI) / Math.max(rootChildren.length, 1);\n\n rootChildren.forEach((childId, index) => {\n const childNode = nodeHierarchy.get(childId);\n if (childNode) {\n const angle = index * childAngleStep;\n childNode.angle = angle;\n childNode.x = width / 2 + childDistanceFromRoot * Math.cos(angle);\n childNode.y = height / 2 + childDistanceFromRoot * Math.sin(angle);\n }\n });\n\n for (const [nodeId, node] of nodeHierarchy.entries()) {\n if (node.depth === 1 && node.angle !== undefined && node.x !== undefined && node.y !== undefined) {\n const childAngle = node.angle;\n const childX = node.x;\n const childY = node.y;\n const grandchildren = node.children;\n\n if (grandchildren.length === 0) continue;\n\n const dirX = childX - width / 2;\n const dirY = childY - height / 2;\n const dirLength = Math.sqrt(dirX * dirX + dirY * dirY);\n\n const normDirX = dirX / dirLength;\n const normDirY = dirY / dirLength;\n\n if (grandchildren.length === 1) {\n const grandchildId = grandchildren[0];\n const grandchildNode = nodeHierarchy.get(grandchildId);\n if (grandchildNode) {\n grandchildNode.x = childX + normDirX * grandchildDistanceFromChild;\n grandchildNode.y = childY + normDirY * grandchildDistanceFromChild;\n grandchildNode.angle = childAngle;\n }\n } else {\n // Multiple grandchildren - arrange in semicircular arc\n const numChildren = grandchildren.length;\n\n // Dynamic arc span: scale from 60° (2 children) to 180° (7+ children)\n const minArc = Math.PI / 3; // 60 degrees\n const maxArc = Math.PI; // 180 degrees\n const arcProgress = Math.min(1, (numChildren - 2) / 5);\n const arcSpan = minArc + arcProgress * (maxArc - minArc);\n\n // Calculate starting angle (center the arc around the radial direction)\n const startAngle = childAngle - arcSpan / 2;\n\n grandchildren.forEach((grandchildId, index) => {\n const grandchildNode = nodeHierarchy.get(grandchildId);\n if (!grandchildNode) return;\n\n // Calculate angle for this child\n const angleOffset = numChildren > 1 ? (index / (numChildren - 1)) * arcSpan : 0;\n const angle = startAngle + angleOffset;\n\n // Position at constant radius from parent\n grandchildNode.x = childX + grandchildDistanceFromChild * Math.cos(angle);\n grandchildNode.y = childY + grandchildDistanceFromChild * Math.sin(angle);\n grandchildNode.angle = angle;\n });\n }\n }\n }\n\n visibleNodes.forEach((node) => {\n const savedPosition = nodePositionsRef.current.get(node.id);\n\n if (savedPosition) {\n node.fx = savedPosition.x;\n node.fy = savedPosition.y;\n } else {\n const hierarchyNode = nodeHierarchy.get(node.id);\n if (hierarchyNode && hierarchyNode.x !== undefined && hierarchyNode.y !== undefined) {\n node.fx = hierarchyNode.x;\n node.fy = hierarchyNode.y;\n // Save the calculated position so it persists across re-renders\n nodePositionsRef.current.set(node.id, { x: hierarchyNode.x, y: hierarchyNode.y });\n } else if (node.id === centralNodeId) {\n node.fx = width / 2;\n node.fy = height / 2;\n // Save the center position\n nodePositionsRef.current.set(node.id, { x: width / 2, y: height / 2 });\n }\n }\n });\n\n const simulation = d3\n .forceSimulation<D3Node>(visibleNodes)\n .force(\n \"link\",\n d3\n .forceLink<D3Node, D3Link>(visibleLinks)\n .id((d) => d.id)\n .distance(nodeRadius * 3)\n .strength(0.1),\n )\n .force(\"charge\", d3.forceManyBody().strength(-500).distanceMax(300))\n .force(\"collision\", d3.forceCollide().radius(nodeRadius * 1.2))\n .force(\"center\", d3.forceCenter(width / 2, height / 2).strength(0.1));\n\n simulation.stop();\n for (let i = 0; i < 100; i++) {\n simulation.tick();\n }\n\n visibleNodes.forEach((node) => {\n if (node.fx === undefined) {\n node.fx = node.x;\n node.fy = node.y;\n }\n });\n\n const link = graphGroup\n .append(\"g\")\n .attr(\"stroke\", \"#999\")\n .attr(\"stroke-opacity\", 0.6)\n .selectAll(\"line\")\n .data(visibleLinks)\n .join(\"line\")\n .attr(\"x1\", (d) => (d.source as D3Node).x || 0)\n .attr(\"y1\", (d) => (d.source as D3Node).y || 0)\n .attr(\"x2\", (d) => (d.target as D3Node).x || 0)\n .attr(\"y2\", (d) => (d.target as D3Node).y || 0)\n .attr(\"stroke-width\", 1.5);\n\n const node = graphGroup\n .append(\"g\")\n .selectAll(\"g\")\n .data(visibleNodes)\n .join(\"g\")\n .attr(\"class\", \"node-group\")\n .attr(\"cursor\", \"pointer\")\n .attr(\"transform\", (d) => `translate(${d.x || 0}, ${d.y || 0})`)\n .call(\n d3\n .drag<SVGGElement, D3Node>()\n .subject(function (d) {\n return d;\n })\n .on(\"start\", function (event, d) {\n d.fx = d.x;\n d.fy = d.y;\n })\n .on(\"drag\", function (event, d) {\n d.fx = event.x;\n d.fy = event.y;\n\n d3.select(this).attr(\"transform\", `translate(${event.x}, ${event.y})`);\n\n d3.select(this).attr(\"transform\", `translate(${event.x}, ${event.y})`);\n\n nodePositionsRef.current.set(d.id, { x: event.x, y: event.y });\n\n link\n .attr(\"x1\", (l) => {\n const source = l.source as D3Node;\n return source.fx || source.x || 0;\n })\n .attr(\"y1\", (l) => {\n const source = l.source as D3Node;\n return source.fy || source.y || 0;\n })\n .attr(\"x2\", (l) => {\n const target = l.target as D3Node;\n return target.fx || target.x || 0;\n })\n .attr(\"y2\", (l) => {\n const target = l.target as D3Node;\n return target.fy || target.y || 0;\n });\n })\n .on(\"end\", function (event, d) {\n d.fx = event.x;\n d.fy = event.y;\n }) as any,\n )\n .on(\"mouseenter\", function (_event, d) {\n // Skip hover effect for root node\n if (d.instanceType === \"root\") return;\n\n const currentNode = d3.select(this);\n\n // Bring node to front\n currentNode.raise();\n\n // Get current zoom scale for counter-scaling text\n const currentZoom = zoomRef.current?.k || 1;\n const targetScreenFontSize = 20; // Target font size in screen pixels\n const baseFontSize = 12; // Base font size in graph coordinates\n\n // Calculate smooth scale factor for transform\n const textScale = targetScreenFontSize / (baseFontSize * currentZoom);\n\n // Calculate text position offset - circle stays in graph coords, only gap is counter-scaled\n const hoverTextOffset = nodeRadius * 1.4 + 5 / currentZoom;\n\n // Scale up the circle with smooth transition (unchanged)\n currentNode\n .select(\"circle\")\n .transition()\n .duration(250)\n .ease(d3.easeExpOut)\n .attr(\"r\", nodeRadius * 1.4)\n .attr(\"filter\", \"drop-shadow(0px 4px 12px rgba(0, 0, 0, 0.3))\");\n\n // Scale up the text with smooth transform scaling around its anchor point\n currentNode\n .select(\"text\")\n .transition()\n .duration(250)\n .ease(d3.easeExpOut)\n .attr(\"dy\", -hoverTextOffset)\n .attr(\"transform\", `translate(0, ${-hoverTextOffset}) scale(${textScale}) translate(0, ${hoverTextOffset})`);\n })\n .on(\"mouseleave\", function (_event, d) {\n // Skip hover effect for root node\n if (d.instanceType === \"root\") return;\n\n const currentNode = d3.select(this);\n\n // Return circle to normal size\n currentNode\n .select(\"circle\")\n .transition()\n .duration(250)\n .ease(d3.easeExpOut)\n .attr(\"r\", nodeRadius)\n .attr(\"filter\", null);\n\n // Return text to normal size with smooth transform\n const normalOffset = nodeRadius + 5;\n currentNode\n .select(\"text\")\n .transition()\n .duration(250)\n .ease(d3.easeExpOut)\n .attr(\"dy\", -normalOffset)\n .attr(\"transform\", `translate(0, ${-normalOffset}) scale(1) translate(0, ${normalOffset})`);\n });\n\n node\n .append(\"circle\")\n .attr(\"r\", nodeRadius)\n .attr(\"fill\", (d) => getNodeColor(d))\n .attr(\"stroke\", \"#fff\")\n .attr(\"stroke-width\", 1.5)\n .on(\"click\", (event, d) => {\n event.preventDefault();\n event.stopPropagation();\n if (zoomBehaviorRef.current) {\n svg.on(\".zoom\", null);\n setTimeout(() => {\n if (zoomBehaviorRef.current) {\n svg\n .call(zoomBehaviorRef.current as any)\n .on(\"wheel.zoom\", null)\n .on(\"dblclick.zoom\", null);\n }\n }, 100);\n }\n onNodeClick(d.id);\n });\n\n node.each(function (d: D3Node) {\n if (d.icon) {\n const Icon = d.icon as React.FC<{ size: number; color: string }>;\n const iconSvg = renderToStaticMarkup(<Icon size={nodeRadius / 2} color=\"white\" />);\n\n const iconGroup = d3\n .select(this)\n .append(\"g\")\n .html(iconSvg)\n .attr(\"transform\", `translate(${-nodeRadius / 4}, ${-nodeRadius / 4})`)\n .style(\"pointer-events\", \"all\")\n .on(\"click\", (event) => {\n event.stopPropagation();\n onNodeClick(d.id);\n });\n }\n });\n\n // Add loading spinner for nodes that are fetching children\n node.each(function (d: D3Node) {\n if (loadingNodeIds && loadingNodeIds.has(d.id)) {\n // Remove existing icon\n d3.select(this).selectAll(\"g\").remove();\n\n // Add spinner\n const spinnerSvg = renderToStaticMarkup(<Loader2 size={nodeRadius / 2} color=\"white\" />);\n\n d3.select(this)\n .append(\"g\")\n .html(spinnerSvg)\n .attr(\"class\", \"animate-spin\")\n .attr(\"transform\", `translate(${-nodeRadius / 4}, ${-nodeRadius / 4})`)\n .style(\"pointer-events\", \"none\");\n }\n });\n\n node.each(function (d: D3Node) {\n const textElement = d3\n .select(this)\n .append(\"text\")\n .attr(\"text-anchor\", \"middle\")\n .attr(\"font-size\", 12)\n .attr(\"pointer-events\", \"none\");\n\n if (d.instanceType === \"root\") {\n // Split text by spaces for multi-line display\n const words = d.name.split(\" \");\n const lineHeight = 1.2; // em units\n const numLines = words.length;\n // Calculate starting position to center the text block vertically\n // Account for the fact that we want the middle of the entire text block at y=0\n const startY = -((numLines - 1) * lineHeight) / 2;\n\n textElement.attr(\"fill\", \"var(--accent-foreground)\").attr(\"dominant-baseline\", \"middle\");\n\n words.forEach((word, index) => {\n textElement\n .append(\"tspan\")\n .attr(\"x\", 0)\n .attr(\"dy\", index === 0 ? `${startY}em` : `${lineHeight}em`)\n .text(word);\n });\n } else {\n // Non-root nodes: single line text above the circle\n textElement\n .attr(\"dy\", -nodeRadius - 5)\n .attr(\"fill\", \"currentColor\")\n .text(d.name);\n }\n });\n\n return () => {\n simulation.stop();\n };\n }, [nodes, links, colorScale, visibleNodeIds, loadingNodeIds, onNodeClick]);\n\n const zoomIn = useCallback(() => {\n if (!svgRef.current || !zoomBehaviorRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const zoom = zoomBehaviorRef.current;\n\n const currentTransform = zoomRef.current || d3.zoomIdentity;\n const newScale = Math.min(currentTransform.k * 1.3, 4);\n\n svg\n .transition()\n .duration(300)\n .call(zoom.transform, d3.zoomIdentity.translate(currentTransform.x, currentTransform.y).scale(newScale));\n }, []);\n\n const zoomOut = useCallback(() => {\n if (!svgRef.current || !zoomBehaviorRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const zoom = zoomBehaviorRef.current;\n\n const currentTransform = zoomRef.current || d3.zoomIdentity;\n const newScale = Math.max(currentTransform.k * 0.7, 0.1);\n\n svg\n .transition()\n .duration(300)\n .call(zoom.transform, d3.zoomIdentity.translate(currentTransform.x, currentTransform.y).scale(newScale));\n }, []);\n\n const zoomToFitAll = useCallback(() => {\n if (!svgRef.current || !zoomBehaviorRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const zoom = zoomBehaviorRef.current;\n\n // Get all visible nodes\n const visibleNodes = visibleNodeIds\n ? nodes.filter((node) => visibleNodeIds.has(node.id))\n : nodes.filter((node) => node.visible !== false);\n\n if (visibleNodes.length === 0) return;\n\n // Calculate bounds of all visible nodes\n const positions: { x: number; y: number }[] = [];\n visibleNodes.forEach((node) => {\n if (node.fx !== undefined && node.fy !== undefined && node.fx !== null && node.fy !== null) {\n positions.push({ x: node.fx, y: node.fy });\n } else if (node.x !== undefined && node.y !== undefined && node.x !== null && node.y !== null) {\n positions.push({ x: node.x, y: node.y });\n }\n });\n\n if (positions.length === 0) return;\n\n const bounds = {\n xMin: Math.min(...positions.map((p) => p.x)),\n xMax: Math.max(...positions.map((p) => p.x)),\n yMin: Math.min(...positions.map((p) => p.y)),\n yMax: Math.max(...positions.map((p) => p.y)),\n };\n\n // Add padding\n const padding = 150;\n bounds.xMin -= padding;\n bounds.xMax += padding;\n bounds.yMin -= padding;\n bounds.yMax += padding;\n\n const width = svgRef.current.clientWidth;\n const height = svgRef.current.clientHeight;\n\n const contentWidth = bounds.xMax - bounds.xMin;\n const contentHeight = bounds.yMax - bounds.yMin;\n\n const scaleX = width / contentWidth;\n const scaleY = height / contentHeight;\n\n let scale = Math.min(scaleX, scaleY);\n scale = Math.min(Math.max(scale, 0.1), 2); // Clamp between 0.1 and 2\n\n const centerX = (bounds.xMin + bounds.xMax) / 2;\n const centerY = (bounds.yMin + bounds.yMax) / 2;\n\n const translateX = width / 2 - centerX * scale;\n const translateY = height / 2 - centerY * scale;\n\n svg.transition().duration(750).call(zoom.transform, d3.zoomIdentity.translate(translateX, translateY).scale(scale));\n }, [nodes, visibleNodeIds]);\n\n // When container size changes (full-screen toggle), zoom to fit all nodes\n // This scales the view instead of recalculating positions, maintaining relative layout\n useEffect(() => {\n if (containerKey !== undefined && containerKey !== prevContainerKeyRef.current) {\n // Small delay to allow the container to finish resizing\n const timeoutId = setTimeout(() => {\n zoomToFitAll();\n }, 100);\n\n prevContainerKeyRef.current = containerKey;\n\n return () => clearTimeout(timeoutId);\n }\n }, [containerKey, zoomToFitAll]);\n\n return { svgRef, zoomIn, zoomOut, zoomToNode, zoomToFitAll };\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-FY4SXJGU.js","../src/hooks/TableGeneratorRegistry.ts","../src/hooks/url.rewriter.ts","../src/hooks/usePageUrlGenerator.ts","../src/hooks/useDataListRetriever.ts","../src/hooks/useDebounce.ts","../src/hooks/useTableGenerator.ts","../src/hooks/useCustomD3Graph.tsx"],"names":[],"mappings":"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","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-FY4SXJGU.js","sourcesContent":[null,"\"use client\";\n\nimport { UseTableStructureHook, UseTableStructureHookParams, UseTableStructureHookReturn } from \"./types\";\n\ntype TableGeneratorHook = UseTableStructureHook<any, any>;\n\nexport class TableGeneratorRegistry {\n private static instance: TableGeneratorRegistry;\n private registry = new Map<string, TableGeneratorHook>();\n\n private constructor() {}\n\n public static getInstance(): TableGeneratorRegistry {\n if (!TableGeneratorRegistry.instance) {\n TableGeneratorRegistry.instance = new TableGeneratorRegistry();\n }\n return TableGeneratorRegistry.instance;\n }\n\n public register<T, U>(type: string, hook: UseTableStructureHook<T, U>): void {\n if (!this.registry.has(type)) this.registry.set(type, hook as TableGeneratorHook);\n }\n\n public get<T, U>(type: string, params: UseTableStructureHookParams<T, U>): UseTableStructureHookReturn<T> {\n const hook = this.registry.get(type);\n if (!hook) {\n throw new Error(\n `Table generator for type \"${type}\" is not registered. Available types: ${Array.from(this.registry.keys()).join(\n \", \",\n )}`,\n );\n }\n return hook(params);\n }\n\n public isRegistered(type: string): boolean {\n return this.registry.has(type);\n }\n\n public getRegisteredTypes(): string[] {\n return Array.from(this.registry.keys());\n }\n\n public unregister(type: string): boolean {\n return this.registry.delete(type);\n }\n\n public clear(): void {\n this.registry.clear();\n }\n}\n\nexport const tableGeneratorRegistry = TableGeneratorRegistry.getInstance();\n","\"use client\";\n\nimport { useLocale } from \"next-intl\";\nimport { useCallback } from \"react\";\nimport { ModuleWithPermissions } from \"../permissions\";\nimport { usePageUrlGenerator } from \"./usePageUrlGenerator\";\n\nexport function useUrlRewriter() {\n const locale = useLocale();\n const generateUrl = usePageUrlGenerator();\n\n return useCallback(\n (params: { page: ModuleWithPermissions | string; id?: string; childPage?: string }): void => {\n window.history.replaceState(\n null,\n \"\",\n generateUrl({ page: params.page, id: params.id, childPage: params.childPage, language: locale }),\n );\n },\n [locale, generateUrl],\n );\n}\n","import { PageUrl } from \"../permissions/types\";\n\nexport function usePageUrlGenerator(): (params: {\n page?: PageUrl | string;\n id?: string;\n childPage?: PageUrl | string;\n childId?: string;\n additionalParameters?: { [key: string]: string | string[] | undefined };\n language?: string;\n}) => string {\n const generateUrl = (params: {\n page?: PageUrl | string;\n id?: string;\n childPage?: PageUrl | string;\n childId?: string;\n additionalParameters?: { [key: string]: string | string[] | undefined };\n language?: string;\n }): string => {\n if (!params.page) return \"/\";\n\n const pathParams: string[] = [\n `${params.language ? `/${params.language}` : \"\"}${typeof params.page === \"string\" ? params.page : params.page.pageUrl}`,\n ];\n\n if (params.id) {\n pathParams.push(params.id);\n if (params.childPage) {\n pathParams.push(typeof params.childPage === \"string\" ? params.childPage : (params.childPage.pageUrl ?? \"\"));\n if (params.childId) {\n pathParams.push(params.childId);\n }\n }\n }\n const response = pathParams.join(`/`);\n\n if (params.additionalParameters) {\n const searchParams = new URLSearchParams();\n for (const key in params.additionalParameters) {\n if (params.additionalParameters[key]) {\n searchParams.append(key, params.additionalParameters[key] as string);\n }\n }\n return `${response}?${searchParams.toString()}`;\n }\n\n return response;\n };\n\n return generateUrl;\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { AbstractService } from \"../core\";\n\nexport type PageInfo = {\n startItem: number;\n endItem: number;\n pageSize: number;\n};\n\nexport type DataListRetriever<T> = {\n ready?: boolean;\n setReady: (state: boolean) => void;\n isLoaded: boolean;\n data: T[] | undefined;\n next?: (onlyNewRecords?: boolean) => Promise<void>;\n previous?: (onlyNewRecords?: boolean) => Promise<void>;\n search: (search: string) => Promise<void>;\n refresh: () => Promise<void>;\n addAdditionalParameter: (key: string, value: any | null) => void;\n removeAdditionalParameter: (key: string) => void;\n setRefreshedElement: (element: T) => void;\n removeElement: (element: T) => void;\n isSearch: boolean;\n pageInfo?: PageInfo;\n};\n\nexport function useDataListRetriever<T>(params: {\n ready?: boolean;\n retriever: (params: any) => Promise<T[]>;\n retrieverParams?: any;\n search?: string;\n addAdditionalParameter?: (key: string, value: any | null) => void;\n requiresSearch?: boolean;\n module: any;\n}): DataListRetriever<T> {\n const [data, setData] = useState<T[] | undefined>(undefined);\n const [nextPage, setNextPage] = useState<string | undefined>(undefined);\n const [previousPage, setPreviousPage] = useState<string | undefined>(undefined);\n const [isLoaded, setIsLoaded] = useState(false);\n const [ready, setReady] = useState<boolean>(params.ready ?? true);\n const searchTermRef = useRef<string>(\"\");\n const additionalParamsRef = useRef<any>({});\n const requestIdRef = useRef(0);\n const abortControllerRef = useRef<AbortController | null>(null);\n const isFetchingRef = useRef(false);\n\n const resolvedType = params.module;\n const resolvedService = AbstractService; // We'll just use AbstractService directly for pagination\n\n // Helper to parse page params from pagination URLs\n const parsePageParams = useCallback((url: string | undefined): { offset: number; size: number } | null => {\n if (!url) return null;\n try {\n const urlObj = new URL(url);\n const offset = parseInt(urlObj.searchParams.get(\"page[offset]\") || \"0\", 10);\n const size = parseInt(urlObj.searchParams.get(\"page[size]\") || \"25\", 10);\n return { offset, size };\n } catch {\n return null;\n }\n }, []);\n\n // Helper to adjust pagination URL offset (used when removing elements)\n const adjustPaginationUrl = useCallback((url: string | undefined, delta: number): string | undefined => {\n if (!url) return undefined;\n try {\n const urlObj = new URL(url);\n const currentOffset = parseInt(urlObj.searchParams.get(\"page[offset]\") || \"0\", 10);\n const newOffset = Math.max(0, currentOffset + delta);\n urlObj.searchParams.set(\"page[offset]\", String(newOffset));\n return urlObj.toString();\n } catch {\n return url;\n }\n }, []);\n\n // Calculate pageInfo from pagination URLs and current data\n const pageInfo = useMemo((): PageInfo | undefined => {\n if (!data || data.length === 0) return undefined;\n\n // Try to determine current offset and page size from pagination URLs\n const nextParams = parsePageParams(nextPage);\n const prevParams = parsePageParams(previousPage);\n\n let currentOffset = 0;\n let pageSize = 25; // default\n\n if (nextParams) {\n // If we have a next page, current offset = next offset - page size\n pageSize = nextParams.size;\n currentOffset = Math.max(0, nextParams.offset - pageSize);\n } else if (prevParams) {\n // If we only have a previous page (we're on the last page)\n pageSize = prevParams.size;\n currentOffset = prevParams.offset + pageSize;\n }\n\n const startItem = currentOffset + 1;\n const endItem = currentOffset + data.length;\n\n return { startItem, endItem, pageSize };\n }, [data, nextPage, previousPage, parsePageParams]);\n\n const stableParams = useMemo(\n () => ({\n service: resolvedService,\n type: resolvedType,\n retriever: params.retriever,\n retrieverParams: params.retrieverParams,\n requiresSearch: params.requiresSearch,\n }),\n [resolvedService, resolvedType, params.retriever, params.retrieverParams, params.requiresSearch],\n );\n\n const fetchData = useCallback(\n async (fetchParams?: { isRefine?: boolean; isRefresh?: boolean; callNext?: boolean; callPrevious?: boolean }) => {\n if (ready === false) {\n return;\n }\n\n // Prevent concurrent fetches (unless it's a pagination call)\n if (isFetchingRef.current && !fetchParams?.callNext && !fetchParams?.callPrevious) {\n return;\n }\n\n const thisRequestId = ++requestIdRef.current;\n isFetchingRef.current = true;\n\n if (stableParams.requiresSearch === true && fetchParams?.isRefine !== true && fetchParams?.isRefresh !== true)\n return;\n\n if (\n !nextPage &&\n !previousPage &&\n isLoaded &&\n fetchParams?.callNext !== true &&\n fetchParams?.callPrevious !== true &&\n params.search === searchTermRef.current\n )\n return;\n\n const currentSearchTerm = searchTermRef.current;\n\n setIsLoaded(false);\n\n try {\n let response: T[];\n const nextRef = { next: undefined };\n const previousRef = { previous: undefined };\n const selfRef = { self: undefined };\n\n if (nextPage && fetchParams?.callNext && fetchParams?.isRefine !== true) {\n const ServiceClass = stableParams.service as typeof AbstractService;\n\n response = await ServiceClass.next<T[]>({\n type: stableParams.type,\n endpoint: nextPage,\n next: nextRef,\n previous: previousRef,\n self: selfRef,\n });\n } else if (previousPage && fetchParams?.callPrevious && fetchParams?.isRefine !== true) {\n const ServiceClass = stableParams.service as typeof AbstractService;\n\n response = await ServiceClass.previous<T[]>({\n type: stableParams.type,\n endpoint: previousPage,\n next: nextRef,\n previous: previousRef,\n self: selfRef,\n });\n } else {\n let retrieverParams = stableParams.retrieverParams ? { ...stableParams.retrieverParams } : {};\n\n retrieverParams = {\n ...retrieverParams,\n ...additionalParamsRef.current,\n };\n\n retrieverParams.search = currentSearchTerm;\n retrieverParams.next = nextRef;\n retrieverParams.previous = previousRef;\n retrieverParams.self = selfRef;\n\n response = await stableParams.retriever(retrieverParams);\n }\n\n // Only update state if this is still the latest request and wasn't aborted\n if (thisRequestId === requestIdRef.current && !abortControllerRef.current?.signal.aborted) {\n if (fetchParams?.isRefresh === true) {\n setData(response);\n } else {\n setData((prevData) => [...(prevData ? (prevData as T[]) : []), ...response]);\n }\n setIsLoaded(true);\n setNextPage(nextRef.next ? nextRef.next : undefined);\n setPreviousPage(previousRef.previous ? previousRef.previous : undefined);\n }\n } catch (error) {\n // Don't update state if request was aborted (AbortController disabled)\n if (thisRequestId === requestIdRef.current) {\n setIsLoaded(true);\n console.error(\"Error fetching data:\", error);\n }\n } finally {\n // Always reset fetching flag when done\n if (thisRequestId === requestIdRef.current) {\n isFetchingRef.current = false;\n }\n }\n },\n [stableParams, ready, params.search],\n );\n\n const setRefreshedElement = useCallback(\n (element: T) => {\n setData((prevData) => {\n if (!prevData) return prevData;\n\n const index = prevData.findIndex((data) => (data as any).id === (element as any).id);\n if (index === -1) return prevData;\n\n // Use immutable update pattern instead of mutation\n return prevData.map((item, i) => (i === index ? element : item));\n });\n },\n [setData],\n );\n\n const removeElement = useCallback(\n (element: T) => {\n setData((prevData) => {\n if (!prevData) return prevData;\n\n const index = prevData.findIndex((data) => (data as any).id === (element as any).id);\n\n if (index === -1) return prevData;\n\n // Adjust nextPage offset since we're removing an item\n setNextPage((prev) => adjustPaginationUrl(prev, -1));\n\n const newData = [...prevData];\n newData.splice(index, 1);\n return newData;\n });\n },\n [adjustPaginationUrl],\n );\n\n // Consolidated effect: Only fetch once when ready and not loaded\n // This prevents the duplicate API calls that occurred when both the mount effect\n // and ready effect fired simultaneously on initial render\n useEffect(() => {\n // Only fetch if ready and haven't loaded yet\n if (ready && !isLoaded) {\n fetchData({ isRefresh: true });\n }\n }, [ready, fetchData]);\n\n const loadNext = useCallback(\n async (onlyNewRecords?: boolean) => {\n if (nextPage) fetchData({ isRefresh: onlyNewRecords, callNext: true });\n },\n [fetchData, nextPage],\n );\n\n const loadPrevious = useCallback(\n async (onlyNewRecords?: boolean) => {\n if (previousPage) fetchData({ isRefresh: onlyNewRecords, callPrevious: true });\n },\n [fetchData, previousPage],\n );\n\n const addAdditionalParameter = useCallback(\n (key: string, value: any | null) => {\n if (value === null) {\n delete additionalParamsRef.current[key];\n } else {\n additionalParamsRef.current[key] = value;\n }\n\n setReady(true);\n setNextPage(undefined);\n setPreviousPage(undefined);\n fetchData({ isRefine: true, isRefresh: true });\n },\n [fetchData],\n );\n\n const removeAdditionalParameter = useCallback(\n (key: string) => {\n if (additionalParamsRef.current[key] !== undefined) {\n delete additionalParamsRef.current[key];\n setNextPage(undefined);\n setPreviousPage(undefined);\n fetchData({ isRefine: true, isRefresh: true });\n }\n },\n [fetchData],\n );\n\n const search = useCallback(\n async (search: string) => {\n if (search === searchTermRef.current) return;\n\n setNextPage(undefined);\n setPreviousPage(undefined);\n searchTermRef.current = search;\n fetchData({ isRefine: true, isRefresh: true });\n },\n [fetchData],\n );\n\n const isSearch = !!searchTermRef.current;\n\n const refresh = useCallback(async () => {\n setNextPage(undefined);\n setPreviousPage(undefined);\n fetchData({ isRefresh: true });\n }, [fetchData]);\n\n // Cleanup abort controller on unmount\n useEffect(() => {\n return () => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n };\n }, []);\n\n return {\n ready,\n setReady,\n isLoaded: isLoaded,\n data: data as T[],\n next: nextPage ? loadNext : undefined,\n previous: previousPage ? loadPrevious : undefined,\n search: search,\n addAdditionalParameter: addAdditionalParameter,\n removeAdditionalParameter: removeAdditionalParameter,\n refresh: refresh,\n setRefreshedElement: setRefreshedElement,\n isSearch: isSearch,\n removeElement: removeElement,\n pageInfo: pageInfo,\n };\n}\n","import { useCallback, useEffect, useRef } from \"react\";\n\nexport function useDebounce<T extends (...args: any[]) => any>(callback: T, delay: number): T & { cancel: () => void } {\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n const callbackRef = useRef(callback);\n\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n const debouncedFunction = useCallback(\n (...args: Parameters<T>) => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n timeoutRef.current = setTimeout(() => {\n callbackRef.current(...args);\n }, delay);\n },\n [delay],\n );\n\n // Attach a cancel method to clear pending timeout\n const cancel = () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n };\n\n return Object.assign(debouncedFunction, { cancel }) as T & { cancel: () => void };\n}\n\nexport default useDebounce;\n","\"use client\";\n\nimport { UseTableStructureHook, UseTableStructureHookParams, UseTableStructureHookReturn } from \"./types\";\nimport { ModuleWithPermissions } from \"../permissions\";\nimport { tableGeneratorRegistry } from \"./TableGeneratorRegistry\";\n\nexport function registerTableGenerator<T, U>(type: ModuleWithPermissions, hook: UseTableStructureHook<T, U>): void {\n tableGeneratorRegistry.register(type.name, hook);\n}\n\nexport function useTableGenerator<T, U>(\n type: ModuleWithPermissions,\n params: UseTableStructureHookParams<T, U>,\n): UseTableStructureHookReturn<T> {\n return tableGeneratorRegistry.get(type.name, params);\n}\n","import * as d3 from \"d3\";\nimport { Loader2 } from \"lucide-react\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { renderToStaticMarkup } from \"react-dom/server\";\nimport { D3Link, D3Node } from \"../interfaces\";\n\n/**\n * Custom hook for D3 graph visualization with larger circles and more interactive features\n */\nexport function useCustomD3Graph(\n nodes: D3Node[],\n links: D3Link[],\n onNodeClick: (nodeId: string) => void,\n visibleNodeIds?: Set<string>,\n loadingNodeIds?: Set<string>,\n containerKey?: string | number,\n) {\n const svgRef = useRef<SVGSVGElement | null>(null);\n const zoomRef = useRef<d3.ZoomTransform | null>(null);\n const zoomBehaviorRef = useRef<d3.ZoomBehavior<SVGSVGElement, unknown> | null>(null);\n const nodePositionsRef = useRef<Map<string, { x: number; y: number }>>(new Map());\n const prevContainerKeyRef = useRef<string | number | undefined>(containerKey);\n\n const zoomToNode = useCallback(\n (nodeId: string, childIds: string[] = []) => {\n if (!svgRef.current || !zoomBehaviorRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const zoom = zoomBehaviorRef.current;\n\n const targetNode = nodes.find((n) => n.id === nodeId);\n const childNodes = nodes.filter((n) => childIds.includes(n.id));\n\n if (!targetNode) return;\n\n const positions: { x: number; y: number }[] = [];\n\n if (\n targetNode.fx !== undefined &&\n targetNode.fy !== undefined &&\n targetNode.fx !== null &&\n targetNode.fy !== null\n ) {\n positions.push({ x: targetNode.fx, y: targetNode.fy });\n } else if (\n targetNode.x !== undefined &&\n targetNode.y !== undefined &&\n targetNode.x !== null &&\n targetNode.y !== null\n ) {\n positions.push({ x: targetNode.x, y: targetNode.y });\n }\n\n childNodes.forEach((child) => {\n if (child.fx !== undefined && child.fy !== undefined && child.fx !== null && child.fy !== null) {\n positions.push({ x: child.fx, y: child.fy });\n } else if (child.x !== undefined && child.y !== undefined && child.x !== null && child.y !== null) {\n positions.push({ x: child.x, y: child.y });\n }\n });\n\n if (positions.length === 0) return;\n\n const bounds = {\n xMin: Math.min(...positions.map((p) => p.x)),\n xMax: Math.max(...positions.map((p) => p.x)),\n yMin: Math.min(...positions.map((p) => p.y)),\n yMax: Math.max(...positions.map((p) => p.y)),\n };\n\n const padding = 150;\n bounds.xMin -= padding;\n bounds.xMax += padding;\n bounds.yMin -= padding;\n bounds.yMax += padding;\n\n const width = svgRef.current.clientWidth;\n const height = svgRef.current.clientHeight;\n\n const contentWidth = bounds.xMax - bounds.xMin;\n const contentHeight = bounds.yMax - bounds.yMin;\n\n const scaleX = width / contentWidth;\n const scaleY = height / contentHeight;\n\n let scale = Math.min(scaleX, scaleY);\n\n scale = Math.min(Math.max(scale, 0.2), 1.5);\n\n const centerX = (bounds.xMin + bounds.xMax) / 2;\n const centerY = (bounds.yMin + bounds.yMax) / 2;\n\n const translateX = width / 2 - centerX * scale;\n const translateY = height / 2 - centerY * scale;\n\n svg\n .transition()\n .duration(750)\n .call(zoom.transform, d3.zoomIdentity.translate(translateX, translateY).scale(scale));\n },\n [nodes],\n );\n\n const colorScale = useMemo(() => {\n const accentColor = \"var(--accent)\";\n\n // Define unified color for all content types\n const contentColor = \"hsl(30, 80%, 55%)\"; // Orange for all content\n\n const groupTypes = new Set<string>();\n nodes.forEach((node) => {\n groupTypes.add(node.instanceType);\n });\n\n const typeColorMap = new Map<string, string>();\n\n Array.from(groupTypes).forEach((type, index) => {\n if (type === nodes[0]?.instanceType) {\n // Root node\n typeColorMap.set(type, accentColor);\n } else if (type === \"documents\" || type === \"articles\" || type === \"hyperlinks\") {\n // All content types get the same orange color\n typeColorMap.set(type, contentColor);\n } else {\n // Topics, Expertises, etc. - use golden angle\n const hueShift = (index * 137.508) % 360;\n typeColorMap.set(type, `hsl(${hueShift}, 32%, 52%)`);\n }\n });\n\n return typeColorMap;\n }, [nodes]);\n\n const washOutColor = useCallback((color: string): string => {\n // Parse HSL color and make it lighter and more desaturated\n const hslMatch = color.match(/hsl\\((\\d+\\.?\\d*),\\s*(\\d+\\.?\\d*)%,\\s*(\\d+\\.?\\d*)%\\)/);\n if (hslMatch) {\n const hue = parseFloat(hslMatch[1]);\n\n // Reduce saturation to 15% and increase lightness to 80%\n return `hsl(${hue}, 15%, 80%)`;\n }\n\n // For var(--accent), return a lighter version\n if (color.includes(\"var(--accent)\")) {\n return \"hsl(0, 0%, 80%)\"; // Light gray for washed out accent\n }\n\n // Fallback\n return \"hsl(0, 0%, 80%)\";\n }, []);\n\n const getNodeColor = useCallback(\n (node: D3Node) => {\n const baseColor = colorScale.get(node.instanceType) || \"gray\";\n if (node.washedOut) {\n return washOutColor(baseColor);\n }\n return baseColor;\n },\n [colorScale, washOutColor],\n );\n\n useEffect(() => {\n if (!nodes.length || !svgRef.current) return;\n\n const visibleNodes = visibleNodeIds\n ? nodes.filter((node) => visibleNodeIds.has(node.id))\n : nodes.filter((node) => node.visible !== false);\n\n const visibleNodeIdSet = new Set(visibleNodes.map((node) => node.id));\n const visibleLinks = links.filter((link) => {\n const sourceId = typeof link.source === \"string\" ? link.source : link.source.id;\n const targetId = typeof link.target === \"string\" ? link.target : link.target.id;\n return visibleNodeIdSet.has(sourceId) && visibleNodeIdSet.has(targetId);\n });\n\n const svg = d3.select<SVGSVGElement, unknown>(svgRef.current);\n svg.selectAll(\"*\").remove();\n\n const container = svgRef.current?.parentElement;\n if (!container) return;\n\n const width = container.clientWidth;\n const height = container.clientHeight;\n\n svg.attr(\"width\", width).attr(\"height\", height).attr(\"viewBox\", `0 0 ${width} ${height}`);\n\n const graphGroup = svg.append(\"g\").attr(\"class\", \"graph-content\");\n\n const zoom = d3\n .zoom<SVGSVGElement, unknown>()\n .scaleExtent([0.1, 4])\n .on(\"zoom\", (event) => {\n const transform = event.transform;\n graphGroup.attr(\"transform\", transform.toString());\n zoomRef.current = transform;\n });\n\n zoomBehaviorRef.current = zoom;\n\n svg\n .call(zoom as any)\n .on(\"wheel.zoom\", null)\n .on(\"dblclick.zoom\", null);\n\n const nodeRadius = 40;\n\n const childDistanceFromRoot = Math.min(width, height) * 0.4;\n const grandchildDistanceFromChild = nodeRadius * 10;\n\n const centralNodeId = nodes[0].id;\n\n const nodeHierarchy = new Map<\n string,\n {\n depth: number;\n parent: string | null;\n children: string[];\n angle?: number;\n x?: number;\n y?: number;\n }\n >();\n\n nodeHierarchy.set(centralNodeId, {\n depth: 0,\n parent: null,\n children: [],\n });\n\n visibleLinks.forEach((link) => {\n const sourceId = typeof link.source === \"string\" ? link.source : link.source.id;\n const targetId = typeof link.target === \"string\" ? link.target : link.target.id;\n\n if (sourceId === centralNodeId) {\n nodeHierarchy.set(targetId, { depth: 1, parent: centralNodeId, children: [] });\n const rootNode = nodeHierarchy.get(centralNodeId);\n if (rootNode) {\n rootNode.children.push(targetId);\n }\n }\n });\n\n visibleLinks.forEach((link) => {\n const sourceId = typeof link.source === \"string\" ? link.source : link.source.id;\n const targetId = typeof link.target === \"string\" ? link.target : link.target.id;\n\n const sourceNode = nodeHierarchy.get(sourceId);\n if (sourceNode && sourceNode.depth === 1 && !nodeHierarchy.has(targetId)) {\n nodeHierarchy.set(targetId, { depth: 2, parent: sourceId, children: [] });\n sourceNode.children.push(targetId);\n }\n });\n\n const rootChildren = nodeHierarchy.get(centralNodeId)?.children || [];\n\n const childAngleStep = (2 * Math.PI) / Math.max(rootChildren.length, 1);\n\n rootChildren.forEach((childId, index) => {\n const childNode = nodeHierarchy.get(childId);\n if (childNode) {\n const angle = index * childAngleStep;\n childNode.angle = angle;\n childNode.x = width / 2 + childDistanceFromRoot * Math.cos(angle);\n childNode.y = height / 2 + childDistanceFromRoot * Math.sin(angle);\n }\n });\n\n for (const [nodeId, node] of nodeHierarchy.entries()) {\n if (node.depth === 1 && node.angle !== undefined && node.x !== undefined && node.y !== undefined) {\n const childAngle = node.angle;\n const childX = node.x;\n const childY = node.y;\n const grandchildren = node.children;\n\n if (grandchildren.length === 0) continue;\n\n const dirX = childX - width / 2;\n const dirY = childY - height / 2;\n const dirLength = Math.sqrt(dirX * dirX + dirY * dirY);\n\n const normDirX = dirX / dirLength;\n const normDirY = dirY / dirLength;\n\n if (grandchildren.length === 1) {\n const grandchildId = grandchildren[0];\n const grandchildNode = nodeHierarchy.get(grandchildId);\n if (grandchildNode) {\n grandchildNode.x = childX + normDirX * grandchildDistanceFromChild;\n grandchildNode.y = childY + normDirY * grandchildDistanceFromChild;\n grandchildNode.angle = childAngle;\n }\n } else {\n // Multiple grandchildren - arrange in semicircular arc\n const numChildren = grandchildren.length;\n\n // Dynamic arc span: scale from 60° (2 children) to 180° (7+ children)\n const minArc = Math.PI / 3; // 60 degrees\n const maxArc = Math.PI; // 180 degrees\n const arcProgress = Math.min(1, (numChildren - 2) / 5);\n const arcSpan = minArc + arcProgress * (maxArc - minArc);\n\n // Calculate starting angle (center the arc around the radial direction)\n const startAngle = childAngle - arcSpan / 2;\n\n grandchildren.forEach((grandchildId, index) => {\n const grandchildNode = nodeHierarchy.get(grandchildId);\n if (!grandchildNode) return;\n\n // Calculate angle for this child\n const angleOffset = numChildren > 1 ? (index / (numChildren - 1)) * arcSpan : 0;\n const angle = startAngle + angleOffset;\n\n // Position at constant radius from parent\n grandchildNode.x = childX + grandchildDistanceFromChild * Math.cos(angle);\n grandchildNode.y = childY + grandchildDistanceFromChild * Math.sin(angle);\n grandchildNode.angle = angle;\n });\n }\n }\n }\n\n visibleNodes.forEach((node) => {\n const savedPosition = nodePositionsRef.current.get(node.id);\n\n if (savedPosition) {\n node.fx = savedPosition.x;\n node.fy = savedPosition.y;\n } else {\n const hierarchyNode = nodeHierarchy.get(node.id);\n if (hierarchyNode && hierarchyNode.x !== undefined && hierarchyNode.y !== undefined) {\n node.fx = hierarchyNode.x;\n node.fy = hierarchyNode.y;\n // Save the calculated position so it persists across re-renders\n nodePositionsRef.current.set(node.id, { x: hierarchyNode.x, y: hierarchyNode.y });\n } else if (node.id === centralNodeId) {\n node.fx = width / 2;\n node.fy = height / 2;\n // Save the center position\n nodePositionsRef.current.set(node.id, { x: width / 2, y: height / 2 });\n }\n }\n });\n\n const simulation = d3\n .forceSimulation<D3Node>(visibleNodes)\n .force(\n \"link\",\n d3\n .forceLink<D3Node, D3Link>(visibleLinks)\n .id((d) => d.id)\n .distance(nodeRadius * 3)\n .strength(0.1),\n )\n .force(\"charge\", d3.forceManyBody().strength(-500).distanceMax(300))\n .force(\"collision\", d3.forceCollide().radius(nodeRadius * 1.2))\n .force(\"center\", d3.forceCenter(width / 2, height / 2).strength(0.1));\n\n simulation.stop();\n for (let i = 0; i < 100; i++) {\n simulation.tick();\n }\n\n visibleNodes.forEach((node) => {\n if (node.fx === undefined) {\n node.fx = node.x;\n node.fy = node.y;\n }\n });\n\n const link = graphGroup\n .append(\"g\")\n .attr(\"stroke\", \"#999\")\n .attr(\"stroke-opacity\", 0.6)\n .selectAll(\"line\")\n .data(visibleLinks)\n .join(\"line\")\n .attr(\"x1\", (d) => (d.source as D3Node).x || 0)\n .attr(\"y1\", (d) => (d.source as D3Node).y || 0)\n .attr(\"x2\", (d) => (d.target as D3Node).x || 0)\n .attr(\"y2\", (d) => (d.target as D3Node).y || 0)\n .attr(\"stroke-width\", 1.5);\n\n const node = graphGroup\n .append(\"g\")\n .selectAll(\"g\")\n .data(visibleNodes)\n .join(\"g\")\n .attr(\"class\", \"node-group\")\n .attr(\"cursor\", \"pointer\")\n .attr(\"transform\", (d) => `translate(${d.x || 0}, ${d.y || 0})`)\n .call(\n d3\n .drag<SVGGElement, D3Node>()\n .subject(function (d) {\n return d;\n })\n .on(\"start\", function (event, d) {\n d.fx = d.x;\n d.fy = d.y;\n })\n .on(\"drag\", function (event, d) {\n d.fx = event.x;\n d.fy = event.y;\n\n d3.select(this).attr(\"transform\", `translate(${event.x}, ${event.y})`);\n\n d3.select(this).attr(\"transform\", `translate(${event.x}, ${event.y})`);\n\n nodePositionsRef.current.set(d.id, { x: event.x, y: event.y });\n\n link\n .attr(\"x1\", (l) => {\n const source = l.source as D3Node;\n return source.fx || source.x || 0;\n })\n .attr(\"y1\", (l) => {\n const source = l.source as D3Node;\n return source.fy || source.y || 0;\n })\n .attr(\"x2\", (l) => {\n const target = l.target as D3Node;\n return target.fx || target.x || 0;\n })\n .attr(\"y2\", (l) => {\n const target = l.target as D3Node;\n return target.fy || target.y || 0;\n });\n })\n .on(\"end\", function (event, d) {\n d.fx = event.x;\n d.fy = event.y;\n }) as any,\n )\n .on(\"mouseenter\", function (_event, d) {\n // Skip hover effect for root node\n if (d.instanceType === \"root\") return;\n\n const currentNode = d3.select(this);\n\n // Bring node to front\n currentNode.raise();\n\n // Get current zoom scale for counter-scaling text\n const currentZoom = zoomRef.current?.k || 1;\n const targetScreenFontSize = 20; // Target font size in screen pixels\n const baseFontSize = 12; // Base font size in graph coordinates\n\n // Calculate smooth scale factor for transform\n const textScale = targetScreenFontSize / (baseFontSize * currentZoom);\n\n // Calculate text position offset - circle stays in graph coords, only gap is counter-scaled\n const hoverTextOffset = nodeRadius * 1.4 + 5 / currentZoom;\n\n // Scale up the circle with smooth transition (unchanged)\n currentNode\n .select(\"circle\")\n .transition()\n .duration(250)\n .ease(d3.easeExpOut)\n .attr(\"r\", nodeRadius * 1.4)\n .attr(\"filter\", \"drop-shadow(0px 4px 12px rgba(0, 0, 0, 0.3))\");\n\n // Scale up the text with smooth transform scaling around its anchor point\n currentNode\n .select(\"text\")\n .transition()\n .duration(250)\n .ease(d3.easeExpOut)\n .attr(\"dy\", -hoverTextOffset)\n .attr(\"transform\", `translate(0, ${-hoverTextOffset}) scale(${textScale}) translate(0, ${hoverTextOffset})`);\n })\n .on(\"mouseleave\", function (_event, d) {\n // Skip hover effect for root node\n if (d.instanceType === \"root\") return;\n\n const currentNode = d3.select(this);\n\n // Return circle to normal size\n currentNode\n .select(\"circle\")\n .transition()\n .duration(250)\n .ease(d3.easeExpOut)\n .attr(\"r\", nodeRadius)\n .attr(\"filter\", null);\n\n // Return text to normal size with smooth transform\n const normalOffset = nodeRadius + 5;\n currentNode\n .select(\"text\")\n .transition()\n .duration(250)\n .ease(d3.easeExpOut)\n .attr(\"dy\", -normalOffset)\n .attr(\"transform\", `translate(0, ${-normalOffset}) scale(1) translate(0, ${normalOffset})`);\n });\n\n node\n .append(\"circle\")\n .attr(\"r\", nodeRadius)\n .attr(\"fill\", (d) => getNodeColor(d))\n .attr(\"stroke\", \"#fff\")\n .attr(\"stroke-width\", 1.5)\n .on(\"click\", (event, d) => {\n event.preventDefault();\n event.stopPropagation();\n if (zoomBehaviorRef.current) {\n svg.on(\".zoom\", null);\n setTimeout(() => {\n if (zoomBehaviorRef.current) {\n svg\n .call(zoomBehaviorRef.current as any)\n .on(\"wheel.zoom\", null)\n .on(\"dblclick.zoom\", null);\n }\n }, 100);\n }\n onNodeClick(d.id);\n });\n\n node.each(function (d: D3Node) {\n if (d.icon) {\n const Icon = d.icon as React.FC<{ size: number; color: string }>;\n const iconSvg = renderToStaticMarkup(<Icon size={nodeRadius / 2} color=\"white\" />);\n\n const iconGroup = d3\n .select(this)\n .append(\"g\")\n .html(iconSvg)\n .attr(\"transform\", `translate(${-nodeRadius / 4}, ${-nodeRadius / 4})`)\n .style(\"pointer-events\", \"all\")\n .on(\"click\", (event) => {\n event.stopPropagation();\n onNodeClick(d.id);\n });\n }\n });\n\n // Add loading spinner for nodes that are fetching children\n node.each(function (d: D3Node) {\n if (loadingNodeIds && loadingNodeIds.has(d.id)) {\n // Remove existing icon\n d3.select(this).selectAll(\"g\").remove();\n\n // Add spinner\n const spinnerSvg = renderToStaticMarkup(<Loader2 size={nodeRadius / 2} color=\"white\" />);\n\n d3.select(this)\n .append(\"g\")\n .html(spinnerSvg)\n .attr(\"class\", \"animate-spin\")\n .attr(\"transform\", `translate(${-nodeRadius / 4}, ${-nodeRadius / 4})`)\n .style(\"pointer-events\", \"none\");\n }\n });\n\n node.each(function (d: D3Node) {\n const textElement = d3\n .select(this)\n .append(\"text\")\n .attr(\"text-anchor\", \"middle\")\n .attr(\"font-size\", 12)\n .attr(\"pointer-events\", \"none\");\n\n if (d.instanceType === \"root\") {\n // Split text by spaces for multi-line display\n const words = d.name.split(\" \");\n const lineHeight = 1.2; // em units\n const numLines = words.length;\n // Calculate starting position to center the text block vertically\n // Account for the fact that we want the middle of the entire text block at y=0\n const startY = -((numLines - 1) * lineHeight) / 2;\n\n textElement.attr(\"fill\", \"var(--accent-foreground)\").attr(\"dominant-baseline\", \"middle\");\n\n words.forEach((word, index) => {\n textElement\n .append(\"tspan\")\n .attr(\"x\", 0)\n .attr(\"dy\", index === 0 ? `${startY}em` : `${lineHeight}em`)\n .text(word);\n });\n } else {\n // Non-root nodes: single line text above the circle\n textElement\n .attr(\"dy\", -nodeRadius - 5)\n .attr(\"fill\", \"currentColor\")\n .text(d.name);\n }\n });\n\n return () => {\n simulation.stop();\n };\n }, [nodes, links, colorScale, visibleNodeIds, loadingNodeIds, onNodeClick]);\n\n const zoomIn = useCallback(() => {\n if (!svgRef.current || !zoomBehaviorRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const zoom = zoomBehaviorRef.current;\n\n const currentTransform = zoomRef.current || d3.zoomIdentity;\n const newScale = Math.min(currentTransform.k * 1.3, 4);\n\n svg\n .transition()\n .duration(300)\n .call(zoom.transform, d3.zoomIdentity.translate(currentTransform.x, currentTransform.y).scale(newScale));\n }, []);\n\n const zoomOut = useCallback(() => {\n if (!svgRef.current || !zoomBehaviorRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const zoom = zoomBehaviorRef.current;\n\n const currentTransform = zoomRef.current || d3.zoomIdentity;\n const newScale = Math.max(currentTransform.k * 0.7, 0.1);\n\n svg\n .transition()\n .duration(300)\n .call(zoom.transform, d3.zoomIdentity.translate(currentTransform.x, currentTransform.y).scale(newScale));\n }, []);\n\n const zoomToFitAll = useCallback(() => {\n if (!svgRef.current || !zoomBehaviorRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const zoom = zoomBehaviorRef.current;\n\n // Get all visible nodes\n const visibleNodes = visibleNodeIds\n ? nodes.filter((node) => visibleNodeIds.has(node.id))\n : nodes.filter((node) => node.visible !== false);\n\n if (visibleNodes.length === 0) return;\n\n // Calculate bounds of all visible nodes\n const positions: { x: number; y: number }[] = [];\n visibleNodes.forEach((node) => {\n if (node.fx !== undefined && node.fy !== undefined && node.fx !== null && node.fy !== null) {\n positions.push({ x: node.fx, y: node.fy });\n } else if (node.x !== undefined && node.y !== undefined && node.x !== null && node.y !== null) {\n positions.push({ x: node.x, y: node.y });\n }\n });\n\n if (positions.length === 0) return;\n\n const bounds = {\n xMin: Math.min(...positions.map((p) => p.x)),\n xMax: Math.max(...positions.map((p) => p.x)),\n yMin: Math.min(...positions.map((p) => p.y)),\n yMax: Math.max(...positions.map((p) => p.y)),\n };\n\n // Add padding\n const padding = 150;\n bounds.xMin -= padding;\n bounds.xMax += padding;\n bounds.yMin -= padding;\n bounds.yMax += padding;\n\n const width = svgRef.current.clientWidth;\n const height = svgRef.current.clientHeight;\n\n const contentWidth = bounds.xMax - bounds.xMin;\n const contentHeight = bounds.yMax - bounds.yMin;\n\n const scaleX = width / contentWidth;\n const scaleY = height / contentHeight;\n\n let scale = Math.min(scaleX, scaleY);\n scale = Math.min(Math.max(scale, 0.1), 2); // Clamp between 0.1 and 2\n\n const centerX = (bounds.xMin + bounds.xMax) / 2;\n const centerY = (bounds.yMin + bounds.yMax) / 2;\n\n const translateX = width / 2 - centerX * scale;\n const translateY = height / 2 - centerY * scale;\n\n svg.transition().duration(750).call(zoom.transform, d3.zoomIdentity.translate(translateX, translateY).scale(scale));\n }, [nodes, visibleNodeIds]);\n\n // When container size changes (full-screen toggle), zoom to fit all nodes\n // This scales the view instead of recalculating positions, maintaining relative layout\n useEffect(() => {\n if (containerKey !== undefined && containerKey !== prevContainerKeyRef.current) {\n // Small delay to allow the container to finish resizing\n const timeoutId = setTimeout(() => {\n zoomToFitAll();\n }, 100);\n\n prevContainerKeyRef.current = containerKey;\n\n return () => clearTimeout(timeoutId);\n }\n }, [containerKey, zoomToFitAll]);\n\n return { svgRef, zoomIn, zoomOut, zoomToNode, zoomToFitAll };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-H6FMOA6B.js"],"names":[],"mappings":"AAAA","file":"/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-H6FMOA6B.js"}
1
+ {"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-H6FMOA6B.js"],"names":[],"mappings":"AAAA","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-H6FMOA6B.js"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-I2REI7OA.js","../src/core/abstracts/AbstractApiData.ts","../src/core/abstracts/AbstractService.ts","../src/core/registry/ModuleRegistrar.ts","../src/core/registry/ModuleRegistry.ts","../src/core/endpoint/EndpointCreator.ts","../src/core/fields/FieldSelector.ts","../src/core/utils/rehydrate.ts"],"names":["includedData","HttpMethod"],"mappings":"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","file":"/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-I2REI7OA.js","sourcesContent":[null,"import { ApiDataInterface } from \"../interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { JsonApiHydratedDataInterface } from \"../interfaces/JsonApiHydratedDataInterface\";\nimport { RehydrationFactory } from \"../factories/RehydrationFactory\";\n\nexport abstract class AbstractApiData implements ApiDataInterface {\n protected _jsonApi?: any;\n protected _included?: any[];\n\n protected _id?: string;\n protected _type?: string;\n protected _createdAt?: Date;\n protected _updatedAt?: Date;\n\n protected _self?: string;\n\n get type(): string {\n if (!this._type) throw new Error(\"Type is not set.\");\n return this._type;\n }\n\n get id(): string {\n if (!this._id) throw new Error(\"Id is not set.\");\n return this._id;\n }\n\n get self(): string | undefined {\n return this._self;\n }\n\n get createdAt(): Date {\n return this._createdAt ?? new Date();\n }\n\n get updatedAt(): Date {\n return this._updatedAt ?? new Date();\n }\n\n get included(): any[] {\n return this._included ?? [];\n }\n\n get jsonApi(): any {\n return this._jsonApi;\n }\n\n ingestJsonApi(_data: JsonApiHydratedDataInterface): void {}\n\n generateApiUrl(_params?: any): string {\n throw new Error(\"Method not implemented.\");\n }\n\n createJsonApi(_data?: any): any {\n throw new Error(\"Method not implemented.\");\n }\n\n protected _readIncluded<T extends ApiDataInterface>(\n data: JsonApiHydratedDataInterface,\n type: string,\n dataType: ApiRequestDataTypeInterface,\n ): T | T[] | undefined {\n if (\n data.included === undefined ||\n data.included.length === 0 ||\n data.jsonApi.relationships === undefined ||\n data.jsonApi.relationships[type] === undefined ||\n data.jsonApi.relationships[type].data === undefined\n ) {\n return undefined;\n }\n\n if (Array.isArray(data.jsonApi.relationships[type].data)) {\n const response: T[] = data.jsonApi.relationships[type].data.map((jsonApiData: any) => {\n const includedData = data.included.find(\n (includedData: any) => includedData.id === jsonApiData.id && includedData.type === jsonApiData.type,\n );\n\n if (includedData === undefined) return undefined;\n\n return RehydrationFactory.rehydrate(dataType, {\n jsonApi: includedData,\n included: data.included,\n }) as T;\n });\n\n return response.filter((item: T | undefined) => item !== undefined) as T[];\n }\n\n const includedData = data.included.find(\n (includedData: any) =>\n includedData.id === data.jsonApi.relationships[type].data.id &&\n includedData.type === data.jsonApi.relationships[type].data.type,\n );\n\n if (includedData === undefined && data.allData !== undefined) {\n // Try to find in allData as a fallback\n const fallbackData = data.allData.find(\n (includedData: any) =>\n includedData.id === data.jsonApi.relationships[type].data.id &&\n includedData.type === data.jsonApi.relationships[type].data.type,\n );\n if (fallbackData !== undefined) {\n return RehydrationFactory.rehydrate(dataType, {\n jsonApi: fallbackData,\n included: data.included,\n }) as T;\n }\n }\n\n if (includedData === undefined) return undefined;\n\n return RehydrationFactory.rehydrate(dataType, {\n jsonApi: includedData,\n included: data.included,\n }) as T;\n }\n\n dehydrate(): JsonApiHydratedDataInterface {\n return {\n jsonApi: this._jsonApi,\n included: this._included ?? [],\n };\n }\n\n rehydrate(data: JsonApiHydratedDataInterface): this {\n this._jsonApi = data.jsonApi;\n this._included = data.included;\n\n this._type = this._jsonApi.type;\n this._id = this._jsonApi.id;\n this._createdAt = this._jsonApi.meta?.createdAt !== undefined ? new Date(this._jsonApi.meta.createdAt) : undefined;\n this._updatedAt = this._jsonApi.meta?.updatedAt !== undefined ? new Date(this._jsonApi.meta.updatedAt) : undefined;\n\n this._self = this._jsonApi.links?.self ?? undefined;\n\n return this;\n }\n}\n","import { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { ApiResponseInterface } from \"../interfaces/ApiResponseInterface\";\n\nexport enum HttpMethod {\n GET = \"GET\",\n POST = \"POST\",\n PUT = \"PUT\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n}\n\nexport interface NextRef {\n next?: string;\n}\n\nexport interface PreviousRef {\n previous?: string;\n}\n\nexport interface SelfRef {\n self?: string;\n}\n\nlet globalErrorHandler: ((status: number, message: string) => void) | null = null;\n\n/**\n * Set a global error handler for API errors (client-side only).\n * This handler will be called instead of throwing errors.\n */\nexport function setGlobalErrorHandler(handler: (status: number, message: string) => void) {\n globalErrorHandler = handler;\n}\n\n/**\n * Get the current global error handler.\n */\nexport function getGlobalErrorHandler(): ((status: number, message: string) => void) | null {\n return globalErrorHandler;\n}\n\n/**\n * Abstract base class for services that interact with the JSON:API.\n * Extend this class to create feature-specific services.\n */\nexport abstract class AbstractService {\n /**\n * Extract locale from client-side URL pathname\n * URL structure: /{locale}/route-path (e.g., /it/accounts)\n * Fallback chain: URL locale → navigator.language → \"en\"\n */\n private static getClientLocale(): string {\n if (typeof window === \"undefined\") {\n return \"en\"; // Server-side fallback\n }\n\n // Extract locale from URL pathname (first segment after leading slash)\n const pathSegments = window.location.pathname.split(\"/\").filter(Boolean);\n const urlLocale = pathSegments[0];\n\n // Validate against supported locales (currently only \"en\")\n const supportedLocales = [\"en\"];\n if (urlLocale && supportedLocales.includes(urlLocale)) {\n return urlLocale;\n }\n\n // Fallback to navigator language\n const navigatorLocale = navigator.language.split(\"-\")[0];\n if (navigatorLocale && supportedLocales.includes(navigatorLocale)) {\n return navigatorLocale;\n }\n\n // Final fallback\n return \"en\";\n }\n\n static async next<T>(params: {\n type: ApiRequestDataTypeInterface;\n endpoint: string;\n next?: NextRef;\n previous?: PreviousRef;\n self?: SelfRef;\n }): Promise<T> {\n return await this.callApi<T>({\n method: HttpMethod.GET,\n type: params.type,\n endpoint: params.endpoint,\n next: params.next,\n previous: params.previous,\n self: params.self,\n });\n }\n\n /**\n * Fetch the previous page of results.\n */\n static async previous<T>(params: {\n type: ApiRequestDataTypeInterface;\n endpoint: string;\n next?: NextRef;\n previous?: PreviousRef;\n self?: SelfRef;\n }): Promise<T> {\n return await this.callApi<T>({\n method: HttpMethod.GET,\n type: params.type,\n endpoint: params.endpoint,\n next: params.next,\n previous: params.previous,\n self: params.self,\n });\n }\n\n /**\n * Make an API call with automatic environment detection and error handling.\n */\n protected static async callApi<T>(params: {\n type: ApiRequestDataTypeInterface;\n method: HttpMethod;\n endpoint: string;\n companyId?: string;\n input?: any;\n overridesJsonApiCreation?: boolean;\n next?: NextRef;\n previous?: PreviousRef;\n self?: SelfRef;\n responseType?: ApiRequestDataTypeInterface;\n files?: { [key: string]: File | Blob } | File | Blob;\n }): Promise<T> {\n // Dynamic import to avoid bundling issues\n const { JsonApiGet, JsonApiPost, JsonApiPut, JsonApiPatch, JsonApiDelete } =\n await import(\"../../unified/JsonApiRequest\");\n\n let apiResponse: ApiResponseInterface;\n\n // Get language based on environment\n let language = \"en\";\n if (typeof window === \"undefined\") {\n const { getLocale } = await import(\"next-intl/server\");\n language = (await getLocale()) ?? \"en\";\n } else {\n // Client-side: extract locale from URL pathname\n language = this.getClientLocale();\n }\n\n switch (params.method) {\n case HttpMethod.GET:\n apiResponse = await JsonApiGet({\n classKey: params.type,\n endpoint: params.endpoint,\n companyId: params.companyId,\n language: language,\n });\n break;\n case HttpMethod.POST:\n apiResponse = await JsonApiPost({\n classKey: params.type,\n endpoint: params.endpoint,\n companyId: params.companyId,\n body: params.input,\n overridesJsonApiCreation: params.overridesJsonApiCreation,\n language: language,\n responseType: params.responseType,\n files: params.files,\n });\n break;\n case HttpMethod.PUT:\n apiResponse = await JsonApiPut({\n classKey: params.type,\n endpoint: params.endpoint,\n companyId: params.companyId,\n body: params.input,\n language: language,\n responseType: params.responseType,\n files: params.files,\n });\n break;\n case HttpMethod.PATCH:\n apiResponse = await JsonApiPatch({\n classKey: params.type,\n endpoint: params.endpoint,\n companyId: params.companyId,\n body: params.input,\n overridesJsonApiCreation: params.overridesJsonApiCreation,\n language: language,\n responseType: params.responseType,\n files: params.files,\n });\n break;\n case HttpMethod.DELETE:\n apiResponse = await JsonApiDelete({\n classKey: params.type,\n endpoint: params.endpoint,\n companyId: params.companyId,\n language: language,\n responseType: params.responseType,\n });\n break;\n default:\n throw new Error(\"Method not found\");\n }\n\n if (!apiResponse.ok) {\n if (globalErrorHandler && typeof window !== \"undefined\") {\n globalErrorHandler(apiResponse.response, apiResponse.error);\n return undefined as any;\n } else {\n const error = new Error(`${apiResponse.response}:${apiResponse.error}`) as any;\n error.status = apiResponse.response;\n error.digest = `HTTP_${apiResponse.response}`;\n throw error;\n }\n }\n\n if (apiResponse.next && params.next) params.next.next = apiResponse.next;\n if (apiResponse.prev && params.previous) params.previous.previous = apiResponse.prev;\n if (apiResponse.self && params.self) params.self.self = apiResponse.self;\n\n return apiResponse.data as T;\n }\n\n /**\n * Get raw JSON:API response data without deserialization.\n */\n protected static async getRawData(params: {\n type: ApiRequestDataTypeInterface;\n method: HttpMethod;\n endpoint: string;\n companyId?: string;\n }): Promise<any> {\n const { JsonApiGet } = await import(\"../../unified/JsonApiRequest\");\n\n let language = \"en\";\n\n if (typeof window === \"undefined\") {\n const { getLocale } = await import(\"next-intl/server\");\n language = (await getLocale()) ?? \"en\";\n } else {\n // Client-side: extract locale from URL pathname\n language = this.getClientLocale();\n }\n\n const apiResponse: ApiResponseInterface = await JsonApiGet({\n classKey: params.type,\n endpoint: params.endpoint,\n companyId: params.companyId,\n language: language,\n });\n\n if (!apiResponse.ok) {\n if (globalErrorHandler && typeof window !== \"undefined\") {\n globalErrorHandler(apiResponse.response, apiResponse.error);\n return undefined as any;\n } else {\n const error = new Error(`${apiResponse.response}:${apiResponse.error}`) as any;\n error.status = apiResponse.response;\n error.digest = `HTTP_${apiResponse.response}`;\n throw error;\n }\n }\n\n return apiResponse.raw;\n }\n}\n","import { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { DataClassRegistry } from \"./DataClassRegistry\";\n\n/**\n * Helper class to bootstrap the registry from a Modules-style class.\n * This supports the pattern where modules are defined as static getters.\n */\nexport class ModuleRegistrar {\n private static _isBootstrapped = false;\n\n /**\n * Bootstrap the registry from a Modules class.\n * Automatically detects static getters and registers their models.\n *\n * @param modulesClass - The Modules class with static getters\n */\n static bootstrap<T extends object>(modulesClass: T): void {\n if (this._isBootstrapped) return;\n\n const data = Object.getOwnPropertyNames(modulesClass)\n .filter((key) => {\n const descriptor = Object.getOwnPropertyDescriptor(modulesClass, key);\n return descriptor && typeof descriptor.get === \"function\";\n })\n .map((key) => (modulesClass as any)[key] as ApiRequestDataTypeInterface);\n\n data.forEach((item) => {\n if (item && item.model) {\n DataClassRegistry.registerObjectClass(item, item.model);\n }\n });\n\n this._isBootstrapped = true;\n }\n\n /**\n * Reset the bootstrapped state. Useful for testing.\n */\n static reset(): void {\n this._isBootstrapped = false;\n DataClassRegistry.clear();\n }\n}\n","import { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { ModuleWithPermissions } from \"../../permissions/types\";\n\n// Foundation module types - defined by LIBRARY\nexport interface FoundationModuleDefinitions {\n S3: ModuleWithPermissions;\n Auth: ModuleWithPermissions;\n User: ModuleWithPermissions;\n Author: ModuleWithPermissions;\n Company: ModuleWithPermissions;\n Role: ModuleWithPermissions;\n Notification: ModuleWithPermissions;\n Push: ModuleWithPermissions;\n Feature: ModuleWithPermissions;\n Module: ModuleWithPermissions;\n Content: ModuleWithPermissions;\n UserTopic: ModuleWithPermissions;\n UserExpertise: ModuleWithPermissions;\n}\n\n// App-specific modules - apps will augment this interface ONLY\n\nexport interface AppModuleDefinitions {}\n\n// Combined type for full autocompletion\nexport type ModuleDefinitions = FoundationModuleDefinitions & AppModuleDefinitions;\n\nclass ModuleRegistryClass {\n private _modules: Map<string, ApiRequestDataTypeInterface> = new Map();\n\n register<K extends string>(name: K, module: ApiRequestDataTypeInterface): void {\n this._modules.set(name, module);\n }\n\n get<K extends keyof ModuleDefinitions>(name: K): ModuleDefinitions[K] {\n const module = this._modules.get(name as string);\n if (!module) {\n throw new Error(`Module \"${String(name)}\" not registered. Call bootstrap() first.`);\n }\n return module as ModuleDefinitions[K];\n }\n\n findByName(moduleName: string): ModuleWithPermissions {\n // Search by module's name property (e.g., \"topics\", \"articles\")\n for (const module of this._modules.values()) {\n if ((module as ModuleWithPermissions).name === moduleName) {\n return module as ModuleWithPermissions;\n }\n }\n throw new Error(`Module not found: ${moduleName}`);\n }\n}\n\nexport const ModuleRegistry = new ModuleRegistryClass();\n\n// Proxy object for Modules.X syntax with autocompletion\nexport const Modules = new Proxy({} as ModuleDefinitions, {\n get(_, prop: string) {\n if (prop === \"findByName\") {\n return (name: string) => ModuleRegistry.findByName(name);\n }\n return ModuleRegistry.get(prop as keyof ModuleDefinitions);\n },\n}) as ModuleDefinitions & { findByName: (name: string) => ModuleWithPermissions };\n","import { FieldSelector } from \"../fields/FieldSelector\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\n\nexport type EndpointQuery = {\n endpoint: ApiRequestDataTypeInterface;\n id?: string;\n childEndpoint?: ApiRequestDataTypeInterface | string;\n childId?: string;\n additionalParams?: { key: string; value: string | string[] }[];\n};\n\nexport class EndpointCreator {\n private _endpoint: EndpointQuery;\n\n constructor(params: {\n endpoint: ApiRequestDataTypeInterface;\n id?: string;\n childEndpoint?: ApiRequestDataTypeInterface | string;\n childId?: string;\n additionalParams?: { key: string; value: string }[];\n }) {\n this._endpoint = {\n endpoint: params.endpoint,\n id: params.id,\n childEndpoint: params.childEndpoint,\n childId: params.childId,\n additionalParams: params.additionalParams ?? [],\n };\n }\n\n endpoint(value: ApiRequestDataTypeInterface): EndpointCreator {\n this._endpoint.endpoint = value;\n return this;\n }\n\n id(value: string): EndpointCreator {\n this._endpoint.id = value;\n return this;\n }\n\n childEndpoint(value: ApiRequestDataTypeInterface | string): EndpointCreator {\n this._endpoint.childEndpoint = value;\n return this;\n }\n\n childId(value: string): EndpointCreator {\n this._endpoint.childId = value;\n return this;\n }\n\n set additionalParams(value: { key: string; value: string }[]) {\n this._endpoint.additionalParams = value;\n }\n\n addAdditionalParam(key: string, value: string | string[]): EndpointCreator {\n if (!this._endpoint.additionalParams) this._endpoint.additionalParams = [];\n this._endpoint.additionalParams.push({ key, value });\n return this;\n }\n\n limitToType(selectors: string[]): this {\n this.addAdditionalParam(`include`, selectors.join(\",\"));\n return this;\n }\n\n limitToFields(selectors: FieldSelector<any>[]): this {\n if (selectors.length === 0) return this;\n\n selectors.forEach((selector) => {\n const fieldString = selector.fields.join(\",\");\n this.addAdditionalParam(`fields[${selector.type}]`, fieldString);\n });\n\n return this;\n }\n\n generate(): string {\n let additionalParams = \"\";\n if (this._endpoint.additionalParams) {\n additionalParams = this._endpoint.additionalParams.map((param) => `${param.key}=${param.value}`).join(\"&\");\n }\n\n let response = `${this._endpoint.endpoint.name}`;\n if (this._endpoint.id) response += `/${this._endpoint.id}`;\n if (this._endpoint.childEndpoint) {\n response += `/${\n typeof this._endpoint.childEndpoint === \"string\"\n ? this._endpoint.childEndpoint\n : this._endpoint.childEndpoint.name\n }`;\n }\n if (this._endpoint.childId) response += `/${this._endpoint.childId}`;\n if (additionalParams) response += `?${additionalParams}`;\n\n return response;\n }\n}\n","export type GetterKeys<T> = {\n [K in keyof T]: T[K] extends () => any ? never : K;\n}[keyof T];\n\nexport type FieldSelector<T> = {\n type: string;\n fields: ReadonlyArray<GetterKeys<T>>;\n};\n\nexport function createJsonApiInclusion<T>(dataType: string, fields: ReadonlyArray<GetterKeys<T>>): FieldSelector<T> {\n return {\n type: dataType,\n fields,\n };\n}\n","import { ApiDataInterface } from \"../interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { JsonApiHydratedDataInterface } from \"../interfaces/JsonApiHydratedDataInterface\";\nimport { RehydrationFactory } from \"../factories/RehydrationFactory\";\n\n/**\n * Rehydrate a single dehydrated object back into its typed class instance.\n */\nexport function rehydrate<T extends ApiDataInterface>(\n classKey: ApiRequestDataTypeInterface,\n data: JsonApiHydratedDataInterface,\n): T {\n return RehydrationFactory.rehydrate(classKey, data) as T;\n}\n\n/**\n * Rehydrate a list of dehydrated objects back into typed class instances.\n */\nexport function rehydrateList<T extends ApiDataInterface>(\n classKey: ApiRequestDataTypeInterface,\n data: JsonApiHydratedDataInterface[],\n): T[] {\n return RehydrationFactory.rehydrateList(classKey, data) as T[];\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-I2REI7OA.js","../src/core/abstracts/AbstractApiData.ts","../src/core/abstracts/AbstractService.ts","../src/core/registry/ModuleRegistrar.ts","../src/core/registry/ModuleRegistry.ts","../src/core/endpoint/EndpointCreator.ts","../src/core/fields/FieldSelector.ts","../src/core/utils/rehydrate.ts"],"names":["includedData","HttpMethod"],"mappings":"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","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-I2REI7OA.js","sourcesContent":[null,"import { ApiDataInterface } from \"../interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { JsonApiHydratedDataInterface } from \"../interfaces/JsonApiHydratedDataInterface\";\nimport { RehydrationFactory } from \"../factories/RehydrationFactory\";\n\nexport abstract class AbstractApiData implements ApiDataInterface {\n protected _jsonApi?: any;\n protected _included?: any[];\n\n protected _id?: string;\n protected _type?: string;\n protected _createdAt?: Date;\n protected _updatedAt?: Date;\n\n protected _self?: string;\n\n get type(): string {\n if (!this._type) throw new Error(\"Type is not set.\");\n return this._type;\n }\n\n get id(): string {\n if (!this._id) throw new Error(\"Id is not set.\");\n return this._id;\n }\n\n get self(): string | undefined {\n return this._self;\n }\n\n get createdAt(): Date {\n return this._createdAt ?? new Date();\n }\n\n get updatedAt(): Date {\n return this._updatedAt ?? new Date();\n }\n\n get included(): any[] {\n return this._included ?? [];\n }\n\n get jsonApi(): any {\n return this._jsonApi;\n }\n\n ingestJsonApi(_data: JsonApiHydratedDataInterface): void {}\n\n generateApiUrl(_params?: any): string {\n throw new Error(\"Method not implemented.\");\n }\n\n createJsonApi(_data?: any): any {\n throw new Error(\"Method not implemented.\");\n }\n\n protected _readIncluded<T extends ApiDataInterface>(\n data: JsonApiHydratedDataInterface,\n type: string,\n dataType: ApiRequestDataTypeInterface,\n ): T | T[] | undefined {\n if (\n data.included === undefined ||\n data.included.length === 0 ||\n data.jsonApi.relationships === undefined ||\n data.jsonApi.relationships[type] === undefined ||\n data.jsonApi.relationships[type].data === undefined\n ) {\n return undefined;\n }\n\n if (Array.isArray(data.jsonApi.relationships[type].data)) {\n const response: T[] = data.jsonApi.relationships[type].data.map((jsonApiData: any) => {\n const includedData = data.included.find(\n (includedData: any) => includedData.id === jsonApiData.id && includedData.type === jsonApiData.type,\n );\n\n if (includedData === undefined) return undefined;\n\n return RehydrationFactory.rehydrate(dataType, {\n jsonApi: includedData,\n included: data.included,\n }) as T;\n });\n\n return response.filter((item: T | undefined) => item !== undefined) as T[];\n }\n\n const includedData = data.included.find(\n (includedData: any) =>\n includedData.id === data.jsonApi.relationships[type].data.id &&\n includedData.type === data.jsonApi.relationships[type].data.type,\n );\n\n if (includedData === undefined && data.allData !== undefined) {\n // Try to find in allData as a fallback\n const fallbackData = data.allData.find(\n (includedData: any) =>\n includedData.id === data.jsonApi.relationships[type].data.id &&\n includedData.type === data.jsonApi.relationships[type].data.type,\n );\n if (fallbackData !== undefined) {\n return RehydrationFactory.rehydrate(dataType, {\n jsonApi: fallbackData,\n included: data.included,\n }) as T;\n }\n }\n\n if (includedData === undefined) return undefined;\n\n return RehydrationFactory.rehydrate(dataType, {\n jsonApi: includedData,\n included: data.included,\n }) as T;\n }\n\n dehydrate(): JsonApiHydratedDataInterface {\n return {\n jsonApi: this._jsonApi,\n included: this._included ?? [],\n };\n }\n\n rehydrate(data: JsonApiHydratedDataInterface): this {\n this._jsonApi = data.jsonApi;\n this._included = data.included;\n\n this._type = this._jsonApi.type;\n this._id = this._jsonApi.id;\n this._createdAt = this._jsonApi.meta?.createdAt !== undefined ? new Date(this._jsonApi.meta.createdAt) : undefined;\n this._updatedAt = this._jsonApi.meta?.updatedAt !== undefined ? new Date(this._jsonApi.meta.updatedAt) : undefined;\n\n this._self = this._jsonApi.links?.self ?? undefined;\n\n return this;\n }\n}\n","import { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { ApiResponseInterface } from \"../interfaces/ApiResponseInterface\";\n\nexport enum HttpMethod {\n GET = \"GET\",\n POST = \"POST\",\n PUT = \"PUT\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n}\n\nexport interface NextRef {\n next?: string;\n}\n\nexport interface PreviousRef {\n previous?: string;\n}\n\nexport interface SelfRef {\n self?: string;\n}\n\nlet globalErrorHandler: ((status: number, message: string) => void) | null = null;\n\n/**\n * Set a global error handler for API errors (client-side only).\n * This handler will be called instead of throwing errors.\n */\nexport function setGlobalErrorHandler(handler: (status: number, message: string) => void) {\n globalErrorHandler = handler;\n}\n\n/**\n * Get the current global error handler.\n */\nexport function getGlobalErrorHandler(): ((status: number, message: string) => void) | null {\n return globalErrorHandler;\n}\n\n/**\n * Abstract base class for services that interact with the JSON:API.\n * Extend this class to create feature-specific services.\n */\nexport abstract class AbstractService {\n /**\n * Extract locale from client-side URL pathname\n * URL structure: /{locale}/route-path (e.g., /it/accounts)\n * Fallback chain: URL locale → navigator.language → \"en\"\n */\n private static getClientLocale(): string {\n if (typeof window === \"undefined\") {\n return \"en\"; // Server-side fallback\n }\n\n // Extract locale from URL pathname (first segment after leading slash)\n const pathSegments = window.location.pathname.split(\"/\").filter(Boolean);\n const urlLocale = pathSegments[0];\n\n // Validate against supported locales (currently only \"en\")\n const supportedLocales = [\"en\"];\n if (urlLocale && supportedLocales.includes(urlLocale)) {\n return urlLocale;\n }\n\n // Fallback to navigator language\n const navigatorLocale = navigator.language.split(\"-\")[0];\n if (navigatorLocale && supportedLocales.includes(navigatorLocale)) {\n return navigatorLocale;\n }\n\n // Final fallback\n return \"en\";\n }\n\n static async next<T>(params: {\n type: ApiRequestDataTypeInterface;\n endpoint: string;\n next?: NextRef;\n previous?: PreviousRef;\n self?: SelfRef;\n }): Promise<T> {\n return await this.callApi<T>({\n method: HttpMethod.GET,\n type: params.type,\n endpoint: params.endpoint,\n next: params.next,\n previous: params.previous,\n self: params.self,\n });\n }\n\n /**\n * Fetch the previous page of results.\n */\n static async previous<T>(params: {\n type: ApiRequestDataTypeInterface;\n endpoint: string;\n next?: NextRef;\n previous?: PreviousRef;\n self?: SelfRef;\n }): Promise<T> {\n return await this.callApi<T>({\n method: HttpMethod.GET,\n type: params.type,\n endpoint: params.endpoint,\n next: params.next,\n previous: params.previous,\n self: params.self,\n });\n }\n\n /**\n * Make an API call with automatic environment detection and error handling.\n */\n protected static async callApi<T>(params: {\n type: ApiRequestDataTypeInterface;\n method: HttpMethod;\n endpoint: string;\n companyId?: string;\n input?: any;\n overridesJsonApiCreation?: boolean;\n next?: NextRef;\n previous?: PreviousRef;\n self?: SelfRef;\n responseType?: ApiRequestDataTypeInterface;\n files?: { [key: string]: File | Blob } | File | Blob;\n }): Promise<T> {\n // Dynamic import to avoid bundling issues\n const { JsonApiGet, JsonApiPost, JsonApiPut, JsonApiPatch, JsonApiDelete } =\n await import(\"../../unified/JsonApiRequest\");\n\n let apiResponse: ApiResponseInterface;\n\n // Get language based on environment\n let language = \"en\";\n if (typeof window === \"undefined\") {\n const { getLocale } = await import(\"next-intl/server\");\n language = (await getLocale()) ?? \"en\";\n } else {\n // Client-side: extract locale from URL pathname\n language = this.getClientLocale();\n }\n\n switch (params.method) {\n case HttpMethod.GET:\n apiResponse = await JsonApiGet({\n classKey: params.type,\n endpoint: params.endpoint,\n companyId: params.companyId,\n language: language,\n });\n break;\n case HttpMethod.POST:\n apiResponse = await JsonApiPost({\n classKey: params.type,\n endpoint: params.endpoint,\n companyId: params.companyId,\n body: params.input,\n overridesJsonApiCreation: params.overridesJsonApiCreation,\n language: language,\n responseType: params.responseType,\n files: params.files,\n });\n break;\n case HttpMethod.PUT:\n apiResponse = await JsonApiPut({\n classKey: params.type,\n endpoint: params.endpoint,\n companyId: params.companyId,\n body: params.input,\n language: language,\n responseType: params.responseType,\n files: params.files,\n });\n break;\n case HttpMethod.PATCH:\n apiResponse = await JsonApiPatch({\n classKey: params.type,\n endpoint: params.endpoint,\n companyId: params.companyId,\n body: params.input,\n overridesJsonApiCreation: params.overridesJsonApiCreation,\n language: language,\n responseType: params.responseType,\n files: params.files,\n });\n break;\n case HttpMethod.DELETE:\n apiResponse = await JsonApiDelete({\n classKey: params.type,\n endpoint: params.endpoint,\n companyId: params.companyId,\n language: language,\n responseType: params.responseType,\n });\n break;\n default:\n throw new Error(\"Method not found\");\n }\n\n if (!apiResponse.ok) {\n if (globalErrorHandler && typeof window !== \"undefined\") {\n globalErrorHandler(apiResponse.response, apiResponse.error);\n return undefined as any;\n } else {\n const error = new Error(`${apiResponse.response}:${apiResponse.error}`) as any;\n error.status = apiResponse.response;\n error.digest = `HTTP_${apiResponse.response}`;\n throw error;\n }\n }\n\n if (apiResponse.next && params.next) params.next.next = apiResponse.next;\n if (apiResponse.prev && params.previous) params.previous.previous = apiResponse.prev;\n if (apiResponse.self && params.self) params.self.self = apiResponse.self;\n\n return apiResponse.data as T;\n }\n\n /**\n * Get raw JSON:API response data without deserialization.\n */\n protected static async getRawData(params: {\n type: ApiRequestDataTypeInterface;\n method: HttpMethod;\n endpoint: string;\n companyId?: string;\n }): Promise<any> {\n const { JsonApiGet } = await import(\"../../unified/JsonApiRequest\");\n\n let language = \"en\";\n\n if (typeof window === \"undefined\") {\n const { getLocale } = await import(\"next-intl/server\");\n language = (await getLocale()) ?? \"en\";\n } else {\n // Client-side: extract locale from URL pathname\n language = this.getClientLocale();\n }\n\n const apiResponse: ApiResponseInterface = await JsonApiGet({\n classKey: params.type,\n endpoint: params.endpoint,\n companyId: params.companyId,\n language: language,\n });\n\n if (!apiResponse.ok) {\n if (globalErrorHandler && typeof window !== \"undefined\") {\n globalErrorHandler(apiResponse.response, apiResponse.error);\n return undefined as any;\n } else {\n const error = new Error(`${apiResponse.response}:${apiResponse.error}`) as any;\n error.status = apiResponse.response;\n error.digest = `HTTP_${apiResponse.response}`;\n throw error;\n }\n }\n\n return apiResponse.raw;\n }\n}\n","import { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { DataClassRegistry } from \"./DataClassRegistry\";\n\n/**\n * Helper class to bootstrap the registry from a Modules-style class.\n * This supports the pattern where modules are defined as static getters.\n */\nexport class ModuleRegistrar {\n private static _isBootstrapped = false;\n\n /**\n * Bootstrap the registry from a Modules class.\n * Automatically detects static getters and registers their models.\n *\n * @param modulesClass - The Modules class with static getters\n */\n static bootstrap<T extends object>(modulesClass: T): void {\n if (this._isBootstrapped) return;\n\n const data = Object.getOwnPropertyNames(modulesClass)\n .filter((key) => {\n const descriptor = Object.getOwnPropertyDescriptor(modulesClass, key);\n return descriptor && typeof descriptor.get === \"function\";\n })\n .map((key) => (modulesClass as any)[key] as ApiRequestDataTypeInterface);\n\n data.forEach((item) => {\n if (item && item.model) {\n DataClassRegistry.registerObjectClass(item, item.model);\n }\n });\n\n this._isBootstrapped = true;\n }\n\n /**\n * Reset the bootstrapped state. Useful for testing.\n */\n static reset(): void {\n this._isBootstrapped = false;\n DataClassRegistry.clear();\n }\n}\n","import { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { ModuleWithPermissions } from \"../../permissions/types\";\n\n// Foundation module types - defined by LIBRARY\nexport interface FoundationModuleDefinitions {\n S3: ModuleWithPermissions;\n Auth: ModuleWithPermissions;\n User: ModuleWithPermissions;\n Author: ModuleWithPermissions;\n Company: ModuleWithPermissions;\n Role: ModuleWithPermissions;\n Notification: ModuleWithPermissions;\n Push: ModuleWithPermissions;\n Feature: ModuleWithPermissions;\n Module: ModuleWithPermissions;\n Content: ModuleWithPermissions;\n UserTopic: ModuleWithPermissions;\n UserExpertise: ModuleWithPermissions;\n}\n\n// App-specific modules - apps will augment this interface ONLY\n\nexport interface AppModuleDefinitions {}\n\n// Combined type for full autocompletion\nexport type ModuleDefinitions = FoundationModuleDefinitions & AppModuleDefinitions;\n\nclass ModuleRegistryClass {\n private _modules: Map<string, ApiRequestDataTypeInterface> = new Map();\n\n register<K extends string>(name: K, module: ApiRequestDataTypeInterface): void {\n this._modules.set(name, module);\n }\n\n get<K extends keyof ModuleDefinitions>(name: K): ModuleDefinitions[K] {\n const module = this._modules.get(name as string);\n if (!module) {\n throw new Error(`Module \"${String(name)}\" not registered. Call bootstrap() first.`);\n }\n return module as ModuleDefinitions[K];\n }\n\n findByName(moduleName: string): ModuleWithPermissions {\n // Search by module's name property (e.g., \"topics\", \"articles\")\n for (const module of this._modules.values()) {\n if ((module as ModuleWithPermissions).name === moduleName) {\n return module as ModuleWithPermissions;\n }\n }\n throw new Error(`Module not found: ${moduleName}`);\n }\n}\n\nexport const ModuleRegistry = new ModuleRegistryClass();\n\n// Proxy object for Modules.X syntax with autocompletion\nexport const Modules = new Proxy({} as ModuleDefinitions, {\n get(_, prop: string) {\n if (prop === \"findByName\") {\n return (name: string) => ModuleRegistry.findByName(name);\n }\n return ModuleRegistry.get(prop as keyof ModuleDefinitions);\n },\n}) as ModuleDefinitions & { findByName: (name: string) => ModuleWithPermissions };\n","import { FieldSelector } from \"../fields/FieldSelector\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\n\nexport type EndpointQuery = {\n endpoint: ApiRequestDataTypeInterface;\n id?: string;\n childEndpoint?: ApiRequestDataTypeInterface | string;\n childId?: string;\n additionalParams?: { key: string; value: string | string[] }[];\n};\n\nexport class EndpointCreator {\n private _endpoint: EndpointQuery;\n\n constructor(params: {\n endpoint: ApiRequestDataTypeInterface;\n id?: string;\n childEndpoint?: ApiRequestDataTypeInterface | string;\n childId?: string;\n additionalParams?: { key: string; value: string }[];\n }) {\n this._endpoint = {\n endpoint: params.endpoint,\n id: params.id,\n childEndpoint: params.childEndpoint,\n childId: params.childId,\n additionalParams: params.additionalParams ?? [],\n };\n }\n\n endpoint(value: ApiRequestDataTypeInterface): EndpointCreator {\n this._endpoint.endpoint = value;\n return this;\n }\n\n id(value: string): EndpointCreator {\n this._endpoint.id = value;\n return this;\n }\n\n childEndpoint(value: ApiRequestDataTypeInterface | string): EndpointCreator {\n this._endpoint.childEndpoint = value;\n return this;\n }\n\n childId(value: string): EndpointCreator {\n this._endpoint.childId = value;\n return this;\n }\n\n set additionalParams(value: { key: string; value: string }[]) {\n this._endpoint.additionalParams = value;\n }\n\n addAdditionalParam(key: string, value: string | string[]): EndpointCreator {\n if (!this._endpoint.additionalParams) this._endpoint.additionalParams = [];\n this._endpoint.additionalParams.push({ key, value });\n return this;\n }\n\n limitToType(selectors: string[]): this {\n this.addAdditionalParam(`include`, selectors.join(\",\"));\n return this;\n }\n\n limitToFields(selectors: FieldSelector<any>[]): this {\n if (selectors.length === 0) return this;\n\n selectors.forEach((selector) => {\n const fieldString = selector.fields.join(\",\");\n this.addAdditionalParam(`fields[${selector.type}]`, fieldString);\n });\n\n return this;\n }\n\n generate(): string {\n let additionalParams = \"\";\n if (this._endpoint.additionalParams) {\n additionalParams = this._endpoint.additionalParams.map((param) => `${param.key}=${param.value}`).join(\"&\");\n }\n\n let response = `${this._endpoint.endpoint.name}`;\n if (this._endpoint.id) response += `/${this._endpoint.id}`;\n if (this._endpoint.childEndpoint) {\n response += `/${\n typeof this._endpoint.childEndpoint === \"string\"\n ? this._endpoint.childEndpoint\n : this._endpoint.childEndpoint.name\n }`;\n }\n if (this._endpoint.childId) response += `/${this._endpoint.childId}`;\n if (additionalParams) response += `?${additionalParams}`;\n\n return response;\n }\n}\n","export type GetterKeys<T> = {\n [K in keyof T]: T[K] extends () => any ? never : K;\n}[keyof T];\n\nexport type FieldSelector<T> = {\n type: string;\n fields: ReadonlyArray<GetterKeys<T>>;\n};\n\nexport function createJsonApiInclusion<T>(dataType: string, fields: ReadonlyArray<GetterKeys<T>>): FieldSelector<T> {\n return {\n type: dataType,\n fields,\n };\n}\n","import { ApiDataInterface } from \"../interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { JsonApiHydratedDataInterface } from \"../interfaces/JsonApiHydratedDataInterface\";\nimport { RehydrationFactory } from \"../factories/RehydrationFactory\";\n\n/**\n * Rehydrate a single dehydrated object back into its typed class instance.\n */\nexport function rehydrate<T extends ApiDataInterface>(\n classKey: ApiRequestDataTypeInterface,\n data: JsonApiHydratedDataInterface,\n): T {\n return RehydrationFactory.rehydrate(classKey, data) as T;\n}\n\n/**\n * Rehydrate a list of dehydrated objects back into typed class instances.\n */\nexport function rehydrateList<T extends ApiDataInterface>(\n classKey: ApiRequestDataTypeInterface,\n data: JsonApiHydratedDataInterface[],\n): T[] {\n return RehydrationFactory.rehydrateList(classKey, data) as T[];\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-IBS6NI7D.js","../src/client/request.ts"],"names":[],"mappings":"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","file":"/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-IBS6NI7D.js","sourcesContent":[null,"\"use client\";\n\nimport { ApiData } from \"../core/interfaces/ApiData\";\n\nexport interface DirectFetchParams {\n method: string;\n url: string;\n token?: string;\n body?: any;\n files?: { [key: string]: File | Blob } | File | Blob;\n companyId?: string;\n language: string;\n additionalHeaders?: Record<string, string>;\n}\n\n/**\n * Client-side direct fetch to bypass server action overhead.\n * Use this for client-side API calls.\n */\nexport async function directFetch(params: DirectFetchParams): Promise<ApiData> {\n const response: ApiData = {\n data: undefined,\n ok: false,\n status: 0,\n statusText: \"\",\n };\n\n const additionalHeaders: Record<string, string> = { ...params.additionalHeaders };\n\n if (params.companyId) {\n additionalHeaders[\"x-companyid\"] = params.companyId;\n }\n additionalHeaders[\"x-language\"] = params.language;\n\n let requestBody: BodyInit | undefined = undefined;\n\n if (params.files) {\n const formData = new FormData();\n if (params.body && typeof params.body === \"object\") {\n for (const key in params.body) {\n if (Object.prototype.hasOwnProperty.call(params.body, key)) {\n formData.append(\n key,\n typeof params.body[key] === \"object\" ? JSON.stringify(params.body[key]) : params.body[key],\n );\n }\n }\n }\n\n if (params.files instanceof Blob) {\n formData.append(\"file\", params.files);\n } else if (typeof params.files === \"object\" && params.files !== null) {\n for (const key in params.files) {\n if (Object.prototype.hasOwnProperty.call(params.files, key)) {\n formData.append(key, params.files[key]);\n }\n }\n }\n\n requestBody = formData;\n } else if (params.body !== undefined) {\n requestBody = JSON.stringify(params.body);\n additionalHeaders[\"Content-Type\"] = \"application/json\";\n }\n\n const options: RequestInit = {\n method: params.method,\n headers: { Accept: \"application/json\", ...additionalHeaders },\n };\n\n if (requestBody !== undefined) {\n options.body = requestBody;\n }\n\n if (params.token) {\n options.headers = { ...options.headers, Authorization: `Bearer ${params.token}` };\n }\n\n try {\n const apiResponse = await fetch(params.url, options);\n\n response.ok = apiResponse.ok;\n response.status = apiResponse.status;\n response.statusText = apiResponse.statusText;\n try {\n response.data = await apiResponse.json();\n } catch {\n response.data = undefined;\n }\n } catch {\n response.ok = false;\n response.status = 500;\n response.data = undefined;\n }\n\n return response;\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-IBS6NI7D.js","../src/client/request.ts"],"names":[],"mappings":"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","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-IBS6NI7D.js","sourcesContent":[null,"\"use client\";\n\nimport { ApiData } from \"../core/interfaces/ApiData\";\n\nexport interface DirectFetchParams {\n method: string;\n url: string;\n token?: string;\n body?: any;\n files?: { [key: string]: File | Blob } | File | Blob;\n companyId?: string;\n language: string;\n additionalHeaders?: Record<string, string>;\n}\n\n/**\n * Client-side direct fetch to bypass server action overhead.\n * Use this for client-side API calls.\n */\nexport async function directFetch(params: DirectFetchParams): Promise<ApiData> {\n const response: ApiData = {\n data: undefined,\n ok: false,\n status: 0,\n statusText: \"\",\n };\n\n const additionalHeaders: Record<string, string> = { ...params.additionalHeaders };\n\n if (params.companyId) {\n additionalHeaders[\"x-companyid\"] = params.companyId;\n }\n additionalHeaders[\"x-language\"] = params.language;\n\n let requestBody: BodyInit | undefined = undefined;\n\n if (params.files) {\n const formData = new FormData();\n if (params.body && typeof params.body === \"object\") {\n for (const key in params.body) {\n if (Object.prototype.hasOwnProperty.call(params.body, key)) {\n formData.append(\n key,\n typeof params.body[key] === \"object\" ? JSON.stringify(params.body[key]) : params.body[key],\n );\n }\n }\n }\n\n if (params.files instanceof Blob) {\n formData.append(\"file\", params.files);\n } else if (typeof params.files === \"object\" && params.files !== null) {\n for (const key in params.files) {\n if (Object.prototype.hasOwnProperty.call(params.files, key)) {\n formData.append(key, params.files[key]);\n }\n }\n }\n\n requestBody = formData;\n } else if (params.body !== undefined) {\n requestBody = JSON.stringify(params.body);\n additionalHeaders[\"Content-Type\"] = \"application/json\";\n }\n\n const options: RequestInit = {\n method: params.method,\n headers: { Accept: \"application/json\", ...additionalHeaders },\n };\n\n if (requestBody !== undefined) {\n options.body = requestBody;\n }\n\n if (params.token) {\n options.headers = { ...options.headers, Authorization: `Bearer ${params.token}` };\n }\n\n try {\n const apiResponse = await fetch(params.url, options);\n\n response.ok = apiResponse.ok;\n response.status = apiResponse.status;\n response.statusText = apiResponse.statusText;\n try {\n response.data = await apiResponse.json();\n } catch {\n response.data = undefined;\n }\n } catch {\n response.ok = false;\n response.status = 500;\n response.data = undefined;\n }\n\n return response;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-J4Q36PMP.js","../src/core/factories/RehydrationFactory.ts"],"names":[],"mappings":"AAAA;AACE;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACA;ACFO,IAAM,mBAAA,EAAN,MAAyB;AAAA,EALhC,OAKgC;AAAA,IAAA,qCAAA,IAAA,EAAA,oBAAA,CAAA;AAAA,EAAA;AAAA,EAC9B,OAAc,SAAA,CACZ,QAAA,EACA,IAAA,EACG;AACH,IAAA,MAAM,aAAA,EAAe,kCAAA,CAAkB,GAAA,CAAI,QAAQ,CAAA;AAEnD,IAAA,MAAM,SAAA,EAAW,IAAI,YAAA,CAAa,CAAA;AAClC,IAAA,OAAO,QAAA,CAAS,SAAA,CAAU,IAAI,CAAA;AAAA,EAChC;AAAA,EAEA,OAAc,aAAA,CACZ,QAAA,EACA,IAAA,EACK;AACL,IAAA,MAAM,aAAA,EAAe,kCAAA,CAAkB,GAAA,CAAI,QAAQ,CAAA;AAEnD,IAAA,MAAM,SAAA,EAAW,IAAA,CAAK,GAAA,CAAI,CAAC,IAAA,EAAA,GAAuC;AAChE,MAAA,MAAM,SAAA,EAAW,IAAI,YAAA,CAAa,CAAA;AAClC,MAAA,OAAO,QAAA,CAAS,SAAA,CAAU,IAAI,CAAA;AAAA,IAChC,CAAC,CAAA;AAED,IAAA,OAAO,QAAA;AAAA,EACT;AACF,CAAA;ADHA;AACA;AACE;AACF,gDAAC","file":"/Users/carlo/Development/phlow2/packages/nextjs-jsonapi/dist/chunk-J4Q36PMP.js","sourcesContent":[null,"import { ApiDataInterface } from \"../interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { JsonApiHydratedDataInterface } from \"../interfaces/JsonApiHydratedDataInterface\";\nimport { DataClassRegistry } from \"../registry/DataClassRegistry\";\n\nexport class RehydrationFactory {\n public static rehydrate<T extends ApiDataInterface>(\n classKey: ApiRequestDataTypeInterface,\n data: JsonApiHydratedDataInterface,\n ): T {\n const factoryClass = DataClassRegistry.get(classKey);\n\n const instance = new factoryClass();\n return instance.rehydrate(data) as T;\n }\n\n public static rehydrateList<T extends ApiDataInterface>(\n classKey: ApiRequestDataTypeInterface,\n data: JsonApiHydratedDataInterface[],\n ): T[] {\n const factoryClass = DataClassRegistry.get(classKey);\n\n const response = data.map((item: JsonApiHydratedDataInterface) => {\n const instance = new factoryClass();\n return instance.rehydrate(item) as T;\n });\n\n return response;\n }\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-J4Q36PMP.js","../src/core/factories/RehydrationFactory.ts"],"names":[],"mappings":"AAAA;AACE;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACA;ACFO,IAAM,mBAAA,EAAN,MAAyB;AAAA,EALhC,OAKgC;AAAA,IAAA,qCAAA,IAAA,EAAA,oBAAA,CAAA;AAAA,EAAA;AAAA,EAC9B,OAAc,SAAA,CACZ,QAAA,EACA,IAAA,EACG;AACH,IAAA,MAAM,aAAA,EAAe,kCAAA,CAAkB,GAAA,CAAI,QAAQ,CAAA;AAEnD,IAAA,MAAM,SAAA,EAAW,IAAI,YAAA,CAAa,CAAA;AAClC,IAAA,OAAO,QAAA,CAAS,SAAA,CAAU,IAAI,CAAA;AAAA,EAChC;AAAA,EAEA,OAAc,aAAA,CACZ,QAAA,EACA,IAAA,EACK;AACL,IAAA,MAAM,aAAA,EAAe,kCAAA,CAAkB,GAAA,CAAI,QAAQ,CAAA;AAEnD,IAAA,MAAM,SAAA,EAAW,IAAA,CAAK,GAAA,CAAI,CAAC,IAAA,EAAA,GAAuC;AAChE,MAAA,MAAM,SAAA,EAAW,IAAI,YAAA,CAAa,CAAA;AAClC,MAAA,OAAO,QAAA,CAAS,SAAA,CAAU,IAAI,CAAA;AAAA,IAChC,CAAC,CAAA;AAED,IAAA,OAAO,QAAA;AAAA,EACT;AACF,CAAA;ADHA;AACA;AACE;AACF,gDAAC","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-J4Q36PMP.js","sourcesContent":[null,"import { ApiDataInterface } from \"../interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { JsonApiHydratedDataInterface } from \"../interfaces/JsonApiHydratedDataInterface\";\nimport { DataClassRegistry } from \"../registry/DataClassRegistry\";\n\nexport class RehydrationFactory {\n public static rehydrate<T extends ApiDataInterface>(\n classKey: ApiRequestDataTypeInterface,\n data: JsonApiHydratedDataInterface,\n ): T {\n const factoryClass = DataClassRegistry.get(classKey);\n\n const instance = new factoryClass();\n return instance.rehydrate(data) as T;\n }\n\n public static rehydrateList<T extends ApiDataInterface>(\n classKey: ApiRequestDataTypeInterface,\n data: JsonApiHydratedDataInterface[],\n ): T[] {\n const factoryClass = DataClassRegistry.get(classKey);\n\n const response = data.map((item: JsonApiHydratedDataInterface) => {\n const instance = new factoryClass();\n return instance.rehydrate(item) as T;\n });\n\n return response;\n }\n}\n"]}