@greatapps/common 1.1.541 → 1.1.543
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/ConfigurationsMyAccountModal.mjs +1 -1
- package/dist/components/account/ConfigurationsMyAccountModal.mjs.map +1 -1
- package/dist/components/account/ConfirmDeleteAccountModal.mjs +46 -7
- package/dist/components/account/ConfirmDeleteAccountModal.mjs.map +1 -1
- package/dist/components/account/DeleteAccountModal.mjs +2 -2
- package/dist/components/account/DeleteAccountModal.mjs.map +1 -1
- package/dist/index.mjs +8 -0
- package/dist/index.mjs.map +1 -1
- package/dist/modules/accounts/actions/account-management.action.mjs +15 -14
- package/dist/modules/accounts/actions/account-management.action.mjs.map +1 -1
- package/dist/modules/auth/utils/require-valid-session.mjs +17 -0
- package/dist/modules/auth/utils/require-valid-session.mjs.map +1 -0
- package/dist/modules/cards/actions/create-card.action.mjs +2 -2
- package/dist/modules/cards/actions/create-card.action.mjs.map +1 -1
- package/dist/modules/cards/actions/delete-card.action.mjs +2 -2
- package/dist/modules/cards/actions/delete-card.action.mjs.map +1 -1
- package/dist/modules/cards/actions/set-default-card.action.mjs +2 -2
- package/dist/modules/cards/actions/set-default-card.action.mjs.map +1 -1
- package/dist/modules/pages/actions/count-pages.action.mjs +12 -0
- package/dist/modules/pages/actions/count-pages.action.mjs.map +1 -0
- package/dist/modules/pages/constants/query-keys.constants.mjs +5 -0
- package/dist/modules/pages/constants/query-keys.constants.mjs.map +1 -0
- package/dist/modules/pages/hooks/count-pages.hook.mjs +23 -0
- package/dist/modules/pages/hooks/count-pages.hook.mjs.map +1 -0
- package/dist/modules/pages/services/pages.service.mjs +24 -0
- package/dist/modules/pages/services/pages.service.mjs.map +1 -0
- package/dist/modules/projects/actions/add-project-user.action.mjs +2 -2
- package/dist/modules/projects/actions/add-project-user.action.mjs.map +1 -1
- package/dist/modules/projects/actions/create-project.action.mjs +2 -2
- package/dist/modules/projects/actions/create-project.action.mjs.map +1 -1
- package/dist/modules/projects/actions/delete-project.action.mjs +2 -2
- package/dist/modules/projects/actions/delete-project.action.mjs.map +1 -1
- package/dist/modules/projects/actions/remove-project-user.action.mjs +2 -2
- package/dist/modules/projects/actions/remove-project-user.action.mjs.map +1 -1
- package/dist/modules/projects/actions/update-project.action.mjs +2 -2
- package/dist/modules/projects/actions/update-project.action.mjs.map +1 -1
- package/dist/modules/subscriptions/actions/update-subscription-plan.action.mjs +2 -2
- package/dist/modules/subscriptions/actions/update-subscription-plan.action.mjs.map +1 -1
- package/dist/modules/users/action/mark-all-messages-as-read.action.mjs +2 -2
- package/dist/modules/users/action/mark-all-messages-as-read.action.mjs.map +1 -1
- package/dist/modules/users/action/mark-message-as-read.action.mjs +2 -2
- package/dist/modules/users/action/mark-message-as-read.action.mjs.map +1 -1
- package/dist/server.mjs +6 -0
- package/dist/server.mjs.map +1 -1
- package/dist/store/useAccountModals.mjs +2 -3
- package/dist/store/useAccountModals.mjs.map +1 -1
- package/dist/utils/safeMutationAction.mjs +13 -0
- package/dist/utils/safeMutationAction.mjs.map +1 -0
- package/package.json +1 -1
- package/src/components/account/ConfigurationsMyAccountModal.tsx +1 -0
- package/src/components/account/ConfirmDeleteAccountModal.tsx +47 -10
- package/src/components/account/DeleteAccountModal.tsx +2 -2
- package/src/index.ts +5 -0
- package/src/modules/accounts/actions/account-management.action.ts +15 -14
- package/src/modules/auth/utils/require-valid-session.ts +35 -0
- package/src/modules/cards/actions/create-card.action.ts +2 -2
- package/src/modules/cards/actions/delete-card.action.ts +2 -2
- package/src/modules/cards/actions/set-default-card.action.ts +2 -2
- package/src/modules/pages/actions/count-pages.action.ts +10 -0
- package/src/modules/pages/constants/query-keys.constants.ts +1 -0
- package/src/modules/pages/hooks/count-pages.hook.ts +22 -0
- package/src/modules/pages/services/pages.service.ts +27 -0
- package/src/modules/projects/actions/add-project-user.action.ts +2 -2
- package/src/modules/projects/actions/create-project.action.ts +2 -2
- package/src/modules/projects/actions/delete-project.action.ts +2 -2
- package/src/modules/projects/actions/remove-project-user.action.ts +2 -2
- package/src/modules/projects/actions/update-project.action.ts +2 -2
- package/src/modules/subscriptions/actions/update-subscription-plan.action.ts +2 -2
- package/src/modules/users/action/mark-all-messages-as-read.action.ts +2 -2
- package/src/modules/users/action/mark-message-as-read.action.ts +2 -2
- package/src/server.ts +3 -0
- package/src/store/useAccountModals.ts +6 -8
- package/src/utils/safeMutationAction.ts +30 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
|
|
3
|
+
import { cache } from 'react';
|
|
4
|
+
|
|
5
|
+
import { ApiError } from '../../../infra/api/types';
|
|
6
|
+
import { getClientInfoFromRequest } from '../../../infra/utils/client-info';
|
|
7
|
+
import { authService } from '../services/auth.service';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Valida a sessão do usuário chamando POST /auth/keep no backend.
|
|
11
|
+
*
|
|
12
|
+
* Garante que o cookie `greatapps`:
|
|
13
|
+
* 1. Existe.
|
|
14
|
+
* 2. Corresponde a uma sessão registrada no banco (não foi forjado).
|
|
15
|
+
* 3. Ainda é considerada válida pelo backend (não foi revogada/expirada).
|
|
16
|
+
*
|
|
17
|
+
* Deduplicada por request via React.cache — múltiplas chamadas dentro do
|
|
18
|
+
* mesmo server action resultam em 1 round-trip ao backend, não N.
|
|
19
|
+
*
|
|
20
|
+
* Use em server actions sensíveis (mutações, billing, destrutivas).
|
|
21
|
+
* Prefira o wrapper `safeMutationAction` que já envelopa isto junto com
|
|
22
|
+
* o `safeServerAction` padrão.
|
|
23
|
+
*
|
|
24
|
+
* Em caso de erro de rede/backend, falha fechada (SESSION_INVALID 401).
|
|
25
|
+
*/
|
|
26
|
+
export const requireValidSession = cache(async (): Promise<void> => {
|
|
27
|
+
if (process.env.DUMMY_AUTH_TOKEN) return;
|
|
28
|
+
|
|
29
|
+
const clientInfo = await getClientInfoFromRequest();
|
|
30
|
+
const isValid = await authService.validateSession(clientInfo);
|
|
31
|
+
|
|
32
|
+
if (!isValid) {
|
|
33
|
+
throw new ApiError('Sessão inválida ou expirada', 'SESSION_INVALID', 401);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { safeMutationAction } from '../../../utils/safeMutationAction';
|
|
4
4
|
import { cardsService } from '../services/cards.service';
|
|
5
5
|
import { CreateCardRequest } from '../types';
|
|
6
6
|
|
|
7
7
|
export async function createCardAction(data: CreateCardRequest) {
|
|
8
|
-
return
|
|
8
|
+
return safeMutationAction(() => cardsService.createCard(data));
|
|
9
9
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { safeMutationAction } from '../../../utils/safeMutationAction';
|
|
4
4
|
import { cardsService } from '../services/cards.service';
|
|
5
5
|
|
|
6
6
|
export async function deleteCardAction(id: string) {
|
|
7
|
-
return
|
|
7
|
+
return safeMutationAction(() => cardsService.deleteCard(id));
|
|
8
8
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { safeMutationAction } from '../../../utils/safeMutationAction';
|
|
4
4
|
import { cardsService } from '../services/cards.service';
|
|
5
5
|
|
|
6
6
|
export async function setDefaultCardAction(cardId: string) {
|
|
7
|
-
return
|
|
7
|
+
return safeMutationAction(() => cardsService.setDefaultCard(cardId));
|
|
8
8
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { safeServerAction } from '../../../utils/safeServerAction';
|
|
4
|
+
import { pagesService } from '../services/pages.service';
|
|
5
|
+
|
|
6
|
+
export async function countPagesAction() {
|
|
7
|
+
return safeServerAction(async () => ({
|
|
8
|
+
total: await pagesService.countPages(),
|
|
9
|
+
}));
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const PAGES_QUERY_KEY = ['pages'] as const;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useQuery } from '@tanstack/react-query';
|
|
4
|
+
import { countPagesAction } from '../actions/count-pages.action';
|
|
5
|
+
import { PAGES_QUERY_KEY } from '../constants/query-keys.constants';
|
|
6
|
+
import { withAction } from '../../../utils/withAction';
|
|
7
|
+
import { useAuthQueryKey } from '../../../hooks/useAuthQueryKey';
|
|
8
|
+
|
|
9
|
+
export const COUNT_PAGES_QUERY_KEY = [...PAGES_QUERY_KEY, 'count'] as const;
|
|
10
|
+
|
|
11
|
+
export function useCountPages() {
|
|
12
|
+
const queryKey = useAuthQueryKey([...COUNT_PAGES_QUERY_KEY]);
|
|
13
|
+
|
|
14
|
+
return useQuery({
|
|
15
|
+
queryKey,
|
|
16
|
+
queryFn: async () => {
|
|
17
|
+
const result = await withAction(countPagesAction)();
|
|
18
|
+
return result.total;
|
|
19
|
+
},
|
|
20
|
+
staleTime: 30_000,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
|
|
3
|
+
import { api } from '../../../infra/api/client';
|
|
4
|
+
import { ApiError, ApiPaginatedActionResult } from '../../../infra/api/types';
|
|
5
|
+
import { getUserContext } from '../../auth/utils/get-user-context';
|
|
6
|
+
|
|
7
|
+
class PagesService {
|
|
8
|
+
async countPages(): Promise<number> {
|
|
9
|
+
const { id_account } = await getUserContext();
|
|
10
|
+
|
|
11
|
+
const url = `/account/${id_account}/pages?limit=1`;
|
|
12
|
+
|
|
13
|
+
const response = await api.pages.get<ApiPaginatedActionResult<unknown>>(url);
|
|
14
|
+
|
|
15
|
+
if (response.status === 0) {
|
|
16
|
+
throw new ApiError(
|
|
17
|
+
response.message || 'Erro ao contar páginas',
|
|
18
|
+
'COUNT_PAGES_FAILED',
|
|
19
|
+
400,
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return response.total;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const pagesService = new PagesService();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { safeMutationAction } from '../../../utils/safeMutationAction';
|
|
4
4
|
import { projectUsersService } from '../services/project-users.service';
|
|
5
5
|
import type { AddRemoveProjectUsersParams } from '../types';
|
|
6
6
|
|
|
7
7
|
export async function addProjectUserAction(params: AddRemoveProjectUsersParams) {
|
|
8
|
-
return
|
|
8
|
+
return safeMutationAction(() => projectUsersService.addToProject(params));
|
|
9
9
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { safeMutationAction } from '../../../utils/safeMutationAction';
|
|
4
4
|
import { projectsService } from '../services/projects.service';
|
|
5
5
|
import type { CreateProjectRequest } from '../types';
|
|
6
6
|
|
|
7
7
|
export async function createProjectAction(data: CreateProjectRequest) {
|
|
8
|
-
return
|
|
8
|
+
return safeMutationAction(() => projectsService.create(data));
|
|
9
9
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { safeMutationAction } from '../../../utils/safeMutationAction';
|
|
4
4
|
import { projectsService } from '../services/projects.service';
|
|
5
5
|
|
|
6
6
|
export async function deleteProjectAction(projectId: number, moveToProjectId: number) {
|
|
7
|
-
return
|
|
7
|
+
return safeMutationAction(() => projectsService.delete(projectId, moveToProjectId));
|
|
8
8
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { safeMutationAction } from '../../../utils/safeMutationAction';
|
|
4
4
|
import { projectUsersService } from '../services/project-users.service';
|
|
5
5
|
import type { AddRemoveProjectUsersParams } from '../types';
|
|
6
6
|
|
|
7
7
|
export async function removeProjectUserAction(params: AddRemoveProjectUsersParams) {
|
|
8
|
-
return
|
|
8
|
+
return safeMutationAction(() => projectUsersService.removeFromProject(params));
|
|
9
9
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { safeMutationAction } from '../../../utils/safeMutationAction';
|
|
4
4
|
import { projectsService } from '../services/projects.service';
|
|
5
5
|
import type { UpdateProjectRequest } from '../types';
|
|
6
6
|
|
|
7
7
|
export async function updateProjectAction(projectId: number, data: UpdateProjectRequest) {
|
|
8
|
-
return
|
|
8
|
+
return safeMutationAction(() => projectsService.update(projectId, data));
|
|
9
9
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { safeMutationAction } from "../../../utils/safeMutationAction";
|
|
4
4
|
import type { UpdateSubscriptionPlanRequest } from "../types/calculate-subscription.type";
|
|
5
5
|
import { subscriptionsService } from "../services/subscriptions.service";
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ export async function updateSubscriptionPlanAction(
|
|
|
8
8
|
subscriptionId: number | string,
|
|
9
9
|
data: UpdateSubscriptionPlanRequest,
|
|
10
10
|
) {
|
|
11
|
-
return
|
|
11
|
+
return safeMutationAction(async () => {
|
|
12
12
|
return subscriptionsService.updateSubscriptionPlan(subscriptionId, data);
|
|
13
13
|
});
|
|
14
14
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { safeMutationAction } from '../../../utils/safeMutationAction';
|
|
4
4
|
import { messagesService } from '../services/messages.service';
|
|
5
5
|
|
|
6
6
|
export async function markAllMessagesAsReadAction() {
|
|
7
|
-
return
|
|
7
|
+
return safeMutationAction(() => messagesService.markAllAsRead());
|
|
8
8
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { safeMutationAction } from '../../../utils/safeMutationAction';
|
|
4
4
|
import { messagesService } from '../services/messages.service';
|
|
5
5
|
|
|
6
6
|
export async function markMessageAsReadAction(messageId: string) {
|
|
7
|
-
return
|
|
7
|
+
return safeMutationAction(() => messagesService.markAsRead(messageId));
|
|
8
8
|
}
|
package/src/server.ts
CHANGED
|
@@ -32,6 +32,7 @@ export { createCardAction } from './modules/cards/actions/create-card.action';
|
|
|
32
32
|
export { resolvePlanExtrasPrices } from './modules/subscriptions/utils/resolve-plan-extras-prices';
|
|
33
33
|
export { hasSubscriptionExpired } from './modules/subscriptions/utils/has-subscription-expired';
|
|
34
34
|
export { listIaCreditsAction } from './modules/ia-credits/actions/list-ia-credits.action';
|
|
35
|
+
export { countPagesAction } from './modules/pages/actions/count-pages.action';
|
|
35
36
|
|
|
36
37
|
// Project Services & Actions (server-only)
|
|
37
38
|
export { projectsService } from './modules/projects/services/projects.service';
|
|
@@ -72,8 +73,10 @@ export {
|
|
|
72
73
|
// Server Utils
|
|
73
74
|
export { getClientInfoFromRequest } from './infra/utils/client-info';
|
|
74
75
|
export { getUserContext } from './modules/auth/utils/get-user-context';
|
|
76
|
+
export { requireValidSession } from './modules/auth/utils/require-valid-session';
|
|
75
77
|
export { buildWlOverride, buildWlOverrideFromJwt } from './modules/auth/utils/build-wl-override';
|
|
76
78
|
export { safeServerAction } from './utils/safeServerAction';
|
|
79
|
+
export { safeMutationAction } from './utils/safeMutationAction';
|
|
77
80
|
|
|
78
81
|
// Image Processing (server-side)
|
|
79
82
|
export { processImageAction } from './modules/images/actions/process-image.action';
|
|
@@ -17,15 +17,14 @@ interface AccountModalsState {
|
|
|
17
17
|
activeModal: AccountModalType | null;
|
|
18
18
|
config: AccountModalsConfig;
|
|
19
19
|
initialSection?: AccountSectionType;
|
|
20
|
-
pagesCount: number;
|
|
21
20
|
|
|
22
21
|
/** Called by <AccountModals> to keep app-level config in sync */
|
|
23
22
|
updateConfig: (config: AccountModalsConfig) => void;
|
|
24
23
|
|
|
25
24
|
openConfigurations: (initialSection?: AccountSectionType) => void;
|
|
26
|
-
openDeleteAccount: (
|
|
25
|
+
openDeleteAccount: () => void;
|
|
27
26
|
openIsntPossibleDelete: () => void;
|
|
28
|
-
openConfirmDelete: (
|
|
27
|
+
openConfirmDelete: () => void;
|
|
29
28
|
close: () => void;
|
|
30
29
|
}
|
|
31
30
|
|
|
@@ -33,21 +32,20 @@ export const useAccountModals = create<AccountModalsState>((set) => ({
|
|
|
33
32
|
activeModal: null,
|
|
34
33
|
config: {},
|
|
35
34
|
initialSection: undefined,
|
|
36
|
-
pagesCount: 0,
|
|
37
35
|
|
|
38
36
|
updateConfig: (config) => set({ config }),
|
|
39
37
|
|
|
40
38
|
openConfigurations: (initialSection) =>
|
|
41
39
|
set({ activeModal: 'configurations', initialSection }),
|
|
42
40
|
|
|
43
|
-
openDeleteAccount: (
|
|
44
|
-
set({ activeModal: 'deleteAccount'
|
|
41
|
+
openDeleteAccount: () =>
|
|
42
|
+
set({ activeModal: 'deleteAccount' }),
|
|
45
43
|
|
|
46
44
|
openIsntPossibleDelete: () =>
|
|
47
45
|
set({ activeModal: 'isntPossibleDelete' }),
|
|
48
46
|
|
|
49
|
-
openConfirmDelete: (
|
|
50
|
-
set({ activeModal: 'confirmDelete'
|
|
47
|
+
openConfirmDelete: () =>
|
|
48
|
+
set({ activeModal: 'confirmDelete' }),
|
|
51
49
|
|
|
52
50
|
close: () =>
|
|
53
51
|
set({ activeModal: null, initialSection: undefined }),
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
|
|
3
|
+
import type { ActionResult } from '../infra/api/types';
|
|
4
|
+
import { requireValidSession } from '../modules/auth/utils/require-valid-session';
|
|
5
|
+
import { safeServerAction } from './safeServerAction';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Wrapper para server actions que mutam estado (delete/update/create/publish/
|
|
9
|
+
* billing/etc.). Faz validação de sessão contra o backend (`POST /auth/keep`)
|
|
10
|
+
* antes de executar a ação e roteia erros via `safeServerAction`.
|
|
11
|
+
*
|
|
12
|
+
* A validação é deduplicada por request — múltiplas actions sensíveis que
|
|
13
|
+
* rodem dentro de uma mesma request pagam 1 round-trip ao backend, não N.
|
|
14
|
+
*
|
|
15
|
+
* Motivação (resumo): o backend confia no par `(whitelabel-token, id_account
|
|
16
|
+
* no path)` nos endpoints de CRUD; o Next.js deriva `id_account` de
|
|
17
|
+
* `atob(cookie)` sem verificar assinatura. Chamar `requireValidSession`
|
|
18
|
+
* aqui garante que o cookie corresponde a uma sessão real no banco antes
|
|
19
|
+
* de qualquer mutação.
|
|
20
|
+
*
|
|
21
|
+
* Para reads não-sensíveis, continue usando `safeServerAction` direto.
|
|
22
|
+
*/
|
|
23
|
+
export async function safeMutationAction<T>(
|
|
24
|
+
fn: () => Promise<T>
|
|
25
|
+
): Promise<ActionResult<T>> {
|
|
26
|
+
return safeServerAction(async () => {
|
|
27
|
+
await requireValidSession();
|
|
28
|
+
return fn();
|
|
29
|
+
});
|
|
30
|
+
}
|