Skip to content

Commit

Permalink
feat: remove immutable
Browse files Browse the repository at this point in the history
  • Loading branch information
pyphilia committed Nov 3, 2023
1 parent 8fdbc63 commit da86a46
Show file tree
Hide file tree
Showing 101 changed files with 5,484 additions and 6,303 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
- name: setup node
uses: actions/setup-node@v4
with:
node-version: '16'
node-version: '18'

- name: install packages
run: yarn
Expand Down
363 changes: 0 additions & 363 deletions .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs

This file was deleted.

874 changes: 0 additions & 874 deletions .yarn/releases/yarn-3.6.4.cjs

This file was deleted.

893 changes: 893 additions & 0 deletions .yarn/releases/yarn-4.0.0.cjs

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
checksumBehavior: update

compressionLevel: mixed

defaultSemverRangePrefix: ""

nodeLinker: node-modules
enableGlobalCache: false

plugins:
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
spec: "@yarnpkg/plugin-interactive-tools"
nodeLinker: node-modules

yarnPath: .yarn/releases/yarn-3.6.4.cjs
yarnPath: .yarn/releases/yarn-4.0.0.cjs
9 changes: 3 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@
"Alexandre Chau"
],
"dependencies": {
"@graasp/sdk": "1.10.1",
"@graasp/sdk": "2.0.0",
"@graasp/translations": "1.19.4",
"axios": "0.27.2",
"crypto-js": "4.1.1",
"http-status-codes": "2.3.0",
"immutable": "4.3.4",
"qs": "6.11.2",
"react-query": "3.39.3",
"uuid": "9.0.1"
Expand All @@ -40,7 +39,6 @@
"@trivago/prettier-plugin-sort-imports": "4.2.1",
"@types/crypto-js": "4.1.3",
"@types/jest": "29.5.6",
"@types/js-cookie": "3.0.5",
"@types/jsdom": "21.1.4",
"@types/node": "20.8.8",
"@types/qs": "6.9.9",
Expand All @@ -63,7 +61,6 @@
"husky": "8.0.3",
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
"js-cookie": "3.0.5",
"mock-socket": "9.3.1",
"nock": "13.3.6",
"prettier": "3.0",
Expand All @@ -88,7 +85,7 @@
"pre-commit": "yarn prettier:check && yarn lint",
"hooks:uninstall": "husky uninstall",
"hooks:install": "husky install",
"test": "jest --silent",
"test": "jest --silent",
"test:watch": "yarn test --watchAll",
"lint": "eslint .",
"post-commit": "git status",
Expand Down Expand Up @@ -119,5 +116,5 @@
"postcss": "8.4.31",
"nth-check": "2.1.1"
},
"packageManager": "yarn@3.6.4"
"packageManager": "yarn@4.0.0"
}
6 changes: 2 additions & 4 deletions src/api/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,10 @@ export const getAggregateActions = async <K extends AggregateBy[]>(
export const exportActions = async (
args: { itemId: UUID },
{ API_HOST, axios }: PartialQueryConfigForApi,
): Promise<void> =>
axios.post(`${API_HOST}/${buildExportActions(args.itemId)}`);
) => axios.post<void>(`${API_HOST}/${buildExportActions(args.itemId)}`);

export const postItemAction = async (
itemId: UUID,
payload: { type: string; extra?: { [key: string]: unknown } },
{ API_HOST, axios }: PartialQueryConfigForApi,
): Promise<Action> =>
axios.post(`${API_HOST}/${buildPostItemAction(itemId)}`, payload);
) => axios.post<Action>(`${API_HOST}/${buildPostItemAction(itemId)}`, payload);
13 changes: 6 additions & 7 deletions src/api/apps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ import { PartialQueryConfigForApi } from '../types';
import { verifyAuthentication } from './axios';
import { buildAppListRoute, buildGetApiAccessTokenRoute } from './routes';

export const getApps = async ({
API_HOST,
axios,
}: PartialQueryConfigForApi): Promise<App[]> =>
export const getApps = async ({ API_HOST, axios }: PartialQueryConfigForApi) =>
verifyAuthentication(() =>
axios.get(`${API_HOST}/${buildAppListRoute}`).then(({ data }) => data),
axios
.get<App[]>(`${API_HOST}/${buildAppListRoute}`)
.then(({ data }) => data),
);

