Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#102 into [email protected] 🐘 add logger support #131

Merged
merged 26 commits into from
Jan 5, 2025
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
155955e
#102 🐘 logger WIP
RiceWithMeat Nov 19, 2023
87a33bd
Merge branch '#128' into #102
RiceWithMeat Nov 21, 2023
da5e3f0
#102 🐘 logger WIP
RiceWithMeat Nov 21, 2023
105cced
#102 🐘 add logger in createRestMockServer and createGraphQLMockServer…
RiceWithMeat Nov 21, 2023
1251aed
#102 🐘 loggers rework
RiceWithMeat Dec 3, 2023
c427ea0
#102 🐘 logger rework
RiceWithMeat Apr 6, 2024
7344d74
Merge branch 'main' into #102
RiceWithMeat Apr 6, 2024
3f7ce6d
Merge remote-tracking branch 'refs/remotes/origin/main' into #102
RiceWithMeat Nov 11, 2024
95a29c1
#102 🐘 another logger rework
RiceWithMeat Nov 11, 2024
8f51139
#102 🐘 simplify logger logic, add log function in interceptor params,…
RiceWithMeat Nov 28, 2024
2973218
#102 🐘 remove loggers field in configs, rework filterTokenValues helper
RiceWithMeat Dec 18, 2024
219b847
#102 🐘 add tests, add readme, move formatTokenValues into helper
RiceWithMeat Dec 20, 2024
87367e4
#102 🐘 fix types in readme
RiceWithMeat Dec 20, 2024
ac14df2
#102 🐘 rename requestInfoMiddleware -> contextMiddleware, contextMidd…
RiceWithMeat Dec 22, 2024
ae46d1d
#102 🐘 remove useless type
RiceWithMeat Dec 22, 2024
3276961
#102 🐘 remove enabled flag for logger
RiceWithMeat Dec 23, 2024
33d52f5
#102 🐘 remove enabled flag for logger in readme
RiceWithMeat Dec 23, 2024
dc32ec2
#102 🐘 simplify logger types, allow use graphql tokens only in global…
RiceWithMeat Dec 30, 2024
26275a2
#102 🐘 add graphQLQuery token, rename types and helpers
RiceWithMeat Jan 3, 2025
179e1fa
#102 🐘 fix Interceptors type, remove logger object options for body, …
RiceWithMeat Jan 3, 2025
98ec2e9
#102 🐘 rename type LoggerTokensToTokenOptions -> LoggerTokensToLogger…
RiceWithMeat Jan 3, 2025
6c501f4
#102 🐘 fix readme and test for logger, swap Data and Api generics in …
RiceWithMeat Jan 5, 2025
53ff177
#102 🐘 move spyOn for Date.now from test into describe
RiceWithMeat Jan 5, 2025
02a09c0
#102 🐘 make tokens and rewrite optional in readme
RiceWithMeat Jan 5, 2025
a0542c0
#102 🐘 rename tokens parameter to options for log function
RiceWithMeat Jan 5, 2025
1ab247e
#102 🐘 rename objectOptions -> nestedOption, fix comments in readme
RiceWithMeat Jan 5, 2025
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
4 changes: 3 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ module.exports = {
'@typescript-eslint/no-unsafe-enum-comparison': 'off',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/naming-convention': 'off',
'@typescript-eslint/no-namespace': ['error', { allowDeclarations: true }],
'no-underscore-dangle': 'off',
'no-restricted-syntax': 'off',
'no-continue': 'off',
'promise/always-return': ['error', { ignoreLastCallback: true }],
'arrow-body-style': ['error', 'as-needed']
'arrow-body-style': ['error', 'as-needed'],
'no-console': ['warn', { allow: ['info', 'dir', 'error'] }]
}
}
]
Expand Down
381 changes: 291 additions & 90 deletions README.md

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions src/core/graphql/createGraphQLRoutes/createGraphQLRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,7 @@ export const createGraphQLRoutes = ({
});
});

if (!matchedRouteConfig) {
return next();
}
if (!matchedRouteConfig) return next();

