mirror of
https://github.com/meienberger/runtipi.git
synced 2024-08-17 08:00:26 +03:00
add fs helpers
This commit is contained in:
parent
1283457268
commit
4e5bf34ece
3
system-api/.eslintignore
Normal file
3
system-api/.eslintignore
Normal file
@ -0,0 +1,3 @@
|
||||
node_modules/
|
||||
dist/
|
||||
*.cjs
|
@ -1,136 +1,16 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
env: { node: true },
|
||||
extends: ['airbnb-base', 'eslint:recommended', 'plugin:import/typescript'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.json'],
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
},
|
||||
extends: ['plugin:prettier/recommended', 'airbnb-typescript', 'plugin:sonarjs/recommended', 'plugin:@typescript-eslint/recommended', 'plugin:unicorn/recommended', 'hardcore'],
|
||||
plugins: ['prettier', '@typescript-eslint', 'no-loops', 'sonarjs', 'deprecate', 'no-secrets', 'jest', 'react'],
|
||||
overrides: [
|
||||
{
|
||||
files: ['**/*.test.ts', '**/*.test.tsx', 'jest.setup.ts', 'jest.config.js'],
|
||||
rules: {
|
||||
'import/unambiguous': 0,
|
||||
'unicorn/consistent-function-scoping': 0,
|
||||
},
|
||||
env: {
|
||||
jest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.d.ts'],
|
||||
rules: {
|
||||
'import/unambiguous': 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
plugins: ['@typescript-eslint', 'import'],
|
||||
rules: {
|
||||
'max-statements': 0,
|
||||
camelcase: 0,
|
||||
'unicorn/prefer-node-protocol': 0,
|
||||
'newline-per-chained-call': 0,
|
||||
'new-cap': 0,
|
||||
'security/detect-non-literal-regexp': 0,
|
||||
'promise/avoid-new': 0,
|
||||
'import/no-commonjs': 0,
|
||||
'unicorn/prefer-module': 0,
|
||||
'@typescript-eslint/no-var-requires': 0,
|
||||
'security/detect-unsafe-regex': 0,
|
||||
'unicorn/no-unsafe-regex': 0,
|
||||
'no-param-reassign': ['error', { props: true, ignorePropertyModificationsFor: ['^draft'] }],
|
||||
'unicorn/no-array-callback-reference': 0,
|
||||
'import/no-namespace': 0,
|
||||
'unicorn/no-null': 0,
|
||||
'unicorn/no-useless-undefined': 0,
|
||||
'import/max-dependencies': 0,
|
||||
'no-use-before-define': 'off',
|
||||
'@typescript-eslint/no-use-before-define': ['error'],
|
||||
'unicorn/no-array-for-each': 0,
|
||||
'unicorn/prevent-abbreviations': 0,
|
||||
'import/order': 0,
|
||||
'import/extensions': 0,
|
||||
'ext/lines-between-object-properties': 0,
|
||||
'putout/putout': 0,
|
||||
'func-style': ['error', 'declaration', { allowArrowFunctions: true }],
|
||||
'deprecate/function': 1,
|
||||
'deprecate/member-expression': 1,
|
||||
'deprecate/import': 1,
|
||||
'no-secrets/no-secrets': 'error',
|
||||
'arrow-body-style': 0,
|
||||
semi: 0,
|
||||
'@typescript-eslint/semi': 0,
|
||||
'@typescript-eslint/indent': 0,
|
||||
'implicit-arrow-linebreak': 0,
|
||||
'function-paren-newline': 0,
|
||||
'operator-linebreak': 0,
|
||||
'import/no-unused-modules': [1, { unusedExports: true }],
|
||||
'import/no-extraneous-dependencies': [
|
||||
'error',
|
||||
{
|
||||
devDependencies: true,
|
||||
},
|
||||
],
|
||||
quotes: ['warn', 'single'],
|
||||
'no-restricted-syntax': 2,
|
||||
'no-await-in-loop': 2,
|
||||
'object-curly-newline': 0,
|
||||
'no-constant-condition': 2,
|
||||
'no-mixed-operators': 1,
|
||||
'no-console': ['error', { allow: ['warn', 'error'] }],
|
||||
'no-underscore-dangle': 0,
|
||||
'no-global-assign': 2,
|
||||
'prefer-const': [
|
||||
'error',
|
||||
{
|
||||
destructuring: 'any',
|
||||
ignoreReadBeforeAssign: false,
|
||||
},
|
||||
],
|
||||
'import/prefer-default-export': 0,
|
||||
'import/no-named-as-default': 0,
|
||||
'max-lines': [
|
||||
'error',
|
||||
{
|
||||
max: 200,
|
||||
skipBlankLines: true,
|
||||
skipComments: true,
|
||||
},
|
||||
],
|
||||
'max-len': [
|
||||
2,
|
||||
200,
|
||||
{
|
||||
ignoreComments: true,
|
||||
ignoreTemplateLiterals: true,
|
||||
ignoreStrings: true,
|
||||
},
|
||||
],
|
||||
curly: 0,
|
||||
'arrow-parens': 0,
|
||||
'no-return-assign': 2,
|
||||
'comma-dangle': 0,
|
||||
'no-multi-str': 0,
|
||||
'newline-before-return': 2,
|
||||
'newline-after-var': 2,
|
||||
'newline-per-chained-call': 2,
|
||||
'import/newline-after-import': 2,
|
||||
'no-loops/no-loops': 2,
|
||||
'jest/no-disabled-tests': 'warn',
|
||||
'jest/no-focused-tests': 'error',
|
||||
'jest/no-identical-title': 'error',
|
||||
'jest/prefer-to-have-length': 'warn',
|
||||
'jest/valid-expect': 'error',
|
||||
'id-length': 0,
|
||||
'no-magic-numbers': 0,
|
||||
'unicorn/prefer-type-error': 0,
|
||||
'unicorn/no-array-method-this-argument': 0,
|
||||
'no-shadow': 'off',
|
||||
'@typescript-eslint/no-shadow': ['error'],
|
||||
},
|
||||
globals: {
|
||||
JSX: true,
|
||||
'no-restricted-exports': 0,
|
||||
'max-len': [{ code: 200 }],
|
||||
'import/extensions': ['error', 'ignorePackages', { js: 'never', jsx: 'never', ts: 'never', tsx: 'never' }],
|
||||
},
|
||||
};
|
||||
|
@ -1,7 +1,6 @@
|
||||
module.exports = {
|
||||
singleQuote: true,
|
||||
semi: true,
|
||||
trailingComma: "all",
|
||||
arrowParens: "avoid",
|
||||
trailingComma: 'all',
|
||||
printWidth: 200,
|
||||
};
|
||||
|
19426
system-api/package-lock.json
generated
19426
system-api/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,7 @@
|
||||
"main": "src/server.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"lint": "eslint . --ext .ts",
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "esbuild --bundle src/server.ts --outdir=dist --allow-overwrite --sourcemap --platform=node --minify --analyze=verbose --external:./node_modules/* --format=esm",
|
||||
"build:watch": "esbuild --bundle src/server.ts --outdir=dist --allow-overwrite --sourcemap --platform=node --external:./node_modules/* --format=esm --watch",
|
||||
@ -26,8 +27,17 @@
|
||||
"devDependencies": {
|
||||
"@types/compression": "^1.7.2",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/validator": "^13.7.2",
|
||||
"concurrently": "^7.1.0",
|
||||
"esbuild": "^0.14.32",
|
||||
"nodemon": "^2.0.15"
|
||||
"eslint": "^8.13.0",
|
||||
"eslint-config-airbnb-typescript": "^17.0.0",
|
||||
"eslint-config-hardcore": "^24.5.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-unicorn": "^42.0.0",
|
||||
"nodemon": "^2.0.15",
|
||||
"prettier": "2.6.2"
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,3 @@
|
||||
// "form_fields": {
|
||||
// "username": {
|
||||
// "type": "text",
|
||||
// "label": "Username",
|
||||
// "max": 50,
|
||||
// "min": 3,
|
||||
// "required": true,
|
||||
// "env_variable": "NEXTCLOUD_USERNAME"
|
||||
// },
|
||||
// "password": {
|
||||
// "type": "password",
|
||||
// "label": "Password",
|
||||
// "max": 50,
|
||||
// "min": 3,
|
||||
// "required": true,
|
||||
// "env_variable": "NEXTCLOUD_PASSWORD"
|
||||
// }
|
||||
|
||||
interface FormField {
|
||||
type: string;
|
||||
label: string;
|
||||
@ -29,5 +11,5 @@ export interface AppConfig {
|
||||
name: string;
|
||||
description: string;
|
||||
version: string;
|
||||
form_fields: Record<string, FormField[]>;
|
||||
form_fields: Record<string, FormField>;
|
||||
}
|
||||
|
@ -2,4 +2,4 @@ import config from '../config';
|
||||
|
||||
export const APP_DATA_FOLDER = 'app-data';
|
||||
export const APPS_FOLDER = 'apps';
|
||||
export const __prod__ = config.NODE_ENV === 'production';
|
||||
export const isProd = config.NODE_ENV === 'production';
|
||||
|
@ -1,2 +0,0 @@
|
||||
export { default as SystemController } from './system.controller';
|
||||
export { default as AppController } from './app.controller';
|
@ -1,15 +0,0 @@
|
||||
import { Request, Response } from "express";
|
||||
import publicIp from "public-ip";
|
||||
import portScanner from "node-port-scanner";
|
||||
|
||||
const isPortOpen = async (req: Request, res: Response<boolean>) => {
|
||||
const port = req.params.port;
|
||||
|
||||
const host = await publicIp.v4();
|
||||
|
||||
const isOpen = await portScanner(host, [port]);
|
||||
|
||||
console.log(port);
|
||||
|
||||
res.status(200).send(isOpen);
|
||||
};
|
3
system-api/src/helpers/helpers.ts
Normal file
3
system-api/src/helpers/helpers.ts
Normal file
@ -0,0 +1,3 @@
|
||||
const objectKeys = <T>(obj: T): (keyof T)[] => Object.keys(obj) as (keyof T)[];
|
||||
|
||||
export default { objectKeys };
|
@ -1,45 +1,37 @@
|
||||
import { Request, Response } from 'express';
|
||||
import fs from 'fs';
|
||||
import process from 'child_process';
|
||||
import config from '../config';
|
||||
import { AppConfig } from '../config/types';
|
||||
import config from '../../config';
|
||||
import { AppConfig } from '../../config/types';
|
||||
import { createFolder, fileExists, readJsonFile, writeFile, copyFile, runScript, deleteFolder } from '../fs/fs.helpers';
|
||||
|
||||
const appScript = `${config.ROOT_FOLDER}/scripts/app.sh`;
|
||||
type AppsState = { installed: string };
|
||||
|
||||
const getAppFolder = (appName: string) => `${config.ROOT_FOLDER}/apps/${appName}`;
|
||||
const getDataFolder = (appName: string) => `${config.ROOT_FOLDER}/app-data/${appName}`;
|
||||
|
||||
const getStateFile = () => {
|
||||
// Add app to apps.json
|
||||
const rawFile = fs.readFileSync(`${config.ROOT_FOLDER}/state/apps.json`).toString();
|
||||
let apps = JSON.parse(rawFile);
|
||||
|
||||
return apps;
|
||||
const getStateFile = (): AppsState => {
|
||||
return readJsonFile('/state/apps.json');
|
||||
};
|
||||
|
||||
const generateEnvFile = (appName: string, form: Record<string, string>) => {
|
||||
const appExists = fs.existsSync(getDataFolder(appName));
|
||||
const appExists = fileExists(`/app-data/${appName}`);
|
||||
|
||||
if (!appExists) {
|
||||
throw new Error(`App ${appName} not installed`);
|
||||
}
|
||||
|
||||
const rawFile = fs.readFileSync(`${getAppFolder(appName)}/config.json`).toString();
|
||||
let configFile: AppConfig = JSON.parse(rawFile);
|
||||
const configFile: AppConfig = readJsonFile(`/apps/${appName}/config.json`);
|
||||
let envFile = '';
|
||||
|
||||
Object.keys(configFile.form_fields).forEach(key => {
|
||||
Object.keys(configFile.form_fields).forEach((key) => {
|
||||
const value = form[key];
|
||||
|
||||
if (value) {
|
||||
const envVar = configFile.form_fields[key].env_variable;
|
||||
envFile += `${envVar}=${value}\n`;
|
||||
} else if (configFile[key].required) {
|
||||
} else if (configFile.form_fields[key].required) {
|
||||
throw new Error(`Variable ${key} is required`);
|
||||
}
|
||||
});
|
||||
|
||||
fs.writeFileSync(`${getDataFolder(appName)}/.env`, envFile);
|
||||
writeFile(`/app-data/${appName}/.env`, envFile);
|
||||
};
|
||||
|
||||
const installApp = (req: Request, res: Response) => {
|
||||
@ -50,30 +42,25 @@ const installApp = (req: Request, res: Response) => {
|
||||
throw new Error('App name is required');
|
||||
}
|
||||
|
||||
const appDataFolder = `${config.ROOT_FOLDER}/app-data/${appName}`;
|
||||
const appFolder = `${config.ROOT_FOLDER}/apps/${appName}`;
|
||||
|
||||
const appExists = fs.existsSync(appDataFolder);
|
||||
const appExists = fileExists(`/app-data/${appName}`);
|
||||
|
||||
if (appExists) {
|
||||
throw new Error(`App ${appName} already installed`);
|
||||
}
|
||||
|
||||
// Create app folder
|
||||
fs.mkdirSync(appFolder);
|
||||
|
||||
createFolder(`/app-data/${appName}`);
|
||||
// Copy default app files from app-data folder
|
||||
fs.copyFileSync(`${appFolder}/data`, `${appDataFolder}/data`);
|
||||
copyFile(`/apps/${appName}/data`, `/app-data/${appName}/data`);
|
||||
|
||||
// Create env file
|
||||
generateEnvFile(appName, form);
|
||||
|
||||
const state = getStateFile();
|
||||
state.installed += ` ${appName}`;
|
||||
|
||||
fs.writeFileSync(`${config.ROOT_FOLDER}/state/apps.json`, JSON.stringify(state));
|
||||
writeFile('/state/apps.json', JSON.stringify(state));
|
||||
|
||||
// Run script
|
||||
process.spawnSync(appScript, ['install', appName], {});
|
||||
runScript('/scripts/app.sh', ['install', appName]);
|
||||
|
||||
res.status(200).json({ message: 'App installed successfully' });
|
||||
} catch (e) {
|
||||
@ -88,22 +75,23 @@ const uninstallApp = (req: Request, res: Response) => {
|
||||
if (!appName) {
|
||||
throw new Error('App name is required');
|
||||
}
|
||||
const appExists = fs.existsSync(getDataFolder(appName));
|
||||
|
||||
const appExists = fileExists(`/app-data/${appName}`);
|
||||
|
||||
if (!appExists) {
|
||||
throw new Error(`App ${appName} not installed`);
|
||||
}
|
||||
|
||||
// Delete app folder
|
||||
fs.rmdirSync(getAppFolder(appName), { recursive: true });
|
||||
deleteFolder(`/app-data/${appName}`);
|
||||
|
||||
// Remove app from apps.json
|
||||
const state = getStateFile();
|
||||
state.installed = state.installed.replace(` ${appName}`, '');
|
||||
fs.writeFileSync(`${config.ROOT_FOLDER}/state/apps.json`, JSON.stringify(state));
|
||||
writeFile('/state/apps.json', JSON.stringify(state));
|
||||
|
||||
// Run script
|
||||
process.spawnSync(appScript, ['uninstall', appName], {});
|
||||
runScript('/scripts/app.sh', ['uninstall', appName]);
|
||||
|
||||
res.status(200).json({ message: 'App uninstalled successfully' });
|
||||
} catch (e) {
|
||||
@ -119,18 +107,18 @@ const stopApp = (req: Request, res: Response) => {
|
||||
throw new Error('App name is required');
|
||||
}
|
||||
|
||||
const appExists = fs.existsSync(getDataFolder(appName));
|
||||
const appExists = fileExists(`/app-data/${appName}`);
|
||||
|
||||
if (!appExists) {
|
||||
throw new Error(`App ${appName} not installed`);
|
||||
}
|
||||
|
||||
// Run script
|
||||
process.spawnSync(appScript, ['stop', appName], {});
|
||||
runScript('/scripts/app.sh', ['stop', appName]);
|
||||
|
||||
res.status(200).json({ message: 'App stopped successfully' });
|
||||
} catch (e) {
|
||||
res.status(500).send(e);
|
||||
res.status(500).end(e);
|
||||
}
|
||||
};
|
||||
|
||||
@ -142,7 +130,7 @@ const updateAppConfig = (req: Request, res: Response) => {
|
||||
throw new Error('App name is required');
|
||||
}
|
||||
|
||||
const appExists = fs.existsSync(getDataFolder(appName));
|
||||
const appExists = fileExists(`/app-data/${appName}`);
|
||||
|
||||
if (!appExists) {
|
||||
throw new Error(`App ${appName} not installed`);
|
||||
@ -151,26 +139,49 @@ const updateAppConfig = (req: Request, res: Response) => {
|
||||
generateEnvFile(appName, form);
|
||||
|
||||
// Run script
|
||||
process.spawnSync(appScript, ['stop', appName], {});
|
||||
process.spawnSync(appScript, ['start', appName], {});
|
||||
runScript('/scripts/app.sh', ['stop', appName]);
|
||||
runScript('/scripts/app.sh', ['start', appName]);
|
||||
|
||||
res.status(200).json({ message: 'App updated successfully' });
|
||||
} catch (e) {
|
||||
res.status(500).send(e);
|
||||
res.status(500).end(e);
|
||||
}
|
||||
};
|
||||
|
||||
const installedApps = (req: Request, res: Response) => {
|
||||
try {
|
||||
const rawFile = fs.readFileSync(`${config.ROOT_FOLDER}/state/apps.json`).toString();
|
||||
const apps = JSON.parse(rawFile);
|
||||
|
||||
const apps = readJsonFile('/state/apps.json');
|
||||
const appNames = apps.installed.split(' ');
|
||||
|
||||
res.status(200).json(appNames);
|
||||
} catch (e) {
|
||||
res.status(500).send(e);
|
||||
res.status(500).end(e);
|
||||
}
|
||||
};
|
||||
|
||||
export default { uninstallApp, installApp, stopApp, updateAppConfig, installedApps };
|
||||
const getAppInfo = (req: Request, res: Response<AppConfig>) => {
|
||||
try {
|
||||
const { appName } = req.body;
|
||||
|
||||
if (!appName) {
|
||||
throw new Error('App name is required');
|
||||
}
|
||||
|
||||
const configFile: AppConfig = readJsonFile(`/apps/${appName}/config.json`);
|
||||
|
||||
res.status(200).json(configFile);
|
||||
} catch (e) {
|
||||
res.status(500).end(e);
|
||||
}
|
||||
};
|
||||
|
||||
const AppController = {
|
||||
uninstallApp,
|
||||
installApp,
|
||||
stopApp,
|
||||
updateAppConfig,
|
||||
installedApps,
|
||||
getAppInfo,
|
||||
};
|
||||
|
||||
export default AppController;
|
@ -1,5 +1,5 @@
|
||||
import { Router } from 'express';
|
||||
import { AppController } from '../controllers';
|
||||
import AppController from './apps.controller';
|
||||
|
||||
const router = Router();
|
||||
|
21
system-api/src/modules/fs/fs.helpers.ts
Normal file
21
system-api/src/modules/fs/fs.helpers.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import fs from 'fs';
|
||||
import childProcess from 'child_process';
|
||||
import config from '../../config';
|
||||
|
||||
export const getAbsolutePath = (path: string) => `${config.ROOT_FOLDER}${path}`;
|
||||
|
||||
export const readJsonFile = (path: string): any => {
|
||||
const rawFile = fs.readFileSync(getAbsolutePath(path)).toString();
|
||||
return JSON.parse(rawFile);
|
||||
};
|
||||
|
||||
export const fileExists = (path: string): boolean => fs.existsSync(getAbsolutePath(path));
|
||||
|
||||
export const writeFile = (path: string, data: any) => fs.writeFileSync(getAbsolutePath(path), data);
|
||||
|
||||
export const createFolder = (path: string) => fs.mkdirSync(getAbsolutePath(path));
|
||||
export const deleteFolder = (path: string) => fs.rmSync(getAbsolutePath(path), { recursive: true });
|
||||
|
||||
export const copyFile = (source: string, destination: string) => fs.copyFileSync(getAbsolutePath(source), getAbsolutePath(destination));
|
||||
|
||||
export const runScript = (path: string, args: string[]) => childProcess.spawnSync(getAbsolutePath(path), args, {});
|
19
system-api/src/modules/network/network.controller.ts
Normal file
19
system-api/src/modules/network/network.controller.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { Request, Response } from 'express';
|
||||
import publicIp from 'public-ip';
|
||||
import portScanner from 'node-port-scanner';
|
||||
|
||||
const isPortOpen = async (req: Request, res: Response<boolean>) => {
|
||||
const { port } = req.params;
|
||||
|
||||
const host = await publicIp.v4();
|
||||
|
||||
const isOpen = await portScanner(host, [port]);
|
||||
|
||||
res.status(200).send(isOpen);
|
||||
};
|
||||
|
||||
const NetworkController = {
|
||||
isPortOpen,
|
||||
};
|
||||
|
||||
export default NetworkController;
|
@ -37,7 +37,7 @@ const getCpuInfo = async (req: Request, res: Response<CpuData>) => {
|
||||
const getDiskInfo = async (req: Request, res: Response<DiskData>) => {
|
||||
const disk = await si.fsSize();
|
||||
|
||||
const rootDisk = disk.find(item => item.mount === '/');
|
||||
const rootDisk = disk.find((item) => item.mount === '/');
|
||||
|
||||
if (!rootDisk) {
|
||||
throw new Error('Could not find root disk');
|
10
system-api/src/modules/system/system.routes.ts
Normal file
10
system-api/src/modules/system/system.routes.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { Router } from 'express';
|
||||
import SystemController from './system.controller';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.route('/cpu').get(SystemController.getCpuInfo);
|
||||
router.route('/disk').get(SystemController.getDiskInfo);
|
||||
router.route('/memory').get(SystemController.getMemoryInfo);
|
||||
|
||||
export default router;
|
@ -1,2 +0,0 @@
|
||||
export { default as systemRoutes } from './system.routes';
|
||||
export { default as appRoutes } from './app.routes';
|
@ -1,10 +0,0 @@
|
||||
import { Router } from "express";
|
||||
import { SystemController } from "../controllers";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.route("/cpu").get(SystemController.getCpuInfo);
|
||||
router.route("/disk").get(SystemController.getDiskInfo);
|
||||
router.route("/memory").get(SystemController.getMemoryInfo);
|
||||
|
||||
export default router;
|
@ -1,19 +1,20 @@
|
||||
import express from 'express';
|
||||
import compression from 'compression';
|
||||
import helmet from 'helmet';
|
||||
import { __prod__ } from './constants/constants';
|
||||
import { appRoutes, systemRoutes } from './routes';
|
||||
import { isProd } from './constants/constants';
|
||||
import appsRoutes from './modules/apps/apps.routes';
|
||||
import systemRoutes from './modules/system/system.routes';
|
||||
|
||||
const app = express();
|
||||
const port = 3001;
|
||||
|
||||
if (__prod__) {
|
||||
if (isProd) {
|
||||
app.use(compression());
|
||||
app.use(helmet());
|
||||
}
|
||||
|
||||
app.use('/system', systemRoutes);
|
||||
app.use('/app', appRoutes);
|
||||
app.use('/app', appsRoutes);
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`System API listening on port ${port}`);
|
||||
|
@ -15,6 +15,6 @@
|
||||
"jsx": "preserve",
|
||||
"incremental": true
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.cjs"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user