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 2, 2023
1 parent 4ddc15f commit 157920c
Show file tree
Hide file tree
Showing 27 changed files with 575 additions and 713 deletions.
2 changes: 1 addition & 1 deletion jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export default {
setupFiles: ['<rootDir>/test/setupTests.ts'],

// A list of paths to modules that run some code to configure or set up the testing framework before each test
setupFilesAfterEnv: ['<rootDir>/test/setupTestsAfterEnv.ts'],
// setupFilesAfterEnv: ['<rootDir>/test/setupTestsAfterEnv.ts'],

// The number of seconds after which a test is considered as slow and reported as such in the results.
// slowTestThreshold: 5,
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
"axios": "0.27.2",
"dexie": "3.2.4",
"http-status-codes": "2.3.0",
"immutable": "4.3.4",
"miragejs": "0.1.48",
"msw": "1.3.2",
"qs": "6.11.2",
Expand Down
12 changes: 6 additions & 6 deletions src/components/withContext.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, { ReactElement, createContext, useContext } from 'react';

import { Context, PermissionLevel, convertJs } from '@graasp/sdk';
import { Context, PermissionLevel, } from '@graasp/sdk';

import { UseQueryResult } from '@tanstack/react-query';

import { LocalContext, LocalContextRecord } from '../types';
import { AutoResizer } from './AutoResizer';
import { LocalContext } from '../types';

export const defaultContextValue: LocalContext = {
apiHost: '',
Expand All @@ -20,14 +20,14 @@ export const defaultContextValue: LocalContext = {
permission: PermissionLevel.Read,
};

const LocalContextContext = createContext<LocalContextRecord>(convertJs(defaultContextValue));
const LocalContextContext = createContext<LocalContext>((defaultContextValue));

interface WithLocalContextProps {
children: ReactElement;
useGetLocalContext: (
itemId: string,
defaultValue: LocalContext,
) => UseQueryResult<LocalContextRecord, unknown>;
) => UseQueryResult<LocalContext, unknown>;
LoadingComponent?: React.ReactElement;
defaultValue: LocalContext;
onError?: (error: unknown) => void;
Expand Down Expand Up @@ -90,7 +90,7 @@ interface Props {
useGetLocalContext: (
itemId: string,
defaultValue: LocalContext,
) => UseQueryResult<LocalContextRecord, unknown>;
) => UseQueryResult<LocalContext, unknown>;
LoadingComponent?: React.ReactElement;
defaultValue: LocalContext;
onError?: (error: unknown) => void;
Expand Down Expand Up @@ -146,6 +146,6 @@ const withContext = <P extends object>(
return WithContextComponent;
};

const useLocalContext = (): LocalContextRecord => useContext(LocalContextContext);
const useLocalContext = (): LocalContext => useContext(LocalContextContext);

export { useLocalContext, WithLocalContext, withContext };
13 changes: 0 additions & 13 deletions src/config/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,6 @@ export const buildPostMessageKeys = (itemId: UUID) =>
POST_AUTO_RESIZE: `POST_AUTO_RESIZE_${itemId}`,
}) as const;

export const MUTATION_KEYS = {
POST_APP_DATA: ['POST_APP_DATA'],
PATCH_APP_DATA: ['PATCH_APP_DATA'],
DELETE_APP_DATA: ['DELETE_APP_DATA'],
PATCH_SETTINGS: ['PATCH_SETTINGS'],
POST_APP_ACTION: ['POST_APP_ACTION'],
POST_APP_SETTING: ['POST_APP_SETTING'],
PATCH_APP_SETTING: ['PATCH_APP_SETTING'],
DELETE_APP_SETTING: ['DELETE_APP_SETTING'],
FILE_UPLOAD: ['FILE_UPLOAD'],
APP_SETTING_FILE_UPLOAD: ['APP_SETTING_FILE_UPLOAD'],
};

