chore(striker-ui-api): switch to TypeScript

main
Tsu-ba-me 3 years ago
parent 4af65abe8e
commit 94dee357d8
  1. 5
      striker-ui-api/.eslintignore
  2. 14
      striker-ui-api/.eslintrc.json
  3. 5
      striker-ui-api/.prettierignore
  4. 4108
      striker-ui-api/package-lock.json
  5. 19
      striker-ui-api/package.json
  6. 8
      striker-ui-api/src/.eslintrc.json
  7. 18
      striker-ui-api/src/app.js
  8. 18
      striker-ui-api/src/app.ts
  9. 4
      striker-ui-api/src/index.ts
  10. 94
      striker-ui-api/src/lib/accessDB.js
  11. 114
      striker-ui-api/src/lib/accessDB.ts
  12. 3
      striker-ui-api/src/lib/consts/API_ROOT_PATH.js
  13. 3
      striker-ui-api/src/lib/consts/API_ROOT_PATH.ts
  14. 18
      striker-ui-api/src/lib/consts/SERVER_PATHS.ts
  15. 2
      striker-ui-api/src/lib/consts/SERVER_PORT.ts
  16. 29
      striker-ui-api/src/lib/request_handlers/files/buildGetFiles.js
  17. 33
      striker-ui-api/src/lib/request_handlers/files/buildGetFiles.ts
  18. 4
      striker-ui-api/src/lib/request_handlers/files/getFileDetail.ts
  19. 4
      striker-ui-api/src/lib/request_handlers/files/getFilesOverview.ts
  20. 6
      striker-ui-api/src/middlewares/uploadSharedFiles.ts
  21. 4
      striker-ui-api/src/routes/echo.ts
  22. 84
      striker-ui-api/src/routes/files.ts
  23. 3
      striker-ui-api/src/types/DBJobAnvilSyncSharedOptions.d.ts
  24. 13
      striker-ui-api/src/types/ServerPath.d.ts
  25. 21
      striker-ui-api/tsconfig.json
  26. 9
      striker-ui-api/webpack.config.js

@ -0,0 +1,5 @@
# dependencies
node_modules
# output
out

@ -0,0 +1,14 @@
{
"env": {
"es2022": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:import/errors",
"plugin:import/typescript",
"plugin:import/warnings",
"prettier"
],
"plugins": ["import"]
}

@ -0,0 +1,5 @@
# dependencies
node_modules
# output
out

File diff suppressed because it is too large Load Diff

