first-commit
This commit is contained in:
commit
054cb94c47
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
node_modules
|
||||
.idea
|
||||
.env
|
||||
build
|
||||
18
Dockerfile
Normal file
18
Dockerfile
Normal file
@ -0,0 +1,18 @@
|
||||
# Declare build-time argument
|
||||
ARG DOCKER_IMAGE_SOURCE
|
||||
|
||||
FROM ${DOCKER_IMAGE_SOURCE}
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
COPY package*.json ./
|
||||
|
||||
RUN npm install
|
||||
|
||||
COPY . .
|
||||
|
||||
EXPOSE ${PORT}
|
||||
|
||||
# CMD npm run build;npm run start
|
||||
# CMD [ "npm", "run", "start-ts" ]
|
||||
CMD ./start.sh
|
||||
22
docker-compose.yml
Normal file
22
docker-compose.yml
Normal file
@ -0,0 +1,22 @@
|
||||
services:
|
||||
svg:
|
||||
build:
|
||||
dockerfile: Dockerfile
|
||||
context: .
|
||||
args:
|
||||
DOCKER_IMAGE_SOURCE: ${DOCKER_IMAGE_SOURCE}
|
||||
ports:
|
||||
- ${PORT}:8000
|
||||
container_name: ${CONTAINER_NAME}
|
||||
tmpfs:
|
||||
- /tmp:size=${TMPFS_SIZE}
|
||||
- /var/log:size=50m
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: ${CPU_LIMIT}
|
||||
memory: ${MEMORY_LIMIT}
|
||||
volumes:
|
||||
- .:/wrkdir
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
34
eslint.config.cjs
Normal file
34
eslint.config.cjs
Normal file
@ -0,0 +1,34 @@
|
||||
// eslint.config.cjs
|
||||
const js = require("@eslint/js");
|
||||
const ts = require("@typescript-eslint/eslint-plugin");
|
||||
const tsParser = require("@typescript-eslint/parser");
|
||||
const prettier = require("eslint-plugin-prettier");
|
||||
const globals = require("globals");
|
||||
|
||||
module.exports = [
|
||||
js.configs.recommended,
|
||||
{
|
||||
files: ["**/*.ts", "**/*.tsx"],
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
globals: {
|
||||
...globals.node,
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
"@typescript-eslint": ts,
|
||||
prettier,
|
||||
},
|
||||
rules: {
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
indent: "off",
|
||||
"linebreak-style": "off",
|
||||
quotes: "off",
|
||||
semi: ["error", "always"],
|
||||
"prettier/prettier": "error",
|
||||
},
|
||||
},
|
||||
];
|
||||
2259
package-lock.json
generated
Normal file
2259
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
31
package.json
Normal file
31
package.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "svg_schemes",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "ts-node src/index.ts",
|
||||
"build": "tsc",
|
||||
"start": "node build/index.js",
|
||||
"lint": "npx eslint \"{src,apps,libs,test}/**/*.ts\" --fix"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.13.10",
|
||||
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
||||
"@typescript-eslint/parser": "^8.26.1",
|
||||
"eslint": "^9.22.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.8.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@eslint/js": "^9.22.0",
|
||||
"@fastify/cors": "^11.0.0",
|
||||
"dotenv": "^16.4.7",
|
||||
"eslint-plugin-prettier": "^5.2.3",
|
||||
"fastify": "^5.2.1",
|
||||
"globals": "^16.0.0"
|
||||
}
|
||||
}
|
||||
30
src/auth/global-access-guard.ts
Normal file
30
src/auth/global-access-guard.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import Config from "../config";
|
||||
|
||||
function isIpPrivate(ip: string): boolean {
|
||||
if ("192.168" === ip.slice(0, 7)) {
|
||||
return true;
|
||||
} else if (
|
||||
ip.slice(0, 3) === "172" &&
|
||||
ip.slice(4, 6) >= "16" &&
|
||||
ip.slice(4, 6) <= "31"
|
||||
) {
|
||||
return true;
|
||||
} else if ("10" === ip.slice(0, 2)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export const GlobalAccessGuard = async (req, reply): Promise<void> => {
|
||||
const ip = req.ip;
|
||||
const token: string = (req.query as any).token;
|
||||
|
||||
if (Config.nodeEnv === "LOCAL") {
|
||||
return;
|
||||
}
|
||||
if (!isIpPrivate(ip) || token !== Config.token) {
|
||||
reply.code(401);
|
||||
throw new Error("Access denied");
|
||||
}
|
||||
};
|
||||
40
src/config/index.ts
Normal file
40
src/config/index.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import * as process from "node:process";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
class Config {
|
||||
public readonly nodeEnv: "DEV" | "PROD" | "LOCAL";
|
||||
public readonly port: number;
|
||||
public readonly token: string;
|
||||
|
||||
constructor() {
|
||||
this.nodeEnv = process.env.NODE_ENV as "DEV" | "PROD" | "LOCAL";
|
||||
this.port = +process.env.PORT;
|
||||
this.token = process.env.TOKEN;
|
||||
|
||||
if (
|
||||
this.nodeEnv !== "DEV" &&
|
||||
this.nodeEnv !== "PROD" &&
|
||||
this.nodeEnv !== "LOCAL"
|
||||
) {
|
||||
throw new Error("Config: nodeEnv is not defined or not valid");
|
||||
}
|
||||
|
||||
const numberValues = ["port"];
|
||||
for (const numberValue of numberValues) {
|
||||
if (!this[numberValue] || typeof this[numberValue] !== "number") {
|
||||
throw new Error(`Config: ${numberValue} is not defined`);
|
||||
}
|
||||
}
|
||||
|
||||
const stringValues = ["token"];
|
||||
for (const stringValue of stringValues) {
|
||||
if (!this[stringValue] || typeof this[stringValue] !== "string") {
|
||||
throw new Error(`Config: ${stringValue} is not defined`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new Config();
|
||||
57
src/index.ts
Normal file
57
src/index.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import fastify from "fastify";
|
||||
import * as cors from "@fastify/cors";
|
||||
import Config from "./config";
|
||||
import { GlobalAccessGuard } from "./auth/global-access-guard";
|
||||
|
||||
let app: fastify.FastifyInstance;
|
||||
|
||||
const createApp = () => {
|
||||
console.log("createApp");
|
||||
app = fastify({
|
||||
logger: true,
|
||||
});
|
||||
|
||||
//accept only private ips + token OR LOCAL
|
||||
app.addHook("preValidation", GlobalAccessGuard);
|
||||
|
||||
app.setErrorHandler((error, request, reply) => {
|
||||
console.error(error.message);
|
||||
// Send error response
|
||||
reply.status(500).send({
|
||||
status: "error",
|
||||
data: {
|
||||
message: error.message,
|
||||
},
|
||||
});
|
||||
});
|
||||
app.register(cors);
|
||||
|
||||
app.get("/health-check", () => ({ statusCode: 200, status: "ok" }));
|
||||
// app.register(authController, { prefix: '/auth' });
|
||||
// if (Config.nodeEnv === 'LOCAL' || Config.nodeEnv === 'DEV') {
|
||||
// app.register(DevController, { prefix: '/dev' });
|
||||
// console.log('register dev controller');
|
||||
// }
|
||||
console.log("appCreated");
|
||||
};
|
||||
|
||||
const start = async (): Promise<void> => {
|
||||
try {
|
||||
createApp();
|
||||
|
||||
await app.listen({
|
||||
port: 8000,
|
||||
host: "0.0.0.0",
|
||||
});
|
||||
|
||||
console.log("Server started on port: 8000");
|
||||
console.log(
|
||||
`You can access it from outside the docker on port ${Config.port}`,
|
||||
);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
start();
|
||||
10
start.sh
Normal file
10
start.sh
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "$NODE" = "LOCAL" ] ; then
|
||||
npm run lint
|
||||
npm run dev
|
||||
else
|
||||
npm run lint
|
||||
npm run build
|
||||
npm run start
|
||||
fi
|
||||
8
tmpls/.env-template
Normal file
8
tmpls/.env-template
Normal file
@ -0,0 +1,8 @@
|
||||
PORT=8000
|
||||
CONTAINER_NAME='svgdev'
|
||||
TMPFS_SIZE='8192m'
|
||||
CPU_LIMIT='10'
|
||||
MEMORY_LIMIT='8g'
|
||||
DOCKER_IMAGE_SOURCE='node:20.12.1-alpine'
|
||||
NODE_ENV='LOCAL'
|
||||
TOKEN='secret_token'
|
||||
10
tsconfig.json
Normal file
10
tsconfig.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2022",
|
||||
"module": "commonjs",
|
||||
"esModuleInterop": true,
|
||||
"strict": true,
|
||||
"rootDir": "src",
|
||||
"outDir": "build",
|
||||
},
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user