export const QUERY_KEYS = {
buildAppDataKey,
buildAppContextKey,
Expand Down
18 changes: 8 additions & 10 deletions src/config/utils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { QueryClient } from '@tanstack/react-query';
// eslint-disable-next-line import/no-extraneous-dependencies
import { StatusCodes } from 'http-status-codes';
import { Record } from 'immutable';

import { LocalContext, LocalContextRecord, QueryClientConfig } from '../types';
import { LocalContext, QueryClientConfig } from '../types';
import {
MissingAppKeyError,
MissingAppOriginError,
Expand All @@ -23,8 +21,8 @@ export class MissingApiHostError extends Error {
}
}

export const getApiHost = (queryClient: QueryClient): string => {
const context = queryClient.getQueryData<LocalContextRecord>(LOCAL_CONTEXT_KEY);
export const getApiHost = (queryClient: QueryClient) => {
const context = queryClient.getQueryData<LocalContext>(LOCAL_CONTEXT_KEY);
const apiHost = context?.apiHost;
if (!apiHost) {
throw new MissingApiHostError();
Expand All @@ -33,8 +31,8 @@ export const getApiHost = (queryClient: QueryClient): string => {
};

export const getPermissionLevel = (queryClient: QueryClient) => {
const context = queryClient.getQueryData<Record<LocalContext>>(LOCAL_CONTEXT_KEY);
const permission = context?.get('permission');
const context = queryClient.getQueryData<LocalContext>(LOCAL_CONTEXT_KEY);
const permission = context?.permission;
if (!permission) {
throw new MissingPermissionError();
}
Expand All @@ -45,16 +43,16 @@ export const getData = (
queryClient: QueryClient,
options: { shouldMemberExist?: boolean } = {},
): { itemId: string; memberId?: string; token: string } => {
const data = queryClient.getQueryData<Record<LocalContext>>(LOCAL_CONTEXT_KEY);
const data = queryClient.getQueryData<LocalContext>(LOCAL_CONTEXT_KEY);
if (!data) {
throw new Error('`LocalContext` was undefined');
}
const token = queryClient.getQueryData<string>(AUTH_TOKEN_KEY);
if (!token) {
throw new MissingNecessaryDataError({ token });
}
const itemId = data.get('itemId');
const memberId = data.get('memberId');
const { itemId } = data;
const { memberId } = data;

if (options.shouldMemberExist ?? true) {
if (!memberId) {
Expand Down
9 changes: 3 additions & 6 deletions src/hooks/app.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import { convertJs } from '@graasp/sdk';

import { StatusCodes } from 'http-status-codes';
import { Record } from 'immutable';
import nock from 'nock';
import { v4 } from 'uuid';

Expand All @@ -23,7 +20,7 @@ const itemId = v4();
describe('App Hooks', () => {
beforeEach(() => {
queryClient.setQueryData(AUTH_TOKEN_KEY, MOCK_TOKEN);
queryClient.setQueryData(LOCAL_CONTEXT_KEY, convertJs(buildMockLocalContext({ itemId })));
queryClient.setQueryData(LOCAL_CONTEXT_KEY, buildMockLocalContext({ itemId }));
});

afterEach(() => {
Expand All @@ -42,10 +39,10 @@ describe('App Hooks', () => {
const endpoints = [{ route, response }];
const { data } = await mockHook({ endpoints, hook, wrapper });

expect(data?.toJS()).toEqual(response);
expect(data).toEqual(response);

// verify cache keys
expect((queryClient.getQueryData(key) as Record<LocalContext>).toJS()).toEqual(response);
expect(queryClient.getQueryData(key)).toEqual(response);
});
it('Cannot fetch context if local context does not exist', async () => {
const response = FIXTURE_CONTEXT;
Expand Down
8 changes: 3 additions & 5 deletions src/hooks/app.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { convertJs } from '@graasp/sdk';

import { useQuery, useQueryClient } from '@tanstack/react-query';

import * as Api from '../api';
import { buildAppContextKey } from '../config/keys';
import { getApiHost, getDataOrThrow } from '../config/utils';
import { AppContextRecord, QueryClientConfig } from '../types';
import { AppContext, QueryClientConfig } from '../types';

// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export default (queryConfig: QueryClientConfig) => {
Expand All @@ -25,12 +23,12 @@ export default (queryConfig: QueryClientConfig) => {

return useQuery({
queryKey: buildAppContextKey(itemId),
queryFn: (): Promise<AppContextRecord> =>
queryFn: (): Promise<AppContext> =>
Api.getContext({
itemId,
token,
apiHost,
}).then((data) => convertJs(data)),
}),
...defaultOptions,
});
},
Expand Down
8 changes: 3 additions & 5 deletions src/hooks/appAction.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { PermissionLevel, convertJs } from '@graasp/sdk';
import { AppActionRecord } from '@graasp/sdk/frontend';
import { PermissionLevel } from '@graasp/sdk';

import { useQuery, useQueryClient } from '@tanstack/react-query';
import { List } from 'immutable';

import * as Api from '../api';
import { buildAppActionsKey } from '../config/keys';
Expand Down Expand Up @@ -35,10 +33,10 @@ export default (queryConfig: QueryClientConfig, websocketClient?: WebsocketClien

return useQuery({
queryKey: buildAppActionsKey(itemId),
queryFn: (): Promise<List<AppActionRecord>> => {
queryFn: () => {
const { token } = getDataOrThrow(queryClient);

return Api.getAppActions({ itemId, token, apiHost }).then((data) => convertJs(data));
return Api.getAppActions({ itemId, token, apiHost }).then((data) => data);
},
...defaultOptions,
enabled,
Expand Down
16 changes: 7 additions & 9 deletions src/hooks/appData.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { convertJs } from '@graasp/sdk';

import { StatusCodes } from 'http-status-codes';
import nock from 'nock';
import { v4 } from 'uuid';
Expand Down Expand Up @@ -27,7 +25,7 @@ const itemId = v4();
describe('App Data Hooks', () => {
beforeEach(() => {
queryClient.setQueryData(AUTH_TOKEN_KEY, MOCK_TOKEN);
queryClient.setQueryData(LOCAL_CONTEXT_KEY, convertJs(buildMockLocalContext({ itemId })));
queryClient.setQueryData(LOCAL_CONTEXT_KEY, buildMockLocalContext({ itemId }));
});

afterEach(() => {
Expand All @@ -45,16 +43,16 @@ describe('App Data Hooks', () => {
const endpoints = [{ route, response }];
const { data } = await mockHook({ endpoints, hook, wrapper });

expect(data?.toJS()).toEqual(response);
expect(data).toEqual(response);

// verify cache keys
expect(queryClient.getQueryData(key)).toEqualImmutable(convertJs(response));
expect(queryClient.getQueryData(key)).toEqual(response);
});
it('Cannot fetch app data if context does not exist', async () => {
queryClient.setQueryData(
LOCAL_CONTEXT_KEY,
convertJs({ ...buildMockLocalContext({ itemId }), apiHost: null }),
);
queryClient.setQueryData(LOCAL_CONTEXT_KEY, {
...buildMockLocalContext({ itemId }),
apiHost: null,
});

const response = FIXTURE_APP_DATA;
const endpoints = [{ route, response }];
Expand Down
8 changes: 2 additions & 6 deletions src/hooks/appData.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import { convertJs } from '@graasp/sdk';
import { AppDataRecord } from '@graasp/sdk/frontend';

import { useQuery, useQueryClient } from '@tanstack/react-query';
import { List } from 'immutable';

import * as Api from '../api';
import { MissingFileIdError } from '../config/errors';
Expand Down Expand Up @@ -40,9 +36,9 @@ export default (

return useQuery({
queryKey: buildAppDataKey(itemId),
queryFn: (): Promise<List<AppDataRecord>> => {
queryFn: () => {
const { token } = getDataOrThrow(queryClient);
return Api.getAppData({ itemId, token, apiHost }).then((data) => convertJs(data));
return Api.getAppData({ itemId, token, apiHost });
},
...defaultOptions,
refetchInterval,
Expand Down
8 changes: 3 additions & 5 deletions src/hooks/appSetting.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { convertJs } from '@graasp/sdk';

import { StatusCodes } from 'http-status-codes';
import nock from 'nock';
import { v4 } from 'uuid';
Expand Down Expand Up @@ -27,7 +25,7 @@ const itemId = v4();
describe('App Settings Hooks', () => {
beforeEach(() => {
queryClient.setQueryData(AUTH_TOKEN_KEY, MOCK_TOKEN);
queryClient.setQueryData(LOCAL_CONTEXT_KEY, convertJs(buildMockLocalContext({ itemId })));
queryClient.setQueryData(LOCAL_CONTEXT_KEY, buildMockLocalContext({ itemId }));
});

afterEach(() => {
Expand All @@ -45,10 +43,10 @@ describe('App Settings Hooks', () => {
const endpoints = [{ route, response }];
const { data } = await mockHook({ endpoints, hook, wrapper });

expect(data?.toJS()).toEqual(response);
expect(data).toEqual(response);

// verify cache keys
expect(queryClient.getQueryData(key)).toEqualImmutable(convertJs(response));
expect(queryClient.getQueryData(key)).toEqual(response);
});
it('Cannot fetch app settings if context does not exist', async () => {
const response = FIXTURE_APP_SETTINGS;
Expand Down
8 changes: 3 additions & 5 deletions src/hooks/appSetting.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { convertJs } from '@graasp/sdk';
import { AppSettingRecord } from '@graasp/sdk/frontend';

import { useQuery, useQueryClient } from '@tanstack/react-query';
import { List } from 'immutable';

import * as Api from '../api';
import { MissingFileIdError } from '../config/errors';
Expand Down Expand Up @@ -34,7 +32,7 @@ export default (queryConfig: QueryClientConfig, websocketClient?: WebsocketClien

return useQuery({
queryKey: buildAppSettingsKey(itemId),
queryFn: (): Promise<List<AppSettingRecord>> => {
queryFn: () => {
const { token: localToken, itemId: localItemId } = getDataOrThrow(queryClient, {
shouldMemberExist: false,
});
Expand All @@ -43,7 +41,7 @@ export default (queryConfig: QueryClientConfig, websocketClient?: WebsocketClien
itemId: localItemId,
token: localToken,
apiHost,
}).then((data) => convertJs(data));
});
},
...defaultOptions,
enabled: Boolean(itemId) && Boolean(token),
Expand Down Expand Up @@ -75,7 +73,7 @@ export default (queryConfig: QueryClientConfig, websocketClient?: WebsocketClien
id: appSettingId,
apiHost,
token: localToken,
}).then((data) => data);
});
},
...defaultOptions,
enabled: Boolean(payload?.appSettingId) && Boolean(token) && enabled,
Expand Down
6 changes: 3 additions & 3 deletions src/hooks/postMessage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
MissingMessageChannelPortError,
} from '../config/errors';
import { AUTH_TOKEN_KEY, LOCAL_CONTEXT_KEY, buildPostMessageKeys } from '../config/keys';
import { LocalContext } from '../types';

const mockItemId = 'mock-item-id';
const POST_MESSAGE_KEYS = buildPostMessageKeys(mockItemId);
Expand Down Expand Up @@ -43,8 +44,7 @@ describe.skip('PostMessage Hooks', () => {
mockWindowForPostMessage(event);

const { data } = await mockHook({ hook, wrapper });

const context = data?.toJS();
const context = data as LocalContext;
expect(context).toEqual({
apiHost: undefined, // @see LocalContextRecord
memberId: undefined, // @see LocalContextRecord
Expand Down Expand Up @@ -85,7 +85,7 @@ describe.skip('PostMessage Hooks', () => {

const { data } = await mockHook({ hook, wrapper });

expect(data?.toJS()).toEqual({
expect(data).toEqual({
...serverResponse,
standalone: false,
});
Expand Down
Loading

0 comments on commit 157920c

Please sign in to comment.