@ -5,10 +5,12 @@
"scripts": {
"build": "webpack",
"build:clean": "rm -rf out",
"dev": "node src/index.js",
"eslint:base": "eslint --ext js,ts --max-warnings=0",
"lint": "npm run eslint:base -- . && npm run prettier:base -- --check",
"lint:fix": "npm run eslint:base -- --fix . && npm run prettier:base -- --write",
"prettier:base": "prettier '**/*.{js,json,md,ts}'",
"rebuild": "npm run build:clean && npm run build",
"start": "npm run rebuild && node out/index.js",
"style:fix": "prettier --write *"
"start": "npm run rebuild && node out/index.js"
},
"dependencies": {
"cors": "^2.8.5",
@ -18,8 +20,19 @@
"devDependencies": {
"@babel/core": "^7.17.8",
"@babel/preset-env": "^7.16.11",
"@babel/preset-typescript": "^7.16.7",
"@types/cors": "^2.8.12",
"@types/express": "^4.17.13",
"@types/multer": "^1.4.7",
"@types/node": "^17.0.22",
"@typescript-eslint/eslint-plugin": "^5.16.0",
"@typescript-eslint/parser": "^5.16.0",
"babel-loader": "^8.2.3",
"eslint": "^8.10.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.25.4",
"prettier": "^2.5.0",
"typescript": "^4.6.2",
"webpack": "^5.70.0",
"webpack-cli": "^4.9.2"
}

@ -0,0 +1,8 @@
{
"extends": ["../.eslintrc.json", "plugin:@typescript-eslint/recommended"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"plugins": ["@typescript-eslint"]
}

@ -1,18 +0,0 @@
const cors = require('cors');
const express = require('express');
const path = require('path');
const API_ROOT_PATH = require('./lib/consts/API_ROOT_PATH');
const echoRouter = require('./routes/echo');
const filesRouter = require('./routes/files');
const app = express();
app.use(express.json());
app.use(cors());
app.use(path.join(API_ROOT_PATH, 'echo'), echoRouter);
app.use(path.join(API_ROOT_PATH, 'files'), filesRouter);
module.exports = app;

@ -0,0 +1,18 @@
import cors from 'cors';
import express from 'express';
import path from 'path';
import API_ROOT_PATH from './lib/consts/API_ROOT_PATH';
import echoRouter from './routes/echo';
import filesRouter from './routes/files';
const app = express();
app.use(express.json());
app.use(cors());
app.use(path.join(API_ROOT_PATH, 'echo'), echoRouter);
app.use(path.join(API_ROOT_PATH, 'files'), filesRouter);
export default app;

@ -1,6 +1,6 @@
const app = require('./app');
import app from './app';
const SERVER_PORT = require('./lib/consts/SERVER_PORT');
import SERVER_PORT from './lib/consts/SERVER_PORT';
app.listen(SERVER_PORT, () => {
console.log(`Listening on localhost:${SERVER_PORT}.`);

@ -1,94 +0,0 @@
const { spawnSync } = require('child_process');
const SERVER_PATHS = require('./consts/SERVER_PATHS');
const execStrikerAccessDatabase = (
args,
options = {
timeout: 10000,
encoding: 'utf-8',
},
) => {
const { error, stdout, stderr } = spawnSync(
SERVER_PATHS.usr.sbin['striker-access-database'].self,
args,
options,
);
if (error) {
throw error;
}
if (stderr) {
throw new Error(stderr);
}
let output;
try {
output = JSON.parse(stdout);
} catch (stdoutParseError) {
output = stdout;
console.warn(
`Failed to parse striker-access-database output [${output}]; error: [${stdoutParseError}]`,
);
}
return {
stdout: output,
};
};
const execDatabaseModuleSubroutine = (subName, subParams, options) => {
const args = ['--sub', subName];
if (subParams) {
args.push('--sub-params', JSON.stringify(subParams));
}
const { stdout } = execStrikerAccessDatabase(args, options);
return {
stdout: stdout['sub_results'],
};
};
const accessDB = {
dbJobAnvilSyncShared: (
jobName,
jobData,
jobTitle,
jobDescription,
{ jobHostUUID } = { jobHostUUID: undefined },
) => {
const subParams = {
file: __filename,
line: 0,
job_command: SERVER_PATHS.usr.sbin['anvil-sync-shared'].self,
job_data: jobData,
job_name: `storage::${jobName}`,
job_title: `job_${jobTitle}`,
job_description: `job_${jobDescription}`,
job_progress: 0,
};
if (jobHostUUID) {
subParams.job_host_uuid = jobHostUUID;
}
console.log(JSON.stringify(subParams, null, 2));
return execDatabaseModuleSubroutine('insert_or_update_jobs', subParams)
.stdout;
},
dbQuery: (query, options) =>
execStrikerAccessDatabase(['--query', query], options),
dbSub: execDatabaseModuleSubroutine,
dbSubRefreshTimestamp: () =>
execDatabaseModuleSubroutine('refresh_timestamp').stdout,
dbWrite: (query, options) =>
execStrikerAccessDatabase(['--query', query, '--mode', 'write'], options),
};
module.exports = accessDB;

@ -0,0 +1,114 @@
import { spawnSync, SpawnSyncOptions } from 'child_process';
import SERVER_PATHS from './consts/SERVER_PATHS';
const execStrikerAccessDatabase = (
args: string[],
options: SpawnSyncOptions = {
timeout: 10000,
encoding: 'utf-8',
},
) => {
const { error, stdout, stderr } = spawnSync(
SERVER_PATHS.usr.sbin['striker-access-database'].self,
args,
options,
);
if (error) {
throw error;
}
if (stderr) {
throw new Error(stderr.toString());
}
let output;
try {
output = JSON.parse(stdout.toString());
} catch (stdoutParseError) {
output = stdout;
console.warn(
`Failed to parse striker-access-database output [${output}]; error: [${stdoutParseError}]`,
);
}
return {
stdout: output,
};
};
const execDatabaseModuleSubroutine = (
subName: string,
subParams?: Record<string, unknown>,
options?: SpawnSyncOptions,
) => {
const args = ['--sub', subName];
if (subParams) {
args.push('--sub-params', JSON.stringify(subParams));
}
const { stdout } = execStrikerAccessDatabase(args, options);
return {
stdout: stdout['sub_results'],
};
};
const dbJobAnvilSyncShared = (
jobName: string,
jobData: string,
jobTitle: string,
jobDescription: string,
{ jobHostUUID }: DBJobAnvilSyncSharedOptions = { jobHostUUID: undefined },
) => {
const subParams: {
file: string;
line: number;
job_command: string;
job_data: string;
job_name: string;
job_title: string;
job_description: string;
job_host_uuid?: string;
job_progress: number;
} = {
file: __filename,
line: 0,
job_command: SERVER_PATHS.usr.sbin['anvil-sync-shared'].self,
job_data: jobData,
job_name: `storage::${jobName}`,
job_title: `job_${jobTitle}`,
job_description: `job_${jobDescription}`,
job_progress: 0,
};
if (jobHostUUID) {
subParams.job_host_uuid = jobHostUUID;
}
console.log(JSON.stringify(subParams, null, 2));
return execDatabaseModuleSubroutine('insert_or_update_jobs', subParams)
.stdout;
};
const dbQuery = (query: string, options?: SpawnSyncOptions) =>
execStrikerAccessDatabase(['--query', query], options);
const dbSubRefreshTimestamp = () =>
execDatabaseModuleSubroutine('refresh_timestamp').stdout;
const dbWrite = (query: string, options?: SpawnSyncOptions) =>
execStrikerAccessDatabase(['--query', query, '--mode', 'write'], options);
export {
dbJobAnvilSyncShared,
dbQuery,
execDatabaseModuleSubroutine as dbSub,
dbSubRefreshTimestamp,
dbWrite,
};

@ -1,3 +0,0 @@
const API_ROOT_PATH = '/api';
module.exports = API_ROOT_PATH;

@ -0,0 +1,3 @@
const API_ROOT_PATH = '/api';
export default API_ROOT_PATH;

@ -1,6 +1,6 @@
const path = require('path');
import path from 'path';
const SERVER_PATHS = {
const EMPTY_SERVER_PATHS: ServerPath = {
mnt: {
shared: {
incoming: {},
@ -15,20 +15,22 @@ const SERVER_PATHS = {
};
const generatePaths = (
currentObject,
currentObject: ServerPath,
parents = path.parse(process.cwd()).root,
) => {
Object.keys(currentObject).forEach((pathKey) => {
const currentPath = path.join(parents, pathKey);
if (pathKey !== 'self') {
const currentPath = path.join(parents, pathKey);
currentObject[pathKey].self = currentPath;
currentObject[pathKey].self = currentPath;
if (pathKey !== 'self') {
generatePaths(currentObject[pathKey], currentPath);
}
});
return currentObject as ReadonlyServerPath;
};
generatePaths(SERVER_PATHS);
const SERVER_PATHS = generatePaths(EMPTY_SERVER_PATHS);
module.exports = SERVER_PATHS;
export default SERVER_PATHS;

@ -1,3 +1,3 @@
const SERVER_PORT = process.env.SERVER_PORT ?? 8080;
module.exports = SERVER_PORT;
export default SERVER_PORT;

@ -1,29 +0,0 @@
const { dbQuery } = require('../../accessDB');
const buildGetFiles = (query) => (request, response) => {
console.log('Calling CLI script to get data.');
let queryStdout;
try {
({ stdout: queryStdout } = dbQuery(
typeof query === 'function' ? query(request) : query,
));
} catch (queryError) {
console.log(`Query error: ${queryError}`);
response.status(500).send();
}
console.log(
`Query stdout (type=[${typeof queryStdout}]): ${JSON.stringify(
queryStdout,
null,
2,
)}`,
);
response.json(queryStdout);
};
module.exports = buildGetFiles;

@ -0,0 +1,33 @@
import { Request, Response } from 'express';
import { dbQuery } from '../../accessDB';
const buildGetFiles =
(query: string | ((request: Request) => string)) =>
(request: Request, response: Response) => {
console.log('Calling CLI script to get data.');
let queryStdout;
try {
({ stdout: queryStdout } = dbQuery(
typeof query === 'function' ? query(request) : query,
));
} catch (queryError) {
console.log(`Query error: ${queryError}`);
response.status(500).send();
}
console.log(
`Query stdout (type=[${typeof queryStdout}]): ${JSON.stringify(
queryStdout,
null,
2,
)}`,
);
response.json(queryStdout);
};
export default buildGetFiles;

@ -1,4 +1,4 @@
const buildGetFiles = require('./buildGetFiles');
import buildGetFiles from './buildGetFiles';
const getFileDetail = buildGetFiles(
(request) =>
@ -22,4 +22,4 @@ const getFileDetail = buildGetFiles(
AND fil.file_type != 'DELETED';`,
);
module.exports = getFileDetail;
export default getFileDetail;

@ -1,4 +1,4 @@
const buildGetFiles = require('./buildGetFiles');
import buildGetFiles from './buildGetFiles';
const getFilesOverview = buildGetFiles(`
SELECT
@ -10,4 +10,4 @@ SELECT
FROM files
WHERE file_type != 'DELETED';`);
module.exports = getFilesOverview;
export default getFilesOverview;

@ -1,6 +1,6 @@
const multer = require('multer');
import multer from 'multer';
const SERVER_PATHS = require('../lib/consts/SERVER_PATHS');
import SERVER_PATHS from '../lib/consts/SERVER_PATHS';
const storage = multer.diskStorage({
destination: (request, file, callback) => {
@ -13,4 +13,4 @@ const storage = multer.diskStorage({
const uploadSharedFiles = multer({ storage });
module.exports = uploadSharedFiles;
export default uploadSharedFiles;

@ -1,4 +1,4 @@
const express = require('express');
import express from 'express';
const router = express.Router();
@ -14,4 +14,4 @@ router
response.status(200).send({ message });
});
module.exports = router;
export default router;

@ -1,14 +1,14 @@
const express = require('express');
import express from 'express';
const {
import {
dbJobAnvilSyncShared,
dbQuery,
dbSubRefreshTimestamp,
dbWrite,
} = require('../lib/accessDB');
const getFilesOverview = require('../lib/request_handlers/files/getFilesOverview');
const getFileDetail = require('../lib/request_handlers/files/getFileDetail');
const uploadSharedFiles = require('../middlewares/uploadSharedFiles');
} from '../lib/accessDB';
import getFilesOverview from '../lib/request_handlers/files/getFilesOverview';
import getFileDetail from '../lib/request_handlers/files/getFileDetail';
import uploadSharedFiles from '../middlewares/uploadSharedFiles';
const router = express.Router();
@ -112,28 +112,35 @@ router
}
if (fileLocations) {
fileLocations.forEach(({ fileLocationUUID, isFileLocationActive }) => {
let fileLocationActive = 0;
let jobName = 'purge';
let jobTitle = '0136';
let jobDescription = '0137';
if (isFileLocationActive) {
fileLocationActive = 1;
jobName = 'pull_file';
jobTitle = '0132';
jobDescription = '0133';
}
fileLocations.forEach(
({
fileLocationUUID,
isFileLocationActive,
}: {
fileLocationUUID: string;
isFileLocationActive: boolean;
}) => {
let fileLocationActive = 0;
let jobName = 'purge';
let jobTitle = '0136';
let jobDescription = '0137';
if (isFileLocationActive) {
fileLocationActive = 1;
jobName = 'pull_file';
jobTitle = '0132';
jobDescription = '0133';
}
query += `
query += `
UPDATE file_locations
SET
file_location_active = '${fileLocationActive}',
modified_date = '${dbSubRefreshTimestamp()}'
WHERE file_location_uuid = '${fileLocationUUID}';`;
const targetHosts = dbQuery(
`SELECT
const targetHosts = dbQuery(
`SELECT
anv.anvil_node1_host_uuid,
anv.anvil_node2_host_uuid,
anv.anvil_dr1_host_uuid
@ -141,22 +148,23 @@ router
JOIN file_locations AS fil_loc
ON anv.anvil_uuid = fil_loc.file_location_anvil_uuid
WHERE fil_loc.file_location_uuid = '${fileLocationUUID}';`,
).stdout;
targetHosts.flat().forEach((hostUUID) => {
if (hostUUID) {
anvilSyncSharedFunctions.push(() =>
dbJobAnvilSyncShared(
jobName,
`file_uuid=${fileUUID}`,
jobTitle,
jobDescription,
{ jobHostUUID: hostUUID },
),
);
}
});
});
).stdout;
targetHosts.flat().forEach((hostUUID: string) => {
if (hostUUID) {
anvilSyncSharedFunctions.push(() =>
dbJobAnvilSyncShared(
jobName,
`file_uuid=${fileUUID}`,
jobTitle,
jobDescription,
{ jobHostUUID: hostUUID },
),
);
}
});
},
);
}
console.log(`Query (type=[${typeof query}]): [${query}]`);
@ -191,4 +199,4 @@ router
response.status(200).send(queryStdout);
});
module.exports = router;
export default router;

@ -0,0 +1,3 @@
type DBJobAnvilSyncSharedOptions = {
jobHostUUID?: string;
};

@ -0,0 +1,13 @@
type ServerPathSelf = {
self?: string;
};
type ServerPath = {
[segment: string]: ServerPath;
} & ServerPathSelf;
type FilledServerPath = {
[segment: string]: FilledServerPath;
} & Required<ServerPathSelf>;
type ReadonlyServerPath = Readonly<FilledServerPath>;

@ -0,0 +1,21 @@
{
"compilerOptions": {
"allowJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"incremental": true,
"isolatedModules": true,
"lib": ["esnext"],
"module": "esnext",
"moduleResolution": "node",
"noImplicitAny": true,
"outDir": "ts_out",
"resolveJsonModule": true,
"strict": true,
"target": "es5",
"types": ["node"],
"typeRoots": ["src/types"]
},
"exclude": ["node_modules"],
"include": ["src/**/*.ts"]
}

@ -1,17 +1,17 @@
const path = require('path');
module.exports = {
entry: './index.js',
entry: './src/index.ts',
mode: 'production',
module: {
rules: [
{
exclude: /node_modules/,
test: /\.m?js$/,
test: /\.ts$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
presets: ['@babel/preset-env', '@babel/preset-typescript'],
},
},
},
@ -24,6 +24,9 @@ module.exports = {
path: path.resolve(__dirname, 'out'),
filename: 'index.js',
},
resolve: {
extensions: ['.js', '.ts'],
},
stats: 'detailed',
target: 'node10',
};

Loading…
Cancel
Save