parent
4af65abe8e
commit
94dee357d8
26 changed files with 4215 additions and 428 deletions
@ -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
@ -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, () => { |
app.listen(SERVER_PORT, () => { |
||||||
console.log(`Listening on localhost:${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,3 +1,3 @@ |
|||||||
const SERVER_PORT = process.env.SERVER_PORT ?? 8080; |
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; |
@ -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"] |
||||||
|
} |
Loading…
Reference in new issue