Skip to content

Commit

Permalink
♻️ refactor(app-config): tighten the typescript checks
Browse files Browse the repository at this point in the history
  • Loading branch information
thrownullexception committed Dec 4, 2023
1 parent a423952 commit a778f10
Show file tree
Hide file tree
Showing 56 changed files with 257 additions and 596 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ jobs:
- name: ⤵️ Check out code from GitHub
uses: actions/checkout@v2
- name: 🏗 Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
- name: 🚀 Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2
266 changes: 27 additions & 239 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
"rollup-plugin-svg-import": "^1.6.0",
"standard-version": "^9.5.0",
"tsup": "^6.2.2",
"typescript": "^4.7.4"
"typescript": "^4.9.5"
},
"engines": {
"node": ">=16"
Expand Down
4 changes: 2 additions & 2 deletions src/__tests__/admin/settings/system.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ describe("pages/admin/settings/system", () => {
<SystemSettings />
</ApplicationRoot>
);
await waitFor(() => {
await waitFor(async () => {
expect(
screen.getByLabelText("Token Validity Duration In Days")
await screen.findByLabelText("Token Validity Duration In Days")
).toHaveValue(5);
});
});
Expand Down
31 changes: 19 additions & 12 deletions src/backend/configuration/configuration.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { IApplicationService } from "backend/types";
import { progammingError } from "backend/lib/errors";
import { AppConfigurationValueType } from "shared/configurations/constants";
import {
createConfigDomainPersistenceService,
AbstractConfigDataPersistenceService,
Expand All @@ -20,16 +21,6 @@ export class ConfigurationApiService implements IApplicationService {
await this._appConfigPersistenceService.setup();
}

private checkConfigKeyEntityRequirement(
key: AppConfigurationKeys,
entity?: string
) {
progammingError(
`Configuration '${key}' requires an entity to be passed in`,
APP_CONFIGURATION_CONFIG[key].requireEntity && !entity
);
}

async showMultipleConfigForEntities<T>(
key: AppConfigurationKeys,
entities: string[]
Expand All @@ -55,7 +46,10 @@ export class ConfigurationApiService implements IApplicationService {
);
}

async show<T>(key: AppConfigurationKeys, entity?: string): Promise<T> {
async show<T extends AppConfigurationKeys>(
key: T,
entity?: string
): Promise<AppConfigurationValueType<T>> {
this.checkConfigKeyEntityRequirement(key, entity);

const value = await this._appConfigPersistenceService.getItem(
Expand All @@ -72,7 +66,7 @@ export class ConfigurationApiService implements IApplicationService {
async getSystemSettings<T extends keyof ISystemSettings>(
key: T
): Promise<ISystemSettings[T]> {
const systemSettings = await this.show<ISystemSettings>("system_settings");
const systemSettings = await this.show("system_settings");
return { ...DEFAULT_SYSTEM_SETTINGS, ...systemSettings }[key];
}

Expand All @@ -88,6 +82,19 @@ export class ConfigurationApiService implements IApplicationService {
value
);
}

private checkConfigKeyEntityRequirement(
key: AppConfigurationKeys,
entity?: string
) {
const config = APP_CONFIGURATION_CONFIG[key];
if ("requireEntity" in config) {
progammingError(
`Configuration '${key}' requires an entity to be passed in`,
config.requireEntity && !entity
);
}
}
}

const appConfigPersistenceService =
Expand Down
24 changes: 8 additions & 16 deletions src/backend/data/data.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
ActionsApiService,
} from "backend/actions/actions.service";
import { BaseAction } from "shared/types/actions";
import { IFieldValidationItem } from "shared/validations/types";
import { IEntityField } from "shared/types/db";
import { IAccountProfile } from "shared/types/user";
import { noop } from "shared/lib/noop";
Expand Down Expand Up @@ -40,7 +39,7 @@ export class DataApiService implements IDataApiService {
) {}

async bootstrap() {
this.getDataAccessInstance().bootstrap();
await this.getDataAccessInstance().bootstrap();
}

private getDataAccessInstance() {
Expand Down Expand Up @@ -132,9 +131,7 @@ export class DataApiService implements IDataApiService {
const [allowedFields, primaryField, entityValidations] = await Promise.all([
this._entitiesApiService.getAllowedCrudsFieldsToShow(entity, "create"),
this._entitiesApiService.getEntityPrimaryField(entity),
this._configurationApiService.show<
Record<string, IFieldValidationItem[]>
>("entity_validations", entity),
this._configurationApiService.show("entity_validations", entity),
]);

noop(entityValidations);
Expand Down Expand Up @@ -235,9 +232,7 @@ export class DataApiService implements IDataApiService {
const [allowedFields, primaryField, entityValidations] = await Promise.all([
this._entitiesApiService.getAllowedCrudsFieldsToShow(entity, "update"),
this._entitiesApiService.getEntityPrimaryField(entity),
this._configurationApiService.show<
Record<string, IFieldValidationItem[]>
>("entity_validations", entity),
this._configurationApiService.show("entity_validations", entity),
]);

// validate only the fields presents in 'data'
Expand Down Expand Up @@ -314,19 +309,16 @@ export class DataApiService implements IDataApiService {
format: string;
fields: string[];
}> {
const relationshipSettings = await this._configurationApiService.show<{
format: string;
fields: string[];
}>("entity_relation_template", entity);
const relationshipSettings = await this._configurationApiService.show(
"entity_relation_template",
entity
);

if (relationshipSettings.fields.length > 0) {
return relationshipSettings;
}
const [hiddenColumns, primaryField, entityFields] = await Promise.all([
this._configurationApiService.show<string[]>(
"hidden_entity_table_columns",
entity
),
this._configurationApiService.show("hidden_entity_table_columns", entity),
this._entitiesApiService.getEntityPrimaryField(entity),
this._entitiesApiService.getEntityFields(entity),
]);
Expand Down
2 changes: 1 addition & 1 deletion src/backend/entities/entities.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class EntitiesApiController {
async listAllEntityRelations(entity: string): Promise<string[]> {
const [entityRelations, disabledEntities] = await Promise.all([
this._entitiesApiService.getEntityRelations(entity),
this._configurationApiService.show<string[]>("disabled_entities"),
this._configurationApiService.show("disabled_entities"),
]);

const allowedEntityRelation = entityRelations.filter(
Expand Down
31 changes: 8 additions & 23 deletions src/backend/entities/entities.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class EntitiesApiService implements IApplicationService {

async getActiveEntities(): Promise<ILabelValue[]> {
const [hiddenEntities, entities] = await Promise.all([
this._configurationApiService.show<string[]>("disabled_entities"),
this._configurationApiService.show("disabled_entities"),
this.getAllEntities(),
]);
return entities.filter(({ value }) => !hiddenEntities.includes(value));
Expand All @@ -48,10 +48,7 @@ export class EntitiesApiService implements IApplicationService {
async getOrderedEntityFields(entity: string) {
const [entityFields, entityFieldsOrder] = await Promise.all([
this.getEntityFields(entity),
this._configurationApiService.show<string[]>(
"entity_fields_orders",
entity
),
this._configurationApiService.show("entity_fields_orders", entity),
]);

sortByList(
Expand Down Expand Up @@ -93,10 +90,7 @@ export class EntitiesApiService implements IApplicationService {
crudKey: DataCrudKeys
): Promise<string[]> {
const [configHiddenFields, entityFields] = await Promise.all([
this._configurationApiService.show<string[]>(
CRUD_KEY_CONFIG[crudKey],
entity
),
this._configurationApiService.show(CRUD_KEY_CONFIG[crudKey], entity),
this.getEntityFields(entity),
]);

Expand Down Expand Up @@ -127,7 +121,7 @@ export class EntitiesApiService implements IApplicationService {

async isEntityDisabled(entity: string): Promise<boolean> {
return (
await this._configurationApiService.show<string[]>("disabled_entities")
await this._configurationApiService.show("disabled_entities")
).includes(entity);
}

Expand All @@ -150,19 +144,10 @@ export class EntitiesApiService implements IApplicationService {
hiddenEntity,
] = await Promise.all([
this.getEntityRelations(entity),
this._configurationApiService.show<string[]>("disabled_entities"),
this._configurationApiService.show<Record<string, string>>(
"entity_relations_labels",
entity
),
this._configurationApiService.show<string[]>(
"entity_relations_order",
entity
),
this._configurationApiService.show<string[]>(
"hidden_entity_relations",
entity
),
this._configurationApiService.show("disabled_entities"),
this._configurationApiService.show("entity_relations_labels", entity),
this._configurationApiService.show("entity_relations_order", entity),
this._configurationApiService.show("hidden_entity_relations", entity),
]);

const allowedEntityRelation =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,9 @@ export const crudEnabledValidationImpl: ValidationImplType<void> = async (

if (
EntityCrudCheck[actionType].entityCrudField &&
!(
await configurationApiService.show<IEntityCrudSettings>(
"entity_crud_settings",
entity
)
)[actionType]
!(await configurationApiService.show("entity_crud_settings", entity))[
actionType
]
) {
throw new ForbiddenError(
`Action '${actionType}' has been disabled for '${entity}'`
Expand Down
4 changes: 2 additions & 2 deletions src/backend/menu/menu.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ export class NavigationMenuApiService
private async getUserEntities(): Promise<ILabelValue[]> {
const [hiddenMenuEntities, entitiesOrder, activeEntities] =
await Promise.all([
this._configurationApiService.show<string[]>("disabled_menu_entities"),
this._configurationApiService.show<string[]>("menu_entities_order"),
this._configurationApiService.show("disabled_menu_entities"),
this._configurationApiService.show("menu_entities_order"),
this._entitiesApiService.getActiveEntities(),
]);

Expand Down
8 changes: 3 additions & 5 deletions src/backend/uploads/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@ import { NextApiRequest } from "next";
import { nanoid } from "nanoid";
import { compileTemplateString } from "shared/lib/strings/templates";
import { configurationApiService } from "backend/configuration/configuration.service";
import { IFileUploadSettings } from "shared/types/file";

export async function parseForm(
req: NextApiRequest
): Promise<{ fields: formidable.Fields; files: formidable.Files }> {
const fileUploadSettings =
await configurationApiService.show<IFileUploadSettings>(
"file_upload_settings"
);
const fileUploadSettings = await configurationApiService.show(
"file_upload_settings"
);
const UPLOAD_CONFIG = {
entity: sluggify("posts"),
maxFileSize: 1024 * 1024 * fileUploadSettings.defaultMaxFileSizeInMB,
Expand Down
8 changes: 4 additions & 4 deletions src/frontend/_layouts/app/LayoutImpl/SideBar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ViewStateMachine } from "frontend/components/ViewStateMachine";
import { useSiteConfig } from "frontend/hooks/app/site.config";
import Link from "next/link";
import React from "react";
import { ChevronRight } from "react-feather";
Expand All @@ -12,6 +11,7 @@ import { useStorageApi } from "frontend/lib/data/useApi";
import { INavigationMenuItem } from "shared/types/menu";
import { useSessionStorage } from "react-use";
import { PlainButton } from "frontend/design-system/components/Button/TextButton";
import { useAppConfiguration } from "frontend/hooks/configuration/configuration.store";
import {
NAVIGATION_MENU_ENDPOINT,
SIDE_BAR_WIDTH_VARIATIONS,
Expand Down Expand Up @@ -95,7 +95,7 @@ export const useNavigationMenuItems = () => {
};

export function SideBar({ isFullWidth, setIsFullWidth }: IProps) {
const siteConfig = useSiteConfig();
const siteConfig = useAppConfiguration("site_settings");
const navigationMenuItems = useNavigationMenuItems();
const getThemeColorShade = useThemeColorShade();

Expand All @@ -122,9 +122,9 @@ export function SideBar({ isFullWidth, setIsFullWidth }: IProps) {
>
<Link href="/">
{isFullWidth ? (
<LogoFull src={siteConfig.fullLogo} alt="full logo" />
<LogoFull src={siteConfig.data.fullLogo} alt="full logo" />
) : (
<LogoSm src={siteConfig.logo} alt="small logo" />
<LogoSm src={siteConfig.data.logo} alt="small logo" />
)}
</Link>
</Brand>
Expand Down
6 changes: 3 additions & 3 deletions src/frontend/_layouts/app/_MainContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { Stack } from "frontend/design-system/primitives/Stack";
import { Breadcrumbs } from "frontend/design-system/components/Breadcrumbs";
import { Typo } from "frontend/design-system/primitives/Typo";
import { Spacer } from "frontend/design-system/primitives/Spacer";
import { useSiteConfig } from "frontend/hooks/app/site.config";
import { useAppConfiguration } from "frontend/hooks/configuration/configuration.store";
import { GoogleTagManager } from "../scripts/GoogleTagManager";
import { DEMO_LINKS } from "./constant";

Expand All @@ -27,7 +27,7 @@ export function MainContent({
actionItems = [],
secondaryActionItems = [],
}: IMainContentProps) {
const siteConfig = useSiteConfig();
const siteConfig = useAppConfiguration("site_settings");
const { history, pushToStack, goToLinkIndex } = useNavigationStack();
const router = useRouter();
const [
Expand Down Expand Up @@ -63,7 +63,7 @@ export function MainContent({
<>
<Head>
<title>
{pageTitle} - {siteConfig.name}
{pageTitle} - {siteConfig.data.name}
</title>
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
</Head>
Expand Down
6 changes: 3 additions & 3 deletions src/frontend/_layouts/guest/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, { ReactNode } from "react";
import Head from "next/head";
import { useSiteConfig } from "frontend/hooks/app/site.config";
import styled from "styled-components";
import { SHADOW_CSS, CardBody } from "frontend/design-system/components/Card";
import { useAppConfiguration } from "frontend/hooks/configuration/configuration.store";
import { useAppTheme } from "../useAppTheme";
import { GoogleTagManager } from "../scripts/GoogleTagManager";
import { PortalProvider } from "../app/portal";
Expand All @@ -27,14 +27,14 @@ const Root = styled.div`
`;

export function AuthLayout({ children, title, subTitle }: IProps) {
const siteConfig = useSiteConfig();
const siteConfig = useAppConfiguration("site_settings");
useAppTheme();

return (
<PortalProvider>
<Head>
<title>
{title} - {siteConfig.name}
{title} - {siteConfig.data.name}
</title>
</Head>
<GuestContainer>
Expand Down
4 changes: 0 additions & 4 deletions src/frontend/_layouts/types.ts

This file was deleted.

3 changes: 1 addition & 2 deletions src/frontend/_layouts/useAppTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { useTheme } from "frontend/design-system/theme/useTheme";
import { useUserPreference } from "frontend/hooks/auth/preferences.store";
import { ColorSchemes } from "shared/types/ui";
import { processThemeColors } from "./portal";
import { IThemeSettings } from "./types";
import { getThemePrimaryColor } from "./utils";

export const THEME_SETTINGS_CRUD_CONFIG = MAKE_CRUD_CONFIG({
Expand All @@ -15,7 +14,7 @@ export const THEME_SETTINGS_CRUD_CONFIG = MAKE_CRUD_CONFIG({
});

export const useUserThemePreference = () => {
const themeColor = useAppConfiguration<IThemeSettings>("theme_color");
const themeColor = useAppConfiguration("theme_color");
const userPreferences = useUserPreference<ColorSchemes>("theme");

const theme: ColorSchemes | IColorMode = userPreferences.data;
Expand Down
3 changes: 1 addition & 2 deletions src/frontend/_layouts/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { DataStateKeys } from "frontend/lib/data/types";
import { ColorSchemes } from "shared/types/ui";
import { IThemeSettings } from "./types";
import { ColorSchemes, IThemeSettings } from "shared/types/ui";

export const getThemePrimaryColor = (
theme: ColorSchemes,
Expand Down
Loading

0 comments on commit a778f10

Please sign in to comment.