@greatapps/common 1.1.779 → 1.1.780
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.
- package/dist/components/account/sections/PreferencesSection.mjs +3 -1
- package/dist/components/account/sections/PreferencesSection.mjs.map +1 -1
- package/dist/hooks/useDomMutationGuardHit.mjs +36 -0
- package/dist/hooks/useDomMutationGuardHit.mjs.map +1 -0
- package/dist/i18n/resolve-locale.mjs +10 -0
- package/dist/i18n/resolve-locale.mjs.map +1 -1
- package/dist/index.mjs +4 -0
- package/dist/index.mjs.map +1 -1
- package/dist/modules/auth/services/auth.service.mjs +12 -6
- package/dist/modules/auth/services/auth.service.mjs.map +1 -1
- package/dist/utils/dom/dom-mutation-guard.mjs +20 -0
- package/dist/utils/dom/dom-mutation-guard.mjs.map +1 -0
- package/dist/utils/intl/locales.mjs +6 -1
- package/dist/utils/intl/locales.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/account/sections/PreferencesSection.tsx +3 -2
- package/src/hooks/useDomMutationGuardHit.ts +55 -0
- package/src/i18n/resolve-locale.ts +19 -4
- package/src/index.ts +3 -0
- package/src/modules/auth/services/auth.service.ts +14 -6
- package/src/utils/dom/dom-mutation-guard.ts +46 -0
- package/src/utils/intl/locales.ts +7 -0
|
@@ -7,7 +7,9 @@ import { useRouter } from "next/navigation";
|
|
|
7
7
|
import { toast } from "sonner";
|
|
8
8
|
import { IconLock } from "@tabler/icons-react";
|
|
9
9
|
import { cn } from "../../../infra/utils/clsx";
|
|
10
|
+
import { isLocale } from "../../../i18n/config";
|
|
10
11
|
import { setLocaleCookie } from "../../../utils/intl/locale-cookie";
|
|
12
|
+
import { localeToApiLanguage } from "../../../utils/intl/locales";
|
|
11
13
|
import { Button } from "../../ui/buttons/Button";
|
|
12
14
|
import { Separator } from "../../ui/data-display/Separator";
|
|
13
15
|
import { Toast } from "../../ui/feedback/Toast";
|
|
@@ -86,7 +88,7 @@ function PreferencesSection({ onClose }) {
|
|
|
86
88
|
const doSave = async (data, accountFields) => {
|
|
87
89
|
setIsSaving(true);
|
|
88
90
|
try {
|
|
89
|
-
const apiLanguage =
|
|
91
|
+
const apiLanguage = isLocale(data.language) ? localeToApiLanguage(data.language) : data.language.toLowerCase();
|
|
90
92
|
await updateAccountUser.mutateAsync({
|
|
91
93
|
language: apiLanguage,
|
|
92
94
|
receive_sms: data.receive_sms,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/account/sections/PreferencesSection.tsx"],"sourcesContent":["'use client';\n\nimport { useState, useEffect } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { useTranslations, useLocale } from 'next-intl';\nimport { useRouter } from 'next/navigation';\nimport { toast } from 'sonner';\nimport { IconLock } from '@tabler/icons-react';\nimport { cn } from '../../../infra/utils/clsx';\nimport type { Locale } from '../../../i18n/config';\nimport { setLocaleCookie } from '../../../utils/intl/locale-cookie';\nimport { Button } from '../../ui/buttons/Button';\nimport { Separator } from '../../ui/data-display/Separator';\nimport { Toast } from '../../ui/feedback/Toast';\nimport { FormField } from '../../ui/form/FormField';\nimport { ComboboxField } from '../../ui/form/ComboboxField';\nimport { SelectField } from '../../ui/form/SelectField';\nimport ConfirmGlobalPreferencesModal from '../ConfirmGlobalPreferencesModal';\nimport { useAuth } from '../../../providers/auth.provider';\nimport { useWhitelabel } from '../../../providers/whitelabel.provider';\nimport { UserProfile } from '../../../modules/users/schema';\nimport type { UpdateAccountRequest } from '../../../modules/accounts/types';\nimport {\n useUpdateAccountUser,\n useUpdateAccount,\n} from '../../../modules/accounts/hooks/useAccountManagement';\nimport {\n LANGUAGE_OPTIONS,\n TIME_FORMAT_OPTIONS,\n} from '../constants';\nimport { useTimezones } from '../../../modules/accounts/hooks/useTimezones';\nimport { useCurrencies } from '../../../modules/accounts/hooks/useCurrencies';\nimport { getCurrencyForGateway } from '../../../utils/format/currency';\n\ninterface PreferencesFormValues {\n companyName: string;\n language: string;\n currency: string;\n timezone: string;\n timeFormat: string;\n receive_sms: boolean;\n receive_email: boolean;\n}\n\ninterface PreferencesSectionProps {\n onClose: () => void;\n}\n\nexport function PreferencesSection({ onClose }: PreferencesSectionProps) {\n // Padrão raiz: um único `translate` chamado pela chave inteira (`common.<modulo>.<chave>`).\n const translate = useTranslations();\n // Exceção: chave dinâmica (option.value) numa lista → namespace escopado.\n const translateLanguage = useTranslations('common.languages');\n const currentLocale = useLocale();\n const router = useRouter();\n const { data: timezones = [] } = useTimezones();\n const { data: currencies = [] } = useCurrencies();\n const { user, account } = useAuth();\n const { whitelabel } = useWhitelabel();\n const languageOptions = LANGUAGE_OPTIONS.map((option) => ({\n ...option,\n label: translateLanguage(option.value as Locale),\n displayValue: translateLanguage(option.value as Locale),\n }));\n const timeFormatOptions = TIME_FORMAT_OPTIONS.map((option) => ({\n ...option,\n label: translate(\n `common.preferences.timeFormatOptions.${option.value === '24h' ? 'h24' : 'h12'}`,\n ),\n }));\n const isOwner = user?.profile === UserProfile.owner;\n const canEditPreferences = isOwner || user?.profile === UserProfile.admin;\n const updateAccountUser = useUpdateAccountUser();\n const updateAccount = useUpdateAccount();\n const [confirmGlobalOpen, setConfirmGlobalOpen] = useState(false);\n const [pendingSubmit, setPendingSubmit] = useState<{\n data: PreferencesFormValues;\n accountFields: UpdateAccountRequest;\n } | null>(null);\n const [isSaving, setIsSaving] = useState(false);\n\n const { watch, setValue, handleSubmit, reset, formState: { dirtyFields } } =\n useForm<PreferencesFormValues>({\n defaultValues: {\n companyName: '',\n language: '',\n currency: '',\n timezone: '',\n timeFormat: '24h',\n receive_sms: false,\n receive_email: false,\n },\n });\n\n useEffect(() => {\n if (!user || !account) return;\n reset({\n companyName: account.name ?? '',\n language: LANGUAGE_OPTIONS.find(\n (o) => o.apiValue === user.language?.toLowerCase()\n )?.value ?? 'pt-br',\n // A moeda é derivada do gateway da conta (read-only para o usuário) —\n // espelha o que useCurrencyFormatter usa no display de preços.\n currency: getCurrencyForGateway(account.gateway).toUpperCase(),\n timezone: account.timezone,\n timeFormat: '24h',\n receive_sms: user.receive_sms ?? false,\n receive_email: user.receive_email ?? false,\n });\n }, [user, account, reset]);\n\n const doSave = async (data: PreferencesFormValues, accountFields: UpdateAccountRequest) => {\n setIsSaving(true);\n try {\n const apiLanguage = LANGUAGE_OPTIONS.find((o) => o.value === data.language)?.apiValue ?? data.language.toLowerCase();\n await updateAccountUser.mutateAsync({\n language: apiLanguage,\n receive_sms: data.receive_sms,\n receive_email: data.receive_email,\n });\n\n if (canEditPreferences && Object.keys(accountFields).length > 0) {\n await updateAccount.mutateAsync(accountFields);\n }\n\n reset(data);\n toast.custom((toastId) => (\n <Toast variant=\"success\" message={translate('common.preferences.savedSuccess')} toastId={toastId} />\n ));\n onClose();\n if (data.language !== currentLocale) {\n setLocaleCookie(data.language, whitelabel?.domain);\n router.refresh();\n }\n } catch (error) {\n toast.custom((toastId) => (\n <Toast\n variant=\"error\"\n message={error instanceof Error ? error.message : translate('common.preferences.saveError')}\n toastId={toastId}\n />\n ));\n } finally {\n setIsSaving(false);\n }\n };\n\n const onSubmit = (data: PreferencesFormValues) => {\n const accountFields: UpdateAccountRequest = {\n ...(isOwner && dirtyFields.companyName && { name: data.companyName }),\n // currency é read-only (derivada do gateway) — não enviada no update.\n ...(canEditPreferences && dirtyFields.timezone && { timezone: data.timezone }),\n };\n const globalFieldChanged = Object.keys(accountFields).length > 0;\n\n if (globalFieldChanged) {\n setPendingSubmit({ data, accountFields });\n setConfirmGlobalOpen(true);\n } else {\n doSave(data, accountFields);\n }\n };\n\n const handleConfirmGlobal = () => {\n setConfirmGlobalOpen(false);\n if (pendingSubmit) {\n doSave(pendingSubmit.data, pendingSubmit.accountFields);\n setPendingSubmit(null);\n }\n };\n\n const handleCancelGlobal = () => {\n setConfirmGlobalOpen(false);\n setPendingSubmit(null);\n };\n\n return (\n <>\n <form onSubmit={handleSubmit(onSubmit)} className=\"flex flex-col h-full\">\n <div className=\"overflow-y-auto overscroll-contain px-4 pb-4 lg:p-5 flex flex-col gap-5 lg:gap-6 flex-1\">\n <span className=\"paragraph-medium-semibold text-gray-950\">{translate('common.preferences.title')}</span>\n <div className=\"flex flex-col gap-8\">\n <div className=\"flex flex-col lg:flex-row items-center gap-3\">\n <FormField\n label={translate('common.preferences.companyName')}\n placeholder={translate('common.preferences.companyNamePlaceholder')}\n classnameContainer={cn('w-full', !isOwner && 'cursor-not-allowed opacity-50')}\n value={watch('companyName')}\n onChange={(e) => setValue('companyName', e.target.value, { shouldDirty: true })}\n disabled={!isOwner}\n />\n </div>\n\n <div className=\"flex flex-col lg:flex-row items-center gap-3\">\n <ComboboxField\n label={translate('common.preferences.language')}\n placeholder={translate('common.preferences.languagePlaceholder')}\n searchPlaceholder={translate('common.preferences.languageSearch')}\n containerClassName=\"w-full\"\n options={languageOptions}\n value={watch('language')}\n onChange={(value) => setValue('language', value, { shouldDirty: true })}\n />\n <ComboboxField\n label={translate('common.preferences.currency')}\n placeholder={translate('common.preferences.currencyPlaceholder')}\n searchPlaceholder={translate('common.preferences.currencySearch')}\n containerClassName=\"w-full\"\n options={currencies}\n value={watch('currency')}\n onChange={() => undefined}\n icon={<IconLock className=\"size-4 text-gray-400\" />}\n disabled\n />\n </div>\n\n <Separator />\n\n <div className=\"flex flex-col gap-4\">\n <span className=\"paragraph-medium-semibold text-gray-950\">{translate('common.preferences.timeDisplay')}</span>\n <div className=\"flex flex-col lg:flex-row items-center gap-3\">\n <ComboboxField\n label={translate('common.preferences.timezone')}\n placeholder={translate('common.preferences.timezonePlaceholder')}\n searchPlaceholder={translate('common.preferences.timezoneSearch')}\n containerClassName=\"w-full\"\n options={timezones}\n value={watch('timezone')}\n onChange={(value) => setValue('timezone', value, { shouldDirty: true })}\n icon={!canEditPreferences ? <IconLock className=\"size-4 text-gray-400\" /> : undefined}\n disabled={!canEditPreferences}\n />\n <SelectField\n label={translate('common.preferences.timeFormat')}\n placeholder={translate('common.preferences.timeFormatPlaceholder')}\n className=\"h-10!\"\n containerClassName=\"w-full\"\n options={timeFormatOptions}\n value={watch('timeFormat')}\n onChange={(value) =>\n setValue('timeFormat', value as string, { shouldDirty: true })\n }\n icon={<IconLock className=\"size-4 text-gray-400\" />}\n disabled\n />\n </div>\n </div>\n\n </div>\n </div>\n\n <div className=\"fixed bottom-0 left-0 right-0 lg:absolute flex items-center h-20 px-4 lg:px-5 border-t border-gray-200 justify-between bg-white z-10\">\n <Button\n variant=\"secondary\"\n className=\"h-10!\"\n type=\"button\"\n disabled={isSaving}\n onClick={() => {\n reset();\n onClose();\n }}\n >\n {translate('common.actions.cancel')}\n </Button>\n <Button className=\"h-10!\" type=\"submit\" disabled={isSaving}>\n {isSaving ? translate('common.actions.saving') : translate('common.actions.saveChanges')}\n </Button>\n </div>\n </form>\n\n <ConfirmGlobalPreferencesModal\n open={confirmGlobalOpen}\n onConfirm={handleConfirmGlobal}\n onCancel={handleCancelGlobal}\n />\n </>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/account/sections/PreferencesSection.tsx"],"sourcesContent":["'use client';\n\nimport { useState, useEffect } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { useTranslations, useLocale } from 'next-intl';\nimport { useRouter } from 'next/navigation';\nimport { toast } from 'sonner';\nimport { IconLock } from '@tabler/icons-react';\nimport { cn } from '../../../infra/utils/clsx';\nimport { isLocale, type Locale } from '../../../i18n/config';\nimport { setLocaleCookie } from '../../../utils/intl/locale-cookie';\nimport { localeToApiLanguage } from '../../../utils/intl/locales';\nimport { Button } from '../../ui/buttons/Button';\nimport { Separator } from '../../ui/data-display/Separator';\nimport { Toast } from '../../ui/feedback/Toast';\nimport { FormField } from '../../ui/form/FormField';\nimport { ComboboxField } from '../../ui/form/ComboboxField';\nimport { SelectField } from '../../ui/form/SelectField';\nimport ConfirmGlobalPreferencesModal from '../ConfirmGlobalPreferencesModal';\nimport { useAuth } from '../../../providers/auth.provider';\nimport { useWhitelabel } from '../../../providers/whitelabel.provider';\nimport { UserProfile } from '../../../modules/users/schema';\nimport type { UpdateAccountRequest } from '../../../modules/accounts/types';\nimport {\n useUpdateAccountUser,\n useUpdateAccount,\n} from '../../../modules/accounts/hooks/useAccountManagement';\nimport {\n LANGUAGE_OPTIONS,\n TIME_FORMAT_OPTIONS,\n} from '../constants';\nimport { useTimezones } from '../../../modules/accounts/hooks/useTimezones';\nimport { useCurrencies } from '../../../modules/accounts/hooks/useCurrencies';\nimport { getCurrencyForGateway } from '../../../utils/format/currency';\n\ninterface PreferencesFormValues {\n companyName: string;\n language: string;\n currency: string;\n timezone: string;\n timeFormat: string;\n receive_sms: boolean;\n receive_email: boolean;\n}\n\ninterface PreferencesSectionProps {\n onClose: () => void;\n}\n\nexport function PreferencesSection({ onClose }: PreferencesSectionProps) {\n // Padrão raiz: um único `translate` chamado pela chave inteira (`common.<modulo>.<chave>`).\n const translate = useTranslations();\n // Exceção: chave dinâmica (option.value) numa lista → namespace escopado.\n const translateLanguage = useTranslations('common.languages');\n const currentLocale = useLocale();\n const router = useRouter();\n const { data: timezones = [] } = useTimezones();\n const { data: currencies = [] } = useCurrencies();\n const { user, account } = useAuth();\n const { whitelabel } = useWhitelabel();\n const languageOptions = LANGUAGE_OPTIONS.map((option) => ({\n ...option,\n label: translateLanguage(option.value as Locale),\n displayValue: translateLanguage(option.value as Locale),\n }));\n const timeFormatOptions = TIME_FORMAT_OPTIONS.map((option) => ({\n ...option,\n label: translate(\n `common.preferences.timeFormatOptions.${option.value === '24h' ? 'h24' : 'h12'}`,\n ),\n }));\n const isOwner = user?.profile === UserProfile.owner;\n const canEditPreferences = isOwner || user?.profile === UserProfile.admin;\n const updateAccountUser = useUpdateAccountUser();\n const updateAccount = useUpdateAccount();\n const [confirmGlobalOpen, setConfirmGlobalOpen] = useState(false);\n const [pendingSubmit, setPendingSubmit] = useState<{\n data: PreferencesFormValues;\n accountFields: UpdateAccountRequest;\n } | null>(null);\n const [isSaving, setIsSaving] = useState(false);\n\n const { watch, setValue, handleSubmit, reset, formState: { dirtyFields } } =\n useForm<PreferencesFormValues>({\n defaultValues: {\n companyName: '',\n language: '',\n currency: '',\n timezone: '',\n timeFormat: '24h',\n receive_sms: false,\n receive_email: false,\n },\n });\n\n useEffect(() => {\n if (!user || !account) return;\n reset({\n companyName: account.name ?? '',\n language: LANGUAGE_OPTIONS.find(\n (o) => o.apiValue === user.language?.toLowerCase()\n )?.value ?? 'pt-br',\n // A moeda é derivada do gateway da conta (read-only para o usuário) —\n // espelha o que useCurrencyFormatter usa no display de preços.\n currency: getCurrencyForGateway(account.gateway).toUpperCase(),\n timezone: account.timezone,\n timeFormat: '24h',\n receive_sms: user.receive_sms ?? false,\n receive_email: user.receive_email ?? false,\n });\n }, [user, account, reset]);\n\n const doSave = async (data: PreferencesFormValues, accountFields: UpdateAccountRequest) => {\n setIsSaving(true);\n try {\n const apiLanguage = isLocale(data.language) ? localeToApiLanguage(data.language) : data.language.toLowerCase();\n await updateAccountUser.mutateAsync({\n language: apiLanguage,\n receive_sms: data.receive_sms,\n receive_email: data.receive_email,\n });\n\n if (canEditPreferences && Object.keys(accountFields).length > 0) {\n await updateAccount.mutateAsync(accountFields);\n }\n\n reset(data);\n toast.custom((toastId) => (\n <Toast variant=\"success\" message={translate('common.preferences.savedSuccess')} toastId={toastId} />\n ));\n onClose();\n if (data.language !== currentLocale) {\n setLocaleCookie(data.language, whitelabel?.domain);\n router.refresh();\n }\n } catch (error) {\n toast.custom((toastId) => (\n <Toast\n variant=\"error\"\n message={error instanceof Error ? error.message : translate('common.preferences.saveError')}\n toastId={toastId}\n />\n ));\n } finally {\n setIsSaving(false);\n }\n };\n\n const onSubmit = (data: PreferencesFormValues) => {\n const accountFields: UpdateAccountRequest = {\n ...(isOwner && dirtyFields.companyName && { name: data.companyName }),\n // currency é read-only (derivada do gateway) — não enviada no update.\n ...(canEditPreferences && dirtyFields.timezone && { timezone: data.timezone }),\n };\n const globalFieldChanged = Object.keys(accountFields).length > 0;\n\n if (globalFieldChanged) {\n setPendingSubmit({ data, accountFields });\n setConfirmGlobalOpen(true);\n } else {\n doSave(data, accountFields);\n }\n };\n\n const handleConfirmGlobal = () => {\n setConfirmGlobalOpen(false);\n if (pendingSubmit) {\n doSave(pendingSubmit.data, pendingSubmit.accountFields);\n setPendingSubmit(null);\n }\n };\n\n const handleCancelGlobal = () => {\n setConfirmGlobalOpen(false);\n setPendingSubmit(null);\n };\n\n return (\n <>\n <form onSubmit={handleSubmit(onSubmit)} className=\"flex flex-col h-full\">\n <div className=\"overflow-y-auto overscroll-contain px-4 pb-4 lg:p-5 flex flex-col gap-5 lg:gap-6 flex-1\">\n <span className=\"paragraph-medium-semibold text-gray-950\">{translate('common.preferences.title')}</span>\n <div className=\"flex flex-col gap-8\">\n <div className=\"flex flex-col lg:flex-row items-center gap-3\">\n <FormField\n label={translate('common.preferences.companyName')}\n placeholder={translate('common.preferences.companyNamePlaceholder')}\n classnameContainer={cn('w-full', !isOwner && 'cursor-not-allowed opacity-50')}\n value={watch('companyName')}\n onChange={(e) => setValue('companyName', e.target.value, { shouldDirty: true })}\n disabled={!isOwner}\n />\n </div>\n\n <div className=\"flex flex-col lg:flex-row items-center gap-3\">\n <ComboboxField\n label={translate('common.preferences.language')}\n placeholder={translate('common.preferences.languagePlaceholder')}\n searchPlaceholder={translate('common.preferences.languageSearch')}\n containerClassName=\"w-full\"\n options={languageOptions}\n value={watch('language')}\n onChange={(value) => setValue('language', value, { shouldDirty: true })}\n />\n <ComboboxField\n label={translate('common.preferences.currency')}\n placeholder={translate('common.preferences.currencyPlaceholder')}\n searchPlaceholder={translate('common.preferences.currencySearch')}\n containerClassName=\"w-full\"\n options={currencies}\n value={watch('currency')}\n onChange={() => undefined}\n icon={<IconLock className=\"size-4 text-gray-400\" />}\n disabled\n />\n </div>\n\n <Separator />\n\n <div className=\"flex flex-col gap-4\">\n <span className=\"paragraph-medium-semibold text-gray-950\">{translate('common.preferences.timeDisplay')}</span>\n <div className=\"flex flex-col lg:flex-row items-center gap-3\">\n <ComboboxField\n label={translate('common.preferences.timezone')}\n placeholder={translate('common.preferences.timezonePlaceholder')}\n searchPlaceholder={translate('common.preferences.timezoneSearch')}\n containerClassName=\"w-full\"\n options={timezones}\n value={watch('timezone')}\n onChange={(value) => setValue('timezone', value, { shouldDirty: true })}\n icon={!canEditPreferences ? <IconLock className=\"size-4 text-gray-400\" /> : undefined}\n disabled={!canEditPreferences}\n />\n <SelectField\n label={translate('common.preferences.timeFormat')}\n placeholder={translate('common.preferences.timeFormatPlaceholder')}\n className=\"h-10!\"\n containerClassName=\"w-full\"\n options={timeFormatOptions}\n value={watch('timeFormat')}\n onChange={(value) =>\n setValue('timeFormat', value as string, { shouldDirty: true })\n }\n icon={<IconLock className=\"size-4 text-gray-400\" />}\n disabled\n />\n </div>\n </div>\n\n </div>\n </div>\n\n <div className=\"fixed bottom-0 left-0 right-0 lg:absolute flex items-center h-20 px-4 lg:px-5 border-t border-gray-200 justify-between bg-white z-10\">\n <Button\n variant=\"secondary\"\n className=\"h-10!\"\n type=\"button\"\n disabled={isSaving}\n onClick={() => {\n reset();\n onClose();\n }}\n >\n {translate('common.actions.cancel')}\n </Button>\n <Button className=\"h-10!\" type=\"submit\" disabled={isSaving}>\n {isSaving ? translate('common.actions.saving') : translate('common.actions.saveChanges')}\n </Button>\n </div>\n </form>\n\n <ConfirmGlobalPreferencesModal\n open={confirmGlobalOpen}\n onConfirm={handleConfirmGlobal}\n onCancel={handleCancelGlobal}\n />\n </>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect, useRef } from "react";
|
|
3
|
+
function useDomMutationGuardHit(onHit) {
|
|
4
|
+
const onHitRef = useRef(onHit);
|
|
5
|
+
onHitRef.current = onHit;
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
let reported = false;
|
|
8
|
+
const report = (kind) => {
|
|
9
|
+
if (reported) return;
|
|
10
|
+
reported = true;
|
|
11
|
+
window.__gpDomGuardOnHit = null;
|
|
12
|
+
onHitRef.current({
|
|
13
|
+
kind,
|
|
14
|
+
language: navigator.language,
|
|
15
|
+
languages: navigator.languages?.join(",") ?? "",
|
|
16
|
+
documentLang: document.documentElement.lang,
|
|
17
|
+
// <font> sem classe é a assinatura do Google Tradutor
|
|
18
|
+
translatedNodes: document.querySelectorAll("font[style]").length,
|
|
19
|
+
path: window.location.pathname
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
const already = window.__gpDomGuard;
|
|
23
|
+
if (already && (already.removeChild > 0 || already.insertBefore > 0)) {
|
|
24
|
+
report(already.insertBefore > 0 ? "insertBefore" : "removeChild");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
window.__gpDomGuardOnHit = report;
|
|
28
|
+
return () => {
|
|
29
|
+
window.__gpDomGuardOnHit = null;
|
|
30
|
+
};
|
|
31
|
+
}, []);
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
useDomMutationGuardHit
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=useDomMutationGuardHit.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/useDomMutationGuardHit.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef } from 'react';\n\nexport type DomMutationGuardHit = {\n kind: 'removeChild' | 'insertBefore';\n language: string;\n languages: string;\n documentLang: string;\n translatedNodes: number;\n path: string;\n}\n\n/**\n * Reporta quando a guarda de mutação de DOM (`DOM_MUTATION_GUARD_SCRIPT`) entra em ação.\n *\n * Sem isso a correção fica cega: o app para de cair, mas ninguém descobre quantos clientes estão\n * navegando com o tradutor do navegador ligado. Reporta UMA vez por sessão — o objetivo é medir\n * quantas sessões são afetadas, não quantas operações de DOM foram salvas.\n */\nexport function useDomMutationGuardHit(onHit: (hit: DomMutationGuardHit) => void): void {\n const onHitRef = useRef(onHit);\n onHitRef.current = onHit;\n\n useEffect(() => {\n let reported = false;\n\n const report = (kind: 'removeChild' | 'insertBefore') => {\n if (reported) return;\n reported = true;\n window.__gpDomGuardOnHit = null;\n onHitRef.current({\n kind,\n language: navigator.language,\n languages: navigator.languages?.join(',') ?? '',\n documentLang: document.documentElement.lang,\n // <font> sem classe é a assinatura do Google Tradutor\n translatedNodes: document.querySelectorAll('font[style]').length,\n path: window.location.pathname,\n });\n };\n\n // Disparos que aconteceram antes deste componente montar.\n const already = window.__gpDomGuard;\n if (already && (already.removeChild > 0 || already.insertBefore > 0)) {\n report(already.insertBefore > 0 ? 'insertBefore' : 'removeChild');\n return;\n }\n\n window.__gpDomGuardOnHit = report;\n return () => {\n window.__gpDomGuardOnHit = null;\n };\n }, []);\n}\n"],"mappings":";AAEA,SAAS,WAAW,cAAc;AAkB3B,SAAS,uBAAuB,OAAiD;AACtF,QAAM,WAAW,OAAO,KAAK;AAC7B,WAAS,UAAU;AAEnB,YAAU,MAAM;AACd,QAAI,WAAW;AAEf,UAAM,SAAS,CAAC,SAAyC;AACvD,UAAI,SAAU;AACd,iBAAW;AACX,aAAO,oBAAoB;AAC3B,eAAS,QAAQ;AAAA,QACf;AAAA,QACA,UAAU,UAAU;AAAA,QACpB,WAAW,UAAU,WAAW,KAAK,GAAG,KAAK;AAAA,QAC7C,cAAc,SAAS,gBAAgB;AAAA;AAAA,QAEvC,iBAAiB,SAAS,iBAAiB,aAAa,EAAE;AAAA,QAC1D,MAAM,OAAO,SAAS;AAAA,MACxB,CAAC;AAAA,IACH;AAGA,UAAM,UAAU,OAAO;AACvB,QAAI,YAAY,QAAQ,cAAc,KAAK,QAAQ,eAAe,IAAI;AACpE,aAAO,QAAQ,eAAe,IAAI,iBAAiB,aAAa;AAChE;AAAA,IACF;AAEA,WAAO,oBAAoB;AAC3B,WAAO,MAAM;AACX,aAAO,oBAAoB;AAAA,IAC7B;AAAA,EACF,GAAG,CAAC,CAAC;AACP;","names":[]}
|
|
@@ -19,6 +19,14 @@ function decodeJwtLocaleInfo(token) {
|
|
|
19
19
|
return null;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
+
function localeFromAcceptLanguage(header) {
|
|
23
|
+
if (!header) return null;
|
|
24
|
+
for (const entry of header.split(",")) {
|
|
25
|
+
const locale = normalizeLocale(entry.split(";")[0].trim());
|
|
26
|
+
if (locale) return locale;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
22
30
|
async function resolveLocale(options = {}) {
|
|
23
31
|
const cookieStore = await cookies();
|
|
24
32
|
const token = process.env.DUMMY_AUTH_TOKEN || cookieStore.get(AUTH_COOKIE)?.value;
|
|
@@ -32,6 +40,8 @@ async function resolveLocale(options = {}) {
|
|
|
32
40
|
const fromCookie = normalizeLocale(cookieStore.get(LOCALE_COOKIE)?.value);
|
|
33
41
|
if (fromCookie) return fromCookie;
|
|
34
42
|
const headersList = await headers();
|
|
43
|
+
const fromAcceptLanguage = localeFromAcceptLanguage(headersList.get("accept-language"));
|
|
44
|
+
if (fromAcceptLanguage) return fromAcceptLanguage;
|
|
35
45
|
const country = jwt?.country ?? headersList.get(GEO_HEADER);
|
|
36
46
|
const fromGeo = localeFromCountry(country);
|
|
37
47
|
if (fromGeo) return fromGeo;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/i18n/resolve-locale.ts"],"sourcesContent":["import 'server-only';\n\nimport { cookies, headers } from 'next/headers';\nimport { DEFAULT_LOCALE, Locale, LOCALE_COOKIE } from './config';\nimport { localeFromCountry } from './country-language';\nimport { normalizeLocale } from './normalize';\nimport { decodeJwtPayload } from '../utils/jwt-payload';\n\nconst AUTH_COOKIE = 'greatapps';\nconst GEO_HEADER = 'cf-ipcountry';\nconst DEFAULT_WHITELABEL_ID = 1;\n\ninterface JwtLocaleInfo {\n id_wl?: number;\n country?: string | null;\n}\n\n/** Lê id_wl e país do JWT sem custo de rede (best-effort). */\nfunction decodeJwtLocaleInfo(token?: string | null): JwtLocaleInfo | null {\n if (!token) return null;\n try {\n const payload = decodeJwtPayload<{ id_wl?: number | string; session?: { location?: { country?: string | null } } }>(token);\n return {\n id_wl: payload?.id_wl != null ? Number(payload.id_wl) : undefined,\n country: payload?.session?.location?.country ?? null,\n };\n } catch {\n return null;\n }\n}\n\nexport interface ResolveLocaleOptions {\n /**\n * Whitelabel id já resolvido (ex.: via `findWhitelabel()`), com prioridade sobre o JWT.\n * Permite detectar domínio whitelabel mesmo para visitante não-logado.\n */\n whitelabelId?: number | null;\n /** Idioma da conta (`user.language`), quando já conhecido pelo chamador. */\n userLanguage?: string | null;\n}\n\n/**\n * Resolve o locale da requisição (server-side). Ordem de prioridade:\n *\n * 1. **Whitelabel não-padrão** (`id_wl != 1`) → `pt` (por enquanto, whitelabels não são localizadas).\n * 2. **Preferência da conta** (`userLanguage`), quando fornecida.\n * 3. **Cookie `NEXT_LOCALE`** — cache da preferência ou escolha manual do visitante.\n * 4. **Inferência por país** — JWT (`session.location.country`) ou header `CF-IPCountry`.\n *
|
|
1
|
+
{"version":3,"sources":["../../src/i18n/resolve-locale.ts"],"sourcesContent":["import 'server-only';\n\nimport { cookies, headers } from 'next/headers';\nimport { DEFAULT_LOCALE, Locale, LOCALE_COOKIE } from './config';\nimport { localeFromCountry } from './country-language';\nimport { normalizeLocale } from './normalize';\nimport { decodeJwtPayload } from '../utils/jwt-payload';\n\nconst AUTH_COOKIE = 'greatapps';\nconst GEO_HEADER = 'cf-ipcountry';\nconst DEFAULT_WHITELABEL_ID = 1;\n\ninterface JwtLocaleInfo {\n id_wl?: number;\n country?: string | null;\n}\n\n/** Lê id_wl e país do JWT sem custo de rede (best-effort). */\nfunction decodeJwtLocaleInfo(token?: string | null): JwtLocaleInfo | null {\n if (!token) return null;\n try {\n const payload = decodeJwtPayload<{ id_wl?: number | string; session?: { location?: { country?: string | null } } }>(token);\n return {\n id_wl: payload?.id_wl != null ? Number(payload.id_wl) : undefined,\n country: payload?.session?.location?.country ?? null,\n };\n } catch {\n return null;\n }\n}\n\nexport interface ResolveLocaleOptions {\n /**\n * Whitelabel id já resolvido (ex.: via `findWhitelabel()`), com prioridade sobre o JWT.\n * Permite detectar domínio whitelabel mesmo para visitante não-logado.\n */\n whitelabelId?: number | null;\n /** Idioma da conta (`user.language`), quando já conhecido pelo chamador. */\n userLanguage?: string | null;\n}\n\nfunction localeFromAcceptLanguage(header: string | null): Locale | null {\n if (!header) return null;\n for (const entry of header.split(',')) {\n const locale = normalizeLocale(entry.split(';')[0].trim());\n if (locale) return locale;\n }\n return null;\n}\n\n/**\n * Resolve o locale da requisição (server-side). Ordem de prioridade:\n *\n * 1. **Whitelabel não-padrão** (`id_wl != 1`) → `pt` (por enquanto, whitelabels não são localizadas).\n * 2. **Preferência da conta** (`userLanguage`), quando fornecida.\n * 3. **Cookie `NEXT_LOCALE`** — cache da preferência ou escolha manual do visitante.\n * 4. **Header `Accept-Language`** do navegador.\n * 5. **Inferência por país** — JWT (`session.location.country`) ou header `CF-IPCountry`.\n * 6. **Fallback** → {@link DEFAULT_LOCALE}.\n */\nexport async function resolveLocale(options: ResolveLocaleOptions = {}): Promise<Locale> {\n const cookieStore = await cookies();\n const token = process.env.DUMMY_AUTH_TOKEN || cookieStore.get(AUTH_COOKIE)?.value;\n const jwt = decodeJwtLocaleInfo(token);\n\n // 1. Whitelabel não-padrão → português\n const whitelabelId = options.whitelabelId ?? jwt?.id_wl ?? null;\n if (whitelabelId != null && whitelabelId !== DEFAULT_WHITELABEL_ID) {\n return 'pt-br';\n }\n\n // 2. Preferência explícita da conta\n const fromUser = normalizeLocale(options.userLanguage);\n if (fromUser) return fromUser;\n\n // 3. Cookie persistido\n const fromCookie = normalizeLocale(cookieStore.get(LOCALE_COOKIE)?.value);\n if (fromCookie) return fromCookie;\n\n const headersList = await headers();\n\n // 4. Header Accept-Language do navegador\n const fromAcceptLanguage = localeFromAcceptLanguage(headersList.get('accept-language'));\n if (fromAcceptLanguage) return fromAcceptLanguage;\n\n // 5. Inferência por país (geo)\n const country = jwt?.country ?? headersList.get(GEO_HEADER);\n const fromGeo = localeFromCountry(country);\n if (fromGeo) return fromGeo;\n\n // 6. Fallback\n return DEFAULT_LOCALE;\n}\n"],"mappings":"AAAA,OAAO;AAEP,SAAS,SAAS,eAAe;AACjC,SAAS,gBAAwB,qBAAqB;AACtD,SAAS,yBAAyB;AAClC,SAAS,uBAAuB;AAChC,SAAS,wBAAwB;AAEjC,MAAM,cAAc;AACpB,MAAM,aAAa;AACnB,MAAM,wBAAwB;AAQ9B,SAAS,oBAAoB,OAA6C;AACxE,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI;AACF,UAAM,UAAU,iBAAoG,KAAK;AACzH,WAAO;AAAA,MACL,OAAO,SAAS,SAAS,OAAO,OAAO,QAAQ,KAAK,IAAI;AAAA,MACxD,SAAS,SAAS,SAAS,UAAU,WAAW;AAAA,IAClD;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAYA,SAAS,yBAAyB,QAAsC;AACtE,MAAI,CAAC,OAAQ,QAAO;AACpB,aAAW,SAAS,OAAO,MAAM,GAAG,GAAG;AACrC,UAAM,SAAS,gBAAgB,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC;AACzD,QAAI,OAAQ,QAAO;AAAA,EACrB;AACA,SAAO;AACT;AAYA,eAAsB,cAAc,UAAgC,CAAC,GAAoB;AACvF,QAAM,cAAc,MAAM,QAAQ;AAClC,QAAM,QAAQ,QAAQ,IAAI,oBAAoB,YAAY,IAAI,WAAW,GAAG;AAC5E,QAAM,MAAM,oBAAoB,KAAK;AAGrC,QAAM,eAAe,QAAQ,gBAAgB,KAAK,SAAS;AAC3D,MAAI,gBAAgB,QAAQ,iBAAiB,uBAAuB;AAClE,WAAO;AAAA,EACT;AAGA,QAAM,WAAW,gBAAgB,QAAQ,YAAY;AACrD,MAAI,SAAU,QAAO;AAGrB,QAAM,aAAa,gBAAgB,YAAY,IAAI,aAAa,GAAG,KAAK;AACxE,MAAI,WAAY,QAAO;AAEvB,QAAM,cAAc,MAAM,QAAQ;AAGlC,QAAM,qBAAqB,yBAAyB,YAAY,IAAI,iBAAiB,CAAC;AACtF,MAAI,mBAAoB,QAAO;AAG/B,QAAM,UAAU,KAAK,WAAW,YAAY,IAAI,UAAU;AAC1D,QAAM,UAAU,kBAAkB,OAAO;AACzC,MAAI,QAAS,QAAO;AAGpB,SAAO;AACT;","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -380,6 +380,8 @@ import { default as default16 } from "./hooks/usePasswordVisibility";
|
|
|
380
380
|
import { default as default17 } from "./hooks/useCountdownTimer";
|
|
381
381
|
import { default as default18 } from "./hooks/useIsMobile";
|
|
382
382
|
import { useDebounce } from "./hooks/useDebounce";
|
|
383
|
+
import { useDomMutationGuardHit } from "./hooks/useDomMutationGuardHit";
|
|
384
|
+
import { DOM_MUTATION_GUARD_SCRIPT } from "./utils/dom/dom-mutation-guard";
|
|
383
385
|
import { useDebouncedEffect } from "./hooks/useDebouncedEffect";
|
|
384
386
|
import { useDebounceState } from "./hooks/useDebounceState";
|
|
385
387
|
import {
|
|
@@ -554,6 +556,7 @@ export {
|
|
|
554
556
|
CreateCardRequestSchema,
|
|
555
557
|
default4 as CreditsDisabledModal,
|
|
556
558
|
CrispEmbed,
|
|
559
|
+
DOM_MUTATION_GUARD_SCRIPT,
|
|
557
560
|
DatePicker,
|
|
558
561
|
DateRangePicker,
|
|
559
562
|
default15 as DefaultCircularProgress,
|
|
@@ -824,6 +827,7 @@ export {
|
|
|
824
827
|
useDeleteProject,
|
|
825
828
|
useDesktopSidebarStore,
|
|
826
829
|
useDialogLayer,
|
|
830
|
+
useDomMutationGuardHit,
|
|
827
831
|
useFreezeNotice,
|
|
828
832
|
useHandleDeleteCard,
|
|
829
833
|
useHasPlanAddon,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Types\nexport * from \"./modules/auth/schema\";\nexport * from \"./modules/users/schema\";\nexport * from \"./modules/whitelabel/schema\";\n// Style types now come from whitelabel schema directly\nexport * from \"./infra/api/types\";\n\n// Contexts\nexport * from \"./providers/query.provider\";\nexport * from \"./providers/auth.provider\";\nexport * from \"./providers/whitelabel.provider\";\nexport {\n NavigationProvider,\n useNavigationFallback,\n} from \"./providers/navigation.provider\";\n\n// Navigation (safe drop-in replacement for next/navigation)\nexport { useRouter } from \"./hooks/useRouter\";\nexport type { SafeAppRouter } from \"./hooks/useRouter\";\nexport {\n usePathname,\n useSearchParams,\n useParams,\n redirect,\n notFound,\n} from \"./utils/next-navigation\";\n\n// Hooks\nexport {\n useListProjectUsers,\n LIST_PROJECT_USERS_QUERY_KEY,\n LIST_PROJECT_USERS_BASE_KEY,\n} from \"./modules/projects/hooks/list-project-users.hook\";\nexport {\n useListAvailableUsers,\n LIST_AVAILABLE_USERS_QUERY_KEY,\n LIST_AVAILABLE_USERS_BASE_KEY,\n} from \"./modules/projects/hooks/list-available-users.hook\";\nexport {\n useListAllAccountUsers,\n LIST_ALL_ACCOUNT_USERS_QUERY_KEY,\n LIST_ALL_ACCOUNT_USERS_BASE_KEY,\n} from \"./modules/projects/hooks/list-all-account-users.hook\";\nexport {\n useProjects,\n PROJECTS_BASE_KEY,\n PROJECTS_QUERY_KEY,\n} from \"./modules/projects/hooks/list-projects.hook\";\nexport {\n useInfiniteProjects,\n INFINITE_PROJECTS_QUERY_KEY,\n} from \"./modules/projects/hooks/list-infinite-projects.hook\";\nexport { useProject } from \"./modules/projects/hooks/find-project.hook\";\nexport { useCreateProject } from \"./modules/projects/hooks/create-project.hook\";\nexport { useUpdateProject } from \"./modules/projects/hooks/update-project.hook\";\nexport { useDeleteProject } from \"./modules/projects/hooks/delete-project.hook\";\nexport type {\n Project,\n ProjectsPage,\n CreateProjectRequest,\n UpdateProjectRequest,\n ProjectUser,\n AccountUser,\n AddRemoveProjectUsersParams,\n ListUsersParams,\n UsersPage,\n} from \"./modules/projects/types\";\nexport { ProjectSchema } from \"./modules/projects/types\";\nexport type { ListProjectsActionParams } from \"./modules/projects/actions/list-projects.action\";\nexport {\n useUserQuery,\n useUserValidateSession,\n useInvalidateUser,\n useSetUserData,\n useTwoFactorVerify,\n USER_QUERY_KEY,\n} from \"./modules/auth/hooks/useUserQuery\";\nexport { useManagementPermissions } from \"./modules/auth/hooks/useManagementPermissions\";\nexport type { ManagementPermission } from \"./modules/auth/types/management-permission.type\";\nexport { useSocialGoogleLogin } from \"./modules/auth/hooks/social-google-login.hook\";\nexport { useSocialGoogleOnboarding } from \"./modules/auth/hooks/social-google-onboarding.hook\";\nexport { useUnlinkGoogle } from \"./modules/auth/hooks/unlink-google.hook\";\nexport { useSubscriptions } from \"./modules/subscriptions/hooks/list-subscriptions.hook\";\nexport {\n SUBSCRIPTIONS_QUERY_KEY,\n CHARGES_QUERY_KEY,\n FREEZE_NOTICE_QUERY_KEY,\n} from \"./modules/subscriptions/constants/query-keys.constants\";\nexport { useActiveSubscription } from \"./modules/subscriptions/hooks/find-active-subscription.hook\";\nexport { useCancelledSubscriptionGuard } from \"./modules/subscriptions/hooks/use-cancelled-subscription-guard\";\nexport { useAccountFreeze } from \"./modules/subscriptions/hooks/use-account-freeze.hook\";\nexport { useFreezeNotice } from \"./modules/subscriptions/hooks/use-freeze-notice.hook\";\nexport { usePlanById } from \"./modules/plans/hooks/use-plan-by-id.hook\";\nexport { useHasPlanAddon } from \"./modules/plans/hooks/use-has-plan-addon.hook\";\nexport { useCalculateSubscription } from \"./modules/subscriptions/hooks/calculate-subscription.hook\";\nexport { useUpdateSubscriptionPlan } from \"./modules/subscriptions/hooks/update-subscription-plan.hook\";\nexport { useUpdateSubscriptionPayment } from \"./modules/subscriptions/hooks/update-subscription-payment.hook\";\nexport { useCards, CARDS_QUERY_KEY } from \"./modules/cards/hooks/cards.hook\";\nexport { useCardById } from \"./modules/cards/hooks/card-by-id.hook\";\nexport { useCreateCard } from \"./modules/cards/hooks/create-card.hook\";\nexport { useCreateSetupIntent } from \"./modules/cards/hooks/create-setup-intent.hook\";\nexport { useSetDefaultCard } from \"./modules/cards/hooks/set-default-card.hook\";\nexport { useDeleteCard } from \"./modules/cards/hooks/delete-card.hook\";\nexport { useDeleteConfirmation } from \"./modules/cards/hooks/delete-confirmation.hook\";\nexport type { DeleteConfirmationFormData } from \"./modules/cards/hooks/delete-confirmation.hook\";\nexport { useHandleDeleteCard } from \"./modules/cards/hooks/handle-delete-card.hook\";\nexport { useCharges } from \"./modules/charges/hooks/charges.hook\";\nexport { useChargeById } from \"./modules/charges/hooks/charge-by-id.hook\";\nexport { useChargeAction } from \"./modules/charges/hooks/charge-action.hook\";\nexport { useIaCredits } from \"./modules/ia-credits/hooks/ia-credits.hook\";\nexport type {\n IaCreditsSummary,\n IaCreditsSummaryData,\n IaCreditAddBatch,\n IaCreditOperation,\n} from \"./modules/ia-credits/types\";\nexport { usePurchaseIaCredits } from \"./modules/ia-credits/hooks/purchase-ia-credits.hook\";\nexport { useAiCreditsOfferEligibility } from \"./modules/ia-credits/hooks/use-offer-eligibility.hook\";\nexport {\n AI_CREDITS_FIRST_PURCHASE_OFFER,\n AI_CREDITS_OFFER_ELIGIBILITY_QUERY_KEY,\n AI_CREDITS_OFFER_MAX_REPEATS,\n AiCreditsOfferStage,\n PAYMENT_METHOD_CARD,\n PAYMENT_METHOD_PIX,\n} from \"./modules/ia-credits/constants/ai-credits-offer.constants\";\nexport type {\n AiCreditsOfferEligibility,\n AiCreditsOfferEligibilityResponse,\n AiCreditsOfferIneligibilityReason,\n PurchaseIaCreditsInput,\n PurchaseIaCreditsResult,\n} from \"./modules/ia-credits/types/ai-credits-offer.type\";\nexport {\n readOfferStageCookie,\n writeOfferStageCookie,\n} from \"./modules/ia-credits/utils/offer-stage-cookie\";\nexport type { OfferStageRecord } from \"./modules/ia-credits/utils/offer-stage-cookie\";\nexport type {\n Subscription,\n SubscriptionItem,\n FindSubscriptionsParams,\n} from \"./modules/subscriptions/types/subscription.type\";\nexport {\n SubscriptionSchema,\n SubscriptionItemSchema,\n} from \"./modules/subscriptions/types/subscription.type\";\nexport {\n ADDON_IDS,\n aiCreditUnitPrice,\n AI_CREDIT_SIZES,\n AI_CREDIT_VALUES,\n buildAiCreditOptions,\n resolveAiCreditPrice,\n} from \"./modules/subscriptions/constants/addons.constants\";\nexport type {\n AddonKindEnum,\n AiCreditOption,\n} from \"./modules/subscriptions/constants/addons.constants\";\nexport type {\n Plan,\n PlanItem,\n UiPlan,\n PlanFeature,\n PlanMainFeatures,\n PlanPricingByPeriod,\n PlanTooltips,\n} from \"./modules/plans/types/plan.type\";\nexport { PlanSchema, PlanItemSchema } from \"./modules/plans/types/plan.type\";\nexport {\n mapApiPlanToUiPlan,\n mapApiPlanToUiPlanForCurrency,\n} from \"./modules/plans/utils/map-api-plan-to-ui\";\nexport type { PlanBillingPeriod } from \"./modules/plans/utils/map-api-plan-to-ui\";\nexport {\n usePlans,\n PLANS_QUERY_KEY,\n} from \"./modules/plans/hooks/list-plans.hook\";\nexport type { BillingPeriod } from \"./modules/subscriptions/types/billing-period.type\";\nexport type {\n CalculateSubscriptionRequest,\n CalculateSubscriptionResponse,\n UpdateSubscriptionPlanRequest,\n} from \"./modules/subscriptions/types/calculate-subscription.type\";\nexport {\n PixPendingDataSchema,\n SubscriptionPendingPixResponseSchema,\n isSubscriptionPendingPixResponse,\n} from \"./modules/subscriptions/types/pix-pending.type\";\nexport type {\n PixPendingData,\n SubscriptionPendingPixResponse,\n} from \"./modules/subscriptions/types/pix-pending.type\";\nexport type {\n Card as PaymentCard,\n CreateCardRequest,\n FindCardsParams,\n SetupIntent,\n} from \"./modules/cards/types\";\nexport {\n CardSchema as PaymentCardSchema,\n CreateCardRequestSchema,\n FindCardsParamsSchema,\n SetupIntentSchema,\n} from \"./modules/cards/types\";\nexport type {\n Charge,\n FindChargesParams,\n PayChargeInput,\n} from \"./modules/charges/types/charge.type\";\nexport {\n ChargeSchema,\n FindChargesParamsSchema,\n PayChargeInputSchema,\n} from \"./modules/charges/types/charge.type\";\nexport { buildPlanExtras } from \"./modules/subscriptions/utils/build-plan-extras\";\nexport { hasSubscriptionExpired } from \"./modules/subscriptions/utils/has-subscription-expired\";\nexport { hasActivePaidSubscription } from \"./modules/subscriptions/utils/has-active-paid-subscription\";\nexport { hasPaidSubscription } from \"./modules/subscriptions/utils/has-paid-subscription\";\nexport {\n confirmPaymentIfRequired,\n PaymentAuthenticationError,\n} from \"./modules/subscriptions/utils/confirm-payment-if-required\";\nexport { SUBSCRIPTION_GRACE_PERIOD_DAYS } from \"./modules/subscriptions/constants/subscription.constants\";\nexport { getSubscriptionCancellationState } from \"./modules/subscriptions/utils/get-subscription-cancellation-state\";\nexport type { SubscriptionCancellationState } from \"./modules/subscriptions/utils/get-subscription-cancellation-state\";\nexport {\n ACCOUNT_FREEZE_AFTER_DAYS,\n FREEZE_WARNING_DAYS_BEFORE,\n} from \"./modules/subscriptions/constants/subscription.constants\";\nexport { getAccountFreezeState } from \"./modules/subscriptions/utils/get-account-freeze-state\";\nexport type { AccountFreezeState } from \"./modules/subscriptions/utils/get-account-freeze-state\";\nexport { getAccountFreezeDate } from \"./modules/subscriptions/utils/get-account-freeze-date\";\nexport type { FreezeNotice } from \"./modules/subscriptions/types/freeze-notice.type\";\nexport {\n useCountPages,\n COUNT_PAGES_QUERY_KEY,\n} from \"./modules/pages/hooks/count-pages.hook\";\nexport { PAGES_QUERY_KEY } from \"./modules/pages/constants/query-keys.constants\";\nexport {\n getPriceFromCalculatedData,\n getOriginalPriceFromCalculatedData,\n periodicityToBillingPeriod,\n} from \"./modules/subscriptions/utils/periodicity\";\nexport { useBuyCreditsModal } from \"./store/useBuyCreditsModal\";\nexport { useCreditsDisabledModal } from \"./store/useCreditsDisabledModal\";\nexport { usePaidPlanRequiredModal } from \"./store/usePaidPlanRequiredModal\";\nexport { useAccountDeletionWarningModal } from \"./store/useAccountDeletionWarningModal\";\nexport { useAiCreditsOfferModal } from \"./store/useAiCreditsOfferModal\";\nexport { default as BuyCreditsModal } from \"./components/modals/BuyCreditsModal\";\nexport { default as AiCreditsOfferModal } from \"./components/modals/promo/AiCreditsOfferModal\";\nexport { AiCreditsOfferGate } from \"./components/layouts/AiCreditsOfferGate\";\nexport type { AiCreditsOfferGateProps } from \"./components/layouts/AiCreditsOfferGate\";\nexport { default as CreditsDisabledModal } from \"./components/modals/CreditsDisabledModal\";\nexport { default as PaidPlanRequiredModal } from \"./components/modals/PaidPlanRequiredModal\";\nexport { default as AccountFrozenModal } from \"./components/modals/AccountFrozenModal\";\nexport { default as AccountDeletionWarningModal } from \"./components/modals/AccountDeletionWarningModal\";\nexport { default as RequiredBillingDataModal } from \"./components/modals/billing/RequiredBillingDataModal\";\nexport { default as AddCardModal } from \"./components/modals/cards/AddCardModal\";\nexport { DeleteCardModal } from \"./components/modals/cards/DeleteCardModal\";\nexport { CannotDeleteCardModal } from \"./components/modals/cards/CannotDeleteCardModal\";\nexport {\n CardFormFields,\n cardFormSchema,\n buildCardFormSchema,\n} from \"./components/modals/cards/CardFormFields\";\nexport type { CardFormData } from \"./components/modals/cards/CardFormFields\";\nexport { Skeleton } from \"./components/ui/feedback/Skeleton\";\nexport { PaymentInfoCard } from \"./components/ui/data-display/PaymentInfoCard\";\nexport { CardBrandIcon } from \"./components/ui/data-display/CardBrandIcons\";\nexport { GoogleIcon } from \"./components/ui/data-display/GoogleIcon\";\nexport { CardItem } from \"./components/ui/data-display/CardItem\";\n\n// Providers\nexport { QueryProvider } from \"./providers/query.provider\";\n\n// Middleware\nexport { createAuthMiddleware } from \"./middlewares/create-auth-middleware\";\nexport { createMiddlewareChain } from \"./middlewares/chain\";\nexport { continueChain, stopChain } from \"./middlewares/types\";\nexport type {\n MiddlewareFunction,\n MiddlewareConfig,\n MiddlewareResult,\n} from \"./middlewares/types\";\n\n// Utils\nexport { cn } from \"./infra/utils/clsx\";\nexport { formatShortDate, formatDateTime, calendarDateSchema, toCalendarDate, daysBetween } from \"./infra/utils/date\";\nexport { buildQueryParams } from \"./infra/utils/params\";\nexport { parseSchema, parseResult } from \"./infra/utils/parser\";\nexport { withAction } from \"./utils/withAction\";\nexport { resolveSafeRedirect, sameHostOr } from \"./utils/redirect\";\nexport { COUNTRIES, flagUrl } from \"./utils/countries\";\nexport type { Country } from \"./utils/countries\";\n\n// Layout\nexport {\n MainLayout,\n MainLayoutContent,\n MainLayoutSpacer,\n MainLayoutMain,\n} from \"./components/layouts/MainLayout\";\nexport { NavBar } from \"./components/layouts/NavBar\";\nexport type { NavBarProps } from \"./components/layouts/NavBar\";\nexport { AppNavBar } from \"./components/layouts/AppNavBar\";\nexport type { AppNavBarProps } from \"./components/layouts/AppNavBar\";\nexport { AppMobileNavBar } from \"./components/layouts/AppMobileNavBar\";\nexport type { AppMobileNavBarProps } from \"./components/layouts/AppMobileNavBar\";\nexport { SideBarNavigation } from \"./components/layouts/SideBarNavigation\";\nexport { MdSideBarNavigation } from \"./components/layouts/MdSideBarNavigation\";\nexport { default as NotificationCard } from \"./components/widgets/notifications/NotificationCard\";\nexport type { NotificationCardProps } from \"./components/widgets/notifications/NotificationCard\";\nexport { NotificationsPopover } from \"./components/layouts/NotificationsPopover\";\nexport type { NotificationsPopoverProps } from \"./components/layouts/NotificationsPopover\";\nexport { NotificationPageContent } from \"./components/pages/notifications/Notifications\";\nexport { NotFoundPage } from \"./components/pages/NotFoundPage\";\nexport { UsersSelectorPopover } from \"./components/layouts/UsersSelectorPopover\";\nexport type { UsersSelectorPopoverProps } from \"./components/layouts/UsersSelectorPopover\";\nexport { ProfilePopover } from \"./components/layouts/ProfilePopover\";\nexport type {\n ProfilePopoverProps,\n ProfileMenuItem,\n} from \"./components/layouts/ProfilePopover\";\nexport { default as WhitelabelCodes } from \"./components/layouts/WhitelabelCodes\";\nexport { NavBarItem } from \"./components/layouts/NavBarItem\";\nexport type { NavBarItemProps } from \"./components/layouts/NavBarItem\";\n\n// Navigation\nexport { AppNavigation } from \"./components/navigation/AppNavigation\";\nexport { CancelledSubscriptionBanner } from \"./components/navigation/CancelledSubscriptionBanner\";\nexport { SubscriptionBanner } from \"./components/navigation/SubscriptionBanner\";\nexport { OverdueInvoiceBanner } from \"./components/navigation/OverdueInvoiceBanner\";\nexport { UpcomingInvoiceBanner } from \"./components/navigation/UpcomingInvoiceBanner\";\nexport { TrialBanner } from \"./components/navigation/TrialBanner\";\nexport { FrozenAccountBanner } from \"./components/navigation/FrozenAccountBanner\";\nexport { FreezeWarningBanner } from \"./components/navigation/FreezeWarningBanner\";\nexport type { NavItemConfig } from \"./components/navigation/subcomponents/NavItems\";\nexport { useMobileNavbarSheet } from \"./store/useMobileNavbarSheet\";\n\n// Auth Query Key Utilities\nexport {\n useAuthQueryKey,\n useWlQueryKey,\n useWlId,\n} from \"./hooks/useAuthQueryKey\";\n\n// Hooks\nexport { default as useCopyToClipboard } from \"./hooks/copy-to-clipboard.hook\";\n\n// UI - Buttons\nexport { Button, buttonVariants } from \"./components/ui/buttons/Button\";\nexport { CopyButton } from \"./components/ui/buttons/CopyButton\";\nexport { default as CancelButton } from \"./components/ui/buttons/CancelButton\";\n\n// UI - Data Display\nexport {\n Accordion,\n AccordionItem,\n AccordionTrigger,\n AccordionContent,\n} from \"./components/ui/data-display/Accordion\";\nexport { Badge, badgeVariants } from \"./components/ui/data-display/Badge\";\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n} from \"./components/ui/data-display/Card\";\nexport {\n Pagination,\n PaginationContent,\n PaginationLink,\n PaginationItem,\n PaginationPrevious,\n PaginationNext,\n PaginationEllipsis,\n} from \"./components/ui/data-display/Pagination\";\nexport { ScrollArea, ScrollBar } from \"./components/ui/data-display/ScrollArea\";\nexport { Separator } from \"./components/ui/data-display/Separator\";\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n} from \"./components/ui/data-display/Table\";\nexport {\n Tabs,\n TabsList,\n TabsTrigger,\n TabsContent,\n} from \"./components/ui/data-display/Tabs\";\nexport { UserAvatar } from \"./components/ui/data-display/UserAvatar\";\nexport type { UserAvatarProps } from \"./components/ui/data-display/UserAvatar\";\n\n// UI - Feedback\nexport { default as CircularProgress } from \"./components/ui/feedback/CircularProgress\";\nexport { default as DefaultCircularProgress } from \"./components/ui/feedback/DefaultCircularProgress\";\nexport { Progress } from \"./components/ui/feedback/Progress\";\nexport { LoadingOverlay } from \"./components/ui/feedback/LoadingOverlay\";\nexport { useBrandLoadingIcon } from \"./hooks/useBrandLoadingIcon\";\nexport {\n Toast,\n toastVariants,\n toastIconContainerVariants,\n} from \"./components/ui/feedback/Toast\";\nexport type { ToastProps } from \"./components/ui/feedback/Toast\";\n\n// UI - Form\nexport { Calendar, CalendarDayButton } from \"./components/ui/form/Calendar\";\nexport { Checkbox } from \"./components/ui/form/Checkbox\";\nexport { DatePicker } from \"./components/ui/form/DatePicker\";\nexport { DateRangePicker } from \"./components/ui/form/DateRangePicker\";\nexport { Input } from \"./components/ui/form/Input\";\nexport {\n InputOTP,\n InputOTPGroup,\n InputOTPSlot,\n InputOTPSeparator,\n} from \"./components/ui/form/InputOtp\";\nexport { RadioGroup, RadioGroupItem } from \"./components/ui/form/RadioGroup\";\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n} from \"./components/ui/form/Select\";\nexport { Switch } from \"./components/ui/form/Switch\";\nexport { Textarea } from \"./components/ui/form/Textarea\";\n\n// UI - Overlay\nexport {\n Command,\n CommandDialog,\n CommandInput,\n CommandList,\n CommandEmpty,\n CommandGroup,\n CommandItem,\n CommandShortcut,\n CommandSeparator,\n} from \"./components/ui/overlay/Command\";\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n} from \"./components/ui/overlay/Dialog\";\nexport { DialogLayer, useDialogLayer } from \"./components/ui/overlay/layers\";\nexport {\n Popover,\n PopoverTrigger,\n PopoverContent,\n PopoverAnchor,\n} from \"./components/ui/overlay/Popover\";\nexport {\n Sheet,\n SheetTrigger,\n SheetClose,\n SheetContent,\n SheetHeader,\n SheetFooter,\n SheetTitle,\n SheetDescription,\n} from \"./components/ui/overlay/Sheet\";\nexport {\n Tooltip,\n TooltipTrigger,\n TooltipContent,\n TooltipProvider,\n} from \"./components/ui/overlay/Tooltip\";\n\n// Embeds\nexport { FrillEmbed } from \"./components/embeds/FrillEmbed\";\nexport {\n CrispEmbed,\n openCrispHelpdesk,\n hideCrisp,\n showCrisp,\n updateCrispUser,\n} from \"./components/embeds/CrispEmbed\";\nexport { EmbedWidgets } from \"./components/embeds/EmbedWidgets\";\nexport { ClarityEmbed } from \"./components/embeds/ClarityEmbed\";\n\n// Store\nexport { useMdSidebarStore } from \"./store/useMdSidebarStore\";\nexport { useDesktopSidebarStore } from \"./store/useDesktopSidebarStore\";\nexport { useModalManager } from \"./store/useModalManager\";\nexport type { ModalData } from \"./store/useModalManager\";\n\n// Enums\nexport { AccountSectionType } from \"./enums/AccountSectionType\";\n\n// Hooks\nexport { default as usePasswordVisibility } from \"./hooks/usePasswordVisibility\";\nexport { default as useCountdownTimer } from \"./hooks/useCountdownTimer\";\nexport { default as useIsMobile } from \"./hooks/useIsMobile\";\nexport { useDebounce } from \"./hooks/useDebounce\";\nexport { useDebouncedEffect } from \"./hooks/useDebouncedEffect\";\nexport { useDebounceState } from \"./hooks/useDebounceState\";\n\n// Utils\nexport {\n formatPhone,\n formatTimer,\n formatFullName,\n formatCPF,\n formatCNPJ,\n formatCardNumber,\n} from \"./utils/format/masks\";\nexport {\n formatCurrency,\n formatCurrencyNumber,\n parseCurrencyToNumber,\n getCurrencyForGateway,\n getLocaleForCurrency,\n} from \"./utils/format/currency\";\nexport type { CurrencyCode } from \"./utils/format/currency\";\nexport {\n USD_GATEWAY,\n isUsdGateway,\n isUsdAccount,\n allowedPaymentMethods,\n isPaymentMethodAllowed,\n canBuyStandaloneAiCredits,\n} from \"./utils/format/gateway\";\nexport type { AccountGatewayLike, PaymentMethodKind } from \"./utils/format/gateway\";\nexport { isValidCPF, isValidCNPJ, isValidTaxId } from \"./utils/validators/common\";\nexport { BR_STATE_OPTIONS } from \"./utils/constants/br-states\";\nexport type { TimezoneOption } from \"./modules/accounts/services/timezone.service\";\nexport {\n buildLocaleOptions,\n LANGUAGE_OPTIONS as LOCALE_LANGUAGE_OPTIONS,\n} from \"./utils/intl/locales\";\nexport type { LocaleOption } from \"./utils/intl/locales\";\nexport { copyToClipboard, readFromClipboard } from \"./utils/browser/clipboard\";\n\n// UI - Form (new widgets)\nexport { FormField } from \"./components/ui/form/FormField\";\nexport { SelectField } from \"./components/ui/form/SelectField\";\nexport { ComboboxField } from \"./components/ui/form/ComboboxField\";\nexport type { ComboboxOption } from \"./components/ui/form/ComboboxField\";\nexport { default as PhoneInput } from \"./components/ui/form/PhoneInput\";\nexport { default as SwitchOptionFieldWithIcon } from \"./components/ui/form/SwitchOptionFieldWithIcon\";\nexport { TextAreaField } from \"./components/ui/form/TextAreaField\";\n\n// Account Module - Hooks\nexport {\n useCurrentAccount,\n ACCOUNT_QUERY_KEY,\n} from \"./modules/accounts/hooks/current-account.hook\";\nexport { useCurrencyFormatter } from \"./modules/accounts/hooks/use-currency-formatter.hook\";\nexport {\n useUpdateAccount,\n useUpdateAccountUser,\n useUpdateAccountUserById,\n useUpdateBillingData,\n useDeleteAccountUser,\n useDeleteAccount,\n ACCOUNT_USERS_QUERY_KEY,\n} from \"./modules/accounts/hooks/useAccountManagement\";\nexport { useViaCep } from \"./modules/accounts/hooks/useViaCep\";\nexport { useAccountToken } from \"./modules/accounts/hooks/use-account-token.hook\";\nexport { useRequiredBillingData } from \"./modules/accounts/hooks/use-required-billing-data.hook\";\nexport {\n hasCompleteBillingData,\n isBrazilianBillingAccount,\n} from \"./modules/accounts/utils/billing-data\";\nexport type { BillingDataSnapshot } from \"./modules/accounts/utils/billing-data\";\n\n// Account Types\nexport type {\n UpdateAccountRequest,\n UpdateBillingDataRequest,\n UpdateAccountUserRequest,\n ChangePasswordRequest,\n DeleteAccountActionResult,\n DeleteUserActionResult,\n UpdateAccountActionResult,\n UpdateUserActionResult,\n TwoFactorGenerateResult,\n TwoFactorActionResult,\n ContactResetResult,\n} from \"./modules/accounts/types\";\n\nexport { default as AccountModals } from \"./components/account/AccountModals\";\nexport { useAccountModals } from \"./store/useAccountModals\";\nexport type { AccountModalsConfig } from \"./store/useAccountModals\";\n\nexport { ModalManager } from \"./components/modals/ModalManager\";\nexport { Modals } from \"./components/modals/Modals\";\n\nexport { default as TwoFactorAuthModal } from \"./components/account/TwoFactorAuthModal\";\nexport { default as DisableTwoFactorAuthModal } from \"./components/account/DisableTwoFactorAuthModal\";\nexport { default as ConfirmGlobalPreferencesModal } from \"./components/account/ConfirmGlobalPreferencesModal\";\nexport { MyProfileSection } from \"./components/account/sections/MyProfileSection\";\nexport { PreferencesSection } from \"./components/account/sections/PreferencesSection\";\nexport { SecuritySection } from \"./components/account/sections/SecuritySection\";\nexport { ChangePasswordSection } from \"./components/account/sections/ChangePasswordSection\";\nexport { ChangeEmailModal } from \"./components/account/sections/ChangeEmailModal\";\nexport { ChangePhoneModal } from \"./components/account/sections/ChangePhoneModal\";\n\n// Account Constants\nexport {\n GENDER_OPTIONS,\n CURRENCY_OPTIONS,\n TIME_FORMAT_OPTIONS,\n NOTIFICATION_TYPES,\n LANGUAGE_OPTIONS,\n} from \"./components/account/constants\";\n\n// Image Upload\nexport {\n ImageUpload,\n ImageCropModal,\n ImageTooSmallModal,\n} from \"./components/widgets/ImageUpload\";\nexport {\n useImageUpload,\n type ImageTooSmallError,\n} from \"./modules/images/hooks/use-image-upload.hook\";\nexport {\n ACCEPTED_IMAGE_FORMATS,\n ACCEPTED_IMAGE_FORMATS_STRING,\n MAX_FILE_SIZE_MB,\n} from \"./modules/images/constants/image.constants\";\nexport type {\n ImageConfig,\n CropArea,\n ProcessedImage,\n CompressImageOptions,\n} from \"./modules/images/types/image.type\";\nexport { compressImage } from \"./modules/images/utils/compress-image\";\nexport { cropImageToCanvas } from \"./modules/images/utils/crop-image\";\nexport { base64ToFile, fileToBase64 } from \"./modules/images/utils/base64\";\nexport {\n validateImage,\n validateImageFormat,\n validateImageSize,\n getImageDimensions,\n} from \"./modules/images/utils/validate-image\";\n"],"mappings":"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","names":["default","LANGUAGE_OPTIONS"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Types\nexport * from \"./modules/auth/schema\";\nexport * from \"./modules/users/schema\";\nexport * from \"./modules/whitelabel/schema\";\n// Style types now come from whitelabel schema directly\nexport * from \"./infra/api/types\";\n\n// Contexts\nexport * from \"./providers/query.provider\";\nexport * from \"./providers/auth.provider\";\nexport * from \"./providers/whitelabel.provider\";\nexport {\n NavigationProvider,\n useNavigationFallback,\n} from \"./providers/navigation.provider\";\n\n// Navigation (safe drop-in replacement for next/navigation)\nexport { useRouter } from \"./hooks/useRouter\";\nexport type { SafeAppRouter } from \"./hooks/useRouter\";\nexport {\n usePathname,\n useSearchParams,\n useParams,\n redirect,\n notFound,\n} from \"./utils/next-navigation\";\n\n// Hooks\nexport {\n useListProjectUsers,\n LIST_PROJECT_USERS_QUERY_KEY,\n LIST_PROJECT_USERS_BASE_KEY,\n} from \"./modules/projects/hooks/list-project-users.hook\";\nexport {\n useListAvailableUsers,\n LIST_AVAILABLE_USERS_QUERY_KEY,\n LIST_AVAILABLE_USERS_BASE_KEY,\n} from \"./modules/projects/hooks/list-available-users.hook\";\nexport {\n useListAllAccountUsers,\n LIST_ALL_ACCOUNT_USERS_QUERY_KEY,\n LIST_ALL_ACCOUNT_USERS_BASE_KEY,\n} from \"./modules/projects/hooks/list-all-account-users.hook\";\nexport {\n useProjects,\n PROJECTS_BASE_KEY,\n PROJECTS_QUERY_KEY,\n} from \"./modules/projects/hooks/list-projects.hook\";\nexport {\n useInfiniteProjects,\n INFINITE_PROJECTS_QUERY_KEY,\n} from \"./modules/projects/hooks/list-infinite-projects.hook\";\nexport { useProject } from \"./modules/projects/hooks/find-project.hook\";\nexport { useCreateProject } from \"./modules/projects/hooks/create-project.hook\";\nexport { useUpdateProject } from \"./modules/projects/hooks/update-project.hook\";\nexport { useDeleteProject } from \"./modules/projects/hooks/delete-project.hook\";\nexport type {\n Project,\n ProjectsPage,\n CreateProjectRequest,\n UpdateProjectRequest,\n ProjectUser,\n AccountUser,\n AddRemoveProjectUsersParams,\n ListUsersParams,\n UsersPage,\n} from \"./modules/projects/types\";\nexport { ProjectSchema } from \"./modules/projects/types\";\nexport type { ListProjectsActionParams } from \"./modules/projects/actions/list-projects.action\";\nexport {\n useUserQuery,\n useUserValidateSession,\n useInvalidateUser,\n useSetUserData,\n useTwoFactorVerify,\n USER_QUERY_KEY,\n} from \"./modules/auth/hooks/useUserQuery\";\nexport { useManagementPermissions } from \"./modules/auth/hooks/useManagementPermissions\";\nexport type { ManagementPermission } from \"./modules/auth/types/management-permission.type\";\nexport { useSocialGoogleLogin } from \"./modules/auth/hooks/social-google-login.hook\";\nexport { useSocialGoogleOnboarding } from \"./modules/auth/hooks/social-google-onboarding.hook\";\nexport { useUnlinkGoogle } from \"./modules/auth/hooks/unlink-google.hook\";\nexport { useSubscriptions } from \"./modules/subscriptions/hooks/list-subscriptions.hook\";\nexport {\n SUBSCRIPTIONS_QUERY_KEY,\n CHARGES_QUERY_KEY,\n FREEZE_NOTICE_QUERY_KEY,\n} from \"./modules/subscriptions/constants/query-keys.constants\";\nexport { useActiveSubscription } from \"./modules/subscriptions/hooks/find-active-subscription.hook\";\nexport { useCancelledSubscriptionGuard } from \"./modules/subscriptions/hooks/use-cancelled-subscription-guard\";\nexport { useAccountFreeze } from \"./modules/subscriptions/hooks/use-account-freeze.hook\";\nexport { useFreezeNotice } from \"./modules/subscriptions/hooks/use-freeze-notice.hook\";\nexport { usePlanById } from \"./modules/plans/hooks/use-plan-by-id.hook\";\nexport { useHasPlanAddon } from \"./modules/plans/hooks/use-has-plan-addon.hook\";\nexport { useCalculateSubscription } from \"./modules/subscriptions/hooks/calculate-subscription.hook\";\nexport { useUpdateSubscriptionPlan } from \"./modules/subscriptions/hooks/update-subscription-plan.hook\";\nexport { useUpdateSubscriptionPayment } from \"./modules/subscriptions/hooks/update-subscription-payment.hook\";\nexport { useCards, CARDS_QUERY_KEY } from \"./modules/cards/hooks/cards.hook\";\nexport { useCardById } from \"./modules/cards/hooks/card-by-id.hook\";\nexport { useCreateCard } from \"./modules/cards/hooks/create-card.hook\";\nexport { useCreateSetupIntent } from \"./modules/cards/hooks/create-setup-intent.hook\";\nexport { useSetDefaultCard } from \"./modules/cards/hooks/set-default-card.hook\";\nexport { useDeleteCard } from \"./modules/cards/hooks/delete-card.hook\";\nexport { useDeleteConfirmation } from \"./modules/cards/hooks/delete-confirmation.hook\";\nexport type { DeleteConfirmationFormData } from \"./modules/cards/hooks/delete-confirmation.hook\";\nexport { useHandleDeleteCard } from \"./modules/cards/hooks/handle-delete-card.hook\";\nexport { useCharges } from \"./modules/charges/hooks/charges.hook\";\nexport { useChargeById } from \"./modules/charges/hooks/charge-by-id.hook\";\nexport { useChargeAction } from \"./modules/charges/hooks/charge-action.hook\";\nexport { useIaCredits } from \"./modules/ia-credits/hooks/ia-credits.hook\";\nexport type {\n IaCreditsSummary,\n IaCreditsSummaryData,\n IaCreditAddBatch,\n IaCreditOperation,\n} from \"./modules/ia-credits/types\";\nexport { usePurchaseIaCredits } from \"./modules/ia-credits/hooks/purchase-ia-credits.hook\";\nexport { useAiCreditsOfferEligibility } from \"./modules/ia-credits/hooks/use-offer-eligibility.hook\";\nexport {\n AI_CREDITS_FIRST_PURCHASE_OFFER,\n AI_CREDITS_OFFER_ELIGIBILITY_QUERY_KEY,\n AI_CREDITS_OFFER_MAX_REPEATS,\n AiCreditsOfferStage,\n PAYMENT_METHOD_CARD,\n PAYMENT_METHOD_PIX,\n} from \"./modules/ia-credits/constants/ai-credits-offer.constants\";\nexport type {\n AiCreditsOfferEligibility,\n AiCreditsOfferEligibilityResponse,\n AiCreditsOfferIneligibilityReason,\n PurchaseIaCreditsInput,\n PurchaseIaCreditsResult,\n} from \"./modules/ia-credits/types/ai-credits-offer.type\";\nexport {\n readOfferStageCookie,\n writeOfferStageCookie,\n} from \"./modules/ia-credits/utils/offer-stage-cookie\";\nexport type { OfferStageRecord } from \"./modules/ia-credits/utils/offer-stage-cookie\";\nexport type {\n Subscription,\n SubscriptionItem,\n FindSubscriptionsParams,\n} from \"./modules/subscriptions/types/subscription.type\";\nexport {\n SubscriptionSchema,\n SubscriptionItemSchema,\n} from \"./modules/subscriptions/types/subscription.type\";\nexport {\n ADDON_IDS,\n aiCreditUnitPrice,\n AI_CREDIT_SIZES,\n AI_CREDIT_VALUES,\n buildAiCreditOptions,\n resolveAiCreditPrice,\n} from \"./modules/subscriptions/constants/addons.constants\";\nexport type {\n AddonKindEnum,\n AiCreditOption,\n} from \"./modules/subscriptions/constants/addons.constants\";\nexport type {\n Plan,\n PlanItem,\n UiPlan,\n PlanFeature,\n PlanMainFeatures,\n PlanPricingByPeriod,\n PlanTooltips,\n} from \"./modules/plans/types/plan.type\";\nexport { PlanSchema, PlanItemSchema } from \"./modules/plans/types/plan.type\";\nexport {\n mapApiPlanToUiPlan,\n mapApiPlanToUiPlanForCurrency,\n} from \"./modules/plans/utils/map-api-plan-to-ui\";\nexport type { PlanBillingPeriod } from \"./modules/plans/utils/map-api-plan-to-ui\";\nexport {\n usePlans,\n PLANS_QUERY_KEY,\n} from \"./modules/plans/hooks/list-plans.hook\";\nexport type { BillingPeriod } from \"./modules/subscriptions/types/billing-period.type\";\nexport type {\n CalculateSubscriptionRequest,\n CalculateSubscriptionResponse,\n UpdateSubscriptionPlanRequest,\n} from \"./modules/subscriptions/types/calculate-subscription.type\";\nexport {\n PixPendingDataSchema,\n SubscriptionPendingPixResponseSchema,\n isSubscriptionPendingPixResponse,\n} from \"./modules/subscriptions/types/pix-pending.type\";\nexport type {\n PixPendingData,\n SubscriptionPendingPixResponse,\n} from \"./modules/subscriptions/types/pix-pending.type\";\nexport type {\n Card as PaymentCard,\n CreateCardRequest,\n FindCardsParams,\n SetupIntent,\n} from \"./modules/cards/types\";\nexport {\n CardSchema as PaymentCardSchema,\n CreateCardRequestSchema,\n FindCardsParamsSchema,\n SetupIntentSchema,\n} from \"./modules/cards/types\";\nexport type {\n Charge,\n FindChargesParams,\n PayChargeInput,\n} from \"./modules/charges/types/charge.type\";\nexport {\n ChargeSchema,\n FindChargesParamsSchema,\n PayChargeInputSchema,\n} from \"./modules/charges/types/charge.type\";\nexport { buildPlanExtras } from \"./modules/subscriptions/utils/build-plan-extras\";\nexport { hasSubscriptionExpired } from \"./modules/subscriptions/utils/has-subscription-expired\";\nexport { hasActivePaidSubscription } from \"./modules/subscriptions/utils/has-active-paid-subscription\";\nexport { hasPaidSubscription } from \"./modules/subscriptions/utils/has-paid-subscription\";\nexport {\n confirmPaymentIfRequired,\n PaymentAuthenticationError,\n} from \"./modules/subscriptions/utils/confirm-payment-if-required\";\nexport { SUBSCRIPTION_GRACE_PERIOD_DAYS } from \"./modules/subscriptions/constants/subscription.constants\";\nexport { getSubscriptionCancellationState } from \"./modules/subscriptions/utils/get-subscription-cancellation-state\";\nexport type { SubscriptionCancellationState } from \"./modules/subscriptions/utils/get-subscription-cancellation-state\";\nexport {\n ACCOUNT_FREEZE_AFTER_DAYS,\n FREEZE_WARNING_DAYS_BEFORE,\n} from \"./modules/subscriptions/constants/subscription.constants\";\nexport { getAccountFreezeState } from \"./modules/subscriptions/utils/get-account-freeze-state\";\nexport type { AccountFreezeState } from \"./modules/subscriptions/utils/get-account-freeze-state\";\nexport { getAccountFreezeDate } from \"./modules/subscriptions/utils/get-account-freeze-date\";\nexport type { FreezeNotice } from \"./modules/subscriptions/types/freeze-notice.type\";\nexport {\n useCountPages,\n COUNT_PAGES_QUERY_KEY,\n} from \"./modules/pages/hooks/count-pages.hook\";\nexport { PAGES_QUERY_KEY } from \"./modules/pages/constants/query-keys.constants\";\nexport {\n getPriceFromCalculatedData,\n getOriginalPriceFromCalculatedData,\n periodicityToBillingPeriod,\n} from \"./modules/subscriptions/utils/periodicity\";\nexport { useBuyCreditsModal } from \"./store/useBuyCreditsModal\";\nexport { useCreditsDisabledModal } from \"./store/useCreditsDisabledModal\";\nexport { usePaidPlanRequiredModal } from \"./store/usePaidPlanRequiredModal\";\nexport { useAccountDeletionWarningModal } from \"./store/useAccountDeletionWarningModal\";\nexport { useAiCreditsOfferModal } from \"./store/useAiCreditsOfferModal\";\nexport { default as BuyCreditsModal } from \"./components/modals/BuyCreditsModal\";\nexport { default as AiCreditsOfferModal } from \"./components/modals/promo/AiCreditsOfferModal\";\nexport { AiCreditsOfferGate } from \"./components/layouts/AiCreditsOfferGate\";\nexport type { AiCreditsOfferGateProps } from \"./components/layouts/AiCreditsOfferGate\";\nexport { default as CreditsDisabledModal } from \"./components/modals/CreditsDisabledModal\";\nexport { default as PaidPlanRequiredModal } from \"./components/modals/PaidPlanRequiredModal\";\nexport { default as AccountFrozenModal } from \"./components/modals/AccountFrozenModal\";\nexport { default as AccountDeletionWarningModal } from \"./components/modals/AccountDeletionWarningModal\";\nexport { default as RequiredBillingDataModal } from \"./components/modals/billing/RequiredBillingDataModal\";\nexport { default as AddCardModal } from \"./components/modals/cards/AddCardModal\";\nexport { DeleteCardModal } from \"./components/modals/cards/DeleteCardModal\";\nexport { CannotDeleteCardModal } from \"./components/modals/cards/CannotDeleteCardModal\";\nexport {\n CardFormFields,\n cardFormSchema,\n buildCardFormSchema,\n} from \"./components/modals/cards/CardFormFields\";\nexport type { CardFormData } from \"./components/modals/cards/CardFormFields\";\nexport { Skeleton } from \"./components/ui/feedback/Skeleton\";\nexport { PaymentInfoCard } from \"./components/ui/data-display/PaymentInfoCard\";\nexport { CardBrandIcon } from \"./components/ui/data-display/CardBrandIcons\";\nexport { GoogleIcon } from \"./components/ui/data-display/GoogleIcon\";\nexport { CardItem } from \"./components/ui/data-display/CardItem\";\n\n// Providers\nexport { QueryProvider } from \"./providers/query.provider\";\n\n// Middleware\nexport { createAuthMiddleware } from \"./middlewares/create-auth-middleware\";\nexport { createMiddlewareChain } from \"./middlewares/chain\";\nexport { continueChain, stopChain } from \"./middlewares/types\";\nexport type {\n MiddlewareFunction,\n MiddlewareConfig,\n MiddlewareResult,\n} from \"./middlewares/types\";\n\n// Utils\nexport { cn } from \"./infra/utils/clsx\";\nexport { formatShortDate, formatDateTime, calendarDateSchema, toCalendarDate, daysBetween } from \"./infra/utils/date\";\nexport { buildQueryParams } from \"./infra/utils/params\";\nexport { parseSchema, parseResult } from \"./infra/utils/parser\";\nexport { withAction } from \"./utils/withAction\";\nexport { resolveSafeRedirect, sameHostOr } from \"./utils/redirect\";\nexport { COUNTRIES, flagUrl } from \"./utils/countries\";\nexport type { Country } from \"./utils/countries\";\n\n// Layout\nexport {\n MainLayout,\n MainLayoutContent,\n MainLayoutSpacer,\n MainLayoutMain,\n} from \"./components/layouts/MainLayout\";\nexport { NavBar } from \"./components/layouts/NavBar\";\nexport type { NavBarProps } from \"./components/layouts/NavBar\";\nexport { AppNavBar } from \"./components/layouts/AppNavBar\";\nexport type { AppNavBarProps } from \"./components/layouts/AppNavBar\";\nexport { AppMobileNavBar } from \"./components/layouts/AppMobileNavBar\";\nexport type { AppMobileNavBarProps } from \"./components/layouts/AppMobileNavBar\";\nexport { SideBarNavigation } from \"./components/layouts/SideBarNavigation\";\nexport { MdSideBarNavigation } from \"./components/layouts/MdSideBarNavigation\";\nexport { default as NotificationCard } from \"./components/widgets/notifications/NotificationCard\";\nexport type { NotificationCardProps } from \"./components/widgets/notifications/NotificationCard\";\nexport { NotificationsPopover } from \"./components/layouts/NotificationsPopover\";\nexport type { NotificationsPopoverProps } from \"./components/layouts/NotificationsPopover\";\nexport { NotificationPageContent } from \"./components/pages/notifications/Notifications\";\nexport { NotFoundPage } from \"./components/pages/NotFoundPage\";\nexport { UsersSelectorPopover } from \"./components/layouts/UsersSelectorPopover\";\nexport type { UsersSelectorPopoverProps } from \"./components/layouts/UsersSelectorPopover\";\nexport { ProfilePopover } from \"./components/layouts/ProfilePopover\";\nexport type {\n ProfilePopoverProps,\n ProfileMenuItem,\n} from \"./components/layouts/ProfilePopover\";\nexport { default as WhitelabelCodes } from \"./components/layouts/WhitelabelCodes\";\nexport { NavBarItem } from \"./components/layouts/NavBarItem\";\nexport type { NavBarItemProps } from \"./components/layouts/NavBarItem\";\n\n// Navigation\nexport { AppNavigation } from \"./components/navigation/AppNavigation\";\nexport { CancelledSubscriptionBanner } from \"./components/navigation/CancelledSubscriptionBanner\";\nexport { SubscriptionBanner } from \"./components/navigation/SubscriptionBanner\";\nexport { OverdueInvoiceBanner } from \"./components/navigation/OverdueInvoiceBanner\";\nexport { UpcomingInvoiceBanner } from \"./components/navigation/UpcomingInvoiceBanner\";\nexport { TrialBanner } from \"./components/navigation/TrialBanner\";\nexport { FrozenAccountBanner } from \"./components/navigation/FrozenAccountBanner\";\nexport { FreezeWarningBanner } from \"./components/navigation/FreezeWarningBanner\";\nexport type { NavItemConfig } from \"./components/navigation/subcomponents/NavItems\";\nexport { useMobileNavbarSheet } from \"./store/useMobileNavbarSheet\";\n\n// Auth Query Key Utilities\nexport {\n useAuthQueryKey,\n useWlQueryKey,\n useWlId,\n} from \"./hooks/useAuthQueryKey\";\n\n// Hooks\nexport { default as useCopyToClipboard } from \"./hooks/copy-to-clipboard.hook\";\n\n// UI - Buttons\nexport { Button, buttonVariants } from \"./components/ui/buttons/Button\";\nexport { CopyButton } from \"./components/ui/buttons/CopyButton\";\nexport { default as CancelButton } from \"./components/ui/buttons/CancelButton\";\n\n// UI - Data Display\nexport {\n Accordion,\n AccordionItem,\n AccordionTrigger,\n AccordionContent,\n} from \"./components/ui/data-display/Accordion\";\nexport { Badge, badgeVariants } from \"./components/ui/data-display/Badge\";\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n} from \"./components/ui/data-display/Card\";\nexport {\n Pagination,\n PaginationContent,\n PaginationLink,\n PaginationItem,\n PaginationPrevious,\n PaginationNext,\n PaginationEllipsis,\n} from \"./components/ui/data-display/Pagination\";\nexport { ScrollArea, ScrollBar } from \"./components/ui/data-display/ScrollArea\";\nexport { Separator } from \"./components/ui/data-display/Separator\";\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n} from \"./components/ui/data-display/Table\";\nexport {\n Tabs,\n TabsList,\n TabsTrigger,\n TabsContent,\n} from \"./components/ui/data-display/Tabs\";\nexport { UserAvatar } from \"./components/ui/data-display/UserAvatar\";\nexport type { UserAvatarProps } from \"./components/ui/data-display/UserAvatar\";\n\n// UI - Feedback\nexport { default as CircularProgress } from \"./components/ui/feedback/CircularProgress\";\nexport { default as DefaultCircularProgress } from \"./components/ui/feedback/DefaultCircularProgress\";\nexport { Progress } from \"./components/ui/feedback/Progress\";\nexport { LoadingOverlay } from \"./components/ui/feedback/LoadingOverlay\";\nexport { useBrandLoadingIcon } from \"./hooks/useBrandLoadingIcon\";\nexport {\n Toast,\n toastVariants,\n toastIconContainerVariants,\n} from \"./components/ui/feedback/Toast\";\nexport type { ToastProps } from \"./components/ui/feedback/Toast\";\n\n// UI - Form\nexport { Calendar, CalendarDayButton } from \"./components/ui/form/Calendar\";\nexport { Checkbox } from \"./components/ui/form/Checkbox\";\nexport { DatePicker } from \"./components/ui/form/DatePicker\";\nexport { DateRangePicker } from \"./components/ui/form/DateRangePicker\";\nexport { Input } from \"./components/ui/form/Input\";\nexport {\n InputOTP,\n InputOTPGroup,\n InputOTPSlot,\n InputOTPSeparator,\n} from \"./components/ui/form/InputOtp\";\nexport { RadioGroup, RadioGroupItem } from \"./components/ui/form/RadioGroup\";\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n} from \"./components/ui/form/Select\";\nexport { Switch } from \"./components/ui/form/Switch\";\nexport { Textarea } from \"./components/ui/form/Textarea\";\n\n// UI - Overlay\nexport {\n Command,\n CommandDialog,\n CommandInput,\n CommandList,\n CommandEmpty,\n CommandGroup,\n CommandItem,\n CommandShortcut,\n CommandSeparator,\n} from \"./components/ui/overlay/Command\";\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n} from \"./components/ui/overlay/Dialog\";\nexport { DialogLayer, useDialogLayer } from \"./components/ui/overlay/layers\";\nexport {\n Popover,\n PopoverTrigger,\n PopoverContent,\n PopoverAnchor,\n} from \"./components/ui/overlay/Popover\";\nexport {\n Sheet,\n SheetTrigger,\n SheetClose,\n SheetContent,\n SheetHeader,\n SheetFooter,\n SheetTitle,\n SheetDescription,\n} from \"./components/ui/overlay/Sheet\";\nexport {\n Tooltip,\n TooltipTrigger,\n TooltipContent,\n TooltipProvider,\n} from \"./components/ui/overlay/Tooltip\";\n\n// Embeds\nexport { FrillEmbed } from \"./components/embeds/FrillEmbed\";\nexport {\n CrispEmbed,\n openCrispHelpdesk,\n hideCrisp,\n showCrisp,\n updateCrispUser,\n} from \"./components/embeds/CrispEmbed\";\nexport { EmbedWidgets } from \"./components/embeds/EmbedWidgets\";\nexport { ClarityEmbed } from \"./components/embeds/ClarityEmbed\";\n\n// Store\nexport { useMdSidebarStore } from \"./store/useMdSidebarStore\";\nexport { useDesktopSidebarStore } from \"./store/useDesktopSidebarStore\";\nexport { useModalManager } from \"./store/useModalManager\";\nexport type { ModalData } from \"./store/useModalManager\";\n\n// Enums\nexport { AccountSectionType } from \"./enums/AccountSectionType\";\n\n// Hooks\nexport { default as usePasswordVisibility } from \"./hooks/usePasswordVisibility\";\nexport { default as useCountdownTimer } from \"./hooks/useCountdownTimer\";\nexport { default as useIsMobile } from \"./hooks/useIsMobile\";\nexport { useDebounce } from \"./hooks/useDebounce\";\nexport { useDomMutationGuardHit } from \"./hooks/useDomMutationGuardHit\";\nexport type { DomMutationGuardHit } from \"./hooks/useDomMutationGuardHit\";\nexport { DOM_MUTATION_GUARD_SCRIPT } from \"./utils/dom/dom-mutation-guard\";\nexport { useDebouncedEffect } from \"./hooks/useDebouncedEffect\";\nexport { useDebounceState } from \"./hooks/useDebounceState\";\n\n// Utils\nexport {\n formatPhone,\n formatTimer,\n formatFullName,\n formatCPF,\n formatCNPJ,\n formatCardNumber,\n} from \"./utils/format/masks\";\nexport {\n formatCurrency,\n formatCurrencyNumber,\n parseCurrencyToNumber,\n getCurrencyForGateway,\n getLocaleForCurrency,\n} from \"./utils/format/currency\";\nexport type { CurrencyCode } from \"./utils/format/currency\";\nexport {\n USD_GATEWAY,\n isUsdGateway,\n isUsdAccount,\n allowedPaymentMethods,\n isPaymentMethodAllowed,\n canBuyStandaloneAiCredits,\n} from \"./utils/format/gateway\";\nexport type { AccountGatewayLike, PaymentMethodKind } from \"./utils/format/gateway\";\nexport { isValidCPF, isValidCNPJ, isValidTaxId } from \"./utils/validators/common\";\nexport { BR_STATE_OPTIONS } from \"./utils/constants/br-states\";\nexport type { TimezoneOption } from \"./modules/accounts/services/timezone.service\";\nexport {\n buildLocaleOptions,\n LANGUAGE_OPTIONS as LOCALE_LANGUAGE_OPTIONS,\n} from \"./utils/intl/locales\";\nexport type { LocaleOption } from \"./utils/intl/locales\";\nexport { copyToClipboard, readFromClipboard } from \"./utils/browser/clipboard\";\n\n// UI - Form (new widgets)\nexport { FormField } from \"./components/ui/form/FormField\";\nexport { SelectField } from \"./components/ui/form/SelectField\";\nexport { ComboboxField } from \"./components/ui/form/ComboboxField\";\nexport type { ComboboxOption } from \"./components/ui/form/ComboboxField\";\nexport { default as PhoneInput } from \"./components/ui/form/PhoneInput\";\nexport { default as SwitchOptionFieldWithIcon } from \"./components/ui/form/SwitchOptionFieldWithIcon\";\nexport { TextAreaField } from \"./components/ui/form/TextAreaField\";\n\n// Account Module - Hooks\nexport {\n useCurrentAccount,\n ACCOUNT_QUERY_KEY,\n} from \"./modules/accounts/hooks/current-account.hook\";\nexport { useCurrencyFormatter } from \"./modules/accounts/hooks/use-currency-formatter.hook\";\nexport {\n useUpdateAccount,\n useUpdateAccountUser,\n useUpdateAccountUserById,\n useUpdateBillingData,\n useDeleteAccountUser,\n useDeleteAccount,\n ACCOUNT_USERS_QUERY_KEY,\n} from \"./modules/accounts/hooks/useAccountManagement\";\nexport { useViaCep } from \"./modules/accounts/hooks/useViaCep\";\nexport { useAccountToken } from \"./modules/accounts/hooks/use-account-token.hook\";\nexport { useRequiredBillingData } from \"./modules/accounts/hooks/use-required-billing-data.hook\";\nexport {\n hasCompleteBillingData,\n isBrazilianBillingAccount,\n} from \"./modules/accounts/utils/billing-data\";\nexport type { BillingDataSnapshot } from \"./modules/accounts/utils/billing-data\";\n\n// Account Types\nexport type {\n UpdateAccountRequest,\n UpdateBillingDataRequest,\n UpdateAccountUserRequest,\n ChangePasswordRequest,\n DeleteAccountActionResult,\n DeleteUserActionResult,\n UpdateAccountActionResult,\n UpdateUserActionResult,\n TwoFactorGenerateResult,\n TwoFactorActionResult,\n ContactResetResult,\n} from \"./modules/accounts/types\";\n\nexport { default as AccountModals } from \"./components/account/AccountModals\";\nexport { useAccountModals } from \"./store/useAccountModals\";\nexport type { AccountModalsConfig } from \"./store/useAccountModals\";\n\nexport { ModalManager } from \"./components/modals/ModalManager\";\nexport { Modals } from \"./components/modals/Modals\";\n\nexport { default as TwoFactorAuthModal } from \"./components/account/TwoFactorAuthModal\";\nexport { default as DisableTwoFactorAuthModal } from \"./components/account/DisableTwoFactorAuthModal\";\nexport { default as ConfirmGlobalPreferencesModal } from \"./components/account/ConfirmGlobalPreferencesModal\";\nexport { MyProfileSection } from \"./components/account/sections/MyProfileSection\";\nexport { PreferencesSection } from \"./components/account/sections/PreferencesSection\";\nexport { SecuritySection } from \"./components/account/sections/SecuritySection\";\nexport { ChangePasswordSection } from \"./components/account/sections/ChangePasswordSection\";\nexport { ChangeEmailModal } from \"./components/account/sections/ChangeEmailModal\";\nexport { ChangePhoneModal } from \"./components/account/sections/ChangePhoneModal\";\n\n// Account Constants\nexport {\n GENDER_OPTIONS,\n CURRENCY_OPTIONS,\n TIME_FORMAT_OPTIONS,\n NOTIFICATION_TYPES,\n LANGUAGE_OPTIONS,\n} from \"./components/account/constants\";\n\n// Image Upload\nexport {\n ImageUpload,\n ImageCropModal,\n ImageTooSmallModal,\n} from \"./components/widgets/ImageUpload\";\nexport {\n useImageUpload,\n type ImageTooSmallError,\n} from \"./modules/images/hooks/use-image-upload.hook\";\nexport {\n ACCEPTED_IMAGE_FORMATS,\n ACCEPTED_IMAGE_FORMATS_STRING,\n MAX_FILE_SIZE_MB,\n} from \"./modules/images/constants/image.constants\";\nexport type {\n ImageConfig,\n CropArea,\n ProcessedImage,\n CompressImageOptions,\n} from \"./modules/images/types/image.type\";\nexport { compressImage } from \"./modules/images/utils/compress-image\";\nexport { cropImageToCanvas } from \"./modules/images/utils/crop-image\";\nexport { base64ToFile, fileToBase64 } from \"./modules/images/utils/base64\";\nexport {\n validateImage,\n validateImageFormat,\n validateImageSize,\n getImageDimensions,\n} from \"./modules/images/utils/validate-image\";\n"],"mappings":"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","names":["default","LANGUAGE_OPTIONS"]}
|
|
@@ -4,6 +4,8 @@ import { ApiError } from "../../../infra/api/types";
|
|
|
4
4
|
import { whitelabelService } from "../../whitelabel/services/whitelabel.service";
|
|
5
5
|
import { buildWlOverrideFromJwt } from "../utils/build-wl-override";
|
|
6
6
|
import { findWhitelabel } from "../../../server";
|
|
7
|
+
import { resolveLocale } from "../../../i18n/resolve-locale";
|
|
8
|
+
import { localeToApiLanguage } from "../../../utils/intl/locales";
|
|
7
9
|
const AUTH_COOKIE_NAME = "greatapps";
|
|
8
10
|
const COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
|
|
9
11
|
const FREE_PLAN_ID = 5;
|
|
@@ -184,12 +186,14 @@ class AuthService {
|
|
|
184
186
|
const trialDays = Math.min(Math.max(data.trialDays ?? 7, 1), 90);
|
|
185
187
|
trialEndDate.setDate(today.getDate() + trialDays);
|
|
186
188
|
const idPlan = await this.resolvePlanId(data.idPlan);
|
|
189
|
+
const whitelabel = await findWhitelabel().catch(() => null);
|
|
190
|
+
const language = localeToApiLanguage(await resolveLocale({ whitelabelId: whitelabel?.id ?? null }));
|
|
187
191
|
const payload = {
|
|
188
192
|
onboarding_token: data.onboardingToken,
|
|
189
193
|
name: data.user.name,
|
|
190
194
|
bussiness_type: data.businessType ?? 0,
|
|
191
|
-
language
|
|
192
|
-
timezone:
|
|
195
|
+
language,
|
|
196
|
+
timezone: clientInfo.timezone,
|
|
193
197
|
currency: "BRL",
|
|
194
198
|
location: clientInfo.location,
|
|
195
199
|
ip: clientInfo.ip,
|
|
@@ -206,7 +210,7 @@ class AuthService {
|
|
|
206
210
|
ddi: data.user.ddi || "55",
|
|
207
211
|
phone: data.user.phone || "",
|
|
208
212
|
profile: "owner",
|
|
209
|
-
language
|
|
213
|
+
language
|
|
210
214
|
},
|
|
211
215
|
subscription: isFreePlan(idPlan) ? {
|
|
212
216
|
type: "free",
|
|
@@ -279,11 +283,13 @@ class AuthService {
|
|
|
279
283
|
const trialDays = Math.min(Math.max(data.trialDays ?? 7, 1), 90);
|
|
280
284
|
trialEndDate.setDate(today.getDate() + trialDays);
|
|
281
285
|
const idPlan = await this.resolvePlanId(data.idPlan);
|
|
286
|
+
const whitelabel = await findWhitelabel().catch(() => null);
|
|
287
|
+
const language = localeToApiLanguage(await resolveLocale({ whitelabelId: whitelabel?.id ?? null }));
|
|
282
288
|
const payload = {
|
|
283
289
|
name: data.accountName,
|
|
284
290
|
bussiness_type: data.businessType ?? 0,
|
|
285
|
-
language
|
|
286
|
-
timezone:
|
|
291
|
+
language,
|
|
292
|
+
timezone: clientInfo.timezone,
|
|
287
293
|
currency: "BRL",
|
|
288
294
|
location: clientInfo.location,
|
|
289
295
|
ip: clientInfo.ip,
|
|
@@ -301,7 +307,7 @@ class AuthService {
|
|
|
301
307
|
phone: data.phone,
|
|
302
308
|
password: data.password,
|
|
303
309
|
profile: "owner",
|
|
304
|
-
language
|
|
310
|
+
language
|
|
305
311
|
},
|
|
306
312
|
subscription: isFreePlan(idPlan) ? {
|
|
307
313
|
type: "free",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/auth/services/auth.service.ts"],"sourcesContent":["import { cookies } from \"next/headers\";\n\nimport { api, type RequestConfig } from \"../../../infra/api/client\";\nimport { ApiError } from \"../../../infra/api/types\";\nimport { whitelabelService } from \"../../whitelabel/services/whitelabel.service\";\nimport { buildWlOverrideFromJwt } from \"../utils/build-wl-override\";\nimport {\n ClientInfo,\n ForgotPasswordRequest,\n ForgotPasswordResponse,\n GeoLocation,\n LoginApiResponse,\n LoginRequest,\n LoginResponse,\n LogoutApiResponse,\n LogoutRequest,\n LogoutResponse,\n RegisterApiRequest,\n RegisterApiResponse,\n RegisterRequest,\n RegisterResponse,\n ResendVerificationRequest,\n ResendVerificationResponse,\n ResetPasswordRequest,\n ResetPasswordResponse,\n SearchPlansApiResponse,\n SessionKeepRequest,\n SessionKeepResponse,\n SocialGoogleApiResponse,\n SocialGoogleResponse,\n SocialOnboardingApiResponse,\n SocialOnboardingRequest,\n SocialOnboardingResponse,\n IsolatedLoginResponse,\n TwoFactorApiResponse,\n TwoFactorRequest,\n TwoFactorResponse,\n UnlinkGoogleApiResponse,\n UnlinkGoogleResponse,\n VerifyEmailRequest,\n VerifyEmailResponse,\n} from \"../schema\";\nimport { findWhitelabel } from \"../../../server\";\n\nconst AUTH_COOKIE_NAME = \"greatapps\";\nconst COOKIE_MAX_AGE = 60 * 60 * 24 * 30;\n\n/** Plano Free (ID fixo). */\nconst FREE_PLAN_ID = 5;\n\n/**\n * O cadastro pede o Free de duas formas, e as duas valem: ausência de plano (que o\n * `resolvePlanId` traduz para o sentinela -1) e o id do próprio Free.\n *\n * Olhar só o sentinela fazia `?id_plan=5` cair no ramo `trial` e criar um trial de 7 dias\n * do plano gratuito, com `date_due` e `trial_days` — estado que não existe no produto.\n */\nfunction isFreePlan(idPlan: number): boolean {\n return idPlan === -1 || idPlan === FREE_PLAN_ID;\n}\n\nconst COOKIE_OPTIONS = {\n httpOnly: true,\n secure: process.env.NODE_ENV === \"production\",\n sameSite: \"lax\" as const,\n path: \"/\",\n};\n\nclass AuthService {\n async login(\n credentials: LoginRequest,\n clientInfo: ClientInfo,\n ): Promise<LoginResponse>;\n async login(\n credentials: LoginRequest,\n clientInfo: ClientInfo,\n options: { setCookie: false },\n ): Promise<IsolatedLoginResponse>;\n async login(\n credentials: LoginRequest,\n clientInfo: ClientInfo,\n options?: { setCookie?: boolean },\n ): Promise<LoginResponse | IsolatedLoginResponse>;\n async login(\n credentials: LoginRequest,\n clientInfo: ClientInfo,\n options?: { setCookie?: boolean },\n ): Promise<LoginResponse | IsolatedLoginResponse> {\n let requestConfig: RequestConfig | undefined;\n if (credentials.id_wl) {\n const wlToken = await whitelabelService.getTokenByWhitelabelId(\n credentials.id_wl,\n );\n requestConfig = { whiteLabelId: credentials.id_wl, authToken: wlToken };\n }\n\n const response = await api.apps.post<LoginApiResponse>(\n \"/auth/login\",\n {\n email: credentials.email,\n password: credentials.password,\n source: credentials?.source,\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n },\n requestConfig,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"E-mail ou senha incorretos\",\n response.code || \"LOGIN_FAILED\",\n 401,\n );\n }\n\n if (!response.cookie) {\n throw new ApiError(\n \"Resposta de autenticação inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n if (response.two_factor_required) {\n return { result: \"two_factor_required\", cookie: response.cookie, twoFactorMode: response.two_factor_required };\n }\n\n // Modo isolado: caller só quer o token, sem afetar a sessão do navegador\n // nem pagar pelas chamadas de user/account (ex.: fluxo de SSO).\n if (options?.setCookie === false) {\n return { result: \"success\", accessToken: response.cookie };\n }\n\n await this.setAuthCookie(response.cookie);\n\n const [{ userService }, { accountService }] = await Promise.all([\n import(\"../../users/services/user.service\"),\n import(\"../../accounts/services/account.service\"),\n ]);\n const [user, account] = await Promise.all([\n userService.findById(\n requestConfig ? { authToken: requestConfig.authToken } : undefined,\n ),\n accountService.findCurrentAccount(requestConfig),\n ]);\n\n return {\n result: \"success\",\n user,\n account,\n accessToken: response.cookie,\n refreshToken: \"\",\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\n };\n }\n\n async verifyTwoFactor(\n cookie: string,\n code: string,\n clientInfo: ClientInfo,\n options?: { window?: number; setCookie?: boolean },\n ): Promise<TwoFactorResponse> {\n const payload: TwoFactorRequest = {\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n cookie,\n code,\n };\n\n const endpoint = options?.window !== undefined ? `/auth/code?window=${options.window}` : '/auth/code';\n const response = await api.apps.post<TwoFactorApiResponse>(\n endpoint,\n payload,\n );\n\n if (response.status === 0) {\n throw new ApiError(\"Código 2FA inválido\", \"TWO_FACTOR_FAILED\", 401);\n }\n\n if (!response?.data?.cookie) {\n throw new ApiError(\n \"Resposta de autenticação inválida após 2FA\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n // Modo isolado: devolve o token sem gravar o cookie — o caller redireciona\n // pra outro lugar (ex.: SSO callback) e não quer mexer na sessão atual.\n if (options?.setCookie === false) {\n return { status: 1, accessToken: response.data.cookie };\n }\n\n await this.setAuthCookie(response.data.cookie);\n\n return { status: 1 };\n }\n\n async socialLoginGoogle(\n code: string,\n clientInfo: ClientInfo,\n ): Promise<SocialGoogleResponse> {\n const response = await api.apps.post<SocialGoogleApiResponse>(\n \"/auth/social/google\",\n {\n code,\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n verification: true,\n },\n );\n\n if (response.status === 0) {\n if (response.code === \"link_requires_password\") {\n return {\n result: \"link_requires_password\",\n message:\n response.message ||\n \"Uma conta com esse e-mail já existe. Faça login com e-mail e senha para vincular sua conta Google.\",\n };\n }\n throw new ApiError(\n response.message || \"Falha no login com Google\",\n response.code || \"GOOGLE_LOGIN_FAILED\",\n 401,\n );\n }\n\n if (response.needs_onboarding) {\n if (!response.onboarding_token || !response.partial?.email) {\n throw new ApiError(\n \"Resposta de onboarding inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n return {\n result: \"needs_onboarding\",\n onboardingToken: response.onboarding_token,\n partial: response.partial,\n };\n }\n\n if (!response.cookie) {\n throw new ApiError(\n \"Resposta de autenticação inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n if (response.two_factor_required) {\n return {\n result: \"two_factor_required\",\n cookie: response.cookie,\n twoFactorMode: response.two_factor_required,\n };\n }\n\n await this.setAuthCookie(response.cookie);\n\n const [{ userService }, { accountService }] = await Promise.all([\n import(\"../../users/services/user.service\"),\n import(\"../../accounts/services/account.service\"),\n ]);\n const [user, account] = await Promise.all([\n userService.findById(),\n accountService.findCurrentAccount(),\n ]);\n\n return {\n result: \"success\",\n user,\n account,\n accessToken: response.cookie,\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\n };\n }\n\n async completeGoogleOnboarding(\n data: SocialOnboardingRequest,\n clientInfo: ClientInfo,\n ): Promise<SocialOnboardingResponse> {\n const today = new Date();\n const trialEndDate = new Date(today);\n const trialDays = Math.min(Math.max(data.trialDays ?? 7, 1), 90);\n trialEndDate.setDate(today.getDate() + trialDays);\n\n const idPlan = await this.resolvePlanId(data.idPlan);\n\n const payload = {\n onboarding_token: data.onboardingToken,\n name: data.user.name,\n bussiness_type: data.businessType ?? 0,\n language: \"pt-br\",\n timezone: \"America/Sao_Paulo\",\n currency: \"BRL\",\n location: clientInfo.location,\n ip: clientInfo.ip,\n agent: clientInfo.agent,\n id_affiliate: data.affiliateId || 0,\n origin: data.origin,\n user: {\n id_api: \"\",\n name: data.user.name || \"\",\n last_name: data.user.last_name || \"\",\n rg: data.user.rg || \"\",\n cpf: data.user.cpf || \"\",\n gender: data.user.gender ?? 1,\n ddi: data.user.ddi || \"55\",\n phone: data.user.phone || \"\",\n profile: \"owner\",\n language: \"pt-br\",\n },\n subscription:\n isFreePlan(idPlan)\n ? {\n type: \"free\",\n id_coupon: data.couponId || 0,\n id_plan: FREE_PLAN_ID,\n id_product: 1,\n }\n : {\n type: \"trial\",\n id_coupon: data.couponId || 0,\n id_plan: idPlan,\n date_due: trialEndDate.toISOString().split(\"T\")[0],\n trial_days: trialDays,\n id_product: 1,\n },\n };\n\n const response = await api.apps.post<SocialOnboardingApiResponse>(\n \"/auth/social/onboarding\",\n payload,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"Erro ao finalizar cadastro com Google\",\n \"ONBOARDING_FAILED\",\n 400,\n );\n }\n\n if (!response.data?.length || !response.cookie) {\n throw new ApiError(\n \"Resposta de cadastro inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n await this.setAuthCookie(response.cookie);\n\n const [{ userService }, { accountService }] = await Promise.all([\n import(\"../../users/services/user.service\"),\n import(\"../../accounts/services/account.service\"),\n ]);\n const [user, account] = await Promise.all([\n userService.findById(),\n accountService.findCurrentAccount(),\n ]);\n\n return {\n user,\n account,\n accessToken: response.cookie,\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\n };\n }\n\n async unlinkGoogle(): Promise<UnlinkGoogleResponse> {\n const { id_account, id_user } = await import(\n \"../utils/get-user-context\"\n ).then((m) => m.getUserContext());\n\n const response = await api.apps.delete<UnlinkGoogleApiResponse>(\n `/accounts/${id_account}/users/${id_user}/social/google`,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"Erro ao desvincular conta Google\",\n \"UNLINK_FAILED\",\n 400,\n );\n }\n\n return {\n success: true,\n message: response.message,\n };\n }\n\n async register(\n data: RegisterRequest,\n clientInfo: ClientInfo,\n ): Promise<RegisterResponse> {\n const today = new Date();\n const trialEndDate = new Date(today);\n const trialDays = Math.min(Math.max(data.trialDays ?? 7, 1), 90);\n trialEndDate.setDate(today.getDate() + trialDays);\n\n const idPlan = await this.resolvePlanId(data.idPlan);\n\n const payload: RegisterApiRequest = {\n name: data.accountName,\n bussiness_type: data.businessType ?? 0,\n language: \"pt-br\",\n timezone: \"America/Sao_Paulo\",\n currency: \"BRL\",\n location: clientInfo.location,\n ip: clientInfo.ip,\n agent: clientInfo.agent,\n id_affiliate: data.affiliateId || 0,\n origin: data.origin,\n user: {\n id_api: \"\",\n name: data.name,\n last_name: data.lastName || \"\",\n rg: data.rg || \"\",\n cpf: data.cpf || \"\",\n gender: data.gender,\n email: data.email,\n phone: data.phone,\n password: data.password,\n profile: \"owner\",\n language: \"pt-br\",\n },\n subscription:\n isFreePlan(idPlan)\n ? {\n type: \"free\",\n id_coupon: data.couponId || 0,\n id_plan: FREE_PLAN_ID,\n id_product: 1,\n }\n : {\n type: \"trial\",\n id_coupon: data.couponId || 0,\n id_plan: idPlan,\n // Fluxo não-Stripe lê `date_due`; fluxo Stripe lê `trial_days`.\n // Mandamos os dois pra cobrir ambos os caminhos da API.\n date_due: trialEndDate.toISOString().split(\"T\")[0],\n trial_days: trialDays,\n id_product: 1,\n },\n };\n\n const response = await api.apps.post<RegisterApiResponse>(\n \"/accounts\",\n payload,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"Erro ao criar conta\",\n \"REGISTER_FAILED\",\n 400,\n );\n }\n\n if (!response.data || response.data.length === 0) {\n throw new ApiError(\n \"Resposta de registro inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n if (!response.cookie) {\n throw new ApiError(\n \"Resposta de autenticação inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n const accountData = response.data[0];\n\n await this.setAuthCookie(response.cookie);\n\n const [{ userService }, { accountService }] = await Promise.all([\n import(\"../../users/services/user.service\"),\n import(\"../../accounts/services/account.service\"),\n ]);\n const [user, account] = await Promise.all([\n userService.findById(),\n accountService.findCurrentAccount(),\n ]);\n\n return {\n user,\n account,\n accessToken: response.cookie,\n refreshToken: \"\",\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\n requiresEmailVerification: !accountData.verified,\n };\n }\n\n async logout(clientInfo: ClientInfo): Promise<LogoutResponse> {\n const cookie = await this.getToken();\n\n if (!cookie) {\n throw new ApiError(\n \"Usuário não autenticado\",\n \"NOT_AUTHENTICATED_LOGOUT\",\n 401\n );\n }\n\n const payload: LogoutRequest = {\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n cookie,\n };\n\n try {\n const response = await api.apps.post<LogoutApiResponse>(\n \"/auth/logout\",\n payload,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"Erro ao realizar logout\",\n response.code || \"LOGOUT_FAILED\",\n 400,\n );\n }\n } finally {\n await this.removeAuthCookie();\n }\n\n return {\n success: true,\n };\n }\n\n async forgotPassword(\n _data: ForgotPasswordRequest,\n ): Promise<ForgotPasswordResponse> {\n throw new ApiError(\n \"Recuperação de senha não implementada\",\n \"NOT_IMPLEMENTED\",\n 501,\n );\n }\n\n async resetPassword(\n _data: ResetPasswordRequest,\n ): Promise<ResetPasswordResponse> {\n throw new ApiError(\n \"Redefinição de senha não implementada\",\n \"NOT_IMPLEMENTED\",\n 501,\n );\n }\n\n async verifyEmail(_data: VerifyEmailRequest): Promise<VerifyEmailResponse> {\n throw new ApiError(\n \"Verificação de email não implementada\",\n \"NOT_IMPLEMENTED\",\n 501,\n );\n }\n\n async resendVerification(\n _data: ResendVerificationRequest,\n ): Promise<ResendVerificationResponse> {\n throw new ApiError(\n \"Reenvio de verificação não implementado\",\n \"NOT_IMPLEMENTED\",\n 501,\n );\n }\n\n async validateSession(clientInfo: ClientInfo): Promise<boolean> {\n const cookie = await this.getToken();\n\n if (!cookie) {\n return false;\n }\n\n try {\n const requestConfig = await buildWlOverrideFromJwt(cookie);\n\n const payload: SessionKeepRequest = {\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n cookie,\n };\n\n const response = await api.apps.post<SessionKeepResponse>(\n \"/auth/keep\",\n payload,\n requestConfig,\n );\n\n return response.status === 1;\n } catch (error) {\n console.error(\"[AuthService] validateSession error\", error);\n return false;\n }\n }\n\n async isAuthenticated(): Promise<boolean> {\n const token = await this.getToken();\n return !!token;\n }\n\n async getToken(): Promise<string | undefined> {\n if (process.env.DUMMY_AUTH_TOKEN) return process.env.DUMMY_AUTH_TOKEN;\n const cookieStore = await cookies();\n return cookieStore.get(AUTH_COOKIE_NAME)?.value;\n }\n\n private async resolvePlanId(idPlan?: number | string | null): Promise<number> {\n if (idPlan == null || idPlan === \"\") return -1;\n if (typeof idPlan === \"number\" || Number(idPlan)) return Number(idPlan);\n\n if (typeof idPlan === \"string\") {\n const response = await api.apps.get<SearchPlansApiResponse>(\n `/plans?search=${encodeURIComponent(idPlan)}`,\n );\n\n if (response.status === 1 && response.data?.length) {\n return response.data[0].id;\n }\n\n throw new ApiError(\n `Plano \"${idPlan}\" não encontrado`,\n \"PLAN_NOT_FOUND\",\n 404,\n );\n }\n return -1;\n }\n\n private async setAuthCookie(token: string): Promise<void> {\n const cookieStore = await cookies();\n const whitelabel = await findWhitelabel().catch(() => null);\n const cookieDomain =\n this.normalizeCookieDomain(whitelabel?.domain);\n\n cookieStore.set(AUTH_COOKIE_NAME, token, {\n ...COOKIE_OPTIONS,\n ...(cookieDomain ? { domain: cookieDomain } : {}),\n maxAge: COOKIE_MAX_AGE,\n });\n }\n\n async removeAuthCookie(): Promise<void> {\n const cookieStore = await cookies();\n const whitelabel = await findWhitelabel().catch(() => null);\n const cookieDomain =\n this.normalizeCookieDomain(whitelabel?.domain);\n\n cookieStore.delete({\n name: AUTH_COOKIE_NAME,\n ...COOKIE_OPTIONS,\n ...(cookieDomain ? { domain: cookieDomain } : {}),\n });\n }\n\n private normalizeCookieDomain(domain?: string | null): string | undefined {\n if (!domain) return undefined;\n\n const normalized = domain.trim();\n if (!normalized) return undefined;\n\n const rawHost = (() => {\n try {\n return new URL(normalized).hostname;\n } catch {\n return normalized\n .replace(/^https?:\\/\\//i, \"\")\n .replace(/^www\\./i, \"\")\n .split(\"/\")[0]\n .split(\":\")[0];\n }\n })();\n\n if (!rawHost || rawHost === \"localhost\") {\n return undefined;\n }\n\n return rawHost.startsWith(\".\") ? rawHost : `.${rawHost}`;\n }\n}\n\nexport const authService = new AuthService();\n\nexport type { ClientInfo, GeoLocation };\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/auth/services/auth.service.ts"],"sourcesContent":["import { cookies } from \"next/headers\";\n\nimport { api, type RequestConfig } from \"../../../infra/api/client\";\nimport { ApiError } from \"../../../infra/api/types\";\nimport { whitelabelService } from \"../../whitelabel/services/whitelabel.service\";\nimport { buildWlOverrideFromJwt } from \"../utils/build-wl-override\";\nimport {\n ClientInfo,\n ForgotPasswordRequest,\n ForgotPasswordResponse,\n GeoLocation,\n LoginApiResponse,\n LoginRequest,\n LoginResponse,\n LogoutApiResponse,\n LogoutRequest,\n LogoutResponse,\n RegisterApiRequest,\n RegisterApiResponse,\n RegisterRequest,\n RegisterResponse,\n ResendVerificationRequest,\n ResendVerificationResponse,\n ResetPasswordRequest,\n ResetPasswordResponse,\n SearchPlansApiResponse,\n SessionKeepRequest,\n SessionKeepResponse,\n SocialGoogleApiResponse,\n SocialGoogleResponse,\n SocialOnboardingApiResponse,\n SocialOnboardingRequest,\n SocialOnboardingResponse,\n IsolatedLoginResponse,\n TwoFactorApiResponse,\n TwoFactorRequest,\n TwoFactorResponse,\n UnlinkGoogleApiResponse,\n UnlinkGoogleResponse,\n VerifyEmailRequest,\n VerifyEmailResponse,\n} from \"../schema\";\nimport { findWhitelabel } from \"../../../server\";\nimport { resolveLocale } from \"../../../i18n/resolve-locale\";\nimport { localeToApiLanguage } from \"../../../utils/intl/locales\";\n\nconst AUTH_COOKIE_NAME = \"greatapps\";\nconst COOKIE_MAX_AGE = 60 * 60 * 24 * 30;\n\n/** Plano Free (ID fixo). */\nconst FREE_PLAN_ID = 5;\n\n/**\n * O cadastro pede o Free de duas formas, e as duas valem: ausência de plano (que o\n * `resolvePlanId` traduz para o sentinela -1) e o id do próprio Free.\n *\n * Olhar só o sentinela fazia `?id_plan=5` cair no ramo `trial` e criar um trial de 7 dias\n * do plano gratuito, com `date_due` e `trial_days` — estado que não existe no produto.\n */\nfunction isFreePlan(idPlan: number): boolean {\n return idPlan === -1 || idPlan === FREE_PLAN_ID;\n}\n\nconst COOKIE_OPTIONS = {\n httpOnly: true,\n secure: process.env.NODE_ENV === \"production\",\n sameSite: \"lax\" as const,\n path: \"/\",\n};\n\nclass AuthService {\n async login(\n credentials: LoginRequest,\n clientInfo: ClientInfo,\n ): Promise<LoginResponse>;\n async login(\n credentials: LoginRequest,\n clientInfo: ClientInfo,\n options: { setCookie: false },\n ): Promise<IsolatedLoginResponse>;\n async login(\n credentials: LoginRequest,\n clientInfo: ClientInfo,\n options?: { setCookie?: boolean },\n ): Promise<LoginResponse | IsolatedLoginResponse>;\n async login(\n credentials: LoginRequest,\n clientInfo: ClientInfo,\n options?: { setCookie?: boolean },\n ): Promise<LoginResponse | IsolatedLoginResponse> {\n let requestConfig: RequestConfig | undefined;\n if (credentials.id_wl) {\n const wlToken = await whitelabelService.getTokenByWhitelabelId(\n credentials.id_wl,\n );\n requestConfig = { whiteLabelId: credentials.id_wl, authToken: wlToken };\n }\n\n const response = await api.apps.post<LoginApiResponse>(\n \"/auth/login\",\n {\n email: credentials.email,\n password: credentials.password,\n source: credentials?.source,\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n },\n requestConfig,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"E-mail ou senha incorretos\",\n response.code || \"LOGIN_FAILED\",\n 401,\n );\n }\n\n if (!response.cookie) {\n throw new ApiError(\n \"Resposta de autenticação inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n if (response.two_factor_required) {\n return { result: \"two_factor_required\", cookie: response.cookie, twoFactorMode: response.two_factor_required };\n }\n\n // Modo isolado: caller só quer o token, sem afetar a sessão do navegador\n // nem pagar pelas chamadas de user/account (ex.: fluxo de SSO).\n if (options?.setCookie === false) {\n return { result: \"success\", accessToken: response.cookie };\n }\n\n await this.setAuthCookie(response.cookie);\n\n const [{ userService }, { accountService }] = await Promise.all([\n import(\"../../users/services/user.service\"),\n import(\"../../accounts/services/account.service\"),\n ]);\n const [user, account] = await Promise.all([\n userService.findById(\n requestConfig ? { authToken: requestConfig.authToken } : undefined,\n ),\n accountService.findCurrentAccount(requestConfig),\n ]);\n\n return {\n result: \"success\",\n user,\n account,\n accessToken: response.cookie,\n refreshToken: \"\",\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\n };\n }\n\n async verifyTwoFactor(\n cookie: string,\n code: string,\n clientInfo: ClientInfo,\n options?: { window?: number; setCookie?: boolean },\n ): Promise<TwoFactorResponse> {\n const payload: TwoFactorRequest = {\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n cookie,\n code,\n };\n\n const endpoint = options?.window !== undefined ? `/auth/code?window=${options.window}` : '/auth/code';\n const response = await api.apps.post<TwoFactorApiResponse>(\n endpoint,\n payload,\n );\n\n if (response.status === 0) {\n throw new ApiError(\"Código 2FA inválido\", \"TWO_FACTOR_FAILED\", 401);\n }\n\n if (!response?.data?.cookie) {\n throw new ApiError(\n \"Resposta de autenticação inválida após 2FA\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n // Modo isolado: devolve o token sem gravar o cookie — o caller redireciona\n // pra outro lugar (ex.: SSO callback) e não quer mexer na sessão atual.\n if (options?.setCookie === false) {\n return { status: 1, accessToken: response.data.cookie };\n }\n\n await this.setAuthCookie(response.data.cookie);\n\n return { status: 1 };\n }\n\n async socialLoginGoogle(\n code: string,\n clientInfo: ClientInfo,\n ): Promise<SocialGoogleResponse> {\n const response = await api.apps.post<SocialGoogleApiResponse>(\n \"/auth/social/google\",\n {\n code,\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n verification: true,\n },\n );\n\n if (response.status === 0) {\n if (response.code === \"link_requires_password\") {\n return {\n result: \"link_requires_password\",\n message:\n response.message ||\n \"Uma conta com esse e-mail já existe. Faça login com e-mail e senha para vincular sua conta Google.\",\n };\n }\n throw new ApiError(\n response.message || \"Falha no login com Google\",\n response.code || \"GOOGLE_LOGIN_FAILED\",\n 401,\n );\n }\n\n if (response.needs_onboarding) {\n if (!response.onboarding_token || !response.partial?.email) {\n throw new ApiError(\n \"Resposta de onboarding inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n return {\n result: \"needs_onboarding\",\n onboardingToken: response.onboarding_token,\n partial: response.partial,\n };\n }\n\n if (!response.cookie) {\n throw new ApiError(\n \"Resposta de autenticação inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n if (response.two_factor_required) {\n return {\n result: \"two_factor_required\",\n cookie: response.cookie,\n twoFactorMode: response.two_factor_required,\n };\n }\n\n await this.setAuthCookie(response.cookie);\n\n const [{ userService }, { accountService }] = await Promise.all([\n import(\"../../users/services/user.service\"),\n import(\"../../accounts/services/account.service\"),\n ]);\n const [user, account] = await Promise.all([\n userService.findById(),\n accountService.findCurrentAccount(),\n ]);\n\n return {\n result: \"success\",\n user,\n account,\n accessToken: response.cookie,\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\n };\n }\n\n async completeGoogleOnboarding(\n data: SocialOnboardingRequest,\n clientInfo: ClientInfo,\n ): Promise<SocialOnboardingResponse> {\n const today = new Date();\n const trialEndDate = new Date(today);\n const trialDays = Math.min(Math.max(data.trialDays ?? 7, 1), 90);\n trialEndDate.setDate(today.getDate() + trialDays);\n\n const idPlan = await this.resolvePlanId(data.idPlan);\n\n const whitelabel = await findWhitelabel().catch(() => null);\n const language = localeToApiLanguage(await resolveLocale({ whitelabelId: whitelabel?.id ?? null }));\n\n const payload = {\n onboarding_token: data.onboardingToken,\n name: data.user.name,\n bussiness_type: data.businessType ?? 0,\n language,\n timezone: clientInfo.timezone,\n currency: \"BRL\",\n location: clientInfo.location,\n ip: clientInfo.ip,\n agent: clientInfo.agent,\n id_affiliate: data.affiliateId || 0,\n origin: data.origin,\n user: {\n id_api: \"\",\n name: data.user.name || \"\",\n last_name: data.user.last_name || \"\",\n rg: data.user.rg || \"\",\n cpf: data.user.cpf || \"\",\n gender: data.user.gender ?? 1,\n ddi: data.user.ddi || \"55\",\n phone: data.user.phone || \"\",\n profile: \"owner\",\n language,\n },\n subscription:\n isFreePlan(idPlan)\n ? {\n type: \"free\",\n id_coupon: data.couponId || 0,\n id_plan: FREE_PLAN_ID,\n id_product: 1,\n }\n : {\n type: \"trial\",\n id_coupon: data.couponId || 0,\n id_plan: idPlan,\n date_due: trialEndDate.toISOString().split(\"T\")[0],\n trial_days: trialDays,\n id_product: 1,\n },\n };\n\n const response = await api.apps.post<SocialOnboardingApiResponse>(\n \"/auth/social/onboarding\",\n payload,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"Erro ao finalizar cadastro com Google\",\n \"ONBOARDING_FAILED\",\n 400,\n );\n }\n\n if (!response.data?.length || !response.cookie) {\n throw new ApiError(\n \"Resposta de cadastro inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n await this.setAuthCookie(response.cookie);\n\n const [{ userService }, { accountService }] = await Promise.all([\n import(\"../../users/services/user.service\"),\n import(\"../../accounts/services/account.service\"),\n ]);\n const [user, account] = await Promise.all([\n userService.findById(),\n accountService.findCurrentAccount(),\n ]);\n\n return {\n user,\n account,\n accessToken: response.cookie,\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\n };\n }\n\n async unlinkGoogle(): Promise<UnlinkGoogleResponse> {\n const { id_account, id_user } = await import(\n \"../utils/get-user-context\"\n ).then((m) => m.getUserContext());\n\n const response = await api.apps.delete<UnlinkGoogleApiResponse>(\n `/accounts/${id_account}/users/${id_user}/social/google`,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"Erro ao desvincular conta Google\",\n \"UNLINK_FAILED\",\n 400,\n );\n }\n\n return {\n success: true,\n message: response.message,\n };\n }\n\n async register(\n data: RegisterRequest,\n clientInfo: ClientInfo,\n ): Promise<RegisterResponse> {\n const today = new Date();\n const trialEndDate = new Date(today);\n const trialDays = Math.min(Math.max(data.trialDays ?? 7, 1), 90);\n trialEndDate.setDate(today.getDate() + trialDays);\n\n const idPlan = await this.resolvePlanId(data.idPlan);\n\n const whitelabel = await findWhitelabel().catch(() => null);\n const language = localeToApiLanguage(await resolveLocale({ whitelabelId: whitelabel?.id ?? null }));\n\n const payload: RegisterApiRequest = {\n name: data.accountName,\n bussiness_type: data.businessType ?? 0,\n language,\n timezone: clientInfo.timezone,\n currency: \"BRL\",\n location: clientInfo.location,\n ip: clientInfo.ip,\n agent: clientInfo.agent,\n id_affiliate: data.affiliateId || 0,\n origin: data.origin,\n user: {\n id_api: \"\",\n name: data.name,\n last_name: data.lastName || \"\",\n rg: data.rg || \"\",\n cpf: data.cpf || \"\",\n gender: data.gender,\n email: data.email,\n phone: data.phone,\n password: data.password,\n profile: \"owner\",\n language,\n },\n subscription:\n isFreePlan(idPlan)\n ? {\n type: \"free\",\n id_coupon: data.couponId || 0,\n id_plan: FREE_PLAN_ID,\n id_product: 1,\n }\n : {\n type: \"trial\",\n id_coupon: data.couponId || 0,\n id_plan: idPlan,\n // Fluxo não-Stripe lê `date_due`; fluxo Stripe lê `trial_days`.\n // Mandamos os dois pra cobrir ambos os caminhos da API.\n date_due: trialEndDate.toISOString().split(\"T\")[0],\n trial_days: trialDays,\n id_product: 1,\n },\n };\n\n const response = await api.apps.post<RegisterApiResponse>(\n \"/accounts\",\n payload,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"Erro ao criar conta\",\n \"REGISTER_FAILED\",\n 400,\n );\n }\n\n if (!response.data || response.data.length === 0) {\n throw new ApiError(\n \"Resposta de registro inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n if (!response.cookie) {\n throw new ApiError(\n \"Resposta de autenticação inválida\",\n \"INVALID_RESPONSE\",\n 500,\n );\n }\n\n const accountData = response.data[0];\n\n await this.setAuthCookie(response.cookie);\n\n const [{ userService }, { accountService }] = await Promise.all([\n import(\"../../users/services/user.service\"),\n import(\"../../accounts/services/account.service\"),\n ]);\n const [user, account] = await Promise.all([\n userService.findById(),\n accountService.findCurrentAccount(),\n ]);\n\n return {\n user,\n account,\n accessToken: response.cookie,\n refreshToken: \"\",\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\n requiresEmailVerification: !accountData.verified,\n };\n }\n\n async logout(clientInfo: ClientInfo): Promise<LogoutResponse> {\n const cookie = await this.getToken();\n\n if (!cookie) {\n throw new ApiError(\n \"Usuário não autenticado\",\n \"NOT_AUTHENTICATED_LOGOUT\",\n 401\n );\n }\n\n const payload: LogoutRequest = {\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n cookie,\n };\n\n try {\n const response = await api.apps.post<LogoutApiResponse>(\n \"/auth/logout\",\n payload,\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || \"Erro ao realizar logout\",\n response.code || \"LOGOUT_FAILED\",\n 400,\n );\n }\n } finally {\n await this.removeAuthCookie();\n }\n\n return {\n success: true,\n };\n }\n\n async forgotPassword(\n _data: ForgotPasswordRequest,\n ): Promise<ForgotPasswordResponse> {\n throw new ApiError(\n \"Recuperação de senha não implementada\",\n \"NOT_IMPLEMENTED\",\n 501,\n );\n }\n\n async resetPassword(\n _data: ResetPasswordRequest,\n ): Promise<ResetPasswordResponse> {\n throw new ApiError(\n \"Redefinição de senha não implementada\",\n \"NOT_IMPLEMENTED\",\n 501,\n );\n }\n\n async verifyEmail(_data: VerifyEmailRequest): Promise<VerifyEmailResponse> {\n throw new ApiError(\n \"Verificação de email não implementada\",\n \"NOT_IMPLEMENTED\",\n 501,\n );\n }\n\n async resendVerification(\n _data: ResendVerificationRequest,\n ): Promise<ResendVerificationResponse> {\n throw new ApiError(\n \"Reenvio de verificação não implementado\",\n \"NOT_IMPLEMENTED\",\n 501,\n );\n }\n\n async validateSession(clientInfo: ClientInfo): Promise<boolean> {\n const cookie = await this.getToken();\n\n if (!cookie) {\n return false;\n }\n\n try {\n const requestConfig = await buildWlOverrideFromJwt(cookie);\n\n const payload: SessionKeepRequest = {\n location: clientInfo.location,\n ip: clientInfo.ip,\n timezone: clientInfo.timezone,\n agent: clientInfo.agent,\n cookie,\n };\n\n const response = await api.apps.post<SessionKeepResponse>(\n \"/auth/keep\",\n payload,\n requestConfig,\n );\n\n return response.status === 1;\n } catch (error) {\n console.error(\"[AuthService] validateSession error\", error);\n return false;\n }\n }\n\n async isAuthenticated(): Promise<boolean> {\n const token = await this.getToken();\n return !!token;\n }\n\n async getToken(): Promise<string | undefined> {\n if (process.env.DUMMY_AUTH_TOKEN) return process.env.DUMMY_AUTH_TOKEN;\n const cookieStore = await cookies();\n return cookieStore.get(AUTH_COOKIE_NAME)?.value;\n }\n\n private async resolvePlanId(idPlan?: number | string | null): Promise<number> {\n if (idPlan == null || idPlan === \"\") return -1;\n if (typeof idPlan === \"number\" || Number(idPlan)) return Number(idPlan);\n\n if (typeof idPlan === \"string\") {\n const response = await api.apps.get<SearchPlansApiResponse>(\n `/plans?search=${encodeURIComponent(idPlan)}`,\n );\n\n if (response.status === 1 && response.data?.length) {\n return response.data[0].id;\n }\n\n throw new ApiError(\n `Plano \"${idPlan}\" não encontrado`,\n \"PLAN_NOT_FOUND\",\n 404,\n );\n }\n return -1;\n }\n\n private async setAuthCookie(token: string): Promise<void> {\n const cookieStore = await cookies();\n const whitelabel = await findWhitelabel().catch(() => null);\n const cookieDomain =\n this.normalizeCookieDomain(whitelabel?.domain);\n\n cookieStore.set(AUTH_COOKIE_NAME, token, {\n ...COOKIE_OPTIONS,\n ...(cookieDomain ? { domain: cookieDomain } : {}),\n maxAge: COOKIE_MAX_AGE,\n });\n }\n\n async removeAuthCookie(): Promise<void> {\n const cookieStore = await cookies();\n const whitelabel = await findWhitelabel().catch(() => null);\n const cookieDomain =\n this.normalizeCookieDomain(whitelabel?.domain);\n\n cookieStore.delete({\n name: AUTH_COOKIE_NAME,\n ...COOKIE_OPTIONS,\n ...(cookieDomain ? { domain: cookieDomain } : {}),\n });\n }\n\n private normalizeCookieDomain(domain?: string | null): string | undefined {\n if (!domain) return undefined;\n\n const normalized = domain.trim();\n if (!normalized) return undefined;\n\n const rawHost = (() => {\n try {\n return new URL(normalized).hostname;\n } catch {\n return normalized\n .replace(/^https?:\\/\\//i, \"\")\n .replace(/^www\\./i, \"\")\n .split(\"/\")[0]\n .split(\":\")[0];\n }\n })();\n\n if (!rawHost || rawHost === \"localhost\") {\n return undefined;\n }\n\n return rawHost.startsWith(\".\") ? rawHost : `.${rawHost}`;\n }\n}\n\nexport const authService = new AuthService();\n\nexport type { ClientInfo, GeoLocation };\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const DOM_MUTATION_GUARD_SCRIPT = `(function(){
|
|
2
|
+
if(typeof Node==="undefined"||!Node.prototype)return;
|
|
3
|
+
if(window.__gpDomGuard)return;
|
|
4
|
+
var s={removeChild:0,insertBefore:0};
|
|
5
|
+
window.__gpDomGuard=s;
|
|
6
|
+
window.__gpDomGuardOnHit=window.__gpDomGuardOnHit||null;
|
|
7
|
+
function hit(k){s[k]++;try{if(window.__gpDomGuardOnHit)window.__gpDomGuardOnHit(k)}catch(e){}}
|
|
8
|
+
var removeChild=Node.prototype.removeChild;
|
|
9
|
+
Node.prototype.removeChild=function(child){
|
|
10
|
+
if(child&&child.parentNode!==this){hit("removeChild");return child}
|
|
11
|
+
return removeChild.apply(this,arguments)};
|
|
12
|
+
var insertBefore=Node.prototype.insertBefore;
|
|
13
|
+
Node.prototype.insertBefore=function(newNode,referenceNode){
|
|
14
|
+
if(referenceNode&&referenceNode.parentNode!==this){hit("insertBefore");return newNode}
|
|
15
|
+
return insertBefore.apply(this,arguments)};
|
|
16
|
+
})();`;
|
|
17
|
+
export {
|
|
18
|
+
DOM_MUTATION_GUARD_SCRIPT
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=dom-mutation-guard.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/dom/dom-mutation-guard.ts"],"sourcesContent":["/**\n * Guarda contra mutação externa do DOM (tradutor do navegador, extensões).\n *\n * PROBLEMA: o Google Tradutor do Chrome substitui cada text node por `<font><font>…</font></font>`.\n * O React continua guardando a referência do text node ORIGINAL no fiber. No commit seguinte ele\n * chama `parent.insertBefore(novo, textNodeAntigo)` ou `parent.removeChild(textNodeAntigo)` — e o nó\n * já não é mais filho daquele pai. O DOM levanta `NotFoundError`, o erro sobe até o root e o app\n * inteiro cai no `global-error.tsx` (evento `render.root_crashed` no Sentry).\n *\n * Isso derrubou clientes reais em CO/PE/MX/AR/FR (zero casos no BR, onde a página já está no idioma\n * do usuário e o Chrome não oferece tradução), inclusive em cima da tela de trocar cartão — o cliente\n * ficava sem conseguir pagar.\n *\n * SOLUÇÃO: transformar essas duas operações em no-op quando o nó de referência já não pertence mais\n * ao pai. O React segue adiante, a página não morre, e o trecho traduzido apenas deixa de receber\n * aquela atualização pontual (o próximo re-render completo normaliza).\n *\n * Precisa rodar ANTES da hidratação, por isso é injetado como `<script>` inline no `<head>` do root\n * layout em vez de virar um `useEffect`.\n */\n\ndeclare global {\n interface Window {\n /** Contadores de quantas vezes a guarda entrou em ação nesta sessão. */\n __gpDomGuard?: { removeChild: number; insertBefore: number };\n /** Hook opcional preenchido pelo reporter para avisar o Sentry no primeiro disparo. */\n __gpDomGuardOnHit?: ((kind: 'removeChild' | 'insertBefore') => void) | null;\n }\n}\n\nexport const DOM_MUTATION_GUARD_SCRIPT = `(function(){\nif(typeof Node===\"undefined\"||!Node.prototype)return;\nif(window.__gpDomGuard)return;\nvar s={removeChild:0,insertBefore:0};\nwindow.__gpDomGuard=s;\nwindow.__gpDomGuardOnHit=window.__gpDomGuardOnHit||null;\nfunction hit(k){s[k]++;try{if(window.__gpDomGuardOnHit)window.__gpDomGuardOnHit(k)}catch(e){}}\nvar removeChild=Node.prototype.removeChild;\nNode.prototype.removeChild=function(child){\nif(child&&child.parentNode!==this){hit(\"removeChild\");return child}\nreturn removeChild.apply(this,arguments)};\nvar insertBefore=Node.prototype.insertBefore;\nNode.prototype.insertBefore=function(newNode,referenceNode){\nif(referenceNode&&referenceNode.parentNode!==this){hit(\"insertBefore\");return newNode}\nreturn insertBefore.apply(this,arguments)};\n})();`;\n"],"mappings":"AA8BO,MAAM,4BAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;","names":[]}
|
|
@@ -6,8 +6,13 @@ const LANGUAGE_OPTIONS = [
|
|
|
6
6
|
function buildLocaleOptions() {
|
|
7
7
|
return LANGUAGE_OPTIONS;
|
|
8
8
|
}
|
|
9
|
+
function localeToApiLanguage(locale) {
|
|
10
|
+
const option = LANGUAGE_OPTIONS.find((o) => o.value === locale);
|
|
11
|
+
return option?.apiValue ?? locale;
|
|
12
|
+
}
|
|
9
13
|
export {
|
|
10
14
|
LANGUAGE_OPTIONS,
|
|
11
|
-
buildLocaleOptions
|
|
15
|
+
buildLocaleOptions,
|
|
16
|
+
localeToApiLanguage
|
|
12
17
|
};
|
|
13
18
|
//# sourceMappingURL=locales.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/intl/locales.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/intl/locales.ts"],"sourcesContent":["import { Locale } from '../../i18n/config';\r\n\r\nexport type LocaleOption = {\r\n value: string;\r\n label: string;\r\n displayValue: string;\r\n apiValue: string;\r\n};\r\n\r\nexport const LANGUAGE_OPTIONS: LocaleOption[] = [\r\n { value: 'pt-br', label: 'Português (Brasil)', displayValue: 'Português (Brasil)', apiValue: 'pt-br' },\r\n { value: 'en-us', label: 'Inglês (EUA)', displayValue: 'Inglês (EUA)', apiValue: 'en' },\r\n { value: 'es-es', label: 'Espanhol', displayValue: 'Espanhol', apiValue: 'es' },\r\n];\r\n\r\nexport function buildLocaleOptions(): LocaleOption[] {\r\n return LANGUAGE_OPTIONS;\r\n}\r\n\r\nexport function localeToApiLanguage(locale: Locale): string {\r\n const option = LANGUAGE_OPTIONS.find((o) => o.value === locale);\r\n return option?.apiValue ?? locale;\r\n}\r\n"],"mappings":"AASO,MAAM,mBAAmC;AAAA,EAC9C,EAAE,OAAO,SAAS,OAAO,yBAAsB,cAAc,yBAAsB,UAAU,QAAQ;AAAA,EACrG,EAAE,OAAO,SAAS,OAAO,mBAAgB,cAAc,mBAAgB,UAAU,KAAK;AAAA,EACtF,EAAE,OAAO,SAAS,OAAO,YAAY,cAAc,YAAY,UAAU,KAAK;AAChF;AAEO,SAAS,qBAAqC;AACnD,SAAO;AACT;AAEO,SAAS,oBAAoB,QAAwB;AAC1D,QAAM,SAAS,iBAAiB,KAAK,CAAC,MAAM,EAAE,UAAU,MAAM;AAC9D,SAAO,QAAQ,YAAY;AAC7B;","names":[]}
|
package/package.json
CHANGED
|
@@ -7,8 +7,9 @@ import { useRouter } from 'next/navigation';
|
|
|
7
7
|
import { toast } from 'sonner';
|
|
8
8
|
import { IconLock } from '@tabler/icons-react';
|
|
9
9
|
import { cn } from '../../../infra/utils/clsx';
|
|
10
|
-
import type
|
|
10
|
+
import { isLocale, type Locale } from '../../../i18n/config';
|
|
11
11
|
import { setLocaleCookie } from '../../../utils/intl/locale-cookie';
|
|
12
|
+
import { localeToApiLanguage } from '../../../utils/intl/locales';
|
|
12
13
|
import { Button } from '../../ui/buttons/Button';
|
|
13
14
|
import { Separator } from '../../ui/data-display/Separator';
|
|
14
15
|
import { Toast } from '../../ui/feedback/Toast';
|
|
@@ -112,7 +113,7 @@ export function PreferencesSection({ onClose }: PreferencesSectionProps) {
|
|
|
112
113
|
const doSave = async (data: PreferencesFormValues, accountFields: UpdateAccountRequest) => {
|
|
113
114
|
setIsSaving(true);
|
|
114
115
|
try {
|
|
115
|
-
const apiLanguage =
|
|
116
|
+
const apiLanguage = isLocale(data.language) ? localeToApiLanguage(data.language) : data.language.toLowerCase();
|
|
116
117
|
await updateAccountUser.mutateAsync({
|
|
117
118
|
language: apiLanguage,
|
|
118
119
|
receive_sms: data.receive_sms,
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect, useRef } from 'react';
|
|
4
|
+
|
|
5
|
+
export type DomMutationGuardHit = {
|
|
6
|
+
kind: 'removeChild' | 'insertBefore';
|
|
7
|
+
language: string;
|
|
8
|
+
languages: string;
|
|
9
|
+
documentLang: string;
|
|
10
|
+
translatedNodes: number;
|
|
11
|
+
path: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Reporta quando a guarda de mutação de DOM (`DOM_MUTATION_GUARD_SCRIPT`) entra em ação.
|
|
16
|
+
*
|
|
17
|
+
* Sem isso a correção fica cega: o app para de cair, mas ninguém descobre quantos clientes estão
|
|
18
|
+
* navegando com o tradutor do navegador ligado. Reporta UMA vez por sessão — o objetivo é medir
|
|
19
|
+
* quantas sessões são afetadas, não quantas operações de DOM foram salvas.
|
|
20
|
+
*/
|
|
21
|
+
export function useDomMutationGuardHit(onHit: (hit: DomMutationGuardHit) => void): void {
|
|
22
|
+
const onHitRef = useRef(onHit);
|
|
23
|
+
onHitRef.current = onHit;
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
let reported = false;
|
|
27
|
+
|
|
28
|
+
const report = (kind: 'removeChild' | 'insertBefore') => {
|
|
29
|
+
if (reported) return;
|
|
30
|
+
reported = true;
|
|
31
|
+
window.__gpDomGuardOnHit = null;
|
|
32
|
+
onHitRef.current({
|
|
33
|
+
kind,
|
|
34
|
+
language: navigator.language,
|
|
35
|
+
languages: navigator.languages?.join(',') ?? '',
|
|
36
|
+
documentLang: document.documentElement.lang,
|
|
37
|
+
// <font> sem classe é a assinatura do Google Tradutor
|
|
38
|
+
translatedNodes: document.querySelectorAll('font[style]').length,
|
|
39
|
+
path: window.location.pathname,
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Disparos que aconteceram antes deste componente montar.
|
|
44
|
+
const already = window.__gpDomGuard;
|
|
45
|
+
if (already && (already.removeChild > 0 || already.insertBefore > 0)) {
|
|
46
|
+
report(already.insertBefore > 0 ? 'insertBefore' : 'removeChild');
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
window.__gpDomGuardOnHit = report;
|
|
51
|
+
return () => {
|
|
52
|
+
window.__gpDomGuardOnHit = null;
|
|
53
|
+
};
|
|
54
|
+
}, []);
|
|
55
|
+
}
|
|
@@ -39,14 +39,24 @@ export interface ResolveLocaleOptions {
|
|
|
39
39
|
userLanguage?: string | null;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
function localeFromAcceptLanguage(header: string | null): Locale | null {
|
|
43
|
+
if (!header) return null;
|
|
44
|
+
for (const entry of header.split(',')) {
|
|
45
|
+
const locale = normalizeLocale(entry.split(';')[0].trim());
|
|
46
|
+
if (locale) return locale;
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
42
51
|
/**
|
|
43
52
|
* Resolve o locale da requisição (server-side). Ordem de prioridade:
|
|
44
53
|
*
|
|
45
54
|
* 1. **Whitelabel não-padrão** (`id_wl != 1`) → `pt` (por enquanto, whitelabels não são localizadas).
|
|
46
55
|
* 2. **Preferência da conta** (`userLanguage`), quando fornecida.
|
|
47
56
|
* 3. **Cookie `NEXT_LOCALE`** — cache da preferência ou escolha manual do visitante.
|
|
48
|
-
* 4. **
|
|
49
|
-
* 5. **
|
|
57
|
+
* 4. **Header `Accept-Language`** do navegador.
|
|
58
|
+
* 5. **Inferência por país** — JWT (`session.location.country`) ou header `CF-IPCountry`.
|
|
59
|
+
* 6. **Fallback** → {@link DEFAULT_LOCALE}.
|
|
50
60
|
*/
|
|
51
61
|
export async function resolveLocale(options: ResolveLocaleOptions = {}): Promise<Locale> {
|
|
52
62
|
const cookieStore = await cookies();
|
|
@@ -67,12 +77,17 @@ export async function resolveLocale(options: ResolveLocaleOptions = {}): Promise
|
|
|
67
77
|
const fromCookie = normalizeLocale(cookieStore.get(LOCALE_COOKIE)?.value);
|
|
68
78
|
if (fromCookie) return fromCookie;
|
|
69
79
|
|
|
70
|
-
// 4. Inferência por país (geo)
|
|
71
80
|
const headersList = await headers();
|
|
81
|
+
|
|
82
|
+
// 4. Header Accept-Language do navegador
|
|
83
|
+
const fromAcceptLanguage = localeFromAcceptLanguage(headersList.get('accept-language'));
|
|
84
|
+
if (fromAcceptLanguage) return fromAcceptLanguage;
|
|
85
|
+
|
|
86
|
+
// 5. Inferência por país (geo)
|
|
72
87
|
const country = jwt?.country ?? headersList.get(GEO_HEADER);
|
|
73
88
|
const fromGeo = localeFromCountry(country);
|
|
74
89
|
if (fromGeo) return fromGeo;
|
|
75
90
|
|
|
76
|
-
//
|
|
91
|
+
// 6. Fallback
|
|
77
92
|
return DEFAULT_LOCALE;
|
|
78
93
|
}
|
package/src/index.ts
CHANGED
|
@@ -515,6 +515,9 @@ export { default as usePasswordVisibility } from "./hooks/usePasswordVisibility"
|
|
|
515
515
|
export { default as useCountdownTimer } from "./hooks/useCountdownTimer";
|
|
516
516
|
export { default as useIsMobile } from "./hooks/useIsMobile";
|
|
517
517
|
export { useDebounce } from "./hooks/useDebounce";
|
|
518
|
+
export { useDomMutationGuardHit } from "./hooks/useDomMutationGuardHit";
|
|
519
|
+
export type { DomMutationGuardHit } from "./hooks/useDomMutationGuardHit";
|
|
520
|
+
export { DOM_MUTATION_GUARD_SCRIPT } from "./utils/dom/dom-mutation-guard";
|
|
518
521
|
export { useDebouncedEffect } from "./hooks/useDebouncedEffect";
|
|
519
522
|
export { useDebounceState } from "./hooks/useDebounceState";
|
|
520
523
|
|
|
@@ -41,6 +41,8 @@ import {
|
|
|
41
41
|
VerifyEmailResponse,
|
|
42
42
|
} from "../schema";
|
|
43
43
|
import { findWhitelabel } from "../../../server";
|
|
44
|
+
import { resolveLocale } from "../../../i18n/resolve-locale";
|
|
45
|
+
import { localeToApiLanguage } from "../../../utils/intl/locales";
|
|
44
46
|
|
|
45
47
|
const AUTH_COOKIE_NAME = "greatapps";
|
|
46
48
|
const COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
|
|
@@ -295,12 +297,15 @@ class AuthService {
|
|
|
295
297
|
|
|
296
298
|
const idPlan = await this.resolvePlanId(data.idPlan);
|
|
297
299
|
|
|
300
|
+
const whitelabel = await findWhitelabel().catch(() => null);
|
|
301
|
+
const language = localeToApiLanguage(await resolveLocale({ whitelabelId: whitelabel?.id ?? null }));
|
|
302
|
+
|
|
298
303
|
const payload = {
|
|
299
304
|
onboarding_token: data.onboardingToken,
|
|
300
305
|
name: data.user.name,
|
|
301
306
|
bussiness_type: data.businessType ?? 0,
|
|
302
|
-
language
|
|
303
|
-
timezone:
|
|
307
|
+
language,
|
|
308
|
+
timezone: clientInfo.timezone,
|
|
304
309
|
currency: "BRL",
|
|
305
310
|
location: clientInfo.location,
|
|
306
311
|
ip: clientInfo.ip,
|
|
@@ -317,7 +322,7 @@ class AuthService {
|
|
|
317
322
|
ddi: data.user.ddi || "55",
|
|
318
323
|
phone: data.user.phone || "",
|
|
319
324
|
profile: "owner",
|
|
320
|
-
language
|
|
325
|
+
language,
|
|
321
326
|
},
|
|
322
327
|
subscription:
|
|
323
328
|
isFreePlan(idPlan)
|
|
@@ -411,11 +416,14 @@ class AuthService {
|
|
|
411
416
|
|
|
412
417
|
const idPlan = await this.resolvePlanId(data.idPlan);
|
|
413
418
|
|
|
419
|
+
const whitelabel = await findWhitelabel().catch(() => null);
|
|
420
|
+
const language = localeToApiLanguage(await resolveLocale({ whitelabelId: whitelabel?.id ?? null }));
|
|
421
|
+
|
|
414
422
|
const payload: RegisterApiRequest = {
|
|
415
423
|
name: data.accountName,
|
|
416
424
|
bussiness_type: data.businessType ?? 0,
|
|
417
|
-
language
|
|
418
|
-
timezone:
|
|
425
|
+
language,
|
|
426
|
+
timezone: clientInfo.timezone,
|
|
419
427
|
currency: "BRL",
|
|
420
428
|
location: clientInfo.location,
|
|
421
429
|
ip: clientInfo.ip,
|
|
@@ -433,7 +441,7 @@ class AuthService {
|
|
|
433
441
|
phone: data.phone,
|
|
434
442
|
password: data.password,
|
|
435
443
|
profile: "owner",
|
|
436
|
-
language
|
|
444
|
+
language,
|
|
437
445
|
},
|
|
438
446
|
subscription:
|
|
439
447
|
isFreePlan(idPlan)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guarda contra mutação externa do DOM (tradutor do navegador, extensões).
|
|
3
|
+
*
|
|
4
|
+
* PROBLEMA: o Google Tradutor do Chrome substitui cada text node por `<font><font>…</font></font>`.
|
|
5
|
+
* O React continua guardando a referência do text node ORIGINAL no fiber. No commit seguinte ele
|
|
6
|
+
* chama `parent.insertBefore(novo, textNodeAntigo)` ou `parent.removeChild(textNodeAntigo)` — e o nó
|
|
7
|
+
* já não é mais filho daquele pai. O DOM levanta `NotFoundError`, o erro sobe até o root e o app
|
|
8
|
+
* inteiro cai no `global-error.tsx` (evento `render.root_crashed` no Sentry).
|
|
9
|
+
*
|
|
10
|
+
* Isso derrubou clientes reais em CO/PE/MX/AR/FR (zero casos no BR, onde a página já está no idioma
|
|
11
|
+
* do usuário e o Chrome não oferece tradução), inclusive em cima da tela de trocar cartão — o cliente
|
|
12
|
+
* ficava sem conseguir pagar.
|
|
13
|
+
*
|
|
14
|
+
* SOLUÇÃO: transformar essas duas operações em no-op quando o nó de referência já não pertence mais
|
|
15
|
+
* ao pai. O React segue adiante, a página não morre, e o trecho traduzido apenas deixa de receber
|
|
16
|
+
* aquela atualização pontual (o próximo re-render completo normaliza).
|
|
17
|
+
*
|
|
18
|
+
* Precisa rodar ANTES da hidratação, por isso é injetado como `<script>` inline no `<head>` do root
|
|
19
|
+
* layout em vez de virar um `useEffect`.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
declare global {
|
|
23
|
+
interface Window {
|
|
24
|
+
/** Contadores de quantas vezes a guarda entrou em ação nesta sessão. */
|
|
25
|
+
__gpDomGuard?: { removeChild: number; insertBefore: number };
|
|
26
|
+
/** Hook opcional preenchido pelo reporter para avisar o Sentry no primeiro disparo. */
|
|
27
|
+
__gpDomGuardOnHit?: ((kind: 'removeChild' | 'insertBefore') => void) | null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const DOM_MUTATION_GUARD_SCRIPT = `(function(){
|
|
32
|
+
if(typeof Node==="undefined"||!Node.prototype)return;
|
|
33
|
+
if(window.__gpDomGuard)return;
|
|
34
|
+
var s={removeChild:0,insertBefore:0};
|
|
35
|
+
window.__gpDomGuard=s;
|
|
36
|
+
window.__gpDomGuardOnHit=window.__gpDomGuardOnHit||null;
|
|
37
|
+
function hit(k){s[k]++;try{if(window.__gpDomGuardOnHit)window.__gpDomGuardOnHit(k)}catch(e){}}
|
|
38
|
+
var removeChild=Node.prototype.removeChild;
|
|
39
|
+
Node.prototype.removeChild=function(child){
|
|
40
|
+
if(child&&child.parentNode!==this){hit("removeChild");return child}
|
|
41
|
+
return removeChild.apply(this,arguments)};
|
|
42
|
+
var insertBefore=Node.prototype.insertBefore;
|
|
43
|
+
Node.prototype.insertBefore=function(newNode,referenceNode){
|
|
44
|
+
if(referenceNode&&referenceNode.parentNode!==this){hit("insertBefore");return newNode}
|
|
45
|
+
return insertBefore.apply(this,arguments)};
|
|
46
|
+
})();`;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Locale } from '../../i18n/config';
|
|
2
|
+
|
|
1
3
|
export type LocaleOption = {
|
|
2
4
|
value: string;
|
|
3
5
|
label: string;
|
|
@@ -14,3 +16,8 @@ export const LANGUAGE_OPTIONS: LocaleOption[] = [
|
|
|
14
16
|
export function buildLocaleOptions(): LocaleOption[] {
|
|
15
17
|
return LANGUAGE_OPTIONS;
|
|
16
18
|
}
|
|
19
|
+
|
|
20
|
+
export function localeToApiLanguage(locale: Locale): string {
|
|
21
|
+
const option = LANGUAGE_OPTIONS.find((o) => o.value === locale);
|
|
22
|
+
return option?.apiValue ?? locale;
|
|
23
|
+
}
|