WIP - Install app

This commit is contained in:
Nicolas Meienberger 2022-04-08 18:52:01 +02:00
parent 524a4e2e20
commit a167cc4bc9
30 changed files with 5372 additions and 3414 deletions

View File

@ -8,6 +8,8 @@ packages:
- base-devel
- docker
- avahi
- nodejs
- npm
username: nicolas

6
ansible/start.yml Normal file
View File

@ -0,0 +1,6 @@
---
- hosts: tipi
become: yes
tasks:
- import_tasks: ./tasks/common/system-api.yml

View File

@ -70,4 +70,4 @@
- name: Enable UFW
community.general.ufw:
state: enabled
state: enabled

View File

@ -0,0 +1,43 @@
- name: Install "pm2" package globally.
community.general.npm:
name: yarn
global: yes
- name: Run pm2 first time
shell: pm2 list
- name: Enable pm2 as a service
shell: sudo env PATH=$PATH:/usr/local/bin pm2 startup -u {{ username }}
- name: Create .env file in /system-api "{{ playbook_dir }}/../system-api/.env"
copy:
dest: "{{ playbook_dir }}/../system-api/.env"
content: |
ROOT_FOLDER={{ playbook_dir }}/../
- name: Install packages based on package.json.
community.general.npm:
path: "{{ playbook_dir }}/../system-api"
- name: Remove dist folder
ansible.builtin.file:
path: "{{ playbook_dir }}/../system-api/dist"
state: absent
- name: Build system-api
shell: cd {{ playbook_dir }}/../system-api && npm run build
- name: Check if app is already running
become_user: "{{ username }}"
shell: pm2 list
register: pm2_result
- name: Start app
become_user: "{{ username }}"
shell: cd {{ playbook_dir }}/../system-api && pm2 start npm --name "system-api" -- start
when: pm2_result.stdout.find("system-api") == -1
- name: Reload app
become_user: "{{ username }}"
shell: pm2 reload system-api
when: pm2_result.stdout.find("system-api") != -1

View File

@ -0,0 +1,22 @@
{
"name": "Nextcloud",
"description": "Nextcloud is a self-hosted, open source, and fully-featured cloud storage solution for your personal files, office documents, and photos.",
"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"
}
}
}

View File

@ -54,8 +54,8 @@ services:
- MYSQL_PASSWORD=password
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- NEXTCLOUD_ADMIN_USER=tipi
- NEXTCLOUD_ADMIN_PASSWORD=password
- NEXTCLOUD_ADMIN_USER=${NEXTCLOUD_ADMIN_USER}
- NEXTCLOUD_ADMIN_PASSWORD=${NEXTCLOUD_ADMIN_PASSWORD}
- NEXTCLOUD_TRUSTED_DOMAINS=tipi.local
depends_on:
- db-nextcloud
@ -69,5 +69,3 @@ services:
# traefik.http.routers.nextcloud.tls: true
# traefik.http.routers.nextcloud.entrypoints: websecure
# traefik.http.services.nextcloud.loadbalancer.server.port: 80

View File

@ -19,8 +19,6 @@ services:
# networks:
# - tipi_main_network
reverse-proxy:
container_name: reverse-proxy
image: traefik:v2.6

View File

@ -92,6 +92,7 @@ compose() {
docker-compose \
--env-file "${env_file}" \
--env-file "${app_dir}/.env" \
--project-name "${app}" \
--file "${app_compose_file}" \
--file "${common_compose_file}" \
@ -101,12 +102,6 @@ compose() {
# Install new app
if [[ "$command" = "install" ]]; then
compose "${app}" pull
# # # Copy env file sample to .env
# if [[ -f "${app_dir}/.env-sample" ]]; then
# # Append to .env
# echo "Copying .env-sample to .env for ${app} if not already done"
# fi
compose "${app}" up -d
exit

View File

@ -39,7 +39,7 @@ if ! command -v ansible-playbook > /dev/null; then
sudo apt-get install -y ansible
fi
ansible-playbook ansible/setup.yml -i ansible/hosts
ansible-playbook ansible/setup.yml -i ansible/hosts -K
echo "Generating config files..."
for template in "${ENV_FILE}"; do

View File

@ -23,6 +23,8 @@ if [[ ! -f "${STATE_FOLDER}/configured" ]]; then
"${ROOT_FOLDER}/scripts/configure.sh"
fi
ansible-playbook ansible/start.yml -i ansible/hosts -K
export DOCKER_CLIENT_TIMEOUT=240
export COMPOSE_HTTP_TIMEOUT=240

View File

@ -1,6 +1,6 @@
{
"installed": "nextcloud",
"installed": "",
"environment": {
"anonaddy": {}
}
}
}

136
system-api/.eslintrc.cjs Normal file
View File

@ -0,0 +1,136 @@
module.exports = {
root: true,
env: {
node: true,
},
parser: '@typescript-eslint/parser',
parserOptions: {
project: ['./tsconfig.json'],
},
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,
},
},
],
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,
},
};