export const requestApiAccessToken = async (
Expand All @@ -21,10 +20,10 @@ export const requestApiAccessToken = async (
app?: string;
},
{ API_HOST, axios }: PartialQueryConfigForApi,
): Promise<{ token: string }> => {
) => {
const { id, key, origin, app } = args;
return axios
.post(`${API_HOST}/${buildGetApiAccessTokenRoute(id)}`, {
.post<{ token: string }>(`${API_HOST}/${buildGetApiAccessTokenRoute(id)}`, {
origin,
key: key ?? app,
})
Expand Down
52 changes: 28 additions & 24 deletions src/api/authentication.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { HttpMethod } from '@graasp/sdk';
import { Password } from '@graasp/sdk/frontend';
import { Password } from '@graasp/sdk';

import { PartialQueryConfigForApi } from '../types';
import { verifyAuthentication } from './axios';
Expand All @@ -13,35 +12,36 @@ import {
SIGN_UP_ROUTE,
} from './routes';

export const signOut = ({
API_HOST,
axios,
}: PartialQueryConfigForApi): Promise<void> =>
export const signOut = ({ API_HOST, axios }: PartialQueryConfigForApi) =>
verifyAuthentication(() =>
axios.get(`${API_HOST}/${SIGN_OUT_ROUTE}`).then(({ data }) => data),
axios.get<void>(`${API_HOST}/${SIGN_OUT_ROUTE}`).then(({ data }) => data),
);

export const signIn = async (
payload: { email: string; captcha: string; url?: string },
{ API_HOST, axios }: PartialQueryConfigForApi,
): Promise<void> => axios.post(`${API_HOST}/${SIGN_IN_ROUTE}`, payload);
) => axios.post<void>(`${API_HOST}/${SIGN_IN_ROUTE}`, payload);

export const mobileSignIn = async (
payload: { email: string; challenge: string; captcha: string },
{ API_HOST, axios }: PartialQueryConfigForApi,
): Promise<void> => axios.post(`${API_HOST}/${MOBILE_SIGN_IN_ROUTE}`, payload);
) => axios.post<void>(`${API_HOST}/${MOBILE_SIGN_IN_ROUTE}`, payload);

export const signInWithPassword = async (
payload: { email: string; password: Password; captcha: string; url?: string },
{ API_HOST, axios }: PartialQueryConfigForApi,
): Promise<{ resource: string }> =>
axios({
method: HttpMethod.POST,
url: `${API_HOST}/${SIGN_IN_WITH_PASSWORD_ROUTE}`,
data: payload,
// Resolve only if the status code is less than 500
validateStatus: (status) => status >= 200 && status < 400,
}).then(({ data }) => data);
) =>
axios
.post<{ resource: string }>(
`${API_HOST}/${SIGN_IN_WITH_PASSWORD_ROUTE}`,
payload,
{
data: payload,
// Resolve only if the status code is less than 500
validateStatus: (status: number) => status >= 200 && status < 400,
},
)
.then(({ data }) => data);

export const mobileSignInWithPassword = async (
payload: {
Expand All @@ -51,20 +51,24 @@ export const mobileSignInWithPassword = async (
captcha: string;
},
{ API_HOST, axios }: PartialQueryConfigForApi,
): Promise<{ resource: string }> =>
) =>
axios
.post(`${API_HOST}/${MOBILE_SIGN_IN_WITH_PASSWORD_ROUTE}`, payload, {
// Resolve only if the status code is less than 500
validateStatus: (status) => status >= 200 && status < 400,
})
.post<{ resource: string }>(
`${API_HOST}/${MOBILE_SIGN_IN_WITH_PASSWORD_ROUTE}`,
payload,
{
// Resolve only if the status code is less than 500
validateStatus: (status) => status >= 200 && status < 400,
},
)
.then(({ data }) => data);

export const signUp = async (
payload: { name: string; email: string; captcha: string; url?: string },
{ API_HOST, axios }: PartialQueryConfigForApi,
): Promise<void> => axios.post(`${API_HOST}/${SIGN_UP_ROUTE}`, payload);
) => axios.post<void>(`${API_HOST}/${SIGN_UP_ROUTE}`, payload);

export const mobileSignUp = async (
payload: { name: string; email: string; challenge: string; captcha: string },
{ API_HOST, axios }: PartialQueryConfigForApi,
): Promise<void> => axios.post(`${API_HOST}/${MOBILE_SIGN_UP_ROUTE}`, payload);
) => axios.post<void>(`${API_HOST}/${MOBILE_SIGN_UP_ROUTE}`, payload);
32 changes: 15 additions & 17 deletions src/api/axios.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { UNAUTHORIZED_RESPONSE, buildResultOfData } from '../../test/constants';
import { splitRequestByIds } from './axios';
import { splitRequestByIdsAndReturn } from './axios';

