Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .idea/dictionaries/project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/node_modules/
/dist/
/.github/release_template.md
README.md
3 changes: 2 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5"
"trailingComma": "es5",
"arrowParens": "avoid"
}
32 changes: 17 additions & 15 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {dirname} from 'path';
import {fileURLToPath} from 'url';
import {FlatCompat} from '@eslint/eslintrc';
import { dirname } from 'path';
import { fileURLToPath } from 'url';
import { FlatCompat } from '@eslint/eslintrc';
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import eslintPluginPrettier from 'eslint-plugin-prettier';
Expand Down Expand Up @@ -50,26 +50,28 @@ export default tseslint.config(
message: 'Do not use `as any`, types must be explicit and safe.',
},
{
selector: "JSXOpeningElement[name.type='JSXIdentifier'][name.name=/^[a-z]/]",
selector:
"JSXOpeningElement[name.type='JSXIdentifier'][name.name=/^[a-z]/]",
message:
'Do not use native HTML elements: use an MUI component (PascalCase) instead.',
},
],

/* Code structure and clarity */
// 'max-params': ['warn', 1],

'default-case': 'warn',
'import/no-unresolved': 'error',
'no-inline-comments': 'warn',
'no-undefined': 'warn',
'no-var': 'error',
'prefer-const': ['error', {destructuring: 'all'}],
'prefer-const': ['error', { destructuring: 'all' }],
'require-await': 'error',
'require-object-destructuring': 'off',

'arrow-parens': ['error', 'as-needed'],
/* Formatting */
'max-len': ['warn', {code: 300, ignoreUrls: true}],
'prettier/prettier': ['warn', {semi: true}],
'max-len': ['warn', { code: 300, ignoreUrls: true }],
'prettier/prettier': ['warn', { semi: true }],
semi: ['error', 'always'],

/* Naming conventions */
Expand Down Expand Up @@ -120,29 +122,29 @@ export default tseslint.config(
],
'@typescript-eslint/explicit-function-return-type': [
'error',
{allowExpressions: false},
{ allowExpressions: false },
],
'@typescript-eslint/explicit-member-accessibility': [
'error',
{accessibility: 'explicit'},
{ accessibility: 'explicit' },
],
'@typescript-eslint/explicit-module-boundary-types': 'error',
'@typescript-eslint/no-empty-function': ['warn'],
'@typescript-eslint/no-extraneous-class': [
'error',
{allowConstructorOnly: false},
{ allowConstructorOnly: false },
],
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-inferrable-types': 'off',
'@typescript-eslint/no-magic-numbers': [
'warn',
{ignoreEnums: true, ignore: [0, 1], enforceConst: true},
{ ignoreEnums: true, ignore: [0, 1], enforceConst: true },
],
'@typescript-eslint/no-namespace': 'off',
'@typescript-eslint/no-unsafe-member-access': 'warn',
'@typescript-eslint/no-unused-vars': [
'error',
{argsIgnorePattern: '^_'},
{ argsIgnorePattern: '^_' },
],
'@typescript-eslint/prefer-function-type': 'warn',
'@typescript-eslint/prefer-readonly': 'warn',
Expand Down Expand Up @@ -187,9 +189,9 @@ export default tseslint.config(

{
files: ['**/*.test.ts', '**/*.spec.ts', '**/*.test.tsx', '**/*.spec.tsx'],
plugins: {jest: eslintPluginJest},
plugins: { jest: eslintPluginJest },
settings: {
jest: {version: 29},
jest: { version: 29 },
},
},
],
Expand Down
5 changes: 2 additions & 3 deletions src/app/api/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { JSX } from 'react';
import React from 'react';
import type { Metadata } from 'next';
import type { SharedLayoutProps } from '@shared/types/props/SharedLayoutProps';