View File

@ -1 +1,2 @@
node_modules
node_modules/
dist/

View File

@ -0,0 +1,7 @@
module.exports = {
singleQuote: true,
semi: true,
trailingComma: "all",
arrowParens: "avoid",
printWidth: 200,
};

View File

@ -1,72 +0,0 @@
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/server.ts
import express from "../node_modules/express/index.js";
// src/routes/system.routes.ts
import { Router } from "../node_modules/express/index.js";
// src/controllers/system.controller.ts
import si from "../node_modules/systeminformation/lib/index.js";
var getCpuInfo = (req, res) => __async(void 0, null, function* () {
const cpuLoad = yield si.currentLoad();
res.status(200).send({ load: cpuLoad.currentLoad });
});
var getDiskInfo = (req, res) => __async(void 0, null, function* () {
const disk = yield si.fsSize();
const rootDisk = disk.find((item) => item.mount === "/");
if (!rootDisk) {
throw new Error("Could not find root disk");
}
const result = {
size: rootDisk.size,
used: rootDisk.used,
available: rootDisk.available
};
res.status(200).send(result);
});
var getMemoryInfo = (req, res) => __async(void 0, null, function* () {
const memory = yield si.mem();
const result = {
total: memory.total,
free: memory.free,
used: memory.used
};
res.status(200).json(result);
});
var system_controller_default = { getCpuInfo, getDiskInfo, getMemoryInfo };
// src/routes/system.routes.ts
var router = Router();
router.route("/cpu").get(system_controller_default.getCpuInfo);
router.route("/disk").get(system_controller_default.getDiskInfo);
router.route("/memory").get(system_controller_default.getMemoryInfo);
var system_routes_default = router;
// src/server.ts
var app = express();
var port = 3001;
app.use("/system", system_routes_default);
app.listen(port, () => {
console.log(`System API listening on port ${port}`);
});
//# sourceMappingURL=server.js.map

View File

@ -1,7 +0,0 @@
{
"version": 3,
"sources": ["../src/server.ts", "../src/routes/system.routes.ts", "../src/controllers/system.controller.ts"],
"sourcesContent": ["import express from \"express\";\nimport { systemRoutes } from \"./routes\";\n\nconst app = express();\nconst port = 3001;\n\napp.use(\"/system\", systemRoutes);\n\napp.listen(port, () => {\n console.log(`System API listening on port ${port}`);\n});\n", "import { Router } from \"express\";\nimport { SystemController } from \"../controllers\";\n\nconst router = Router();\n\nrouter.route(\"/cpu\").get(SystemController.getCpuInfo);\nrouter.route(\"/disk\").get(SystemController.getDiskInfo);\nrouter.route(\"/memory\").get(SystemController.getMemoryInfo);\n\nexport default router;\n", "import { Request, Response } from \"express\";\nimport si from \"systeminformation\";\n\ntype CpuData = {\n load: number;\n};\n\ntype DiskData = {\n size: number;\n used: number;\n available: number;\n};\n\ntype MemoryData = {\n total: number;\n free: number;\n used: number;\n};\n\n/**\n *\n * @param req\n * @param res\n */\nconst getCpuInfo = async (req: Request, res: Response<CpuData>) => {\n // const cpuInfo = await cpu.getCpuInfo();\n const cpuLoad = await si.currentLoad();\n\n res.status(200).send({ load: cpuLoad.currentLoad });\n};\n\n/**\n *\n * @param req\n * @param res\n */\nconst getDiskInfo = async (req: Request, res: Response<DiskData>) => {\n const disk = await si.fsSize();\n\n const rootDisk = disk.find((item) => item.mount === \"/\");\n\n if (!rootDisk) {\n throw new Error(\"Could not find root disk\");\n }\n\n const result: DiskData = {\n size: rootDisk.size,\n used: rootDisk.used,\n available: rootDisk.available,\n };\n\n res.status(200).send(result);\n};\n\n/**\n *\n * @param req\n * @param res\n */\nconst getMemoryInfo = async (req: Request, res: Response<MemoryData>) => {\n const memory = await si.mem();\n\n const result: MemoryData = {\n total: memory.total,\n free: memory.free,\n used: memory.used,\n };\n\n res.status(200).json(result);\n};\n\nexport default { getCpuInfo, getDiskInfo, getMemoryInfo };\n"],
"mappings": ";;;;;;;;;;;;;;;;;;;;;;AAAA;;;ACAA;;;ACCA;AAuBA,IAAM,aAAa,CAAO,KAAc,QAA2B;AAEjE,QAAM,UAAU,MAAM,GAAG,YAAY;AAErC,MAAI,OAAO,GAAG,EAAE,KAAK,EAAE,MAAM,QAAQ,YAAY,CAAC;AACpD;AAOA,IAAM,cAAc,CAAO,KAAc,QAA4B;AACnE,QAAM,OAAO,MAAM,GAAG,OAAO;AAE7B,QAAM,WAAW,KAAK,KAAK,CAAC,SAAS,KAAK,UAAU,GAAG;AAEvD,MAAI,CAAC,UAAU;AACb,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC5C;AAEA,QAAM,SAAmB;AAAA,IACvB,MAAM,SAAS;AAAA,IACf,MAAM,SAAS;AAAA,IACf,WAAW,SAAS;AAAA,EACtB;AAEA,MAAI,OAAO,GAAG,EAAE,KAAK,MAAM;AAC7B;AAOA,IAAM,gBAAgB,CAAO,KAAc,QAA8B;AACvE,QAAM,SAAS,MAAM,GAAG,IAAI;AAE5B,QAAM,SAAqB;AAAA,IACzB,OAAO,OAAO;AAAA,IACd,MAAM,OAAO;AAAA,IACb,MAAM,OAAO;AAAA,EACf;AAEA,MAAI,OAAO,GAAG,EAAE,KAAK,MAAM;AAC7B;AAEA,IAAO,4BAAQ,EAAE,YAAY,aAAa,cAAc;;;ADpExD,IAAM,SAAS,OAAO;AAEtB,OAAO,MAAM,MAAM,EAAE,IAAI,0BAAiB,UAAU;AACpD,OAAO,MAAM,OAAO,EAAE,IAAI,0BAAiB,WAAW;AACtD,OAAO,MAAM,SAAS,EAAE,IAAI,0BAAiB,aAAa;AAE1D,IAAO,wBAAQ;;;ADNf,IAAM,MAAM,QAAQ;AACpB,IAAM,OAAO;AAEb,IAAI,IAAI,WAAW,qBAAY;AAE/B,IAAI,OAAO,MAAM,MAAM;AACrB,UAAQ,IAAI,gCAAgC,MAAM;AACpD,CAAC;",
"names": []
}

