From 3e5efdff744ddbb293f92c886376de4af52451c0 Mon Sep 17 00:00:00 2001 From: Karel Kremer Date: Sun, 17 Dec 2023 13:51:47 +0100 Subject: [PATCH 1/9] create a typescript package out of mu-helpers, ready to be published together with the template --- .dockerignore | 2 + .gitignore | 2 + babel.config.json | 8 +- helpers/README | 3 + helpers/mu/{index.js => index.ts} | 32 +- helpers/mu/server.js | 49 -- helpers/mu/server.ts | 60 ++ helpers/mu/sparql-client-2.d.ts | 1 + helpers/mu/sparql.js | 192 ----- helpers/mu/sparql.ts | 227 +++++ helpers/package-lock.json | 1321 +++++++++++++++++++++++++++++ helpers/package.json | 27 + helpers/tsconfig.json | 26 + package.json | 6 +- run-development.sh | 1 + transpile-sources.sh | 17 +- 16 files changed, 1705 insertions(+), 269 deletions(-) create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 helpers/README rename helpers/mu/{index.js => index.ts} (58%) delete mode 100644 helpers/mu/server.js create mode 100644 helpers/mu/server.ts create mode 100644 helpers/mu/sparql-client-2.d.ts delete mode 100644 helpers/mu/sparql.js create mode 100644 helpers/mu/sparql.ts create mode 100644 helpers/package-lock.json create mode 100644 helpers/package.json create mode 100644 helpers/tsconfig.json diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..1524074 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +helpers/dist +helpers/node_modules diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9421307 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +helpers/dist diff --git a/babel.config.json b/babel.config.json index b8eae3d..48b8f33 100644 --- a/babel.config.json +++ b/babel.config.json @@ -1,6 +1,7 @@ { "presets": [ - ["@babel/preset-env", + [ + "@babel/preset-env", { "targets": { "node": 18 @@ -9,11 +10,10 @@ ], ["@babel/preset-typescript"] ], - "plugins": [ - ["@babel/plugin-proposal-decorators", { "version": "2023-05" }] - ], + "plugins": [["@babel/plugin-proposal-decorators", { "version": "2023-05" }]], "ignore": [ "./node_modules", + "/usr/src/processing/temp/app/app/node_modules", "/usr/src/processing/build/node_modules" ] } diff --git a/helpers/README b/helpers/README new file mode 100644 index 0000000..f960e8e --- /dev/null +++ b/helpers/README @@ -0,0 +1,3 @@ +this allows the mu-helpers to be published as a typescript package as well from within the template repository, making sure that the template and the package are always published together + +One caveat is that the dependencies for the package are fewer than the dependencies that are added by default in the template (e.g. babel, coffeescript etc) so when publishing, care should be taken to keep those in sync to avoid surprises by consumers diff --git a/helpers/mu/index.js b/helpers/mu/index.ts similarity index 58% rename from helpers/mu/index.js rename to helpers/mu/index.ts index 54b0c0d..ff9f159 100644 --- a/helpers/mu/index.js +++ b/helpers/mu/index.ts @@ -1,6 +1,6 @@ -import { app, errorHandler } from './server'; -import sparql from './sparql'; -import { v1 as uuidV1 } from 'uuid'; +import { app, errorHandler } from "./server"; +import sparql from "./sparql"; +import { v1 as uuidV1 } from "uuid"; // generates a uuid const uuid = uuidV1; @@ -21,21 +21,21 @@ const mu = { sparqlEscapeDateTime: sparql.sparqlEscapeDateTime, sparqlEscapeBool: sparql.sparqlEscapeBool, uuid, - errorHandler + errorHandler, }; const SPARQL = mu.SPARQL, - query = mu.query, - update = mu.update, - sparqlEscape = mu.sparqlEscape, - sparqlEscapeString = mu.sparqlEscapeString, - sparqlEscapeUri = mu.sparqlEscapeUri, - sparqlEscapeInt = mu.sparqlEscapeInt, - sparqlEscapeDecimal = mu.sparqlEscapeDecimal, - sparqlEscapeFloat = mu.sparqlEscapeFloat, - sparqlEscapeDate = mu.sparqlEscapeDate, - sparqlEscapeDateTime = mu.sparqlEscapeDateTime, - sparqlEscapeBool = mu.sparqlEscapeBool; + query = mu.query, + update = mu.update, + sparqlEscape = mu.sparqlEscape, + sparqlEscapeString = mu.sparqlEscapeString, + sparqlEscapeUri = mu.sparqlEscapeUri, + sparqlEscapeInt = mu.sparqlEscapeInt, + sparqlEscapeDecimal = mu.sparqlEscapeDecimal, + sparqlEscapeFloat = mu.sparqlEscapeFloat, + sparqlEscapeDate = mu.sparqlEscapeDate, + sparqlEscapeDateTime = mu.sparqlEscapeDateTime, + sparqlEscapeBool = mu.sparqlEscapeBool; export { app, @@ -53,7 +53,7 @@ export { sparqlEscapeDateTime, sparqlEscapeBool, uuid, - errorHandler + errorHandler, }; export default mu; diff --git a/helpers/mu/server.js b/helpers/mu/server.js deleted file mode 100644 index 9ff7aeb..0000000 --- a/helpers/mu/server.js +++ /dev/null @@ -1,49 +0,0 @@ -import httpContext from 'express-http-context'; -import express from 'express'; -import bodyParser from 'body-parser'; - -var app = express(); - -var port = process.env.PORT || '80'; -var hostname = process.env.HOST || '0.0.0.0'; -var bodySizeLimit = process.env.MAX_BODY_SIZE || '100kb'; - -// parse JSONAPI content type -app.use(bodyParser.json({ - type: function(req) { return /^application\/vnd\.api\+json/.test(req.get('content-type')); }, - limit: bodySizeLimit -})); -app.use(bodyParser.urlencoded({ extended: false })); - -// set JSONAPI content type -app.use('/', function(req, res, next) { - res.type('application/vnd.api+json'); - next(); -}); - -app.use(httpContext.middleware); - -app.use(function(req, res, next) { - httpContext.set('request', req); - httpContext.set('response', res); - next(); -}); - -const errorHandler = function(err, req, res, next) { - res.status(err.status || 400); - res.json({ - errors: [ {title: err.message} ] - }); -}; - -// start server -app.listen( port, hostname, function() { - console.log(`Starting server on ${hostname}:${port} in ${app.get('env')} mode`); -}); - -export default app; - -export { - app, - errorHandler -} diff --git a/helpers/mu/server.ts b/helpers/mu/server.ts new file mode 100644 index 0000000..a3653cc --- /dev/null +++ b/helpers/mu/server.ts @@ -0,0 +1,60 @@ +import httpContext from "express-http-context"; +import express from "express"; +import bodyParser from "body-parser"; + +var app = express(); + +var port = parseInt(process.env.PORT || "80") || 80; +var hostname = process.env.HOST || "0.0.0.0"; +var bodySizeLimit = process.env.MAX_BODY_SIZE || "100kb"; + +// parse JSONAPI content type +app.use( + bodyParser.json({ + type: function (req) { + const expressReq = req as express.Request; + return /^application\/vnd\.api\+json/.test( + expressReq.get("content-type") || "" + ); + }, + limit: bodySizeLimit, + }) +); +app.use(bodyParser.urlencoded({ extended: false })); + +// set JSONAPI content type +app.use("/", function (req, res, next) { + res.type("application/vnd.api+json"); + next(); +}); + +app.use(httpContext.middleware); + +app.use(function (req, res, next) { + httpContext.set("request", req); + httpContext.set("response", res); + next(); +}); + +const errorHandler: express.ErrorRequestHandler = function ( + err, + req, + res, + next +) { + res.status(err.status || 400); + res.json({ + errors: [{ title: err.message }], + }); +}; + +// start server +app.listen(port, hostname, function () { + console.log( + `Starting server on ${hostname}:${port} in ${app.get("env")} mode` + ); +}); + +export default app; + +export { app, errorHandler }; diff --git a/helpers/mu/sparql-client-2.d.ts b/helpers/mu/sparql-client-2.d.ts new file mode 100644 index 0000000..3888c5a --- /dev/null +++ b/helpers/mu/sparql-client-2.d.ts @@ -0,0 +1 @@ +declare module "sparql-client-2"; diff --git a/helpers/mu/sparql.js b/helpers/mu/sparql.js deleted file mode 100644 index 4a23432..0000000 --- a/helpers/mu/sparql.js +++ /dev/null @@ -1,192 +0,0 @@ -import httpContext from 'express-http-context'; -import SC2 from 'sparql-client-2'; -import env from 'env-var'; - -const { SparqlClient, SPARQL } = SC2; - -const LOG_SPARQL_QUERIES = process.env.LOG_SPARQL_QUERIES != undefined ? env.get('LOG_SPARQL_QUERIES').asBool() : env.get('LOG_SPARQL_ALL').asBool(); -const LOG_SPARQL_UPDATES = process.env.LOG_SPARQL_UPDATES != undefined ? env.get('LOG_SPARQL_UPDATES').asBool() : env.get('LOG_SPARQL_ALL').asBool(); -const DEBUG_AUTH_HEADERS = env.get('DEBUG_AUTH_HEADERS').asBool(); - -//==-- logic --==// - -// builds a new sparqlClient -function newSparqlClient() { - let options = { requestDefaults: { headers: { } } }; - - if (httpContext.get('request')) { - options.requestDefaults.headers['mu-session-id'] = httpContext.get('request').get('mu-session-id'); - options.requestDefaults.headers['mu-call-id'] = httpContext.get('request').get('mu-call-id'); - options.requestDefaults.headers['mu-auth-allowed-groups'] = httpContext.get('request').get('mu-auth-allowed-groups'); // groups of incoming request - } - - if (httpContext.get('response')) { - const allowedGroups = httpContext.get('response').get('mu-auth-allowed-groups'); // groups returned by a previous SPARQL query - if (allowedGroups) - options.requestDefaults.headers['mu-auth-allowed-groups'] = allowedGroups; - } - - if (DEBUG_AUTH_HEADERS) { - console.log(`Headers set on SPARQL client: ${JSON.stringify(options)}`); - } - - return new SparqlClient(process.env.MU_SPARQL_ENDPOINT, options).register({ - mu: 'http://mu.semte.ch/vocabularies/', - muCore: 'http://mu.semte.ch/vocabularies/core/', - muExt: 'http://mu.semte.ch/vocabularies/ext/' - }); -} - -// executes a query (you can use the template syntax) -function query( queryString ) { - if (LOG_SPARQL_QUERIES) { - console.log(queryString); - } - return executeQuery(queryString); -}; - -// executes an update query -function update( queryString ) { - if (LOG_SPARQL_UPDATES) { - console.log(queryString); - } - return executeQuery(queryString); -}; - -function executeQuery( queryString ) { - return newSparqlClient().query(queryString).executeRaw().then(response => { - const temp = httpContext; - if (httpContext.get('response') && !httpContext.get('response').headersSent) { - // set mu-auth-allowed-groups on outgoing response - const allowedGroups = response.headers['mu-auth-allowed-groups']; - if (allowedGroups) { - httpContext.get('response').setHeader('mu-auth-allowed-groups', allowedGroups); - if (DEBUG_AUTH_HEADERS) { - console.log(`Update mu-auth-allowed-groups to ${allowedGroups}`); - } - } else { - httpContext.get('response').removeHeader('mu-auth-allowed-groups'); - if (DEBUG_AUTH_HEADERS) { - console.log('Remove mu-auth-allowed-groups'); - } - } - - // set mu-auth-used-groups on outgoing response - const usedGroups = response.headers['mu-auth-used-groups']; - if (usedGroups) { - httpContext.get('response').setHeader('mu-auth-used-groups', usedGroups); - if (DEBUG_AUTH_HEADERS) { - console.log(`Update mu-auth-used-groups to ${usedGroups}`); - } - } else { - httpContext.get('response').removeHeader('mu-auth-used-groups'); - if (DEBUG_AUTH_HEADERS) { - console.log('Remove mu-auth-used-groups'); - } - } - } - - function maybeParseJSON(body) { - // Catch invalid JSON - try { - return JSON.parse(body); - } catch (ex) { - return null; - } - } - - return maybeParseJSON(response.body); - }); -} - -function sparqlEscapeString( value ){ - return '"""' + value.replace(/[\\"]/g, function(match) { return '\\' + match; }) + '"""'; -}; - -function sparqlEscapeUri( value ){ - return '<' + value.replace(/[\\"<>]/g, function(match) { return '\\' + match; }) + '>'; -}; - -function sparqlEscapeDecimal( value ){ - return '"' + Number.parseFloat(value) + '"^^xsd:decimal'; -}; - -function sparqlEscapeInt( value ){ - return '"' + Number.parseInt(value) + '"^^xsd:integer'; -}; - -function sparqlEscapeFloat( value ){ - return '"' + Number.parseFloat(value) + '"^^xsd:float'; -}; - -function sparqlEscapeDate( value ){ - return '"' + new Date(value).toISOString().substring(0, 10) + '"^^xsd:date'; // only keep 'YYYY-MM-DD' portion of the string -}; - -function sparqlEscapeDateTime( value ){ - return '"' + new Date(value).toISOString() + '"^^xsd:dateTime'; -}; - -function sparqlEscapeBool( value ){ - return value ? '"true"^^xsd:boolean' : '"false"^^xsd:boolean'; -}; - -function sparqlEscape( value, type ){ - switch(type) { - case 'string': - return sparqlEscapeString(value); - case 'uri': - return sparqlEscapeUri(value); - case 'bool': - return sparqlEscapeBool(value); - case 'decimal': - return sparqlEscapeDecimal(value); - case 'int': - return sparqlEscapeInt(value); - case 'float': - return sparqlEscapeFloat(value); - case 'date': - return sparqlEscapeDate(value); - case 'dateTime': - return sparqlEscapeDateTime(value); - default: - console.error(`WARN: Unknown escape type '${type}'. Escaping as string`); - return sparqlEscapeString(value); - } -} - -//==-- exports --==// -const exports = { - newSparqlClient: newSparqlClient, - SPARQL: SPARQL, - sparql: SPARQL, - query: query, - update: update, - sparqlEscape: sparqlEscape, - sparqlEscapeString: sparqlEscapeString, - sparqlEscapeUri: sparqlEscapeUri, - sparqlEscapeInt: sparqlEscapeInt, - sparqlEscapeFloat: sparqlEscapeFloat, - sparqlEscapeDate: sparqlEscapeDate, - sparqlEscapeDateTime: sparqlEscapeDateTime, - sparqlEscapeBool: sparqlEscapeBool -} -export default exports; - -export { - newSparqlClient, - SPARQL as SPARQL, - SPARQL as sparql, - query, - update, - sparqlEscape, - sparqlEscapeString, - sparqlEscapeUri, - sparqlEscapeDecimal, - sparqlEscapeInt, - sparqlEscapeFloat, - sparqlEscapeDate, - sparqlEscapeDateTime, - sparqlEscapeBool -}; - diff --git a/helpers/mu/sparql.ts b/helpers/mu/sparql.ts new file mode 100644 index 0000000..d6b1ce6 --- /dev/null +++ b/helpers/mu/sparql.ts @@ -0,0 +1,227 @@ +import httpContext from "express-http-context"; +import SC2 from "sparql-client-2"; +import env from "env-var"; + +const { SparqlClient, SPARQL } = SC2; + +const LOG_SPARQL_QUERIES = + process.env.LOG_SPARQL_QUERIES != undefined + ? env.get("LOG_SPARQL_QUERIES").asBool() + : env.get("LOG_SPARQL_ALL").asBool(); +const LOG_SPARQL_UPDATES = + process.env.LOG_SPARQL_UPDATES != undefined + ? env.get("LOG_SPARQL_UPDATES").asBool() + : env.get("LOG_SPARQL_ALL").asBool(); +const DEBUG_AUTH_HEADERS = env.get("DEBUG_AUTH_HEADERS").asBool(); + +//==-- logic --==// + +// builds a new sparqlClient +function newSparqlClient() { + let options = { requestDefaults: { headers: {} as Record } }; + + if (httpContext.get("request")) { + options.requestDefaults.headers["mu-session-id"] = httpContext + .get("request") + .get("mu-session-id"); + options.requestDefaults.headers["mu-call-id"] = httpContext + .get("request") + .get("mu-call-id"); + options.requestDefaults.headers["mu-auth-allowed-groups"] = httpContext + .get("request") + .get("mu-auth-allowed-groups"); // groups of incoming request + } + + if (httpContext.get("response")) { + const allowedGroups = httpContext + .get("response") + .get("mu-auth-allowed-groups"); // groups returned by a previous SPARQL query + if (allowedGroups) + options.requestDefaults.headers["mu-auth-allowed-groups"] = allowedGroups; + } + + if (DEBUG_AUTH_HEADERS) { + console.log(`Headers set on SPARQL client: ${JSON.stringify(options)}`); + } + + return new SparqlClient(process.env.MU_SPARQL_ENDPOINT, options).register({ + mu: "http://mu.semte.ch/vocabularies/", + muCore: "http://mu.semte.ch/vocabularies/core/", + muExt: "http://mu.semte.ch/vocabularies/ext/", + }); +} + +// executes a query (you can use the template syntax) +function query(queryString: string) { + if (LOG_SPARQL_QUERIES) { + console.log(queryString); + } + return executeQuery(queryString); +} + +// executes an update query +function update(queryString: string) { + if (LOG_SPARQL_UPDATES) { + console.log(queryString); + } + return executeQuery(queryString); +} + +function executeQuery(queryString: string) { + return newSparqlClient() + .query(queryString) + .executeRaw() + .then((response: any) => { + const temp = httpContext; + if ( + httpContext.get("response") && + !httpContext.get("response").headersSent + ) { + // set mu-auth-allowed-groups on outgoing response + const allowedGroups = response.headers["mu-auth-allowed-groups"]; + if (allowedGroups) { + httpContext + .get("response") + .setHeader("mu-auth-allowed-groups", allowedGroups); + if (DEBUG_AUTH_HEADERS) { + console.log(`Update mu-auth-allowed-groups to ${allowedGroups}`); + } + } else { + httpContext.get("response").removeHeader("mu-auth-allowed-groups"); + if (DEBUG_AUTH_HEADERS) { + console.log("Remove mu-auth-allowed-groups"); + } + } + + // set mu-auth-used-groups on outgoing response + const usedGroups = response.headers["mu-auth-used-groups"]; + if (usedGroups) { + httpContext + .get("response") + .setHeader("mu-auth-used-groups", usedGroups); + if (DEBUG_AUTH_HEADERS) { + console.log(`Update mu-auth-used-groups to ${usedGroups}`); + } + } else { + httpContext.get("response").removeHeader("mu-auth-used-groups"); + if (DEBUG_AUTH_HEADERS) { + console.log("Remove mu-auth-used-groups"); + } + } + } + + function maybeParseJSON(body: any) { + // Catch invalid JSON + try { + return JSON.parse(body); + } catch (ex) { + return null; + } + } + + return maybeParseJSON(response.body); + }); +} + +function sparqlEscapeString(value: string) { + return ( + '"""' + + value.replace(/[\\"]/g, function (match) { + return "\\" + match; + }) + + '"""' + ); +} + +function sparqlEscapeUri(value: string) { + return ( + "<" + + value.replace(/[\\"<>]/g, function (match) { + return "\\" + match; + }) + + ">" + ); +} + +function sparqlEscapeDecimal(value: number | string) { + return '"' + Number.parseFloat(`${value}`) + '"^^xsd:decimal'; +} + +function sparqlEscapeInt(value: number | string) { + return '"' + Number.parseInt(`${value}`) + '"^^xsd:integer'; +} + +function sparqlEscapeFloat(value: number | string) { + return '"' + Number.parseFloat(`${value}`) + '"^^xsd:float'; +} + +function sparqlEscapeDate(value: string | Date) { + return '"' + new Date(value).toISOString().substring(0, 10) + '"^^xsd:date'; // only keep 'YYYY-MM-DD' portion of the string +} + +function sparqlEscapeDateTime(value: string | Date) { + return '"' + new Date(value).toISOString() + '"^^xsd:dateTime'; +} + +function sparqlEscapeBool(value: boolean | null | undefined) { + return value ? '"true"^^xsd:boolean' : '"false"^^xsd:boolean'; +} + +function sparqlEscape(value: any, type: string) { + switch (type) { + case "string": + return sparqlEscapeString(value); + case "uri": + return sparqlEscapeUri(value); + case "bool": + return sparqlEscapeBool(value); + case "decimal": + return sparqlEscapeDecimal(value); + case "int": + return sparqlEscapeInt(value); + case "float": + return sparqlEscapeFloat(value); + case "date": + return sparqlEscapeDate(value); + case "dateTime": + return sparqlEscapeDateTime(value); + default: + console.error(`WARN: Unknown escape type '${type}'. Escaping as string`); + return sparqlEscapeString(value); + } +} + +const defaultExports = { + newSparqlClient: newSparqlClient, + SPARQL: SPARQL, + sparql: SPARQL, + query: query, + update: update, + sparqlEscape: sparqlEscape, + sparqlEscapeString: sparqlEscapeString, + sparqlEscapeUri: sparqlEscapeUri, + sparqlEscapeInt: sparqlEscapeInt, + sparqlEscapeFloat: sparqlEscapeFloat, + sparqlEscapeDecimal: sparqlEscapeDecimal, + sparqlEscapeDate: sparqlEscapeDate, + sparqlEscapeDateTime: sparqlEscapeDateTime, + sparqlEscapeBool: sparqlEscapeBool, +}; +export default defaultExports; + +export { + newSparqlClient, + SPARQL as SPARQL, + SPARQL as sparql, + query, + update, + sparqlEscape, + sparqlEscapeString, + sparqlEscapeUri, + sparqlEscapeDecimal, + sparqlEscapeInt, + sparqlEscapeFloat, + sparqlEscapeDate, + sparqlEscapeDateTime, + sparqlEscapeBool, +}; diff --git a/helpers/package-lock.json b/helpers/package-lock.json new file mode 100644 index 0000000..89b1b5c --- /dev/null +++ b/helpers/package-lock.json @@ -0,0 +1,1321 @@ +{ + "name": "works-ts-helpers", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "works-ts-helpers", + "version": "0.0.1", + "license": "ISC", + "dependencies": { + "body-parser": "~1.20.1", + "env-var": "^7.4.1", + "express": "^4.18.2", + "express-http-context": "~1.2.4", + "sparql-client-2": "^0.6.3", + "uuid": "^9.0.1" + }, + "devDependencies": { + "@types/uuid": "^9.0.7", + "typescript": "^5.3.3" + } + }, + "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==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cls-hooked": { + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/@types/cls-hooked/-/cls-hooked-4.3.8.tgz", + "integrity": "sha512-tf/7H883gFA6MPlWI15EQtfNZ+oPL0gLKkOlx9UHFrun1fC/FkuyNBpTKq1B5E3T4fbvjId6WifHUdSGsMMuPg==", + "dependencies": { + "@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==", + "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==", + "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.17.41", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", + "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", + "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==" + }, + "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==" + }, + "node_modules/@types/node": { + "version": "20.10.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", + "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/qs": { + "version": "6.9.10", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz", + "integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==" + }, + "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==" + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", + "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/uuid": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", + "integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==", + "dev": true + }, + "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==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "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==" + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/async-hook-jl": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/async-hook-jl/-/async-hook-jl-1.7.6.tgz", + "integrity": "sha512-gFaHkFfSxTjvoxDMYqDuGHlcRyUuamF8s+ZTtJdDzqjws4mCt7v0vuV79/E2Wr2/riMQgtG4/yUtXWs1gZ7JMg==", + "dependencies": { + "stack-chain": "^1.3.7" + }, + "engines": { + "node": "^4.7 || >=6.9 || >=7.3" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "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.11.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/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dependencies": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + }, + "node_modules/cls-hooked": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/cls-hooked/-/cls-hooked-4.2.2.tgz", + "integrity": "sha512-J4Xj5f5wq/4jAvcdgoGsL3G103BtWpZrMo8NEinRltN+xpTZdI+M38pyQqhuFU/P792xkMFvnKSf+Lm81U1bxw==", + "dependencies": { + "async-hook-jl": "^1.7.6", + "emitter-listener": "^1.0.1", + "semver": "^5.4.1" + }, + "engines": { + "node": "^4.7 || >=6.9 || >=7.3 || >=8.2.1" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "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==", + "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==", + "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==", + "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==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denodeify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", + "integrity": "sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg==" + }, + "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==", + "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==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "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==" + }, + "node_modules/emitter-listener": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", + "integrity": "sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ==", + "dependencies": { + "shimmer": "^1.2.0" + } + }, + "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==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/env-var": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/env-var/-/env-var-7.4.1.tgz", + "integrity": "sha512-H8Ga2SbXTQwt6MKEawWSvmxoH1+J6bnAXkuyE7eDvbGmrhIL2i+XGjzGM3DFHcJu8GY1zY9/AnBJY8uGQYPHiw==", + "engines": { + "node": ">=10" + } + }, + "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==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "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-http-context": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/express-http-context/-/express-http-context-1.2.4.tgz", + "integrity": "sha512-jPpBbF1MWWdRcUU1rxsX0CPnA8ueEj8xgWvpRGHoXWGI4l5KqhPY4Bq+Gt6s2IhqHQQ0g0wIvJ3jFfbUuJJycQ==", + "dependencies": { + "@types/cls-hooked": "^4.2.1", + "@types/express": "^4.16.0", + "cls-hooked": "^4.2.2" + }, + "engines": { + "node": ">=8.0.0 <10.0.0 || >=10.4.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==", + "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/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==", + "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/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "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/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "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==", + "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==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "dependencies": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "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==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "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==", + "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/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "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==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "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==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "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==", + "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==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "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==", + "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==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "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==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "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==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "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==" + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "node_modules/promise-nodeify": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/promise-nodeify/-/promise-nodeify-0.1.0.tgz", + "integrity": "sha512-DfFqhZ0M1bZwLighBvNHWxTy/LRvmZfbWE7/NKdPf1cUQzXzgzOAmp8VMCxcjZyoAZHYH+b10xeB5AkviOh0gw==", + "engines": { + "node": ">=0.10", + "npm": ">=1.3.7" + } + }, + "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==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "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==", + "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==", + "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/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "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" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "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/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "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==", + "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.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "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==" + }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sparql-client-2": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/sparql-client-2/-/sparql-client-2-0.6.3.tgz", + "integrity": "sha512-wG2bYg5mkEb3DWLPVrVC7W7rkNnbzz+CeItHvhZuZHWE69JSYAYr/bz51tCmeePGQMzcBl2+k+qcG7sgFtGYbw==", + "dependencies": { + "denodeify": "^1.2.1", + "lodash": "^4.0.1", + "promise-nodeify": "^0.1.0", + "request": "^2.40.0" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stack-chain": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-1.3.7.tgz", + "integrity": "sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug==" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "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==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, + "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==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "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==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "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==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + } + } +} diff --git a/helpers/package.json b/helpers/package.json new file mode 100644 index 0000000..6d58bc0 --- /dev/null +++ b/helpers/package.json @@ -0,0 +1,27 @@ +{ + "name": "works-ts-helpers", + "version": "0.0.1", + "description": "", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "tsc" + }, + "main": "dist/index.js", + "types": "dist/index.d.ts", + "type": "commonjs", + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@types/uuid": "^9.0.7", + "typescript": "^5.3.3" + }, + "dependencies": { + "env-var": "^7.4.1", + "express": "^4.18.2", + "express-http-context": "~1.2.4", + "sparql-client-2": "^0.6.3", + "body-parser": "~1.20.1", + "uuid": "^9.0.1" + } +} diff --git a/helpers/tsconfig.json b/helpers/tsconfig.json new file mode 100644 index 0000000..b281c59 --- /dev/null +++ b/helpers/tsconfig.json @@ -0,0 +1,26 @@ +{ + "include": ["mu/**/*"], + // We don't need to transpile these directories + "exclude": ["node_modules", "dist"], + "compilerOptions": { + // Tells TypeScript to read JS files, as + // normally they are ignored as source files + "allowJs": false, + // Generate d.ts files + "declaration": true, + // This compiler run should + // only output d.ts files + "emitDeclarationOnly": false, + // Types should go into this directory. + // Removing this would place the .d.ts files + // next to the .js files + "outDir": "dist", + // go to js file when using IDE functions like + // "Go to Definition" in VSCode + "declarationMap": true, + "strict": true, + "esModuleInterop": true, + "moduleResolution": "Node", + "module": "commonjs" + } +} diff --git a/package.json b/package.json index 7148a03..d3db713 100644 --- a/package.json +++ b/package.json @@ -20,12 +20,12 @@ "body-parser": "~1.20.1", "coffeescript": "^2.6.1", "env-var": "^7.0.0", - "express": "^4.17.1", + "express": "^4.18.2", "express-http-context": "~1.2.4", "nodemon": "^2.0.20", "sparql-client-2": "https://github.com/erikap/node-sparql-client.git", - "typescript": "^4.6.2", - "uuid": "^9.0.0" + "typescript": "^5.3.3", + "uuid": "^9.0.1" }, "author": "Aad Versteden ", "license": "MIT", diff --git a/run-development.sh b/run-development.sh index f823f79..460b66d 100755 --- a/run-development.sh +++ b/run-development.sh @@ -67,4 +67,5 @@ fi cd /usr/src/build/ /usr/src/app/node_modules/.bin/babel-node \ --inspect="0.0.0.0:9229" \ + --enable-source-maps \ ./app.js diff --git a/transpile-sources.sh b/transpile-sources.sh index d990c1b..a7ad79e 100755 --- a/transpile-sources.sh +++ b/transpile-sources.sh @@ -56,12 +56,19 @@ cp -R ./app/* build docker-rsync /usr/src/processing/coffeescript-transpilation/ /usr/src/processing/build/ +echo "build:" +mkdir -p temp/app/app +mv ./build/* ./temp/app/app/ + + /usr/src/app/node_modules/.bin/babel \ - ./build/ \ - --out-dir ./typescript-transpilation/ \ - --source-maps true \ + ./temp/app/app/ \ + --out-dir ./temp/typescript-transpilation/ \ + --source-maps "both" \ --extensions ".ts,.js" +mv ./temp/typescript-transpilation/* ./typescript-transpilation/ + rm -Rf ./build mv typescript-transpilation /usr/src/build @@ -92,9 +99,9 @@ cd /usr/src/processing/ mkdir /usr/src/processing/built-mu /usr/src/app/node_modules/.bin/babel \ /usr/src/processing/helpers/mu/ \ - --source-maps true \ + --source-maps "both" \ --out-dir /usr/src/processing/built-mu \ - --extensions ".js" + --extensions ".js,.ts" cp -R /usr/src/processing/built-mu /usr/src/build/node_modules/mu From 41b23491a6b4c32268cc99d41f05906b6b5c81ba Mon Sep 17 00:00:00 2001 From: Karel Kremer Date: Mon, 25 Dec 2023 10:42:50 +0100 Subject: [PATCH 2/9] run with node, remove other changes to transpile for now --- run-development.sh | 5 +++-- transpile-sources.sh | 17 +++++------------ 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/run-development.sh b/run-development.sh index 460b66d..a79f387 100755 --- a/run-development.sh +++ b/run-development.sh @@ -58,6 +58,8 @@ fi ./transpile-sources.sh +docker-rsync --include="*/" --include="*.ts" --include="*.coffee" --exclude="*" /app/ /usr/src/build/ + ############## @@ -65,7 +67,6 @@ fi ############## cd /usr/src/build/ -/usr/src/app/node_modules/.bin/babel-node \ +node \ --inspect="0.0.0.0:9229" \ - --enable-source-maps \ ./app.js diff --git a/transpile-sources.sh b/transpile-sources.sh index a7ad79e..d89e4dc 100755 --- a/transpile-sources.sh +++ b/transpile-sources.sh @@ -56,19 +56,12 @@ cp -R ./app/* build docker-rsync /usr/src/processing/coffeescript-transpilation/ /usr/src/processing/build/ -echo "build:" -mkdir -p temp/app/app -mv ./build/* ./temp/app/app/ - - /usr/src/app/node_modules/.bin/babel \ - ./temp/app/app/ \ - --out-dir ./temp/typescript-transpilation/ \ - --source-maps "both" \ + ./build/ \ + --out-dir ./typescript-transpilation/ \ + --source-maps "true" \ --extensions ".ts,.js" -mv ./temp/typescript-transpilation/* ./typescript-transpilation/ - rm -Rf ./build mv typescript-transpilation /usr/src/build @@ -99,7 +92,7 @@ cd /usr/src/processing/ mkdir /usr/src/processing/built-mu /usr/src/app/node_modules/.bin/babel \ /usr/src/processing/helpers/mu/ \ - --source-maps "both" \ + --source-maps "true" \ --out-dir /usr/src/processing/built-mu \ --extensions ".js,.ts" @@ -112,4 +105,4 @@ cp -R /usr/src/processing/built-mu /usr/src/build/node_modules/mu ## We have created garbage, let's remove it cd /usr/src/ -rm -Rf /usr/src/processing +#rm -Rf /usr/src/processing From a0029d26bcfe163ba8c2fbe00bd3fec50c0f02d8 Mon Sep 17 00:00:00 2001 From: Karel Kremer Date: Mon, 25 Dec 2023 13:58:50 +0100 Subject: [PATCH 3/9] WIP: working typescript compilation and breakpoints --- Dockerfile | 31 +++++----- boot.sh | 10 ++-- build-production.sh | 15 ++--- build-template-package.sh | 9 +++ run-development.sh | 43 ++++---------- transpile-sources.sh | 120 ++++++++++++-------------------------- 6 files changed, 88 insertions(+), 140 deletions(-) create mode 100644 build-template-package.sh diff --git a/Dockerfile b/Dockerfile index b6ef318..1c65e5a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,26 +14,29 @@ ENV PORT '80' ENV LOG_SPARQL_ALL 'true' ENV DEBUG_AUTH_HEADERS 'true' -WORKDIR /usr/src/app -COPY package.json /usr/src/app/package.json -COPY ./scripts /app/scripts -RUN npm install -COPY . /usr/src/app -RUN chmod +x /usr/src/app/run-development.sh -RUN chmod +x /usr/src/app/build-production.sh +WORKDIR /app +RUN mkdir /template && mkdir -p /app/src +COPY package.json /template/package.json +COPY ./scripts /template/scripts +RUN cd /template && npm install +COPY . /template +RUN chmod +x /template/run-development.sh +RUN chmod +x /template/build-production.sh +RUN chmod +x /template/build-template-package.sh +RUN /template/build-template-package.sh EXPOSE ${PORT} -CMD bash boot.sh +CMD bash /template/boot.sh # This stuff only runs when building an image from the template -ONBUILD RUN rm -Rf /app/scripts -ONBUILD ADD . /app/ -ONBUILD RUN /usr/src/app/build-production.sh +ONBUILD RUN rm -Rf /app/src/scripts +ONBUILD ADD . /app/src +ONBUILD RUN /template/build-production.sh -ONBUILD RUN if [ -f /app/on-build.sh ]; \ +ONBUILD RUN if [ -f /app/src/on-build.sh ]; \ then \ echo "Running custom on-build.sh of child" \ - && chmod +x /app/on-build.sh \ - && /bin/bash /app/on-build.sh ;\ + && chmod +x /app/src/on-build.sh \ + && /bin/bash /app/src/on-build.sh ;\ fi diff --git a/boot.sh b/boot.sh index c39f0b9..018e187 100755 --- a/boot.sh +++ b/boot.sh @@ -2,11 +2,11 @@ if [ "$NODE_ENV" == "development" ] then # Run live-reload development - exec /usr/src/app/node_modules/.bin/nodemon \ - --watch /app \ + exec /template/node_modules/.bin/nodemon \ + --watch /app/src \ --watch /config \ --ext js,coffee,ts,mjs,cjs,json \ - --exec /usr/src/app/run-development.sh + --exec /template/run-development.sh elif [ "$NODE_ENV" == "production" ] then diff -rq /app /app.original > /dev/null @@ -14,7 +14,7 @@ then diff -rq /config /config.original > /dev/null CONFIG_FILES_CHANGED="$?" - if [ ! -f /usr/src/build/app.js ] + if [ ! -f /app/dist/app.js ] then echo "No built sources found. If you mount new sources, please set the NODE_ENV=\"development\" environment variable." sleep 5; @@ -28,7 +28,7 @@ then then echo "Rebuilding sources to include /config." - # move new configuration into app for transpilation + # move new configuration into app for transpilation TODO:karel what happens with config? if [[ "$(ls -A /config 2> /dev/null)" ]] then cp -Rf /config/* /usr/src/app/app/config/ diff --git a/build-production.sh b/build-production.sh index 33517d7..b8477e4 100755 --- a/build-production.sh +++ b/build-production.sh @@ -2,14 +2,15 @@ # Builds sources in production # -# We want to compare the used sources from the one available in /app +# We want to compare the used sources from the one available in /source # so we can warn at runtime in case developers accidentally mount # sources without setting the development environment variable. # Copy sources from /app to where they can be built -cd /usr/src/app -rm -rf ./app /app.original -cp -r /app ./ +cd /app +rm -rf /build +mkdir /build +cp -r /app /build mkdir -p /config /config.original @@ -22,12 +23,12 @@ fi cp -r /app /app.original # Install custom packages if need be -if [ -f ./app/package.json ] +if [ -f /build/package.json ] then echo "Running npm install" - cd /usr/src/app/app/ + cd /build/ npm install - cd /usr/src/app/ + cd /build/ fi ./transpile-sources.sh diff --git a/build-template-package.sh b/build-template-package.sh new file mode 100644 index 0000000..01143b3 --- /dev/null +++ b/build-template-package.sh @@ -0,0 +1,9 @@ +mkdir /template/built-mu +cd /template +/template/node_modules/.bin/babel \ + /template/helpers/mu/ \ + --source-maps "true" \ + --out-dir /template/built-mu \ + --extensions ".js,.ts" + +cp -R /template/built-mu /template/node_modules/mu diff --git a/run-development.sh b/run-development.sh index a79f387..2b4ce2a 100755 --- a/run-development.sh +++ b/run-development.sh @@ -1,6 +1,6 @@ #!/bin/bash -source ./helpers.sh +source /template/helpers.sh # We want to run from /app but don't want to touch that folder. # @@ -11,7 +11,7 @@ source ./helpers.sh # - Only run npm install when the package.json has changed. # Move to right folder -cd /usr/src/app/ +cd /app/ @@ -20,53 +20,34 @@ cd /usr/src/app/ ###################### ## Check if package.json existed and did not change since previous build (/usr/src/app/app/ is copied later in this script, at first run from the template itself it doesn't exist but that's fine for comparison) -cmp -s /app/package.json /usr/src/app/app/package.json +cmp -s /check/package.json /app/src/package.json CHANGE_IN_PACKAGE_JSON="$?" -## Ensure we _sync_ the sources from the hosted app and _copy_ the node_modules. -## -## We don't want to do --delete on the node_modules because this allows us -## to depend on the node_modules installed in an earlier update cycle as well as -## taking node_modules from the hosted app into account. -docker-rsync --delete --exclude node_modules /app/ /usr/src/app/app/ -if [ -d /app/node_modules/ ] -then - docker-rsync /app/node_modules /usr/src/app/app/ -fi - -## Copy config folder -if [[ "$(ls -A /config/ 2> /dev/null)" ]] -then - mkdir -p ./app/config/ - cp -rf /config/* ./app/config/ -fi - ## Install dependencies on first boot -if [ $CHANGE_IN_PACKAGE_JSON != "0" ] && [ -f ./app/package.json ] +if [ $CHANGE_IN_PACKAGE_JSON != "0" ] && [ -f /app/src/package.json ] then echo "Running npm install" - cd /usr/src/app/app/ + cp /app/src/package.json /app/package.json npm install - cd /usr/src/app/ + rm -rf /check + mkdir /check + cp /app/src/package.json /check/package.json fi - +docker-rsync /template/node_modules/ /app/node_modules/ ############### # Transpilation ############### -./transpile-sources.sh - -docker-rsync --include="*/" --include="*.ts" --include="*.coffee" --exclude="*" /app/ /usr/src/build/ - +/template/transpile-sources.sh ############## # Start server ############## -cd /usr/src/build/ +cd /app/ node \ --inspect="0.0.0.0:9229" \ - ./app.js + ./dist/app.js diff --git a/transpile-sources.sh b/transpile-sources.sh index d89e4dc..492a4cc 100755 --- a/transpile-sources.sh +++ b/transpile-sources.sh @@ -1,6 +1,6 @@ #!/bin/bash -source ./helpers.sh +source /template/helpers.sh #### #### BUILDS SOURCES @@ -9,100 +9,54 @@ source ./helpers.sh #### /usr/src/app/app/ and stores the resulting build in /usr/src/build # Clean starting state -rm -Rf /usr/src/processing /usr/src/build +# rm -Rf /processing /dist -# Copy template (/usr/src/app/) and app (/usr/src/app/app/) sources -# without package.json, which we want to skip as it would conflict -# building sources. +# # Copy template (/usr/src/app/) and app (/usr/src/app/app/) sources +# # without package.json, which we want to skip as it would conflict +# # building sources. -cp -R /usr/src/app /usr/src/processing -rm -f /usr/src/processing/app/package.json +# cp -R /template /processing +# rm -f /processing/app/package.json -## CoffeeScript -## -## Coffeescript is transpiled ready for nodejs. This is then moved into -## app so we have the javascript available which other preprocessors may -## expect to exist. -## -## In order to generate the sourcemaps correctly, it seems we have to be -## next to the folder where we want the sources to land, but in order to -## transpile correctly we also need the node_modules for babel and the -## babelrc file. We temporarily move those around. - -cd /usr/src/ +# ## CoffeeScript +# ## +# ## Coffeescript is transpiled ready for nodejs. This is then moved into +# ## app so we have the javascript available which other preprocessors may +# ## expect to exist. +# ## +# ## In order to generate the sourcemaps correctly, it seems we have to be +# ## next to the folder where we want the sources to land, but in order to +# ## transpile correctly we also need the node_modules for babel and the +# ## babelrc file. We temporarily move those around. -# prepare the build folders -mkdir /usr/src/build /usr/src/build.coffee -cp -R /usr/src/processing/app/* /usr/src/build/ -cp /usr/src/processing/babel.config.json /usr/src/ -cp -R /usr/src/processing/node_modules/ /usr/src/ +# # prepare the build folders +# mkdir /dist /build.coffee +# cp -R /processing/app/* /usr/src/build/ +# cp /usr/src/processing/babel.config.json /usr/src/ +# cp -R /usr/src/processing/node_modules/ /usr/src/ -# make the build and move to coffeescript-transpilation -/usr/src/app/node_modules/.bin/coffee -M -m --compile -t --output ./build.coffee/ ./build -mv build.coffee/ /usr/src/processing/coffeescript-transpilation +# # make the build and move to coffeescript-transpilation +# /usr/src/app/node_modules/.bin/coffee -M -m --compile -t --output ./build.coffee/ ./build +# mv build.coffee/ /usr/src/processing/coffeescript-transpilation -# clean up -rm -Rf /usr/src/build /usr/src/node_modules/ -rm /usr/src/babel.config.json +# # clean up +# rm -Rf /usr/src/build /usr/src/node_modules/ +# rm /usr/src/babel.config.json ## TypeScript and ES6 ## ## Transpiles TypeScript and ES6 to something nodejs wants to run. -cd /usr/src/processing/ - -mkdir typescript-transpilation build -cp -R ./app/* build - -docker-rsync /usr/src/processing/coffeescript-transpilation/ /usr/src/processing/build/ +cd /template -/usr/src/app/node_modules/.bin/babel \ - ./build/ \ - --out-dir ./typescript-transpilation/ \ +/template/node_modules/.bin/babel \ + /app/src \ + --out-dir /app/dist/ \ --source-maps "true" \ --extensions ".ts,.js" -rm -Rf ./build -mv typescript-transpilation /usr/src/build - -# We move the coffeescript files again because the previous step will -# have built the sources coffeescript generated, but these sources were -# already node compliant. We could make coffeescript emit ES6 and -# transpile them to nodejs in this step, but that breaks SourceMaps. -docker-rsync /usr/src/processing/coffeescript-transpilation/ /usr/src/build/ - - -############## -# Node modules -############## -cd /usr/src/processing/ - -## template modules -cp -R /usr/src/processing/node_modules /usr/src/build/ - -## app modules -if [ -d /usr/src/processing/app/node_modules ] -then - docker-rsync /usr/src/processing/app/node_modules /usr/src/build/ -fi - -## mu helpers -cd /usr/src/processing/ - -mkdir /usr/src/processing/built-mu -/usr/src/app/node_modules/.bin/babel \ - /usr/src/processing/helpers/mu/ \ - --source-maps "true" \ - --out-dir /usr/src/processing/built-mu \ - --extensions ".js,.ts" - -cp -R /usr/src/processing/built-mu /usr/src/build/node_modules/mu - - - -## Clean temporary folders -## -## We have created garbage, let's remove it -cd /usr/src/ - -#rm -Rf /usr/src/processing +# # We move the coffeescript files again because the previous step will +# # have built the sources coffeescript generated, but these sources were +# # already node compliant. We could make coffeescript emit ES6 and +# # transpile them to nodejs in this step, but that breaks SourceMaps. +# docker-rsync /usr/src/processing/coffeescript-transpilation/ /usr/src/build/ From 3fb6afcd3de20bd7f3a66d1d0c2fa72ffcbc1f1f Mon Sep 17 00:00:00 2001 From: Karel Kremer Date: Mon, 25 Dec 2023 14:04:37 +0100 Subject: [PATCH 4/9] ignore dist folder in nodemon --- boot.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/boot.sh b/boot.sh index 018e187..f18390d 100755 --- a/boot.sh +++ b/boot.sh @@ -5,6 +5,7 @@ then exec /template/node_modules/.bin/nodemon \ --watch /app/src \ --watch /config \ + --ignore /app/src/dist \ --ext js,coffee,ts,mjs,cjs,json \ --exec /template/run-development.sh elif [ "$NODE_ENV" == "production" ] From edfd97e7bb5bf35d97b0162c41959b37df2e06ed Mon Sep 17 00:00:00 2001 From: Karel Kremer Date: Mon, 25 Dec 2023 16:05:41 +0100 Subject: [PATCH 5/9] working for node_env production --- boot.sh | 24 ++++++++++++++++-------- build-production.sh | 18 ++++++++++-------- run-development.sh | 7 +++++++ 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/boot.sh b/boot.sh index f18390d..0ad493f 100755 --- a/boot.sh +++ b/boot.sh @@ -1,3 +1,5 @@ +source /template/helpers.sh + #!/bin/bash if [ "$NODE_ENV" == "development" ] then @@ -10,7 +12,8 @@ then --exec /template/run-development.sh elif [ "$NODE_ENV" == "production" ] then - diff -rq /app /app.original > /dev/null + # diff but accept items created during build process + diff -x 'dist*' -x "node_modules" -x "package-lock.json" -x "package.json" -rq /app /app.original > /dev/null APP_FILES_CHANGED="$?" diff -rq /config /config.original > /dev/null CONFIG_FILES_CHANGED="$?" @@ -29,10 +32,10 @@ then then echo "Rebuilding sources to include /config." - # move new configuration into app for transpilation TODO:karel what happens with config? + # move new configuration into app for transpilation if [[ "$(ls -A /config 2> /dev/null)" ]] then - cp -Rf /config/* /usr/src/app/app/config/ + cp -Rf /config/* /app/src/config/ fi # make a backup of the used configuration so we can detect changes @@ -44,14 +47,19 @@ then fi # transpile sources - cd /usr/src/app/ + cd /app/ + + # add node modules from template back in + docker-rsync /template/node_modules/ /app/node_modules/ ./transpile-sources.sh # boot transpiled sources - cd /usr/src/build/ - exec node ./app.js + cd /app/ + exec node /app/dist/app.js else - cd /usr/src/build/ - exec node ./app.js + cd /app/ + # add node modules from template back in + docker-rsync /template/node_modules/ /app/node_modules/ + exec node /app/dist/app.js fi fi diff --git a/build-production.sh b/build-production.sh index b8477e4..9598030 100755 --- a/build-production.sh +++ b/build-production.sh @@ -2,15 +2,14 @@ # Builds sources in production # -# We want to compare the used sources from the one available in /source +# We want to compare the used sources from the one available in /app/src/ # so we can warn at runtime in case developers accidentally mount # sources without setting the development environment variable. # Copy sources from /app to where they can be built cd /app -rm -rf /build -mkdir /build -cp -r /app /build +rm -rf /app/dist +mkdir /app/dist mkdir -p /config /config.original @@ -23,12 +22,15 @@ fi cp -r /app /app.original # Install custom packages if need be -if [ -f /build/package.json ] +if [ -f /app/src/package.json ] then echo "Running npm install" - cd /build/ + cd /app/ + cp /app/src/package.json /app/package.json npm install - cd /build/ fi -./transpile-sources.sh +# add node modules from template back in +docker-rsync /template/node_modules/ /app/node_modules/ + +/template/transpile-sources.sh diff --git a/run-development.sh b/run-development.sh index 2b4ce2a..679641d 100755 --- a/run-development.sh +++ b/run-development.sh @@ -23,6 +23,13 @@ cd /app/ cmp -s /check/package.json /app/src/package.json CHANGE_IN_PACKAGE_JSON="$?" +## Copy config folder +if [[ "$(ls -A /config/ 2> /dev/null)" ]] +then + mkdir -p /app/src/config/ + cp -rf /config/* /app/src/config/ +fi + ## Install dependencies on first boot if [ $CHANGE_IN_PACKAGE_JSON != "0" ] && [ -f /app/src/package.json ] then From 154e9a23c16182cd57c9bf2516b91bd7ce474cba Mon Sep 17 00:00:00 2001 From: Karel Kremer Date: Mon, 25 Dec 2023 16:22:12 +0100 Subject: [PATCH 6/9] production mode with config js --- boot.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot.sh b/boot.sh index 0ad493f..ce3c5e4 100755 --- a/boot.sh +++ b/boot.sh @@ -35,6 +35,7 @@ then # move new configuration into app for transpilation if [[ "$(ls -A /config 2> /dev/null)" ]] then + mkdir -p /app/src/config/ cp -Rf /config/* /app/src/config/ fi @@ -51,7 +52,7 @@ then # add node modules from template back in docker-rsync /template/node_modules/ /app/node_modules/ - ./transpile-sources.sh + /template/transpile-sources.sh # boot transpiled sources cd /app/ From 79a38cc2fb181ec39ec1dc6184404ddd0cae2ff4 Mon Sep 17 00:00:00 2001 From: Karel Kremer Date: Tue, 26 Dec 2023 15:08:38 +0100 Subject: [PATCH 7/9] working coffeescript + typescript combo in production mode --- transpile-sources.sh | 47 +++++++++++++++----------------------------- 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/transpile-sources.sh b/transpile-sources.sh index 492a4cc..54fa04e 100755 --- a/transpile-sources.sh +++ b/transpile-sources.sh @@ -19,44 +19,29 @@ source /template/helpers.sh # rm -f /processing/app/package.json -# ## CoffeeScript -# ## -# ## Coffeescript is transpiled ready for nodejs. This is then moved into -# ## app so we have the javascript available which other preprocessors may -# ## expect to exist. -# ## -# ## In order to generate the sourcemaps correctly, it seems we have to be -# ## next to the folder where we want the sources to land, but in order to -# ## transpile correctly we also need the node_modules for babel and the -# ## babelrc file. We temporarily move those around. - -# # prepare the build folders -# mkdir /dist /build.coffee -# cp -R /processing/app/* /usr/src/build/ -# cp /usr/src/processing/babel.config.json /usr/src/ -# cp -R /usr/src/processing/node_modules/ /usr/src/ - -# # make the build and move to coffeescript-transpilation -# /usr/src/app/node_modules/.bin/coffee -M -m --compile -t --output ./build.coffee/ ./build -# mv build.coffee/ /usr/src/processing/coffeescript-transpilation - -# # clean up -# rm -Rf /usr/src/build /usr/src/node_modules/ -# rm /usr/src/babel.config.json +## CoffeeScript +## +## Coffeescript is transpiled ready for nodejs. This is then moved into +## app so we have the javascript available which other preprocessors may +## expect to exist. +## + +# our babel config is in /template let's run all commands from there +# and use absolute paths +cd /template + +# prepare the build folders +mkdir /dist /build.coffee + +# make the build and move to coffeescript-transpilation +/template/node_modules/.bin/coffee -M -m --compile -t --output /app/dist /app/src ## TypeScript and ES6 ## ## Transpiles TypeScript and ES6 to something nodejs wants to run. -cd /template /template/node_modules/.bin/babel \ /app/src \ --out-dir /app/dist/ \ --source-maps "true" \ --extensions ".ts,.js" - -# # We move the coffeescript files again because the previous step will -# # have built the sources coffeescript generated, but these sources were -# # already node compliant. We could make coffeescript emit ES6 and -# # transpile them to nodejs in this step, but that breaks SourceMaps. -# docker-rsync /usr/src/processing/coffeescript-transpilation/ /usr/src/build/ From 98368e05e7c2a029b6e6a08398199abface90fe0 Mon Sep 17 00:00:00 2001 From: Karel Kremer Date: Tue, 26 Dec 2023 15:53:14 +0100 Subject: [PATCH 8/9] fix node modules being picked up by babel --- babel.config.json | 6 +----- transpile-sources.sh | 4 +--- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/babel.config.json b/babel.config.json index 48b8f33..b64909a 100644 --- a/babel.config.json +++ b/babel.config.json @@ -11,9 +11,5 @@ ["@babel/preset-typescript"] ], "plugins": [["@babel/plugin-proposal-decorators", { "version": "2023-05" }]], - "ignore": [ - "./node_modules", - "/usr/src/processing/temp/app/app/node_modules", - "/usr/src/processing/build/node_modules" - ] + "ignore": ["./node_modules", "/app/src/node_modules"] } diff --git a/transpile-sources.sh b/transpile-sources.sh index 54fa04e..2738a1e 100755 --- a/transpile-sources.sh +++ b/transpile-sources.sh @@ -30,9 +30,6 @@ source /template/helpers.sh # and use absolute paths cd /template -# prepare the build folders -mkdir /dist /build.coffee - # make the build and move to coffeescript-transpilation /template/node_modules/.bin/coffee -M -m --compile -t --output /app/dist /app/src @@ -45,3 +42,4 @@ mkdir /dist /build.coffee --out-dir /app/dist/ \ --source-maps "true" \ --extensions ".ts,.js" + From ca867e81a057a4cab041ef9151490ddbcfb0198d Mon Sep 17 00:00:00 2001 From: Karel Kremer Date: Tue, 26 Dec 2023 17:14:05 +0100 Subject: [PATCH 9/9] allow specifying whether or not to run using babel node, don't include coffee maps --- run-development.sh | 15 ++++++++++++--- transpile-sources.sh | 5 +++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/run-development.sh b/run-development.sh index 679641d..fcc926e 100755 --- a/run-development.sh +++ b/run-development.sh @@ -55,6 +55,15 @@ docker-rsync /template/node_modules/ /app/node_modules/ ############## cd /app/ -node \ - --inspect="0.0.0.0:9229" \ - ./dist/app.js +if [ "$NO_BABEL_NODE" == "true" ] +then + echo "running without babel-node" + node \ + --inspect="0.0.0.0:9229" \ + ./dist/app.js +else + /template/node_modules/.bin/babel-node \ + --enable-source-maps \ + --inspect="0.0.0.0:9229" \ + ./dist/app.js +fi diff --git a/transpile-sources.sh b/transpile-sources.sh index 2738a1e..01de631 100755 --- a/transpile-sources.sh +++ b/transpile-sources.sh @@ -30,8 +30,9 @@ source /template/helpers.sh # and use absolute paths cd /template -# make the build and move to coffeescript-transpilation -/template/node_modules/.bin/coffee -M -m --compile -t --output /app/dist /app/src +# build coffeescript (note: don't use -M as it seems vscode is confused about inline sourcemaps) +# chrome still happily works with .map files too though so we're all good! +/template/node_modules/.bin/coffee -m --compile -t --output /app/dist /app/src ## TypeScript and ES6 ##