diff --git a/frameworks/JavaScript/hyperexpress/README.md b/frameworks/JavaScript/hyperexpress/README.md new file mode 100644 index 00000000000..6c177db57d2 --- /dev/null +++ b/frameworks/JavaScript/hyperexpress/README.md @@ -0,0 +1,62 @@ +# HyperExpress Benchmarking Test + +HyperExpress is a high performance Node.js webserver with a simple-to-use API powered by µWebSockets.js under the hood. (https://github.com/kartikk221/hyper-express) + +µWebSockets.js is a web server bypass for Node.js (https://github.com/uNetworking/uWebSockets.js) + +## Important Libraries + +The tests were run with: + +- [hyper-express](https://github.com/kartikk221/hyper-express) +- [postgres](https://github.com/porsager/postgres) +- [mysql2](https://github.com/sidorares/node-mysql2) +- [lru-cache](https://github.com/isaacs/node-lru-cache) + +## Database + +There are individual handlers for each DB approach. The logic for each of them are found here: + +- [Postgres](database/postgres.js) +- [MySQL](database/mysql.js) + +There are **no database endpoints** or drivers attached by default. + +To initialize the application with one of these, run any _one_ of the following commands: + +```sh +$ DATABASE=postgres npm start +$ DATABASE=mysql npm start +``` + +## Test Endpoints + +> Visit the test requirements [here](https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview) + +```sh +$ curl localhost:8080/json +$ curl localhost:8080/plaintext + +# The following are only available with the DATABASE env var + +$ curl localhost:8080/db +$ curl localhost:8080/fortunes + +$ curl localhost:8080/queries?queries=2 +$ curl localhost:8080/queries?queries=0 +$ curl localhost:8080/queries?queries=foo +$ curl localhost:8080/queries?queries=501 +$ curl localhost:8080/queries?queries= + +$ curl localhost:8080/updates?queries=2 +$ curl localhost:8080/updates?queries=0 +$ curl localhost:8080/updates?queries=foo +$ curl localhost:8080/updates?queries=501 +$ curl localhost:8080/updates?queries= + +$ curl localhost:8080/cached-worlds?count=2 +$ curl localhost:8080/cached-worlds?count=0 +$ curl localhost:8080/cached-worlds?count=foo +$ curl localhost:8080/cached-worlds?count=501 +$ curl localhost:8080/cached-worlds?count= +``` diff --git a/frameworks/JavaScript/hyperexpress/app.js b/frameworks/JavaScript/hyperexpress/app.js new file mode 100644 index 00000000000..df5088a87c1 --- /dev/null +++ b/frameworks/JavaScript/hyperexpress/app.js @@ -0,0 +1,134 @@ +import { escape } from 'html-escaper' +import { Server } from 'hyper-express' +import { LRUCache } from 'lru-cache' +import cluster, { isWorker } from 'node:cluster' +import { maxQuery, maxRows } from './config.js' +const { DATABASE } = process.env +const db = DATABASE ? await import(`./database/${DATABASE}.js`) : null + +const generateRandomNumber = () => Math.ceil(Math.random() * maxRows) + +const parseQueries = (i) => Math.min(Math.max(parseInt(i, 10) || 1, 1), maxQuery) + +const cache = new LRUCache({ + max: maxRows +}) + +const app = new Server() + +// use middleware to add `Server` into response header +app.use((_request, response, next) => { + response.header('Server', 'hyperexpress') + next() +}) + +app.get('/plaintext', (_request, response) => { + response.atomic(() => { + response + .type('text') + .send('Hello, World!') + }) +}) + +app.get('/json', (_request, response) => { + response.json({ message: 'Hello, World!' }) +}) + +if (db) { + // populate cache + (async () => { + const worlds = await db.getAllWorlds() + for (let i = 0; i < worlds.length; i++) { + cache.set(worlds[i].id, worlds[i]) + } + })() + + app.get('/db', async (_request, response) => { + try { + const world = await db.find(generateRandomNumber()) + response.json(world) + } catch (error) { + throw error + } + }) + + app.get('/queries', async (request, response) => { + try { + const queries = parseQueries(request.query.queries) + const worldPromises = [] + + for (let i = 0; i < queries; i++) { + worldPromises.push(db.find(generateRandomNumber())) + } + + const worlds = await Promise.all(worldPromises) + response.json(worlds) + } catch (error) { + throw error + } + }) + + app.get('/updates', async (request, response) => { + try { + const queries = parseQueries(request.query.queries) + const worldPromises = [] + + for (let i = 0; i < queries; i++) { + worldPromises.push(db.find(generateRandomNumber())) + } + + const worlds = await Promise.all(worldPromises) + + const updatedWorlds = await Promise.all(worlds.map(async (world) => { + world.randomNumber = generateRandomNumber() + await db.update(world) + return world + })) + response.json(updatedWorlds) + } catch (error) { + throw error + } + }) + + app.get('/fortunes', async (_request, response) => { + try { + const fortunes = await db.fortunes() + + fortunes.push({ id: 0, message: 'Additional fortune added at request time.' }) + + fortunes.sort((a, b) => a.message.localeCompare(b.message)) + + let i = 0, html = 'Fortunes' + for (; i < fortunes.length; i++) html += `` + html += '
idmessage
${fortunes[i].id}${escape(fortunes[i].message)}
' + + response.atomic(() => { + response + // .type('html') + .header('Content-Type', 'text/html; charset=utf-8') + .send(html) + }) + } catch (error) { + throw error + } + }) + + app.get('/cached-worlds', async (request, response) => { + try { + const count = parseQueries(request.query.count) + const worlds = [] + + for (let i = 0; i < count; i++) { + worlds[i] = cache.get(generateRandomNumber()) + } + + response.json(worlds) + } catch (error) { + throw error + } + }) +} + +app.listen(8080).then(() => { + console.log(`${isWorker ? `${cluster.worker.id}: ` : ''}Successfully bound to http://0.0.0.0:8080`) +}) \ No newline at end of file diff --git a/frameworks/JavaScript/hyperexpress/benchmark_config.json b/frameworks/JavaScript/hyperexpress/benchmark_config.json new file mode 100755 index 00000000000..ed0d2f886bb --- /dev/null +++ b/frameworks/JavaScript/hyperexpress/benchmark_config.json @@ -0,0 +1,70 @@ +{ + "framework": "hyperexpress", + "tests": [ + { + "default": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "database": "None", + "framework": "hyperexpress", + "language": "JavaScript", + "flavor": "None", + "orm": "Raw", + "platform": "NodeJS", + "webserver": "µws", + "os": "Linux", + "database_os": "Linux", + "display_name": "hyperexpress", + "notes": "", + "versus": "nodejs" + }, + "postgres": { + "db_url": "/db", + "fortune_url": "/fortunes", + "query_url": "/queries?queries=", + "update_url": "/updates?queries=", + "cached_query_url": "/cached-worlds?count=", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "database": "Postgres", + "framework": "hyperexpress", + "language": "JavaScript", + "flavor": "None", + "orm": "Raw", + "platform": "NodeJS", + "webserver": "µws", + "os": "Linux", + "database_os": "Linux", + "display_name": "hyperexpress", + "notes": "", + "versus": "nodejs" + }, + "mysql": { + "db_url": "/db", + "fortune_url": "/fortunes", + "query_url": "/queries?queries=", + "update_url": "/updates?queries=", + "cached_query_url": "/cached-worlds?count=", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "database": "MySQL", + "framework": "hyperexpress", + "language": "JavaScript", + "flavor": "None", + "orm": "Raw", + "platform": "NodeJS", + "webserver": "µws", + "os": "Linux", + "database_os": "Linux", + "display_name": "hyperexpress", + "notes": "", + "versus": "nodejs" + } + } + ] +} diff --git a/frameworks/JavaScript/hyperexpress/clustered.js b/frameworks/JavaScript/hyperexpress/clustered.js new file mode 100644 index 00000000000..6bf96c8a57f --- /dev/null +++ b/frameworks/JavaScript/hyperexpress/clustered.js @@ -0,0 +1,15 @@ +import cluster, { isPrimary, setupPrimary, fork } from 'node:cluster' +import { cpus } from 'node:os' + +if (isPrimary) { + setupPrimary({ + exec: 'app.js', + }) + cluster.on('exit', (worker) => { + console.log(`worker ${worker.process.pid} died`) + process.exit(1) + }) + for (let i = 0; i < cpus().length; i++) { + fork() + } +} \ No newline at end of file diff --git a/frameworks/JavaScript/hyperexpress/config.js b/frameworks/JavaScript/hyperexpress/config.js new file mode 100644 index 00000000000..b85d510b405 --- /dev/null +++ b/frameworks/JavaScript/hyperexpress/config.js @@ -0,0 +1,8 @@ +export const maxQuery = 500 +export const maxRows = 10000 +export const clientOpts = { + host: 'tfb-database', + user: 'benchmarkdbuser', + password: 'benchmarkdbpass', + database: 'hello_world', +} \ No newline at end of file diff --git a/frameworks/JavaScript/hyperexpress/database/mysql.js b/frameworks/JavaScript/hyperexpress/database/mysql.js new file mode 100644 index 00000000000..da653611f84 --- /dev/null +++ b/frameworks/JavaScript/hyperexpress/database/mysql.js @@ -0,0 +1,33 @@ +import { createPool, createConnection } from 'mysql2/promise' +import { isWorker } from 'node:cluster' +import { cpus } from 'node:os' +import { clientOpts } from '../config.js' + +const client = await createConnection(clientOpts) + +const res = await client.query('SHOW VARIABLES LIKE "max_connections"') + +let maxConnections = 150 + +if (isWorker) { + maxConnections = cpus().length > 2 ? Math.ceil(res[0][0].Value * 0.96 / cpus().length) : maxConnections +} + +await client.end() + +const pool = createPool(Object.assign({ ...clientOpts }, { + connectionLimit: maxConnections, + idleTimeout: 600000 +})) + +const execute = async (text, values) => (await pool.execute(text, values || undefined))[0] + +export const fortunes = async () => execute('SELECT * FROM fortune') + +export const find = async (id) => execute('SELECT id, randomNumber FROM world WHERE id = ?', [id]).then(arr => arr[0]) + +export const getAllWorlds = async () => execute('SELECT * FROM world') + +export const update = async (obj) => execute('UPDATE world SET randomNumber = ? WHERE id = ?', [obj.randomNumber, obj.id]) + +await Promise.all([...Array(maxConnections).keys()].map(fortunes)) \ No newline at end of file diff --git a/frameworks/JavaScript/hyperexpress/database/postgres.js b/frameworks/JavaScript/hyperexpress/database/postgres.js new file mode 100644 index 00000000000..e55be551737 --- /dev/null +++ b/frameworks/JavaScript/hyperexpress/database/postgres.js @@ -0,0 +1,14 @@ +import postgres from 'postgres' +import { clientOpts } from '../config.js' + +const sql = postgres(clientOpts) + +export const fortunes = async () => sql`SELECT * FROM fortune` + +export const find = async (id) => sql`SELECT id, randomNumber FROM world WHERE id = ${id}`.then((arr) => arr[0]) + +export const getAllWorlds = async () => sql`SELECT * FROM world` + +export const update = async (obj) => sql`UPDATE world SET randomNumber = ${obj.randomNumber} WHERE id = ${obj.id}` + +await Promise.all([...Array(150).keys()].map(fortunes)) diff --git a/frameworks/JavaScript/hyperexpress/hyperexpress-mysql.dockerfile b/frameworks/JavaScript/hyperexpress/hyperexpress-mysql.dockerfile new file mode 100644 index 00000000000..f6bfe15f24b --- /dev/null +++ b/frameworks/JavaScript/hyperexpress/hyperexpress-mysql.dockerfile @@ -0,0 +1,18 @@ +# syntax=docker/dockerfile:1 +FROM node:18-slim + +WORKDIR /app + +COPY --chown=node:node . . + +ENV NODE_ENV production + +ENV DATABASE mysql + +RUN npm install + +USER node + +EXPOSE 8080 + +CMD ["node", "clustered.js"] \ No newline at end of file diff --git a/frameworks/JavaScript/hyperexpress/hyperexpress-postgres.dockerfile b/frameworks/JavaScript/hyperexpress/hyperexpress-postgres.dockerfile new file mode 100644 index 00000000000..65886ea70b7 --- /dev/null +++ b/frameworks/JavaScript/hyperexpress/hyperexpress-postgres.dockerfile @@ -0,0 +1,18 @@ +# syntax=docker/dockerfile:1 +FROM node:18-slim + +WORKDIR /app + +COPY --chown=node:node . . + +ENV NODE_ENV production + +ENV DATABASE postgres + +RUN npm install + +USER node + +EXPOSE 8080 + +CMD ["node", "clustered.js"] \ No newline at end of file diff --git a/frameworks/JavaScript/hyperexpress/hyperexpress.dockerfile b/frameworks/JavaScript/hyperexpress/hyperexpress.dockerfile new file mode 100644 index 00000000000..909840912ef --- /dev/null +++ b/frameworks/JavaScript/hyperexpress/hyperexpress.dockerfile @@ -0,0 +1,16 @@ +# syntax=docker/dockerfile:1 +FROM node:18-slim + +WORKDIR /app + +COPY --chown=node:node . . + +ENV NODE_ENV production + +RUN npm install + +USER node + +EXPOSE 8080 + +CMD ["node", "clustered.js"] \ No newline at end of file diff --git a/frameworks/JavaScript/hyperexpress/package-lock.json b/frameworks/JavaScript/hyperexpress/package-lock.json new file mode 100644 index 00000000000..f09867de1e0 --- /dev/null +++ b/frameworks/JavaScript/hyperexpress/package-lock.json @@ -0,0 +1,689 @@ +{ + "name": "hyperexpress", + "version": "0.0.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "version": "0.0.1", + "license": "MIT", + "dependencies": { + "html-escaper": "^3.0.3", + "hyper-express": "^6.7.1", + "lru-cache": "^10.0.0", + "mysql2": "^3.5.0", + "postgres": "^3.3.5" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/busboy": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@types/busboy/-/busboy-0.3.2.tgz", + "integrity": "sha512-iEvdm9Z9KdSs/ozuh1Z7ZsXrOl8F4M/CLMXPZHr3QuJ4d6Bjn+HBMC5EMKpwpAo8oi8iK9GZfFoHaIMrrZgwVw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "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.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" + }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "node_modules/@types/node": { + "version": "16.18.38", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.38.tgz", + "integrity": "sha512-6sfo1qTulpVbkxECP+AVrHV9OoJqhzCsfTNp5NIG+enM4HyM3HvZCO798WShIXBN0+QtDIcutJCjsVYnQP5rIQ==" + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "node_modules/@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", + "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "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/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.1.tgz", + "integrity": "sha512-78KWk9T26NhzXtuL26cIJ8/qNHANyJ/ZYrmEXFzUmhZdjpBv+DlWlOANRTGBt48YcyslsLrj0bMLFTmXvLRCOw==", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dependencies": { + "is-property": "^1.0.2" + } + }, + "node_modules/html-escaper": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", + "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==" + }, + "node_modules/hyper-express": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/hyper-express/-/hyper-express-6.7.1.tgz", + "integrity": "sha512-QjcHXsMZ/ujoTOp6yI9r1OOw14CloghO4iHxlRyUEmTwhVW4p+2Ak8iNrpsdDUV/MczhYNGkQ5Rw3lm+yGSoeA==", + "dependencies": { + "@types/busboy": "^0.3.1", + "@types/express": "^4.17.13", + "@types/node": "^16.11.6", + "accepts": "^1.3.7", + "busboy": "^1.0.0", + "cookie": "^0.4.1", + "cookie-signature": "^1.1.0", + "mime-types": "^2.1.33", + "range-parser": "^1.2.1", + "type-is": "^1.6.18", + "typed-emitter": "^2.1.0", + "uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.25.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "node_modules/lru-cache": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.0.tgz", + "integrity": "sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==", + "engines": { + "node": "14 || >=16.14" + } + }, + "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/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/mysql2": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.5.0.tgz", + "integrity": "sha512-WKlxITp5D8Xx8vsREf/cF0MB7QtqkAgedxtMA0iD9D0ugxmeBdph7J7xaLXdIZXWWmRyNGaCFTUiGo144XdL5g==", + "dependencies": { + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^5.2.1", + "lru-cache": "^8.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/mysql2/node_modules/lru-cache": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", + "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==", + "engines": { + "node": ">=16.14" + } + }, + "node_modules/named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "dependencies": { + "lru-cache": "^7.14.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, + "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/postgres": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.3.5.tgz", + "integrity": "sha512-+JD93VELV9gHkqpV5gdL5/70HdGtEw4/XE1S4BC8f1mcPmdib3K5XsKVbnR1XcAyC41zOnifJ+9YRKxdIsXiUw==", + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/porsager" + } + }, + "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/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "optional": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "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/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "optional": true + }, + "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/typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-2.1.0.tgz", + "integrity": "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==", + "dependencies": { + "rxjs": "*" + }, + "optionalDependencies": { + "rxjs": "*" + } + }, + "node_modules/uWebSockets.js": { + "version": "20.25.0", + "resolved": "git+ssh://git@github.com/uNetworking/uWebSockets.js.git#e6ecc2102d68d99dc35969b0898fbd201e0f252b" + } + }, + "dependencies": { + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/busboy": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@types/busboy/-/busboy-0.3.2.tgz", + "integrity": "sha512-iEvdm9Z9KdSs/ozuh1Z7ZsXrOl8F4M/CLMXPZHr3QuJ4d6Bjn+HBMC5EMKpwpAo8oi8iK9GZfFoHaIMrrZgwVw==", + "requires": { + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "@types/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" + }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "@types/node": { + "version": "16.18.38", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.38.tgz", + "integrity": "sha512-6sfo1qTulpVbkxECP+AVrHV9OoJqhzCsfTNp5NIG+enM4HyM3HvZCO798WShIXBN0+QtDIcutJCjsVYnQP5rIQ==" + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/serve-static": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", + "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "requires": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "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==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "requires": { + "streamsearch": "^1.1.0" + } + }, + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + }, + "cookie-signature": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.1.tgz", + "integrity": "sha512-78KWk9T26NhzXtuL26cIJ8/qNHANyJ/ZYrmEXFzUmhZdjpBv+DlWlOANRTGBt48YcyslsLrj0bMLFTmXvLRCOw==" + }, + "denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" + }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "requires": { + "is-property": "^1.0.2" + } + }, + "html-escaper": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", + "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==" + }, + "hyper-express": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/hyper-express/-/hyper-express-6.7.1.tgz", + "integrity": "sha512-QjcHXsMZ/ujoTOp6yI9r1OOw14CloghO4iHxlRyUEmTwhVW4p+2Ak8iNrpsdDUV/MczhYNGkQ5Rw3lm+yGSoeA==", + "requires": { + "@types/busboy": "^0.3.1", + "@types/express": "^4.17.13", + "@types/node": "^16.11.6", + "accepts": "^1.3.7", + "busboy": "^1.0.0", + "cookie": "^0.4.1", + "cookie-signature": "^1.1.0", + "mime-types": "^2.1.33", + "range-parser": "^1.2.1", + "type-is": "^1.6.18", + "typed-emitter": "^2.1.0", + "uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.25.0" + } + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + }, + "long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "lru-cache": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.0.tgz", + "integrity": "sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==" + }, + "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==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "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==", + "requires": { + "mime-db": "1.52.0" + } + }, + "mysql2": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.5.0.tgz", + "integrity": "sha512-WKlxITp5D8Xx8vsREf/cF0MB7QtqkAgedxtMA0iD9D0ugxmeBdph7J7xaLXdIZXWWmRyNGaCFTUiGo144XdL5g==", + "requires": { + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^5.2.1", + "lru-cache": "^8.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "dependencies": { + "lru-cache": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", + "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==" + } + } + }, + "named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "requires": { + "lru-cache": "^7.14.1" + }, + "dependencies": { + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" + } + } + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "postgres": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.3.5.tgz", + "integrity": "sha512-+JD93VELV9gHkqpV5gdL5/70HdGtEw4/XE1S4BC8f1mcPmdib3K5XsKVbnR1XcAyC41zOnifJ+9YRKxdIsXiUw==" + }, + "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==" + }, + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "optional": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, + "sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==" + }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" + }, + "tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "optional": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-2.1.0.tgz", + "integrity": "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==", + "requires": { + "rxjs": "*" + } + }, + "uWebSockets.js": { + "version": "git+ssh://git@github.com/uNetworking/uWebSockets.js.git#e6ecc2102d68d99dc35969b0898fbd201e0f252b", + "from": "uWebSockets.js@github:uNetworking/uWebSockets.js#v20.25.0" + } + } +} diff --git a/frameworks/JavaScript/hyperexpress/package.json b/frameworks/JavaScript/hyperexpress/package.json new file mode 100644 index 00000000000..d9b92cf0aec --- /dev/null +++ b/frameworks/JavaScript/hyperexpress/package.json @@ -0,0 +1,18 @@ +{ + "name": "hyperexpress", + "version": "0.0.1", + "main": "app.js", + "scripts": { + "start": "node clustered.js" + }, + "author": "", + "license": "MIT", + "dependencies": { + "html-escaper": "^3.0.3", + "hyper-express": "^6.7.1", + "lru-cache": "^10.0.0", + "mysql2": "^3.5.0", + "postgres": "^3.3.5" + }, + "type": "module" +}