if (matchedRouteConfig.interceptors?.request) {
await callRequestInterceptor({
Expand Down
44 changes: 44 additions & 0 deletions src/core/middlewares/contextMiddleware/contextMiddleware.ts
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не хватает тестов на этот файл

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { Express } from 'express';

import { getGraphQLInput, parseQuery } from '@/utils/helpers';
import type { GraphQLEntity, GraphQLOperationName, GraphQLOperationType } from '@/utils/types';

declare global {
namespace Express {
export interface Request {
id: number;
timestamp: number;
graphQL: {
operationType: GraphQLOperationType;
operationName: GraphQLOperationName;
variables?: GraphQLEntity<'variables'>;
} | null;
}
}
}

export const contextMiddleware = (server: Express) => {
let requestId = 0;

server.use((request, _response, next) => {
requestId += 1;
request.id = requestId;

request.timestamp = Date.now();

const graphQLInput = getGraphQLInput(request);
const graphQLQuery = parseQuery(graphQLInput.query ?? '');

if (graphQLInput.query && graphQLQuery) {
request.graphQL = {
operationType: graphQLQuery.operationType as GraphQLOperationType,
operationName: graphQLQuery.operationName as GraphQLOperationName,
RiceWithMeat marked this conversation as resolved.
Show resolved Hide resolved
variables: graphQLInput.variables
};
return next();
}

request.graphQL = null;
return next();
});
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
type Cookies = Record<string, string>;
import type { Cookies } from '@/utils/types';

export const parseCookie = (cookieHeader: string) => {
if (!cookieHeader) return {};
Expand Down
1 change: 1 addition & 0 deletions src/core/middlewares/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './contextMiddleware/contextMiddleware';
export * from './cookieParseMiddleware/cookieParseMiddleware';
export * from './corsMiddleware/corsMiddleware';
export * from './destroyerMiddleware/destroyerMiddleware';
Expand Down
6 changes: 4 additions & 2 deletions src/core/middlewares/notFoundMiddleware/notFoundMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,19 @@ export const notFoundMiddleware = (
});
}

response.status(404);

const isRequestSupportHtml =
request.headers.accept?.includes('text/html') || request.headers.accept?.includes('*/*');
if (isRequestSupportHtml) {
response.status(404).render('pages/404', {
response.render('pages/404', {
restRequestSuggestions,
graphqlRequestSuggestions
});
return;
}

response.status(404).json({
response.json({
message: 'Request or page not found. Similar requests in data',
data: {
restRequestSuggestions,
Expand Down
4 changes: 1 addition & 3 deletions src/core/rest/createRestRoutes/createRestRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,7 @@ export const createRestRoutes = ({
});
});

if (!matchedRouteConfig) {
return next();
}
if (!matchedRouteConfig) return next();

if (matchedRouteConfig.interceptors?.request) {
await callRequestInterceptor({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import express from 'express';

import { createDatabaseRoutes } from '@/core/database';
import {
contextMiddleware,
cookieParseMiddleware,
corsMiddleware,
errorMiddleware,
Expand Down Expand Up @@ -32,6 +33,8 @@ export const createDatabaseMockServer = (

server.use(bodyParser.text());

contextMiddleware(server);

cookieParseMiddleware(server);

const serverRequestInterceptor = databaseMockServerConfig.interceptors?.request;
Expand Down
3 changes: 3 additions & 0 deletions src/server/createGraphQLMockServer/createGraphQLMockServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import express from 'express';
import { createDatabaseRoutes } from '@/core/database';
import { createGraphQLRoutes } from '@/core/graphql';
import {
contextMiddleware,
cookieParseMiddleware,
corsMiddleware,
errorMiddleware,
Expand Down Expand Up @@ -33,6 +34,8 @@ export const createGraphQLMockServer = (

server.use(bodyParser.text());

contextMiddleware(server);

cookieParseMiddleware(server);

const serverRequestInterceptor = graphqlMockServerConfig.interceptors?.request;
Expand Down
3 changes: 3 additions & 0 deletions src/server/createMockServer/createMockServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import express from 'express';
import { createDatabaseRoutes } from '@/core/database';
import { createGraphQLRoutes } from '@/core/graphql';
import {
contextMiddleware,
cookieParseMiddleware,
corsMiddleware,
errorMiddleware,
Expand Down Expand Up @@ -34,6 +35,8 @@ export const createMockServer = (

server.use(bodyParser.text());

contextMiddleware(server);

cookieParseMiddleware(server);

const serverRequestInterceptor = mockServerConfig.interceptors?.request;
Expand Down
3 changes: 3 additions & 0 deletions src/server/createRestMockServer/createRestMockServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import express from 'express';

import { createDatabaseRoutes } from '@/core/database';
import {
contextMiddleware,
cookieParseMiddleware,
corsMiddleware,
errorMiddleware,
Expand Down Expand Up @@ -33,6 +34,8 @@ export const createRestMockServer = (

server.use(bodyParser.text());

contextMiddleware(server);

cookieParseMiddleware(server);

const serverRequestInterceptor = restMockServerConfig.interceptors?.request;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const startDatabaseMockServer = (databaseMockServerConfig: DatabaseMockSe
const port = databaseMockServerConfig.port ?? DEFAULT.PORT;

const server = mockServer.listen(port, () => {
console.log(color.green(`🎉 Database Mock Server is running at http://localhost:${port}`));
console.info(color.green(`🎉 Database Mock Server is running at http://localhost:${port}`));
});

// ✅ important: add destroy method for closing keep-alive connections after server shutdown
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const startGraphQLMockServer = (graphQLMockServerConfig: GraphQLMockServe
const port = graphQLMockServerConfig.port ?? DEFAULT.PORT;

const server = mockServer.listen(port, () => {
console.log(color.green(`🎉 GraphQL Mock Server is running at http://localhost:${port}`));
console.info(color.green(`🎉 GraphQL Mock Server is running at http://localhost:${port}`));
});

// ✅ important: add destroy method for closing keep-alive connections after server shutdown
Expand Down
2 changes: 1 addition & 1 deletion src/server/startMockServer/startMockServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const startMockServer = (mockServerConfig: MockServerConfig) => {
const port = mockServerConfig.port ?? DEFAULT.PORT;

const server = mockServer.listen(port, () => {
console.log(color.green(`🎉 Mock Server is running at http://localhost:${port}`));
console.info(color.green(`🎉 Mock Server is running at http://localhost:${port}`));
});

// ✅ important: add destroy method for closing keep-alive connections after server shutdown
Expand Down
2 changes: 1 addition & 1 deletion src/server/startRestMockServer/startRestMockServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const startRestMockServer = (restMockServerConfig: RestMockServerConfig)
const port = restMockServerConfig.port ?? DEFAULT.PORT;

const server = mockServer.listen(port, () => {
console.log(color.green(`🎉 Rest Mock Server is running at http://localhost:${port}`));
console.info(color.green(`🎉 Rest Mock Server is running at http://localhost:${port}`));
});

// ✅ important: add destroy method for closing keep-alive connections after server shutdown
Expand Down
135 changes: 66 additions & 69 deletions src/static/views/pages/404/index.ejs
Original file line number Diff line number Diff line change
@@ -1,85 +1,82 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>404 - 🎉 Mock Config Server</title>

<title>404 - 🎉 Mock Config Server</title>
<link rel="stylesheet" href="/assets/styles/global.css" />
<link rel="stylesheet" href="/pages/404/index.css" />

<link rel="stylesheet" href="/assets/styles/global.css" />
<link rel="stylesheet" href="/pages/404/index.css" />
<% const api = { rest: "REST", graphql: "GraphQL" } %>

<% const api = { rest: "REST", graphql: "GraphQL" } %>
<% const rootPath = (path) => `../../${path}` %>
<%- include(rootPath('features/scheme/index')) -%>
<%- include(rootPath('features/tab/index')) -%>
</head>

<% const rootPath = (path) => `../../${path}` %>
<%- include(rootPath('features/scheme/index')) -%>
<%- include(rootPath('features/tab/index')) -%>
</head>

<body class="tab_item-<%= graphqlRequestSuggestions.length ? api.graphql : api.rest %>">
<%- include(rootPath('components/header/index')) -%>
<div class="margin_container">
<div class="hero">
<div class="title">
<img src="/assets/images/404.png" />
404
</div>
<div class="description">
Such request or page not found ☹️
<a class="link" href="/">
Return on main page
</a>
</div>
</div>
</div>
<div class="margin_container">
<div class="content">
<div class="content_head">
<div class="tab_items">
<% Object.values(api).forEach((variant)=> { %>
<div id="tab_item-<%=variant%>" class="tab_item">
<%=variant%>
</div>
<% }) %>
<body class="tab_item-<%= graphqlRequestSuggestions.length ? api.graphql : api.rest %>">
<%- include(rootPath('components/header/index')) -%>
<div class="margin_container">
<div class="hero">
<div class="title">
<img src="/assets/images/404.png" />
404
</div>
</div>
<div id="tab_content-<%=api.rest%>" class="tab_content">
<div class="description">
<% if (restRequestSuggestions.length) { %>
<span>We searched a bit, maybe this will help you:</span>
<% restRequestSuggestions.forEach((requestSuggestion) => { %>
<span><%= requestSuggestion.method.toUpperCase() %> <%=
requestSuggestion.path %></span>
<% })} else { %>
<span>We searched, but found nothing.</span>
<span>Maybe you don't have <%=api.rest%> configs? 👀</span>
<a class="link" href="https://github.com/siberiacancode/mock-config-server#configs" rel="noopener noreferrer" target="_blank">
Read documentation 📘 for more information
Such request or page not found ☹️
<a class="link" href="/">
Return on main page
</a>
<% } %>
</div>
</div>
</div>
<div class="margin_container">
<div class="content">
<div class="content_head">
<div class="tab_items">
<% Object.values(api).forEach((variant)=> { %>
<div id="tab_item-<%=variant%>" class="tab_item">
<%=variant%>
</div>
<% }) %>
</div>
</div>
<div id="tab_content-<%=api.rest%>" class="tab_content">
<div class="description">
<% if (restRequestSuggestions.length) { %>
<span>We searched a bit, maybe this will help you:</span>
<% restRequestSuggestions.forEach((requestSuggestion) => { %>
<span><%= requestSuggestion.method.toUpperCase() %> <%=
requestSuggestion.path %></span>
<% })} else { %>
<span>We searched, but found nothing.</span>
<span>Maybe you don't have <%=api.rest%> configs? 👀</span>
<a class="link" href="https://github.com/siberiacancode/mock-config-server#configs" rel="noopener noreferrer" target="_blank">
Read documentation 📘 for more information
</a>
<% } %>
</div>
</div>

<div id="tab_content-<%=api.graphql%>" class="tab_content">
<div class="description">
<% if (graphqlRequestSuggestions.length) { %>
<span>We searched a bit, maybe this will help you:</span>
<% graphqlRequestSuggestions.forEach((requestSuggestion) => { %>
<span><%= requestSuggestion.operationType %> <%=
requestSuggestion.operationName %></span>
<% })} else { %>
<span>We searched, but found nothing.</span>
<span>Maybe you don't have <%=api.graphql%> configs? 👀</span>
<a class="link" href="https://github.com/siberiacancode/mock-config-server#configs" rel="noopener noreferrer" target="_blank">
Read documentation 📘 for more information
</a>
<% } %>
<div id="tab_content-<%=api.graphql%>" class="tab_content">
<div class="description">
<% if (graphqlRequestSuggestions.length) { %>
<span>We searched a bit, maybe this will help you:</span>
<% graphqlRequestSuggestions.forEach((requestSuggestion) => { %>
<span><%= requestSuggestion.operationType %> <%=
requestSuggestion.operationName %></span>
<% })} else { %>
<span>We searched, but found nothing.</span>
<span>Maybe you don't have <%=api.graphql%> configs? 👀</span>
<a class="link" href="https://github.com/siberiacancode/mock-config-server#configs" rel="noopener noreferrer" target="_blank">
Read documentation 📘 for more information
</a>
<% } %>
</div>
</div>
</div>
</div>
</div>
</div>
</body>

</html>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { formatTimestamp } from './formatTimestamp';

describe('formatTimestamp', () => {
test('Should correctly format timestamp', () => {
expect(formatTimestamp(1735623296789)).toBe('31.12.2024, 12:34:56,789');
});
});
9 changes: 9 additions & 0 deletions src/utils/helpers/date/formatTimestamp/formatTimestamp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const formatTimestamp = (timestamp: number) =>
new Date(timestamp).toLocaleString('ru-RU', {
day: 'numeric',
month: 'numeric',
year: 'numeric',
hour: 'numeric',
minute: 'numeric',
fractionalSecondDigits: 3
});
1 change: 1 addition & 0 deletions src/utils/helpers/date/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './formatTimestamp/formatTimestamp';
Loading