4861
system-api/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -9,17 +9,22 @@
"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",
"start:dev": "NODE_ENV=development nodemon --trace-deprecation --trace-warnings --watch dist dist/server.js",
"dev": "concurrently \"yarn build:watch\" \"yarn start:dev\""
"dev": "concurrently \"yarn build:watch\" \"yarn start:dev\"",
"start": "NODE_ENV=production node dist/server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"compression": "^1.7.4",
"dotenv": "^16.0.0",
"express": "^4.17.3",
"helmet": "^5.0.2",
"node-port-scanner": "^3.0.1",
"public-ip": "^5.0.0",
"systeminformation": "^5.11.9"
},
"devDependencies": {
"@types/compression": "^1.7.2",
"@types/express": "^4.17.13",
"concurrently": "^7.1.0",
"esbuild": "^0.14.32",

View File

@ -0,0 +1,25 @@
import * as dotenv from 'dotenv';
interface IConfig {
NODE_ENV: string;
ROOT_FOLDER: string;
}
dotenv.config();
const { NODE_ENV = 'development', ROOT_FOLDER = '' } = process.env;
const missing = [];
if (!ROOT_FOLDER) missing.push('ROOT_FOLDER');
if (missing.length > 0) {
throw new Error(`Missing environment variables: ${missing.join(', ')}`);
}
const config: IConfig = {
NODE_ENV,
ROOT_FOLDER,
};
export default config;

View File

@ -0,0 +1 @@
export { default } from './config';

View File

@ -0,0 +1,33 @@
// "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;
max?: number;
min?: number;
required?: boolean;
env_variable?: string;
}
export interface AppConfig {
name: string;
description: string;
version: string;
form_fields: Record<string, FormField[]>;
}

View File

@ -0,0 +1,5 @@
import config from '../config';
export const APP_DATA_FOLDER = 'app-data';
export const APPS_FOLDER = 'apps';
export const __prod__ = config.NODE_ENV === 'production';

View File

