Skip to content

Commit

Permalink
feat: improve endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
letehaha committed Nov 10, 2024
1 parent 9c195ac commit 67c8de9
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 7 deletions.
21 changes: 21 additions & 0 deletions src/common/lib/zod/custom-types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
import { z } from 'zod';

export const recordId = () => z.coerce.number().int().positive().finite();

/**
* Used for the case when array is expected to be received like 1,2,3.
* For example GET queries
*/
export const commaSeparatedRecordIds = z.string().transform((str, ctx) => {
const idSchema = recordId();
const ids = str.split(',').map((id) => {
const result = idSchema.safeParse(id);
return result.success ? result.data : null;
});

if (ids.some((id) => id === null)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: 'Not all values are valid record IDs',
});
return z.NEVER;
}
return ids as number[];
});
11 changes: 10 additions & 1 deletion src/controllers/account-groups/get-groups.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { z } from 'zod';
import type { CustomResponse } from '@common/types';
import { commaSeparatedRecordIds } from '@common/lib/zod/custom-types';
import { API_RESPONSE_STATUS } from 'shared-types';
import { errorHandler } from '@controllers/helpers';
import * as accountGroupService from '@services/account-groups';

export const getAccountGroups = async (req, res: CustomResponse) => {
try {
const { id: userId } = req.user;
const { accountIds }: GetAccountGroupsParams['query'] = req.validated.query;

const groups = await accountGroupService.getAccountGroups({ userId });
const groups = await accountGroupService.getAccountGroups({ userId, accountIds });

return res.status(200).json({
status: API_RESPONSE_STATUS.success,
Expand All @@ -17,3 +20,9 @@ export const getAccountGroups = async (req, res: CustomResponse) => {
errorHandler(res, err);
}
};

export const getAccountGroupsSchema = z.object({
query: z.object({ accountIds: commaSeparatedRecordIds.optional() }),
});

type GetAccountGroupsParams = z.infer<typeof getAccountGroupsSchema>;
5 changes: 4 additions & 1 deletion src/controllers/account-groups/remove-account-from-group.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { z } from 'zod';
import { API_RESPONSE_STATUS } from 'shared-types';
import type { CustomResponse } from '@common/types';
import { recordId } from '@common/lib/zod/custom-types';
import { errorHandler } from '@controllers/helpers';
Expand All @@ -13,7 +14,9 @@ export const removeAccountFromGroup = async (req, res: CustomResponse) => {
groupId,
});

return res.status(204).send();
return res.status(200).json({
status: API_RESPONSE_STATUS.success,
});
} catch (err) {
errorHandler(res, err);
}
Expand Down
7 changes: 6 additions & 1 deletion src/routes/account-groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ router.post(
accountGroupController.createAccountGroup,
);

router.get('/', authenticateJwt, accountGroupController.getAccountGroups);
router.get(
'/',
authenticateJwt,
validateEndpoint(accountGroupController.getAccountGroupsSchema),
accountGroupController.getAccountGroups,
);

router.put(
'/:groupId',
Expand Down
20 changes: 18 additions & 2 deletions src/services/account-groups/get-account-groups.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
import AccountGroup from '@models/accounts-groups/AccountGroups.model';
import { withTransaction } from '../common';
import { Op } from 'sequelize';
import Accounts from '@models/Accounts.model';

export const getAccountGroups = withTransaction(
async ({ userId }: { userId: number }): Promise<AccountGroup[]> => {
async ({
userId,
accountIds = [],
}: {
userId: number;
accountIds?: number[];
}): Promise<AccountGroup[]> => {
return AccountGroup.findAll({
where: { userId },
include: [{ model: AccountGroup, as: 'childGroups' }],
include: [
{ model: AccountGroup, as: 'childGroups' },
{
model: Accounts,
where: accountIds.length > 0 ? { id: { [Op.in]: accountIds } } : undefined,
through: { attributes: [] },
required: accountIds.length > 0,
},
],
});
},
);
4 changes: 2 additions & 2 deletions src/services/account-groups/remove-account-from-group.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe('Remove account from group', () => {
groupId: group.id,
});

expect(result.statusCode).toBe(204);
expect(result.statusCode).toBe(200);
});

it('fails when trying to remove non-existing account', async () => {
Expand Down Expand Up @@ -48,6 +48,6 @@ describe('Remove account from group', () => {
groupId: group.id,
});

expect(result.statusCode).toBe(204);
expect(result.statusCode).toBe(200);
});
});

0 comments on commit 67c8de9

Please sign in to comment.