const chunkSize = 5;
const ids = Array.from({ length: chunkSize * 3 + 1 }, (_, idx) =>
Expand All @@ -10,43 +10,41 @@ const buildRequest = async (chunk: typeof ids) =>

describe('Axios Tests', () => {
describe('Axios Tests', () => {
it('result contains the correct number of responses', async () => {
it('Throw for empty responses', async () => {
const zero = 0;
const result0 = await splitRequestByIds(
ids.slice(0, zero),
chunkSize,
buildRequest,
);
expect(result0).toBeNull();

expect(() =>
splitRequestByIdsAndReturn(ids.slice(0, zero), chunkSize, buildRequest),
).rejects.toThrow();
});
it('result contains the correct number of responses', async () => {
const small = 2;
const result1 = await splitRequestByIds(
const result1 = await splitRequestByIdsAndReturn(
ids.slice(0, small),
chunkSize,
buildRequest,
);
expect(result1.data.toSeq().size).toEqual(small);
expect(Object.values(result1!.data).length).toEqual(small);

const twice = chunkSize + 1;
const result2 = await splitRequestByIds(
const result2 = await splitRequestByIdsAndReturn(
ids.slice(0, twice),
chunkSize,
buildRequest,
);
expect(result2.data.toSeq().size).toEqual(twice);
expect(Object.values(result2!.data).length).toEqual(twice);

const big = ids.length;
const result3 = await splitRequestByIds(
const result3 = await splitRequestByIdsAndReturn(
ids.slice(0, big),
chunkSize,
buildRequest,
);
expect(result3.data.toSeq().size).toEqual(big);
expect(Object.values(result3!.data).length).toEqual(big);
});

it('throws if one of the request throws', async () => {
await expect(
splitRequestByIds(ids.slice(0, 2), 1, async ([id]) => {
splitRequestByIdsAndReturn(ids.slice(0, 2), 1, async ([id]) => {
if (id === '1') {
throw new Error();
}
Expand All @@ -59,7 +57,7 @@ describe('Axios Tests', () => {
let thrownError;

try {
await splitRequestByIds(ids.slice(0, 2), 1, async ([id]) => {
await splitRequestByIdsAndReturn(ids.slice(0, 2), 1, async ([id]) => {
if (id === '1') {
return buildResultOfData([], (el) => el, [UNAUTHORIZED_RESPONSE]);
}
Expand Down
43 changes: 22 additions & 21 deletions src/api/axios.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,9 @@
import { ResultOf, parseStringToDate, spliceIntoChunks } from '@graasp/sdk';
import { ResultOf, spliceIntoChunks } from '@graasp/sdk';

import axios, { AxiosError } from 'axios';

const configureAxios = () => {
axios.defaults.withCredentials = true;
axios.defaults.transformResponse = [
(data) => {
try {
const content = JSON.parse(data);
return parseStringToDate(content);
} catch (e) {
// the data was a normal string and we return it
return data;
}
},
];

return axios;
};
Expand Down Expand Up @@ -50,27 +39,40 @@ export default configureAxios;

/**
* Split a given request in multiple smallest requests, so it conforms to the backend limitations
* The response is parsed to detect errors, and is transformed into a deep immutable data
* @param {string[]} ids elements' id
* @param {number} chunkSize maximum number of ids per request
* @param {function} buildRequest builder for the request given the chunk ids
* @param {boolean} [ignoreErrors=false] whether we ignore errors
*/
export const splitRequestByIds = async <T>(
ids: string[],
chunkSize: number,
buildRequest: (ids: string[]) => Promise<ResultOf<T> | void>,
) => {
const shunkedIds = spliceIntoChunks(ids, chunkSize);
return Promise.all(shunkedIds.map((groupedIds) => buildRequest(groupedIds)));
};

/**
* Split a given request in multiple smallest requests, so it conforms to the backend limitations
* The response is parsed to detect errors, and is transformed into a deep data
* @param {string[]} ids elements' id
* @param {number} chunkSize maximum number of ids per request
* @param {function} buildRequest builder for the request given the chunk ids
* @param {boolean} [ignoreErrors=false] whether we ignore errors
* @returns {Promise} all requests returning their data merged
*/
export const splitRequestByIds = <T>(
export const splitRequestByIdsAndReturn = <T>(
ids: string[],
chunkSize: number,
buildRequest: (ids: string[]) => Promise<ResultOf<T> | void>,
ignoreErrors = false,
): Promise<ResultOf<T>> => {
const shunkedIds = spliceIntoChunks(ids, chunkSize);
return Promise.all(
shunkedIds.map((groupedIds) => buildRequest(groupedIds)),
).then((responses) => {
) =>
splitRequestByIds(ids, chunkSize, buildRequest).then((responses) => {
// only get request returns
// todo: not ideal..
if (responses.every((r) => !r?.data)) {
return null;
throw new Error('responses is empty');
}

const result = (responses as ResultOf<T>[]).reduce(
Expand All @@ -86,4 +88,3 @@ export const splitRequestByIds = <T>(
}
return result;
});
};
Loading

0 comments on commit da86a46

Please sign in to comment.