export const metadata: Metadata = {
title: 'LockLite API',
Expand All @@ -9,9 +10,7 @@ export const metadata: Metadata = {

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}): JSX.Element {
}: SharedLayoutProps): JSX.Element {
return (
// eslint-disable-next-line no-restricted-syntax
<html lang="en">
Expand Down
5 changes: 2 additions & 3 deletions src/app/ui/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React from 'react';
import ThemeRegistry from '@ui/providers/ThemeRegistry';
import { AppBar, Container, Toolbar, Typography } from '@mui/material';
import PageContainer from '@ui/components/common/PageContainer';
import type { SharedLayoutProps } from '@shared/types/props/SharedLayoutProps';

export const metadata: Metadata = {
title: {
Expand All @@ -15,9 +16,7 @@ export const metadata: Metadata = {

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}): JSX.Element {
}: SharedLayoutProps): JSX.Element {
return (
// eslint-disable-next-line no-restricted-syntax
<html lang="en" style={{ height: '100%' }}>
Expand Down
6 changes: 3 additions & 3 deletions src/app/ui/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import type { JSX } from 'react';
import { redirect } from 'next/navigation';

export default function Home(): JSX.Element {
return <></>;
export default function HomePage(): JSX.Element {
redirect('/ui/workspace');
}
7 changes: 7 additions & 0 deletions src/app/ui/workspace/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';
import type { JSX } from 'react';
import type { SharedLayoutProps } from '@shared/types/props/SharedLayoutProps';

export default function WorkspaceLayout(props: SharedLayoutProps): JSX.Element {
return <>{props.children}</>;
}
98 changes: 98 additions & 0 deletions src/app/ui/workspace/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
'use client';

import 'reflect-metadata';
import React, { useState } from 'react';
import type { JSX } from 'react';
import type { VaultModelDto } from '@shared/dto/models/vault.model.dto';
import ErrorMessage from '@ui/components/common/ErrorMessage';
import CircularLoader from '@ui/components/common/CircularLoader';
import { VaultsGateway } from '@ui/gateways/vaults.gateway';
import { container } from 'tsyringe';
import type { GetMyVaultsResponseDto } from '@shared/dto/responses/get-my-vaults.response.dto';
import { useApi } from '@ui/hooks/useApi';
import {
Box,
Card,
CardContent,
CardHeader,
Container,
Grid,
Typography,
} from '@mui/material';

export default function WorkspacePage(): JSX.Element {
const [vaults, setVaults] = useState<VaultModelDto[]>([]);
const [error, setError] = useState<Error | null>(null);
const vaultsGateway: VaultsGateway = container.resolve(VaultsGateway);

const { loading } = useApi<GetMyVaultsResponseDto>({
request: () => vaultsGateway.getMyVaults(),
onSuccess: data => setVaults(data.myVaults),
onError: error => setError(error),
deps: [],
});

return (
<Container
sx={{
padding: '2rem',
display: 'flex',
flexDirection: 'column',
gap: '3rem',
}}
>
<Typography variant={'h3'} textAlign={'left'}>
My vaults
</Typography>
<ErrorMessage error={error} />
<CircularLoader loading={loading} />
{!loading && vaults.length === 0 && (
<Typography>No results found</Typography>
)}
{vaults.length > 0 && (
<Grid
container
spacing={{ xs: 2, md: 3, lg: 3, xl: 4 }}
columns={{ xs: 1, md: 2, lg: 3, xl: 3 }}
overflow={'auto'}
height={'70vh'}
>
{vaults.map(vault => (
<Grid key={vault.id} size={1}>
<Card
sx={{
bgcolor: 'background.paper',
}}
>
<CardHeader title={vault.label} />
<CardContent>
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
gap: '1rem',
}}
>
<Typography variant="body2" color="text.secondary">
Secret:
</Typography>
<Typography
variant="body2"
color="text.secondary"
fontFamily={'monospace'}
overflow={'scroll'}
textOverflow={'ellipsis'}
>
{vault.secret}
</Typography>
</Box>
</CardContent>
</Card>
</Grid>
))}
</Grid>
)}
</Container>
);
}
50 changes: 50 additions & 0 deletions src/modules/shared/services/abstract/request.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
export abstract class RequestService {
protected constructor(private readonly _baseApiUrl: string = '') {}

private async _fetch<T>(uri: string, options: RequestInit): Promise<T> {
const response: Response = await fetch(`${this._baseApiUrl}${uri}`, {
...options,
headers: {
'Content-Type': 'application/json',
...(options.headers ?? {}),
},
});

if (!response.ok) {
let message: string = 'Unexpected error';
try {
// eslint-disable-next-line @typescript-eslint/typedef
const errorJson = await response.json();
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
message = errorJson?.error ?? message;
} catch {
message = await response.text();
}
throw new Error(message);
}

return response.json();
}

public async get<T>(uri: string): Promise<T> {
return await this._fetch<T>(uri, { method: 'GET' });
}

public async post<T>(uri: string, body: unknown): Promise<T> {
return await this._fetch<T>(uri, {
method: 'POST',
body: JSON.stringify(body),
});
}

public async put<T>(uri: string, body: unknown): Promise<T> {
return await this._fetch<T>(uri, {
method: 'PUT',
body: JSON.stringify(body),
});
}

public async delete<T>(uri: string): Promise<T> {
return await this._fetch<T>(uri, { method: 'DELETE' });
}
}
50 changes: 0 additions & 50 deletions src/modules/shared/services/request.service.ts

This file was deleted.

5 changes: 5 additions & 0 deletions src/modules/shared/types/props/SharedChildrenProps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type React from 'react';

export type SharedChildrenProps = {
children: React.ReactNode;
};
3 changes: 3 additions & 0 deletions src/modules/shared/types/props/SharedLayoutProps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import type { SharedChildrenProps } from '@shared/types/props/SharedChildrenProps';

export type SharedLayoutProps = SharedChildrenProps;
7 changes: 2 additions & 5 deletions src/modules/ui/components/common/PageContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import type { JSX } from 'react';
import React from 'react';
import { Container } from '@mui/material';
import type { SharedChildrenProps } from '@shared/types/props/SharedChildrenProps';

type PageContainerProps = {
children: React.ReactNode;
};

export default function PageContainer(props: PageContainerProps): JSX.Element {
export default function PageContainer(props: SharedChildrenProps): JSX.Element {
return (
<Container
sx={{
Expand Down
Empty file removed src/modules/ui/gateways/.gitkeep
Empty file.
Loading