@ -0,0 +1,184 @@
import { Request, Response } from 'express';
import fs from 'fs';
import process from 'child_process';
import config from '../config';
import { AppConfig } from '../config/types';
const appScript = `${config.ROOT_FOLDER}/scripts/app.sh`;
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 generateEnvFile = (appName: string, form: Record<string, string>) => {
const appFolder = `${config.ROOT_FOLDER}/apps/${appName}`;
const appDataFolder = `${config.ROOT_FOLDER}/app-data/${appName}`;
const appExists = fs.existsSync(appDataFolder);
if (!appExists) {
throw new Error(`App ${appName} not installed`);
}
const rawFile = fs.readFileSync(`${appFolder}/config.json`).toString();
let configFile: AppConfig = JSON.parse(rawFile);
let envFile = '';
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) {
throw new Error(`Variable ${key} is required`);
}
});
fs.writeFileSync(`${appDataFolder}/.env`, envFile);
};
const installApp = (req: Request, res: Response) => {
try {
const { appName, form } = req.body;
if (!appName) {
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);
if (appExists) {
throw new Error(`App ${appName} already installed`);
}
// Create app folder
fs.mkdirSync(appFolder);
// Copy default app files from app-data folder
fs.copyFileSync(`${appFolder}/data`, `${appDataFolder}/data`);
generateEnvFile(appName, form);
const state = getStateFile();
state.installed += ` ${appName}`;
fs.writeFileSync(`${config.ROOT_FOLDER}/state/apps.json`, JSON.stringify(state));
// Run script
process.spawnSync(appScript, ['install', appName], {});
res.status(200).json({ message: 'App installed successfully' });
} catch (e) {
res.status(500).send(e);
}
};
const uninstallApp = (req: Request, res: Response) => {
try {
const { appName } = req.body;
if (!appName) {
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);
if (!appExists) {
throw new Error(`App ${appName} not installed`);
}
// Delete app folder
fs.rmdirSync(appFolder, { recursive: true });
// 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));
// Run script
process.spawnSync(appScript, ['uninstall', appName], {});
res.status(200).json({ message: 'App uninstalled successfully' });
} catch (e) {
res.status(500).send(e);
}
};
const stopApp = (req: Request, res: Response) => {
try {
const { appName } = req.body;
if (!appName) {
throw new Error('App name is required');
}
const appDataFolder = `${config.ROOT_FOLDER}/app-data/${appName}`;
const appExists = fs.existsSync(appDataFolder);
if (!appExists) {
throw new Error(`App ${appName} not installed`);
}
// Run script
process.spawnSync(appScript, ['stop', appName], {});
res.status(200).json({ message: 'App stopped successfully' });
} catch (e) {
res.status(500).send(e);
}
};
const updateAppConfig = (req: Request, res: Response) => {
try {
const { appName, form } = req.body;
if (!appName) {
throw new Error('App name is required');
}
const appDataFolder = `${config.ROOT_FOLDER}/app-data/${appName}`;
const appExists = fs.existsSync(appDataFolder);
if (!appExists) {
throw new Error(`App ${appName} not installed`);
}
generateEnvFile(appName, form);
// Run script
process.spawnSync(appScript, ['stop', appName], {});
process.spawnSync(appScript, ['start', appName], {});
res.status(200).json({ message: 'App updated successfully' });
} catch (e) {
res.status(500).send(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 appNames = apps.installed.split(' ');
res.status(200).json(appNames);
} catch (e) {
res.status(500).send(e);
}
};
export default { uninstallApp, installApp, stopApp, updateAppConfig, installedApps };

View File

@ -1 +1,2 @@
export { default as SystemController } from "./system.controller";
export { default as SystemController } from './system.controller';
export { default as AppController } from './app.controller';

View File

@ -1,5 +1,5 @@
import { Request, Response } from "express";
import si from "systeminformation";
import { Request, Response } from 'express';
import si from 'systeminformation';
type CpuData = {
load: number;
@ -37,10 +37,10 @@ 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");
throw new Error('Could not find root disk');
}
const result: DiskData = {

View File

@ -0,0 +1,10 @@
import { Router } from 'express';
import { AppController } from '../controllers';
const router = Router();
router.route('/install').post(AppController.installApp);
router.route('/uninstall').post(AppController.uninstallApp);
router.route('/list').get(AppController.installedApps);
export default router;

View File

@ -1 +1,2 @@
export { default as systemRoutes } from "./system.routes";
export { default as systemRoutes } from './system.routes';
export { default as appRoutes } from './app.routes';

View File

@ -1,10 +1,19 @@
import express from "express";
import { systemRoutes } from "./routes";
import express from 'express';
import compression from 'compression';
import helmet from 'helmet';
import { __prod__ } from './constants/constants';
import { appRoutes, systemRoutes } from './routes';
const app = express();
const port = 3001;
app.use("/system", systemRoutes);
if (__prod__) {
app.use(compression());
app.use(helmet());
}
app.use('/system', systemRoutes);
app.use('/app', appRoutes);
app.listen(port, () => {
console.log(`System API listening on port ${port}`);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff