commit 23c54057cd27e228ef8b3de35310d0c36cd4e534 Author: mattmcw Date: Wed Oct 16 19:57:08 2024 -0400 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fb35c99 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules +.env +*.DS_Store \ No newline at end of file diff --git a/default.env b/default.env new file mode 100644 index 0000000..e7ff69e --- /dev/null +++ b/default.env @@ -0,0 +1,4 @@ +PORT=7474 +BIN=openpose +CWD=. + diff --git a/dist/env/index.js b/dist/env/index.js new file mode 100644 index 0000000..3e70b10 --- /dev/null +++ b/dist/env/index.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.envString = envString; +exports.envFloat = envFloat; +exports.envInt = envInt; +function envString(variable, defaultString) { + return typeof process.env[variable] !== 'undefined' ? process.env[variable] : defaultString; +} +function envFloat(variable, defaultFloat) { + return typeof process.env[variable] !== 'undefined' ? parseFloat(process.env[variable]) : defaultFloat; +} +function envInt(variable, defaultInt) { + return typeof process.env[variable] !== 'undefined' ? parseInt(process.env[variable]) : defaultInt; +} +module.exports = { envString, envFloat, envInt }; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/env/index.js.map b/dist/env/index.js.map new file mode 100644 index 0000000..0e8ffb0 --- /dev/null +++ b/dist/env/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/env/index.ts"],"names":[],"mappings":";;AAAA,8BAEC;AAED,4BAEC;AAED,wBAEC;AAVD,SAAgB,SAAS,CAAE,QAAiB,EAAE,aAAsB;IACnE,OAAO,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;AAC7F,CAAC;AAED,SAAgB,QAAQ,CAAE,QAAiB,EAAE,YAAqB;IACjE,OAAO,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;AACxG,CAAC;AAED,SAAgB,MAAM,CAAE,QAAiB,EAAE,UAAmB;IAC7D,OAAO,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;AACpG,CAAC;AAED,MAAM,CAAC,OAAO,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..83225a8 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,155 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +require("dotenv/config"); +const express_1 = __importDefault(require("express")); +const promises_1 = require("fs/promises"); +const os_1 = require("os"); +const path_1 = require("path"); +const body_parser_1 = __importDefault(require("body-parser")); +const multer_1 = __importDefault(require("multer")); +const uuid_1 = require("uuid"); +const log_1 = require("./log"); +const env_1 = require("./env"); +const shell_1 = require("./shell"); +const PORT = (0, env_1.envInt)('PORT', 7474); +const BIN = (0, env_1.envString)('BIN', 'openpose'); +const CWD = (0, env_1.envString)('CWD', '.'); +const log = (0, log_1.createLog)('openpose_api'); +const app = (0, express_1.default)(); +const tmp = (0, os_1.tmpdir)(); +const storage = multer_1.default.diskStorage({ + destination: function (req, file, cb) { + cb(null, tmp); + }, + filename: function (req, file, cb) { + cb(null, `${+new Date()}_${file.originalname}`); + } +}); +async function exists(path) { + try { + await (0, promises_1.access)(path); + return true; + } + catch { + return false; + } +} +app.use(body_parser_1.default.json()); +app.use(body_parser_1.default.urlencoded({ extended: true })); +const uploadImage = (0, multer_1.default)({ storage }); +app.get('/', (req, res, next) => { + return res.send('/'); +}); +//./build/examples/openpose/openpose.bin -v 1 -image_dir ./examples/media/ -write_images ./output -write_json ./json --face --hand +app.post('/openpose', uploadImage.single('image'), async (req, res, next) => { + const id = (0, uuid_1.v4)(); + const dir = (0, path_1.join)(tmp, id); + const image_dir = (0, path_1.join)(dir, 'image'); + const json_dir = (0, path_1.join)(dir, 'json'); + const json_file = (0, path_1.join)(json_dir, 'openpose_keypoints.json'); + let json_exists = false; + let openpose_str = '{}'; + let output; + let image_file; + let image_ext; + let sh; + // + const args = [ + BIN, + '--render_pose', '0', + '-display', '0', + '-image_dir', image_dir, + '-write_json', json_dir + ]; + if (typeof req.file === 'undefined') { + return next(new Error('No image uploaded')); + } + image_ext = (0, path_1.extname)((0, path_1.basename)(req.file.path)); + image_file = (0, path_1.join)(image_dir, `openpose${image_ext}`); + if (typeof req.body.face !== 'undefined' && req.body.face === 'true') { + args.push('--face'); + } + if (typeof req.body.hand !== 'undefined' && req.body.hand === 'true') { + args.push('--hand'); + } + try { + await (0, promises_1.mkdir)(dir); + } + catch (err) { + log.error(`Error making directory ${dir}`, err); + return next(new Error('Error making dir')); + } + try { + await (0, promises_1.mkdir)(image_dir); + } + catch (err) { + log.error(`Error making directory ${image_dir}`, err); + return next(new Error('Error making image_dir')); + } + try { + await (0, promises_1.mkdir)(json_dir); + } + catch (err) { + log.error(`Error making directory ${image_dir}`, err); + return next(new Error('Error making image_dir')); + } + try { + await (0, promises_1.copyFile)(req.file.path, image_file); + } + catch (err) { + log.error(`Error copying file ${req.file.path}`, err); + return next(new Error('Error copying temp image')); + } + sh = new shell_1.Shell(args, CWD, null, null, null, true); + try { + await sh.execute(); + } + catch (err) { + log.error(`Error executing ${args.join(' ')}`, err); + return next(new Error('Error running openpose')); + } + try { + json_exists = await exists(json_file); + } + catch (err) { + log.error(`Error checking json ${json_file} exists`, err); + return next(new Error('Error checking json exists')); + } + if (json_exists) { + try { + openpose_str = await (0, promises_1.readFile)(json_file, 'utf8'); + } + catch (err) { + log.error(`Error reading json file ${json_file}`, err); + return next(new Error('Error reading json file')); + } + } + else { + log.error(`The json file ${json_file} does not exist`); + return next(new Error('Error running openpose')); + } + try { + output = JSON.parse(openpose_str); + } + catch (err) { + log.error(`Error parsing openpose json`, err); + return next(new Error('Error parsing openpose json')); + } + output.image = req.file.originalname; + try { + await (0, promises_1.rm)(dir, { recursive: true }); + } + catch (err) { + log.error(`Error unlinking ${dir}`, err); + return next(new Error('Error unlinking temp dir')); + } + return res.json(output); +}); +app.listen(PORT, () => { + log.info(`Openpose API server running on port ${PORT}`); + log.info(`Using openpose binary ${BIN}`); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/index.js.map b/dist/index.js.map new file mode 100644 index 0000000..b2145b9 --- /dev/null +++ b/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/log/index.js b/dist/log/index.js new file mode 100644 index 0000000..3c12bb5 --- /dev/null +++ b/dist/log/index.js @@ -0,0 +1,48 @@ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createLog = createLog; +/** @module log */ +/** Wrapper for winston that tags streams and optionally writes files with a simple interface. */ +/** Module now also supports optional papertrail integration, other services to follow */ +const winston_1 = require("winston"); +const { SPLAT } = require('triple-beam'); +const { isObject } = require('lodash'); +const APP_NAME = process.env.APP_NAME || 'default'; +function formatObject(param) { + if (isObject(param)) { + return JSON.stringify(param); + } + return param; +} +const all = (0, winston_1.format)((info) => { + const splat = info[SPLAT] || []; + const message = formatObject(info.message); + const rest = splat.map(formatObject).join(' '); + info.message = `${message} ${rest}`; + return info; +}); +const myFormat = winston_1.format.printf(({ level, message, label, timestamp }) => { + return `${timestamp} [${label}] ${level}: ${message}`; +}); +/** +* Returns a winston logger configured to service +* +* @param {string} label Label appearing on logger +* @param {string} filename Optional file to write log to +* +* @returns {object} Winston logger +*/ +function createLog(label, filename = null) { + const tports = [new (winston_1.transports.Console)()]; + const fmat = winston_1.format.combine(all(), winston_1.format.label({ label }), winston_1.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }), winston_1.format.colorize(), myFormat); + let papertrailOpts; + if (filename !== null) { + tports.push(new (winston_1.transports.File)({ filename })); + } + return (0, winston_1.createLogger)({ + format: fmat, + transports: tports + }); +} +module.exports = { createLog }; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/log/index.js.map b/dist/log/index.js.map new file mode 100644 index 0000000..56aa0df --- /dev/null +++ b/dist/log/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/log/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAuCZ,8BAmBC;AAxDD,kBAAkB;AAClB,iGAAiG;AACjG,yFAAyF;AAEzF,qCAA2D;AAC3D,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AACzC,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEvC,MAAM,QAAQ,GAAY,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,SAAS,CAAC;AAE5D,SAAS,YAAY,CAAE,KAAW;IAChC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,GAAG,GAAG,IAAA,gBAAM,EAAC,CAAC,IAAU,EAAE,EAAE;IAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAChC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,IAAI,CAAC,OAAO,GAAG,GAAG,OAAO,IAAI,IAAI,EAAE,CAAC;IACpC,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC,CAAC;AAEH,MAAM,QAAQ,GAAG,gBAAM,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAQ,EAAE,EAAE;IAC5E,OAAO,GAAG,SAAS,KAAK,KAAK,KAAK,KAAK,KAAK,OAAO,EAAE,CAAC;AACxD,CAAC,CAAC,CAAC;AAEH;;;;;;;EAOE;AACF,SAAgB,SAAS,CAAE,KAAc,EAAE,WAAoB,IAAI;IAC/D,MAAM,MAAM,GAAW,CAAE,IAAI,CAAC,oBAAU,CAAC,OAAO,CAAC,EAAE,CAAE,CAAC;IACtD,MAAM,IAAI,GAAS,gBAAM,CAAC,OAAO,CAC7B,GAAG,EAAE,EACL,gBAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,EACvB,gBAAM,CAAC,SAAS,CAAC,EAAC,MAAM,EAAE,yBAAyB,EAAC,CAAC,EACrD,gBAAM,CAAC,QAAQ,EAAE,EACjB,QAAQ,CACX,CAAC;IACF,IAAI,cAAoB,CAAC;IAEzB,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACpB,MAAM,CAAC,IAAI,CAAE,IAAI,CAAC,oBAAU,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAE,CAAC;IACvD,CAAC;IAED,OAAO,IAAA,sBAAY,EAAC;QAChB,MAAM,EAAG,IAAI;QACb,UAAU,EAAG,MAAM;KACtB,CAAC,CAAC;AACP,CAAC;AAED,MAAM,CAAC,OAAO,GAAG,EAAE,SAAS,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/shell/index.js b/dist/shell/index.js new file mode 100644 index 0000000..cc271a1 --- /dev/null +++ b/dist/shell/index.js @@ -0,0 +1,71 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Shell = void 0; +const child_process_1 = require("child_process"); +const log_1 = require("../log"); +const os_1 = require("os"); +class Shell { + constructor(args, cwd = null, stdio = null, stderr = null, after = null, silent = false) { + this.lines = []; + this.stdio = null; + this.stderr = null; + this.after = null; + this.silent = false; + const bin = args.shift(); + this.bin = bin; + this.args = args; + this.stdio = stdio; + this.stderr = stderr; + this.silent = silent; + this.after = after; + this.cwd = cwd; + this.log = (0, log_1.createLog)(bin); + } + async execute() { + return new Promise((resolve, reject) => { + const options = {}; + if (this.cwd !== null) { + options.cwd = this.cwd; + } + this.child = (0, child_process_1.spawn)(this.bin, this.args, options); + this.log.info(`Shell: ${this.bin} ${this.args.join(' ')}`); + this.child.stdout.on('data', (data) => { + if (!this.silent) + this.log.info(data); + if (this.after !== null) + this.lines.push(data); + if (this.stdio !== null) { + this.stdio(data); + } + }); + this.child.stderr.on('data', (data) => { + if (!this.silent) + this.log.warn(data); + if (this.stderr !== null) { + this.stderr(data); + } + }); + this.child.on('close', (code) => { + if (this.after !== null) { + this.after(this.lines.join(os_1.EOL)); + } + if (code === 0) { + this.log.info(`Complete: ${this.bin} ${this.args.join(' ')}`); + return resolve(code); + } + else { + this.log.error(`Error executing: ${this.bin} ${this.args.join(' ')}`); + return reject(code); + } + }); + }); + } + kill() { + this.log.warn(`Killing: ${this.bin} ${this.args.join(' ')}`); + //this.child.stdin.pause(); + this.child.kill(); + } +} +exports.Shell = Shell; +module.exports = { Shell }; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/shell/index.js.map b/dist/shell/index.js.map new file mode 100644 index 0000000..da3709a --- /dev/null +++ b/dist/shell/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shell/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/notes/openpose_help.txt b/notes/openpose_help.txt new file mode 100644 index 0000000..9261019 --- /dev/null +++ b/notes/openpose_help.txt @@ -0,0 +1,432 @@ + Flags from ./src/logging.cc: + -alsologtoemail (log messages go to these email addresses in addition to + logfiles) type: string default: "" + -alsologtostderr (log messages go to stderr in addition to logfiles) + type: bool default: false + -colorlogtostderr (color messages logged to stderr (if supported by + terminal)) type: bool default: false + -drop_log_memory (Drop in-memory buffers of log contents. Logs can grow + very quickly and they are rarely read before they need to be evicted from + memory. Instead, drop them from memory as soon as they are flushed to + disk.) type: bool default: true + -log_backtrace_at (Emit a backtrace when logging at file:linenum.) + type: string default: "" + -log_dir (If specified, logfiles are written into this directory instead of + the default logging directory.) type: string default: "" + -log_link (Put additional links to the log files in this directory) + type: string default: "" + -log_prefix (Prepend the log prefix to the start of each log line) + type: bool default: true + -logbuflevel (Buffer log messages logged at this level or lower (-1 means + don't buffer; 0 means buffer INFO only; ...)) type: int32 default: 0 + -logbufsecs (Buffer log messages for at most this many seconds) type: int32 + default: 30 + -logemaillevel (Email log messages logged at this level or higher (0 means + email all; 3 means email FATAL only; ...)) type: int32 default: 999 + -logfile_mode (Log file mode/permissions.) type: int32 default: 436 + -logmailer (Mailer used to send logging email) type: string + default: "/bin/mail" + -logtostderr (log messages go to stderr instead of logfiles) type: bool + default: false + -max_log_size (approx. maximum log file size (in MB). A value of 0 will be + silently overridden to 1.) type: int32 default: 1800 + -minloglevel (Messages logged at a lower level than this don't actually get + logged anywhere) type: int32 default: 0 + -stderrthreshold (log messages at or above this level are copied to stderr + in addition to logfiles. This flag obsoletes --alsologtostderr.) + type: int32 default: 2 + -stop_logging_if_full_disk (Stop attempting to log to disk if the disk is + full.) type: bool default: false + + Flags from ./src/utilities.cc: + -symbolize_stacktrace (Symbolize the stack trace in the tombstone) + type: bool default: true + + Flags from ./src/vlog_is_on.cc: + -v (Show all VLOG(m) messages for m <= this. Overridable by --vmodule.) + type: int32 default: 0 + -vmodule (per-module verbose level. Argument is a comma-separated list of + =. is a glob pattern, matched + against the filename base (that is, name ignoring .cc/.h./-inl.h). overrides any value given by --v.) type: string default: "" + + + + Flags from /build/gflags-WDCpEz/gflags-2.2.2/src/gflags.cc: + -flagfile (load flags from file) type: string default: "" + -fromenv (set flags from the environment [use 'export FLAGS_flag1=value']) + type: string default: "" + -tryfromenv (set flags from the environment if present) type: string + default: "" + -undefok (comma-separated list of flag names that it is okay to specify on + the command line even if the program does not define a flag with that + name. IMPORTANT: flags in this list that have arguments MUST use the + flag=value format) type: string default: "" + + Flags from /build/gflags-WDCpEz/gflags-2.2.2/src/gflags_completions.cc: + -tab_completion_columns (Number of columns to use in output for tab + completion) type: int32 default: 80 + -tab_completion_word (If non-empty, HandleCommandLineCompletions() will + hijack the process and attempt to do bash-style command line flag + completion on this value.) type: string default: "" + + Flags from /build/gflags-WDCpEz/gflags-2.2.2/src/gflags_reporting.cc: + -help (show help on all flags [tip: all flags can have two dashes]) + type: bool default: false currently: true + -helpfull (show help on all flags -- same as -help) type: bool + default: false + -helpmatch (show help on modules whose name contains the specified substr) + type: string default: "" + -helpon (show help on the modules named by this flag value) type: string + default: "" + -helppackage (show help on all modules in the main package) type: bool + default: false + -helpshort (show help on only the main module for this program) type: bool + default: false + -helpxml (produce an xml version of help) type: bool default: false + -version (show version and build info and exit) type: bool default: false + + + + Flags from /home/mmcwilliams/src/openpose/include/openpose/flags.hpp: + -3d (Running OpenPose 3-D reconstruction demo: 1) Reading from a stereo + camera system. 2) Performing 3-D reconstruction from the multiple views. + 3) Displaying 3-D reconstruction results. Note that it will only display + 1 person. If multiple people is present, it will fail.) type: bool + default: false + -3d_min_views (Minimum number of views required to reconstruct each + keypoint. By default (-1), it will require max(2, min(4, #cameras-1)) + cameras to see the keypoint in order to reconstruct it.) type: int32 + default: -1 + -3d_views (Complementary option for `--image_dir` or `--video`. OpenPose + will read as many images per iteration, allowing tasks such as stereo + camera processing (`--3d`). Note that `--camera_parameter_path` must be + set. OpenPose must find as many `xml` files in the parameter folder as + this number indicates.) type: int32 default: -1 + -alpha_heatmap (Blending factor (range 0-1) between heatmap and original + frame. 1 will only show the heatmap, 0 will only show the frame. Only + valid for GPU rendering.) type: double default: 0.69999999999999996 + -alpha_pose (Blending factor (range 0-1) for the body part rendering. 1 + will show it completely, 0 will hide it. Only valid for GPU rendering.) + type: double default: 0.59999999999999998 + -body (Select 0 to disable body keypoint detection (e.g., for faster but + less accurate face keypoint detection, custom hand detector, etc.), 1 + (default) for body keypoint estimation, and 2 to disable its internal + body pose estimation network but still still run the greedy association + parsing algorithm) type: int32 default: 1 + -caffemodel_path (The combination `--model_folder` + `--caffemodel_path` + represents the whole path to the caffemodel file. If empty, it will use + the default OpenPose CaffeModel file.) type: string default: "" + -camera (The camera index for cv::VideoCapture. Integer in the range [0, + 9]. Select a negative number (by default), to auto-detect and open the + first available camera.) type: int32 default: -1 + -camera_parameter_path (String with the folder where the camera parameters + are located. If there is only 1 XML file (for single video, webcam, or + images from the same camera), you must specify the whole XML file path + (ending in .xml).) type: string default: "models/cameraParameters/flir/" + -camera_resolution (Set the camera resolution (either `--camera` or + `--flir_camera`). `-1x-1` will use the default 1280x720 for `--camera`, + or the maximum flir camera resolution available for `--flir_camera`) + type: string default: "-1x-1" + -cli_verbose (If -1, it will be disabled (default). If it is a positive + integer number, it will print on the command line every `verbose` frames. + If number in the range (0,1), it will print the progress every `verbose` + times the total of frames.) type: double default: -1 + -disable_blending (If enabled, it will render the results (keypoint + skeletons or heatmaps) on a black background, instead of being rendered + into the original image. Related: `part_to_show`, `alpha_pose`, and + `alpha_pose`.) type: bool default: false + -disable_multi_thread (It would slightly reduce the frame rate in order to + highly reduce the lag. Mainly useful for 1) Cases where it is needed a + low latency (e.g., webcam in real-time scenarios with low-range GPU + devices); and 2) Debugging OpenPose when it is crashing to locate the + error.) type: bool default: false + -display (Display mode: -1 for automatic selection; 0 for no display + (useful if there is no X server and/or to slightly speed up the + processing if visual output is not required); 2 for 2-D display; 3 for + 3-D display (if `--3d` enabled); and 1 for both 2-D and 3-D display.) + type: int32 default: -1 + -face (Enables face keypoint detection. It will share some parameters from + the body pose, e.g. `model_folder`. Note that this will considerable slow + down the performance and increase the required GPU memory. In addition, + the greater number of people on the image, the slower OpenPose will be.) + type: bool default: false + -face_alpha_heatmap (Analogous to `alpha_heatmap` but applied to face.) + type: double default: 0.69999999999999996 + -face_alpha_pose (Analogous to `alpha_pose` but applied to face.) + type: double default: 0.59999999999999998 + -face_detector (Kind of face rectangle detector. Select 0 (default) to + select OpenPose body detector (most accurate one and fastest one if body + is enabled), 1 to select OpenCV face detector (not implemented for + hands), 2 to indicate that it will be provided by the user, or 3 to also + apply hand tracking (only for hand). Hand tracking might improve hand + keypoint detection for webcam (if the frame rate is high enough, i.e., >7 + FPS per GPU) and video. This is not person ID tracking, it simply looks + for hands in positions at which hands were located in previous frames, + but it does not guarantee the same person ID among frames.) type: int32 + default: 0 + -face_net_resolution (Multiples of 16 and squared. Analogous to + `net_resolution` but applied to the face keypoint detector. 320x320 + usually works fine while giving a substantial speed up when multiple + faces on the image.) type: string default: "368x368" + -face_render (Analogous to `render_pose` but applied to the face. Extra + option: -1 to use the same configuration that `render_pose` is using.) + type: int32 default: -1 + -face_render_threshold (Analogous to `render_threshold`, but applied to the + face keypoints.) type: double default: 0.40000000000000002 + -flir_camera (Whether to use FLIR (Point-Grey) stereo camera.) type: bool + default: false + -flir_camera_index (Select -1 (default) to run on all detected flir cameras + at once. Otherwise, select the flir camera index to run, where 0 + corresponds to the detected flir camera with the lowest serial number, + and `n` to the `n`-th lowest serial number camera.) type: int32 + default: -1 + -fps_max (Maximum processing frame rate. By default (-1), OpenPose will + process frames as fast as possible. Example usage: If OpenPose is + displaying images too quickly, this can reduce the speed so the user can + analyze better each frame from the GUI.) type: double default: -1 + -frame_first (Start on desired frame number. Indexes are 0-based, i.e., the + first frame has index 0.) type: uint64 default: 0 + -frame_flip (Flip/mirror each frame (e.g., for real time webcam + demonstrations).) type: bool default: false + -frame_last (Finish on desired frame number. Select -1 to disable. Indexes + are 0-based, e.g., if set to 10, it will process 11 frames (0-10).) + type: uint64 default: 18446744073709551615 + -frame_rotate (Rotate each frame, 4 possible values: 0, 90, 180, 270.) + type: int32 default: 0 + -frame_step (Step or gap between processed frames. E.g., `--frame_step 5` + would read and process frames 0, 5, 10, etc..) type: uint64 default: 1 + -frame_undistort (If false (default), it will not undistort the image, if + true, it will undistortionate them based on the camera parameters found + in `camera_parameter_path`) type: bool default: false + -frames_repeat (Repeat frames when finished.) type: bool default: false + -fullscreen (Run in full-screen mode (press f during runtime to toggle).) + type: bool default: false + -hand (Enables hand keypoint detection. It will share some parameters from + the body pose, e.g. `model_folder`. Analogously to `--face`, it will also + slow down the performance, increase the required GPU memory and its speed + depends on the number of people.) type: bool default: false + -hand_alpha_heatmap (Analogous to `alpha_heatmap` but applied to hand.) + type: double default: 0.69999999999999996 + -hand_alpha_pose (Analogous to `alpha_pose` but applied to hand.) + type: double default: 0.59999999999999998 + -hand_detector (Kind of hand rectangle detector. Analogous to + `--face_detector`.) type: int32 default: 0 + -hand_net_resolution (Multiples of 16 and squared. Analogous to + `net_resolution` but applied to the hand keypoint detector.) type: string + default: "368x368" + -hand_render (Analogous to `render_pose` but applied to the hand. Extra + option: -1 to use the same configuration that `render_pose` is using.) + type: int32 default: -1 + -hand_render_threshold (Analogous to `render_threshold`, but applied to the + hand keypoints.) type: double default: 0.20000000000000001 + -hand_scale_number (Analogous to `scale_number` but applied to the hand + keypoint detector. Our best results were found with `hand_scale_number` = + 6 and `hand_scale_range` = 0.4.) type: int32 default: 1 + -hand_scale_range (Analogous purpose than `scale_gap` but applied to the + hand keypoint detector. Total range between smallest and biggest scale. + The scales will be centered in ratio 1. E.g., if scaleRange = 0.4 and + scalesNumber = 2, then there will be 2 scales, 0.8 and 1.2.) type: double + default: 0.40000000000000002 + -heatmaps_add_PAFs (Same functionality as `add_heatmaps_parts`, but adding + the PAFs.) type: bool default: false + -heatmaps_add_bkg (Same functionality as `add_heatmaps_parts`, but adding + the heatmap corresponding to background.) type: bool default: false + -heatmaps_add_parts (If true, it will fill op::Datum::poseHeatMaps array + with the body part heatmaps, and analogously face & hand heatmaps to + op::Datum::faceHeatMaps & op::Datum::handHeatMaps. If more than one + `add_heatmaps_X` flag is enabled, it will place then in sequential memory + order: body parts + bkg + PAFs. It will follow the order on + POSE_BODY_PART_MAPPING in `src/openpose/pose/poseParameters.cpp`. Program + speed will considerably decrease. Not required for OpenPose, enable it + only if you intend to explicitly use this information later.) type: bool + default: false + -heatmaps_scale (Set 0 to scale op::Datum::poseHeatMaps in the range + [-1,1], 1 for [0,1]; 2 for integer rounded [0,255]; and 3 for no + scaling.) type: int32 default: 2 + -identification (Experimental, not available yet. Whether to enable people + identification across frames.) type: bool default: false + -ik_threads (Experimental, not available yet. Whether to enable inverse + kinematics (IK) from 3-D keypoints to obtain 3-D joint angles. By default + (0 threads), it is disabled. Increasing the number of threads will + increase the speed but also the global system latency.) type: int32 + default: 0 + -image_dir (Process a directory of images. Use `examples/media/` for our + default example folder with 20 images. Read all standard formats (jpg, + png, bmp, etc.).) type: string default: "" + -ip_camera (String with the IP camera URL. It supports protocols like RTSP + and HTTP.) type: string default: "" + -keypoint_scale (Scaling of the (x,y) coordinates of the final pose data + array, i.e., the scale of the (x,y) coordinates that will be saved with + the `write_json` & `write_keypoint` flags. Select `0` to scale it to the + original source resolution; `1`to scale it to the net output size (set + with `net_resolution`); `2` to scale it to the final output size (set + with `resolution`); `3` to scale it in the range [0,1], where (0,0) would + be the top-left corner of the image, and (1,1) the bottom-right one; and + 4 for range [-1,1], where (-1,-1) would be the top-left corner of the + image, and (1,1) the bottom-right one. Non related with `scale_number` + and `scale_gap`.) type: int32 default: 0 + -logging_level (The logging level. Integer in the range [0, 255]. 0 will + output any opLog() message, while 255 will not output any. Current + OpenPose library messages are in the range 0-4: 1 for low priority + messages and 4 for important ones.) type: int32 default: 3 + -maximize_positives (It reduces the thresholds to accept a person + candidate. It highly increases both false and true positives. I.e., it + maximizes average recall but could harm average precision.) type: bool + default: false + -model_folder (Folder path (absolute or relative) where the models (pose, + face, ...) are located.) type: string default: "models/" + -model_pose (Model to be used. E.g., `BODY_25` (fastest for CUDA version, + most accurate, and includes foot keypoints), `COCO` (18 keypoints), `MPI` + (15 keypoints, least accurate model but fastest on CPU), `MPI_4_layers` + (15 keypoints, even faster but less accurate).) type: string + default: "BODY_25" + -net_resolution (Multiples of 16. If it is increased, the accuracy + potentially increases. If it is decreased, the speed increases. For + maximum speed-accuracy balance, it should keep the closest aspect ratio + possible to the images or videos to be processed. Using `-1` in any of + the dimensions, OP will choose the optimal aspect ratio depending on the + user's input value. E.g., the default `-1x368` is equivalent to `656x368` + in 16:9 resolutions, e.g., full HD (1980x1080) and HD (1280x720) + resolutions.) type: string default: "-1x368" + -net_resolution_dynamic (This flag only applies to images or custom inputs + (not to video or webcam). If it is zero or a negative value, it means + that using `-1` in `net_resolution` will behave as explained in its + description. Otherwise, and to avoid out of memory errors, the `-1` in + `net_resolution` will clip to this value times the default 16/9 aspect + ratio value (which is 656 width for a 368 height). E.g., + `net_resolution_dynamic 10 net_resolution -1x368` will clip to 6560x368 + (10 x 656). Recommended 1 for small GPUs (to avoid out of memory errors + but maximize speed) and 0 for big GPUs (for maximum accuracy and speed).) + type: double default: 1 + -no_gui_verbose (Do not write text on output images on GUI (e.g., number of + current frame and people). It does not affect the pose rendering.) + type: bool default: false + -num_gpu (The number of GPU devices to use. If negative, it will use all + the available GPUs in your machine.) type: int32 default: -1 + -num_gpu_start (GPU device start number.) type: int32 default: 0 + -number_people_max (This parameter will limit the maximum number of people + detected, by keeping the people with top scores. The score is based in + person area over the image, body part score, as well as joint score + (between each pair of connected body parts). Useful if you know the exact + number of people in the scene, so it can remove false positives (if all + the people have been detected. However, it might also include false + negatives by removing very small or highly occluded people. -1 will keep + them all.) type: int32 default: -1 + -output_resolution (The image resolution (display and output). Use "-1x-1" + to force the program to use the input image resolution.) type: string + default: "-1x-1" + -part_candidates (Also enable `write_json` in order to save this + information. If true, it will fill the op::Datum::poseCandidates array + with the body part candidates. Candidates refer to all the detected body + parts, before being assembled into people. Note that the number of + candidates is equal or higher than the number of final body parts (i.e., + after being assembled into people). The empty body parts are filled with + 0s. Program speed will slightly decrease. Not required for OpenPose, + enable it only if you intend to explicitly use this information.) + type: bool default: false + -part_to_show (Prediction channel to visualize: 0 (default) for all the + body parts, 1 for the background heat map, 2 for the superposition of + heatmaps, 3 for the superposition of PAFs, 4-(4+#keypoints) for each body + part heat map, the following ones for each body part pair PAF.) + type: int32 default: 0 + -process_real_time (Enable to keep the original source frame rate (e.g., + for video). If the processing time is too long, it will skip frames. If + it is too fast, it will slow it down.) type: bool default: false + -profile_speed (If PROFILER_ENABLED was set in CMake or Makefile.config + files, OpenPose will show some runtime statistics at this frame number.) + type: int32 default: 1000 + -prototxt_path (The combination `--model_folder` + `--prototxt_path` + represents the whole path to the prototxt file. If empty, it will use the + default OpenPose ProtoTxt file.) type: string default: "" + -render_pose (Set to 0 for no rendering, 1 for CPU rendering (slightly + faster), and 2 for GPU rendering (slower but greater functionality, e.g., + `alpha_X` flags). If -1, it will pick CPU if CPU_ONLY is enabled, or GPU + if CUDA is enabled. If rendering is enabled, it will render both + `outputData` and `cvOutputData` with the original image and desired body + part to be shown (i.e., keypoints, heat maps or PAFs).) type: int32 + default: -1 + -render_threshold (Only estimated keypoints whose score confidences are + higher than this threshold will be rendered. Note: Rendered refers only + to visual display in the OpenPose basic GUI, not in the saved results. + Generally, a high threshold (> 0.5) will only render very clear body + parts; while small thresholds (~0.1) will also output guessed and + occluded keypoints, but also more false positives (i.e., wrong + detections).) type: double default: 0.050000000000000003 + -scale_gap (Scale gap between scales. No effect unless scale_number > 1. + Initial scale is always 1. If you want to change the initial scale, you + actually want to multiply the `net_resolution` by your desired initial + scale.) type: double default: 0.25 + -scale_number (Number of scales to average.) type: int32 default: 1 + -tracking (Experimental, not available yet. Whether to enable people + tracking across frames. The value indicates the number of frames where + tracking is run between each OpenPose keypoint detection. Select -1 + (default) to disable it or 0 to run simultaneously OpenPose keypoint + detector and tracking for potentially higher accuracy than only + OpenPose.) type: int32 default: -1 + -udp_host (Experimental, not available yet. IP for UDP communication. E.g., + `192.168.0.1`.) type: string default: "" + -udp_port (Experimental, not available yet. Port number for UDP + communication.) type: string default: "8051" + -upsampling_ratio (Upsampling ratio between the `net_resolution` and the + output net results. A value less or equal than 0 (default) will use the + network default value (recommended).) type: double default: 0 + -video (Use a video file instead of the camera. Use + `examples/media/video.avi` for our default example video.) type: string + default: "" + -write_bvh (Experimental, not available yet. E.g., + `~/Desktop/mocapResult.bvh`.) type: string default: "" + -write_coco_json (Full file path to write people pose data with JSON COCO + validation format. If foot, face, hands, etc. JSON is also desired + (`--write_coco_json_variants`), they are saved with different file name + suffix.) type: string default: "" + -write_coco_json_variant (Currently, this option is experimental and only + makes effect on car JSON generation. It selects the COCO variant for + cocoJsonSaver.) type: int32 default: 0 + -write_coco_json_variants (Add 1 for body, add 2 for foot, 4 for face, + and/or 8 for hands. Use 0 to use all the possible candidates. E.g., 7 + would mean body+foot+face COCO JSON.) type: int32 default: 1 + -write_heatmaps (Directory to write body pose heatmaps in PNG format. At + least 1 `add_heatmaps_X` flag must be enabled.) type: string default: "" + -write_heatmaps_format (File extension and format for `write_heatmaps`, + analogous to `write_images_format`. For lossless compression, recommended + `png` for integer `heatmaps_scale` and `float` for floating values. See + `doc/02_output.md` for more details.) type: string default: "png" + -write_images (Directory to write rendered frames in `write_images_format` + image format.) type: string default: "" + -write_images_format (File extension and format for `write_images`, e.g., + png, jpg or bmp. Check the OpenCV function cv::imwrite for all compatible + extensions.) type: string default: "png" + -write_json (Directory to write OpenPose output in JSON format. It includes + body, hand, and face pose keypoints (2-D and 3-D), as well as pose + candidates (if `--part_candidates` enabled).) type: string default: "" + -write_keypoint ((Deprecated, use `write_json`) Directory to write the + people pose keypoint data. Set format with `write_keypoint_format`.) + type: string default: "" + -write_keypoint_format ((Deprecated, use `write_json`) File extension and + format for `write_keypoint`: json, xml, yaml & yml. Json not available + for OpenCV < 3.0, use `write_json` instead.) type: string default: "yml" + -write_video (Full file path to write rendered frames in motion JPEG video + format. It might fail if the final path does not finish in `.avi`. It + internally uses cv::VideoWriter. Flag `write_video_fps` controls FPS. + Alternatively, the video extension can be `.mp4`, resulting in a file + with a much smaller size and allowing `--write_video_with_audio`. + However, that would require: 1) Ubuntu or Mac system, 2) FFmpeg library + installed (`sudo apt-get install ffmpeg`), 3) the creation temporarily of + a folder with the same file path than the final video (without the + extension) to storage the intermediate frames that will later be used to + generate the final MP4 video.) type: string default: "" + -write_video_3d (Analogous to `--write_video`, but applied to the 3D + output.) type: string default: "" + -write_video_adam (Experimental, not available yet. Analogous to + `--write_video`, but applied to Adam model.) type: string default: "" + -write_video_fps (Frame rate for the recorded video. By default, it will + try to get the input frames producer frame rate (e.g., input video or + webcam frame rate). If the input frames producer does not have a set FPS + (e.g., image_dir or webcam if OpenCV not compiled with its support), set + this value accordingly (e.g., to the frame rate displayed by the OpenPose + GUI).) type: double default: -1 + -write_video_with_audio (If the input is video and the output is so too, it + will save the video with audio. It requires the output video file path + finishing in `.mp4` format (see `write_video` for details).) type: bool + default: false diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..be3b366 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1563 @@ +{ + "name": "openpose_api", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "openpose_api", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "body-parser": "^1.20.3", + "dotenv": "^16.4.5", + "express": "^4.18.2", + "lodash": "^4.17.21", + "mime": "^4.0.4", + "multer": "^1.4.5-lts.1", + "triple-beam": "^1.4.1", + "uuid": "^10.0.0", + "winston": "^3.15.0" + }, + "devDependencies": { + "@types/body-parser": "^1.19.5", + "@types/express": "^4.17.21", + "@types/multer": "^1.4.12", + "@types/node": "^22.7.5", + "@types/uuid": "^10.0.0", + "typescript": "^5.6.3" + } + }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "license": "MIT", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/multer": { + "version": "1.4.12", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.12.tgz", + "integrity": "sha512-pQ2hoqvXiJt2FP9WQVLPRO+AmiIm/ZYkavPlIQnx282u4ZrVdztx0pkh3jjpQt0Kz+YI0YhSG264y08UJKoUQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/node": { + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/qs": { + "version": "6.9.16", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", + "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", + "license": "MIT" + }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "license": "MIT" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "license": "MIT", + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/express/node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/express/node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", + "license": "MIT" + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", + "license": "MIT" + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT" + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/logform": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.1.tgz", + "integrity": "sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==", + "license": "MIT", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/logform/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "license": "MIT" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.4.tgz", + "integrity": "sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==", + "funding": [ + "https://github.com/sponsors/broofa" + ], + "license": "MIT", + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "license": "MIT", + "dependencies": { + "fn.name": "1.x.x" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "license": "MIT" + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "license": "MIT", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", + "license": "MIT" + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/winston": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.15.0.tgz", + "integrity": "sha512-RhruH2Cj0bV0WgNL+lOfoUBI4DVfdUNjVnJGVovWZmrcKtrFTTRzgXYK2O9cymSGjrERCtaAeHwMNnUWXlwZow==", + "license": "MIT", + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.6.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.7.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.8.0.tgz", + "integrity": "sha512-qxSTKswC6llEMZKgCQdaWgDuMJQnhuvF5f2Nk3SNXc4byfQ+voo2mX1Px9dkNOuR8p0KAjfPG29PuYUSIb+vSA==", + "license": "MIT", + "dependencies": { + "logform": "^2.6.1", + "readable-stream": "^4.5.2", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/winston-transport/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/winston/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..4561be1 --- /dev/null +++ b/package.json @@ -0,0 +1,31 @@ +{ + "name": "openpose_api", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "compile": "./node_modules/.bin/tsc -p tsconfig.json", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "mattmcw", + "license": "MIT", + "description": "", + "devDependencies": { + "@types/body-parser": "^1.19.5", + "@types/express": "^4.17.21", + "@types/multer": "^1.4.12", + "@types/node": "^22.7.5", + "@types/uuid": "^10.0.0", + "typescript": "^5.6.3" + }, + "dependencies": { + "body-parser": "^1.20.3", + "dotenv": "^16.4.5", + "express": "^4.18.2", + "lodash": "^4.17.21", + "mime": "^4.0.4", + "multer": "^1.4.5-lts.1", + "triple-beam": "^1.4.1", + "uuid": "^10.0.0", + "winston": "^3.15.0" + } +} diff --git a/scripts/test.sh b/scripts/test.sh new file mode 100644 index 0000000..b0b8ac6 --- /dev/null +++ b/scripts/test.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# -F "hand=true" \ +# -F "face=true" \ + +curl \ + -m 240 \ + -F "image=@examples/two_standing.jpg" \ + 'http://localhost:7474/openpose' \ No newline at end of file diff --git a/src/env/index.ts b/src/env/index.ts new file mode 100644 index 0000000..faeb173 --- /dev/null +++ b/src/env/index.ts @@ -0,0 +1,13 @@ +export function envString (variable : string, defaultString : string) : string { + return typeof process.env[variable] !== 'undefined' ? process.env[variable] : defaultString; +} + +export function envFloat (variable : string, defaultFloat : number ) : number { + return typeof process.env[variable] !== 'undefined' ? parseFloat(process.env[variable]) : defaultFloat; +} + +export function envInt (variable : string, defaultInt : number ) : number { + return typeof process.env[variable] !== 'undefined' ? parseInt(process.env[variable]) : defaultInt; +} + +module.exports = { envString, envFloat, envInt }; \ No newline at end of file diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..8e1667c --- /dev/null +++ b/src/index.ts @@ -0,0 +1,166 @@ +import 'dotenv/config'; +import express from 'express'; +import { Express, Request, Response, NextFunction } from 'express' +import { access, copyFile, unlink, mkdir, readFile, rm } from 'fs/promises'; +import { tmpdir } from 'os'; +import { join, basename, resolve, extname } from 'path'; +import bodyParser from 'body-parser'; +import multer, { FileFilterCallback } from 'multer'; +import { v4 as uuid } from 'uuid'; +import getType from 'mime'; +import { createLog } from './log' +import type { Logger } from 'winston'; +import { envInt, envString } from './env'; +import { Shell } from './shell'; + +const PORT : number = envInt('PORT', 7474); +const BIN : string = envString('BIN', 'openpose'); +const CWD : string = envString('CWD', '.'); + +const log : Logger = createLog('openpose_api'); +const app : Express = express(); +const tmp : string = tmpdir(); + +const storage = multer.diskStorage({ + destination: function (req : Request, file : Express.Multer.File, cb : Function) { + cb(null, tmp) + }, + filename: function (req : Request, file : Express.Multer.File, cb : Function) { + cb(null, `${+new Date()}_${file.originalname}`) + } +}); + +async function exists (path : string) : Promise { + try { + await access(path); + return true; + } catch { + return false; + } +} + +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: true })); + +const uploadImage : any = multer({ storage }); + +app.get('/', (req: Request, res: Response, next : NextFunction) => { + return res.send('/'); +}); + +//./build/examples/openpose/openpose.bin -v 1 -image_dir ./examples/media/ -write_images ./output -write_json ./json --face --hand +app.post('/openpose', uploadImage.single('image'), async (req: Request, res: Response, next : NextFunction) => { + const id : string = uuid(); + const dir : string = join(tmp, id); + const image_dir : string = join(dir, 'image'); + const json_dir : string = join(dir, 'json'); + const json_file : string = join(json_dir, 'openpose_keypoints.json'); + let json_exists : boolean = false; + let openpose_str : string = '{}'; + let output : any; + let image_file : string; + let image_ext : string; + let sh : Shell; + // + const args : string[] = [ + BIN, + '--render_pose', '0', + '-display', '0', + '-image_dir', image_dir, + '-write_json', json_dir + ]; + + if (typeof req.file === 'undefined') { + return next(new Error('No image uploaded')); + } + + image_ext = extname(basename(req.file.path)); + image_file = join(image_dir, `openpose${image_ext}`); + + if (typeof req.body.face !== 'undefined' && req.body.face === 'true') { + args.push('--face'); + } + + if (typeof req.body.hand !== 'undefined' && req.body.hand === 'true') { + args.push('--hand'); + } + + try { + await mkdir(dir); + } catch (err) { + log.error(`Error making directory ${dir}`, err); + return next(new Error('Error making dir')); + } + + try { + await mkdir(image_dir); + } catch (err) { + log.error(`Error making directory ${image_dir}`, err); + return next(new Error('Error making image_dir')); + } + + try { + await mkdir(json_dir); + } catch (err) { + log.error(`Error making directory ${image_dir}`, err); + return next(new Error('Error making image_dir')); + } + + try { + await copyFile(req.file.path, image_file); + } catch (err) { + log.error(`Error copying file ${req.file.path}`, err); + return next(new Error('Error copying temp image')); + } + + sh = new Shell(args, CWD, null, null, null, true); + + try { + await sh.execute(); + } catch (err) { + log.error(`Error executing ${args.join(' ')}`, err); + return next(new Error('Error running openpose')); + } + + try { + json_exists = await exists(json_file); + } catch (err) { + log.error(`Error checking json ${json_file} exists`, err); + return next(new Error('Error checking json exists')); + } + + if (json_exists) { + try { + openpose_str = await readFile(json_file, 'utf8'); + } catch (err) { + log.error(`Error reading json file ${json_file}`, err); + return next(new Error('Error reading json file')); + } + } else { + log.error(`The json file ${json_file} does not exist`); + return next(new Error('Error running openpose')); + } + + try { + output = JSON.parse(openpose_str); + } catch (err) { + log.error(`Error parsing openpose json`, err); + return next(new Error('Error parsing openpose json')); + } + + output.image = req.file.originalname; + + try { + await rm(dir, { recursive: true }); + } catch (err) { + log.error(`Error unlinking ${dir}`, err); + return next(new Error('Error unlinking temp dir')); + } + + return res.json(output); +}); + +app.listen(PORT, () => { + log.info(`Openpose API server running on port ${PORT}`); + log.info(`Using openpose binary ${BIN}`); +}); \ No newline at end of file diff --git a/src/log/index.ts b/src/log/index.ts new file mode 100644 index 0000000..798bc27 --- /dev/null +++ b/src/log/index.ts @@ -0,0 +1,61 @@ +'use strict' + +/** @module log */ +/** Wrapper for winston that tags streams and optionally writes files with a simple interface. */ +/** Module now also supports optional papertrail integration, other services to follow */ + +import { format, transports, createLogger } from 'winston'; +const { SPLAT } = require('triple-beam'); +const { isObject } = require('lodash'); + +const APP_NAME : string = process.env.APP_NAME || 'default'; + +function formatObject (param : any) { + if (isObject(param)) { + return JSON.stringify(param); + } + return param; +} + +const all = format((info : any) => { + const splat = info[SPLAT] || []; + const message = formatObject(info.message); + const rest = splat.map(formatObject).join(' '); + info.message = `${message} ${rest}`; + return info; +}); + +const myFormat = format.printf(({ level, message, label, timestamp } : any) => { + return `${timestamp} [${label}] ${level}: ${message}`; +}); + +/** +* Returns a winston logger configured to service +* +* @param {string} label Label appearing on logger +* @param {string} filename Optional file to write log to +* +* @returns {object} Winston logger +*/ +export function createLog (label : string, filename : string = null) { + const tports : any[] = [ new (transports.Console)() ]; + const fmat : any = format.combine( + all(), + format.label({ label }), + format.timestamp({format: 'YYYY-MM-DD HH:mm:ss.SSS'}), + format.colorize(), + myFormat, + ); + let papertrailOpts : any; + + if (filename !== null) { + tports.push( new (transports.File)({ filename }) ); + } + + return createLogger({ + format : fmat, + transports : tports + }); +} + +module.exports = { createLog }; diff --git a/src/shell/index.ts b/src/shell/index.ts new file mode 100644 index 0000000..3ae57bd --- /dev/null +++ b/src/shell/index.ts @@ -0,0 +1,77 @@ +import { spawn, ChildProcessWithoutNullStreams } from 'child_process'; +import { createLog } from '../log'; +import type { Logger } from 'winston'; +import { EOL } from 'os'; + +export class Shell { + private child : ChildProcessWithoutNullStreams; + private log : Logger; + private bin : string; + private args : any[]; + private cwd : string; + private lines : string[] = []; + private stdio : Function = null; + private stderr : Function = null; + private after : Function = null; + private silent : boolean = false; + + constructor (args : any[], cwd : string = null, stdio : Function = null, stderr : Function = null, after : Function = null, silent : boolean = false) { + const bin : string = args.shift(); + this.bin = bin; + this.args = args; + this.stdio = stdio; + this.stderr = stderr; + this.silent = silent; + this.after = after; + this.cwd = cwd; + this.log = createLog(bin); + } + + public async execute () : Promise { + return new Promise((resolve : Function, reject : Function) => { + const options : any = {}; + if (this.cwd !== null) { + options.cwd = this.cwd; + } + this.child = spawn(this.bin, this.args, options); + + this.log.info(`Shell: ${this.bin} ${this.args.join(' ')}`); + + this.child.stdout.on('data', (data : string) => { + if (!this.silent) this.log.info(data); + if (this.after !== null) this.lines.push(data); + if (this.stdio !== null) { + this.stdio(data); + } + }); + + this.child.stderr.on('data', (data : string) => { + if (!this.silent) this.log.warn(data); + if (this.stderr !== null) { + this.stderr(data); + } + }); + + this.child.on('close', (code : number) => { + if (this.after !== null) { + this.after(this.lines.join(EOL)); + } + if (code === 0) { + this.log.info(`Complete: ${this.bin} ${this.args.join(' ')}`); + return resolve(code); + } else { + this.log.error(`Error executing: ${this.bin} ${this.args.join(' ')}`); + return reject(code); + } + }); + }); + } + + public kill () { + this.log.warn(`Killing: ${this.bin} ${this.args.join(' ')}`); + //this.child.stdin.pause(); + this.child.kill(); + } +} + +module.exports = { Shell }; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..4d7003c --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "module": "commonjs", + "esModuleInterop": true, + "target": "ES2020", + "noImplicitAny": true, + "moduleResolution": "node", + "sourceMap": true, + "removeComments" : false, + "baseUrl" : "dist", + "outDir": "./dist/", + "rootDir" : "./src/", + "paths" : { + } + }, + "exclude" : [ + "./dist", + "./node_modules" + ] +} \ No newline at end of file