Skip to content

Commit

Permalink
crud operations
Browse files Browse the repository at this point in the history
  • Loading branch information
Piootrekk committed Dec 4, 2024
1 parent 00e0b0d commit 1c137a8
Show file tree
Hide file tree
Showing 18 changed files with 716 additions and 8 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ $RECYCLE.BIN/
.yarn/cache/
.yarn/unplugged/
.yarn/build-state.yml
.yarn/*
!.yarn/cache
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

# Katalogi specyficzne dla różnych narzędzi
.idea/
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 6 additions & 0 deletions fastify-proxy/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
"dev": "tsnd --respawn --transpile-only --exit-child src/server.ts"
},
"dependencies": {
"@fastify/cors": "^10.0.1",
"@fastify/swagger": "^9.4.0",
"@fastify/swagger-ui": "^5.2.0",
"axios": "^1.7.9",
"dotenv": "^16.4.7",
"fastify": "^5.1.0",
"fastify-plugin": "^5.0.1",
"fastify-zod": "^1.4.0",
"zod": "^3.23.8",
"zod-to-json-schema": "^3.23.5"
Expand Down
7 changes: 7 additions & 0 deletions fastify-proxy/src/app.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import Fastify from "fastify";
import urlRoutes from "./modules/url/url.route";
import swaggerPlugin from "./plugins/swagger";
import cors from "@fastify/cors";

const buildApp = async () => {
const app = Fastify({
logger: true,
});

app.register(cors);
app.register(swaggerPlugin);
app.register(urlRoutes, { prefix: "url" });

return app;
};

Expand Down
4 changes: 3 additions & 1 deletion fastify-proxy/src/config/env.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { z } from "zod";
import { config } from "dotenv";

config();
const envSchema = z.object({
PORT: z.string(),
PORT: z.string().min(1).transform(Number),
});
const { PORT } = process.env;
const parsedEnv = envSchema.safeParse({ PORT });
Expand Down
124 changes: 124 additions & 0 deletions fastify-proxy/src/modules/url/url.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { FastifyReply, FastifyRequest } from "fastify";
import {
deleteUrlData,
getUrlData,
patchUrlData,
postUrlData,
putUrlData,
} from "./url.service";
import { TUrlQuery, TErrorResponse, TUrlBody } from "./url.schema";
import { AxiosError } from "axios";

const errorHandler = (err: unknown): Omit<TErrorResponse, "path"> => {
if (err instanceof AxiosError)
return {
message: err.message,
code: err.code,
status: err.response?.status,
};
else {
return {
message: "Unknown error",
code: "ERROR",
status: 500,
};
}
};

const getUrlHandler = async (
request: FastifyRequest<{ Querystring: TUrlQuery }>,
reply: FastifyReply
) => {
const { link } = request.query;
try {
const response = await getUrlData(link);
reply.status(200).send(response.data);
} catch (error) {
const errHandler = errorHandler(error);
reply.status(errHandler.status || 500).send({
...errHandler,
path: link,
});
}
};

const deletetUrlHandler = async (
request: FastifyRequest<{ Querystring: TUrlQuery }>,
reply: FastifyReply
) => {
const { link } = request.query;
try {
const response = await deleteUrlData(link);
reply.status(200).send(response.data);
} catch (error) {
const errHandler = errorHandler(error);
reply.status(errHandler.status || 500).send({
...errHandler,
path: link,
});
}
};

const postUrlHandler = async (
request: FastifyRequest<{ Querystring: TUrlQuery; Body: TUrlBody }>,
reply: FastifyReply
) => {
const { link } = request.query;
const data = request.body;

try {
const response = await postUrlData(link, data);
reply.status(response.status).send(response.data);
} catch (error) {
const errHandler = errorHandler(error);
reply.status(errHandler.status || 500).send({
...errHandler,
path: link,
});
}
};

const patchUrlHandler = async (
request: FastifyRequest<{ Querystring: TUrlQuery; Body: TUrlBody }>,
reply: FastifyReply
) => {
const { link } = request.query;
const data = request.body;
try {
const response = await patchUrlData(link, data);
reply.status(response.status).send(response.data);
} catch (error) {
const errHandler = errorHandler(error);
reply.status(errHandler.status || 500).send({
...errHandler,
path: link,
});
}
};

const putUrlHandler = async (
request: FastifyRequest<{ Querystring: TUrlQuery; Body: TUrlBody }>,
reply: FastifyReply
) => {
const { link } = request.query;
const data = request.body;

try {
const response = await putUrlData(link, data);
reply.status(response.status).send(response.data);
} catch (error) {
const errHandler = errorHandler(error);
reply.status(errHandler.status || 500).send({
...errHandler,
path: link,
});
}
};

export {
getUrlHandler,
postUrlHandler,
deletetUrlHandler,
putUrlHandler,
patchUrlHandler,
};
91 changes: 91 additions & 0 deletions fastify-proxy/src/modules/url/url.route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { FastifyInstance } from "fastify";
import {
getUrlHandler,
postUrlHandler,
deletetUrlHandler,
putUrlHandler,
patchUrlHandler,
} from "./url.controller";
import {
urlBodySchemaJson,
urlQuerySchemaJson,
urlResponseRerrorSchemaJson,
urlResponseSchemaJson,
} from "./url.schema";

const urlRoutes = async (server: FastifyInstance) => {
server.get(
"/",
{
schema: {
querystring: urlQuerySchemaJson,
response: {
"2xx": urlResponseSchemaJson,
"4xx": urlResponseRerrorSchemaJson,
"5xx": urlResponseRerrorSchemaJson,
},
},
},
getUrlHandler
);
server.post(
"/",
{
schema: {
querystring: urlQuerySchemaJson,
body: urlBodySchemaJson,
response: {
"2xx": urlResponseSchemaJson,
"4xx": urlResponseRerrorSchemaJson,
"5xx": urlResponseRerrorSchemaJson,
},
},
},
postUrlHandler
);
server.delete(
"/",
{
schema: {
querystring: urlQuerySchemaJson,
response: {
"2xx": urlResponseSchemaJson,
"4xx": urlResponseRerrorSchemaJson,
"5xx": urlResponseRerrorSchemaJson,
},
},
},
deletetUrlHandler
);
server.put(
"/",
{
schema: {
querystring: urlQuerySchemaJson,
body: urlBodySchemaJson,
response: {
"2xx": urlResponseSchemaJson,
"4xx": urlResponseRerrorSchemaJson,
"5xx": urlResponseRerrorSchemaJson,
},
},
},
putUrlHandler
);
server.patch(
"/",
{
schema: {
querystring: urlQuerySchemaJson,
body: urlBodySchemaJson,
response: {
"2xx": urlResponseSchemaJson,
"4xx": urlResponseRerrorSchemaJson,
"5xx": urlResponseRerrorSchemaJson,
},
},
},
patchUrlHandler
);
};
export default urlRoutes;
42 changes: 42 additions & 0 deletions fastify-proxy/src/modules/url/url.schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { z } from "zod";
import zodToJsonSchema from "zod-to-json-schema";

export const urlQuerySchema = z.object({
link: z.string().refine(
(val) => {
try {
new URL(val);
return true;
} catch {
return false;
}
},
{ message: "Invalid URL format" }
),
});

const urlBodySchema = z.record(z.any());
const urlResponseErrorSchema = z.object({
message: z.string().optional(),
status: z.number().optional(),
code: z.string().optional(),
path: z.string().url(),
});
const urlResponseSchema = z.any();

const urlResponseRerrorSchemaJson = zodToJsonSchema(urlResponseErrorSchema);
const urlQuerySchemaJson = zodToJsonSchema(urlQuerySchema);
const urlResponseSchemaJson = zodToJsonSchema(urlResponseSchema);
const urlBodySchemaJson = zodToJsonSchema(urlBodySchema);

type TUrlQuery = z.infer<typeof urlQuerySchema>;
type TErrorResponse = z.infer<typeof urlResponseErrorSchema>;
type TUrlBody = z.infer<typeof urlBodySchema>;

export {
urlQuerySchemaJson,
urlResponseSchemaJson,
urlBodySchemaJson,
urlResponseRerrorSchemaJson,
};
export type { TUrlQuery, TErrorResponse, TUrlBody };
29 changes: 29 additions & 0 deletions fastify-proxy/src/modules/url/url.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import axios from "axios";
import { TJsonable } from "../../types/jsonable.types";

const getUrlData = async (link: string) => {
const response = await axios.get(link);
return response;
};

const deleteUrlData = async (link: string) => {
const response = await axios.delete(link);
return response;
};

const postUrlData = async (link: string, body: TJsonable) => {
const response = await axios.post(link, body);
return response;
};

const putUrlData = async (link: string, body: TJsonable) => {
const response = await axios.put(link, body);
return response;
};

const patchUrlData = async (link: string, body: TJsonable) => {
const response = await axios.patch(link, body);
return response;
};

export { getUrlData, postUrlData, patchUrlData, putUrlData, deleteUrlData };
22 changes: 22 additions & 0 deletions fastify-proxy/src/plugins/swagger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { FastifyPluginCallback } from "fastify";
import FastifySwagger from "@fastify/swagger";
import FastifySwaggerUi from "@fastify/swagger-ui";

const swagger: FastifyPluginCallback = async (fastify, _, done) => {
await fastify.register(FastifySwagger, {
openapi: {
info: {
title: "CRUD PROXY",
version: "1.0.0",
},
},
});

await fastify.register(FastifySwaggerUi, {
routePrefix: "/docs",
});

done();
};

export default swagger;
2 changes: 1 addition & 1 deletion fastify-proxy/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import env from "./config/env";
const main = async () => {
const server = await buildApp();
try {
await server.listen({ port: Number(env.PORT) });
await server.listen({ port: env.PORT });
} catch (error) {
server.log.error("Can't startup server");
process.exit(1);
Expand Down
9 changes: 9 additions & 0 deletions fastify-proxy/src/types/jsonable.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
type TJsonable =
| string
| number
| boolean
| null
| TJsonable[]
| { [key: string]: TJsonable };

export type { TJsonable };
Loading

0 comments on commit 1c137a8

Please sign in to comment.