openvibers/openvibe.examples Commits

Examples: the webhook-consumer's inbox runs on PostgreSQL (PGlite locally), not better-sqlite3 (#16)

OP OpenVibers committed 11 Oct 2026 · 1b0316c0e8 · 7 files, +189 −467

Plan T1, the deletion ledger: the webhook-consumer example was the last user of the SDK's better-sqlite3 inbox. openvibe-sdk 0.44.0 (SDK#41) removes that inbox, and this moves the example to PostgreSQL first, on the current pin (0.43 already has `createPgInbox`).

- **`createPgInbox(db)`** on an `openvibe-sdk/db` handle.
  - The database is `OV_DATABASE_URL`, or an embedded PGlite in `OV_DATA_DIR` (default `./data/pg`) when no URL is set, so the example still runs with nothing installed but Node.
  - `openDatabase(config)` creates the inbox table (`inboxSchema()`) and the app's own `received_events` table, which no longer has a `seq` column: Events sends none since Events#60.
- **The handler:** `handle(event, { attempt }, t)` is async and gets the transaction handle, so the app's write commits with the receipt (it was synchronous, inside a SQLite transaction).
- **Dependencies:** the example now needs `@electric-sql/pglite` and `pg` instead of `better-sqlite3`, which leaves the workspace lockfile.
- The header comment (the delivery body is `{ event }`), the README, `.env.example` and the catalogue row describe it.

`examples/webhook-consumer/test/smoke.test.js` runs the same cases against the PGlite store:
- delivered once;
- a replay answered as a duplicate;
- a handler failure retried with no receipt left behind;
- forged, tampered, v1-only and stale deliveries refused;
- secret rotation;
- the receipt and the app's row written together.

It passes, and so does the event-subscriber smoke test.

Changes

ddiff --git a/README.md b/README.md
iindex 058a0f5..3d553a4 100644
---- a/README.md
++++ b/README.md
@@@ -30,7 +30,7 @@ Each example is small, runs on its own and proves one thing with a smoke test.
| [node-server-app](examples/node-server-app) | Client-credentials app token per audience and what it carries, registry discovery, contracts version check, trace propagation | `openvibe-sdk/auth` (`getTokenInfo`), `/registry`, `/core` |
| [media-uploader](examples/media-uploader) | Upload into, read from and delete in your project's Media tenant; sandbox files come back with signed URLs | `openvibe-sdk/media` |
| [event-subscriber](examples/event-subscriber) | Publish to your project's topic `app.<project_key>.*`, pull it with a durable cursor, gaps; anonymous realtime for public events | `openvibe-sdk/events` (`createAppEvents`), `/realtime` |
--| [webhook-consumer](examples/webhook-consumer) | An app subscription on your own topic; `X-OpenVibe-Signature-V2` (±300 s replay window) verified on the raw body; exactly-once handling with an inbox; secret rotation | `openvibe-sdk/events` (`createAppEvents`, `parseDelivery`, `createInbox`) |
++| [webhook-consumer](examples/webhook-consumer) | An app subscription on your own topic; `X-OpenVibe-Signature-V2` (±300 s replay window) verified on the raw body; exactly-once handling with an inbox; secret rotation | `openvibe-sdk/events` (`createAppEvents`, `parseDelivery`, `createPgInbox`) |
| [tool-job](examples/tool-job) | An OpenVibe.Tools job submitted once (idempotency key), reattached after a restart, its SSE stream resumed with `Last-Event-ID` | `openvibe-sdk/jobs` |
| [oauth-app](examples/oauth-app) | Authorization code + PKCE for a confidential app, exchange on the server, offline app-token verification, session hygiene | `openvibe-sdk/auth` |
| [chat-bot](examples/chat-bot) | A bot on Chat's WebSocket protocol that stays in its one configured room and always identifies as a bot | Chat `/ws/chat` protocol (no SDK client: Chat is first-party) |
ddiff --git a/examples/webhook-consumer/.env.example b/examples/webhook-consumer/.env.example
iindex 52d41dd..1facc50 100644
---- a/examples/webhook-consumer/.env.example
++++ b/examples/webhook-consumer/.env.example
@@@ -3,7 +3,9 @@ OV_WEBHOOK_SECRET=
# While rotating: the previous secret, accepted until you remove it.
OV_WEBHOOK_SECRET_PREVIOUS=
OV_WEBHOOK_PATH=/webhooks/openvibe
--OV_DB_PATH=./data/webhook-consumer.db
++# PostgreSQL for the inbox and the received_events table; empty: an embedded PGlite in OV_DATA_DIR.
++OV_DATABASE_URL=
++OV_DATA_DIR=./data/pg
OV_PORT=3003
# subscribe.js: a CONFIDENTIAL sandbox app holding events.app.subscribe (audience openvibe.events).
ddiff --git a/examples/webhook-consumer/README.md b/examples/webhook-consumer/README.md
iindex b3cf8ec..d7677ca 100644
---- a/examples/webhook-consumer/README.md
++++ b/examples/webhook-consumer/README.md
@@@ -21,8 +21,10 @@ node --env-file=.env --env-file=.env.webhook server.js
- **Signature first, on the raw bytes.** `parseDelivery()` checks
`sha256=<HMAC-SHA256 of the raw body>` in constant time before anything is parsed. A wrong
secret, a changed byte or a missing header is `401`, with no detail.
--- **Exactly once.** `createInbox(db).once(consumer, event_id, fn)` writes the receipt and runs your
-- handler in one SQLite transaction. A redelivery (a retry after a lost `2xx`, a replay) is
++- **Exactly once.** `createPgInbox(db).once(consumer, event_id, fn)` writes the receipt and runs your
++ handler in one PostgreSQL transaction (`fn` gets the transaction handle; write with it and the write
++ commits with the receipt). The database is `OV_DATABASE_URL`, or an embedded PGlite in `OV_DATA_DIR`
++ (default `./data/pg`) when no URL is set, so the example needs nothing installed but Node. A redelivery (a retry after a lost `2xx`, a replay) is
answered `200 { duplicate: true }` without running the handler. A handler that throws leaves
no receipt, the consumer answers `500`, and Events retries with backoff.
- **The signed body is the truth.** `X-OpenVibe-Event-Id` must match the body's `event_id`.
ddiff --git a/examples/webhook-consumer/package.json b/examples/webhook-consumer/package.json
iindex 1d11e80..88fb153 100644
---- a/examples/webhook-consumer/package.json
++++ b/examples/webhook-consumer/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-example-webhook-consumer",
-- "version": "0.2.0",
++ "version": "0.3.0",
"private": true,
"description": "Webhook consumer: verify X-OpenVibe-Signature and process each event exactly once through an inbox.",
"license": "MIT",
@@@ -14,6 +14,7 @@
},
"dependencies": {
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.43.0",
-- "better-sqlite3": "^11.10.0"
++ "@electric-sql/pglite": "^0.5.8",
++ "pg": "^8.23.0"
}
}
ddiff --git a/examples/webhook-consumer/server.js b/examples/webhook-consumer/server.js
iindex db5d787..2d38913 100644
---- a/examples/webhook-consumer/server.js
++++ b/examples/webhook-consumer/server.js
@@@ -6,7 +6,7 @@
*
* node --env-file=.env server.js # POST http://localhost:3003/webhooks/openvibe
*
-- * A delivery is POSTed as { "event": <events.event-envelope@1>, "seq": <n> } with
++ * A delivery is POSTed as { "event": <events.event-envelope@1> } (no sequence number: dedupe on the event id) with
* X-OpenVibe-Timestamp: <unix seconds> and
* X-OpenVibe-Signature-V2: t=<that timestamp>,v2=<HMAC-SHA256 of "<t>.<raw body>" with the subscription secret>
* (plus the older body-only X-OpenVibe-Signature, which this consumer does not accept on its own).
@@@ -16,16 +16,20 @@
* constant time, refuses a timestamp more than 300 s from this clock or a missing v2 header
* (a replayed capture), and parses it. A bad signature is 401 and nothing else is said.
* 3. Delivery is at least once (retries, replays). inbox.once() records the event id and runs
-- * the handler in ONE SQLite transaction, so a repeat is answered 200 without running it again,
-- * and a handler that throws leaves no receipt: the 500 makes Events retry later.
++ * the handler in ONE PostgreSQL transaction (openvibe-sdk/events createPgInbox), so a repeat is
++ * answered 200 without running it again, and a handler that throws leaves no receipt: the 500 makes
++ * Events retry later.
++ *
++ * The database is PostgreSQL: OV_DATABASE_URL, or an embedded PGlite in OV_DATA_DIR (default ./data/pg) when no URL
++ * is set, so the example runs with nothing installed but Node.
*
* Secret rotation: set OV_WEBHOOK_SECRET_PREVIOUS to the old secret while both are in use.
*/
const fs = require('node:fs');
const http = require('node:http');
const path = require('node:path');
--const Database = require('better-sqlite3');
--const { parseDelivery, createInbox } = require('openvibe-sdk/events');
++const { createDb, sql } = require('openvibe-sdk/db');
++const { parseDelivery, createPgInbox, inboxSchema } = require('openvibe-sdk/events');
const MAX_BODY = 1024 * 1024;
const CONSUMER = 'webhook-consumer';
@@@ -38,36 +42,41 @@ function loadConfig(env = process.env) {
}
return {
secrets: [env.OV_WEBHOOK_SECRET, env.OV_WEBHOOK_SECRET_PREVIOUS].filter(Boolean),
-- dbPath: env.OV_DB_PATH || path.join(__dirname, 'data', 'webhook-consumer.db'),
++ databaseUrl: env.OV_DATABASE_URL || null,
++ dataDir: env.OV_DATA_DIR || path.join(__dirname, 'data', 'pg'),
port: Number(env.OV_PORT || 3003),
path: env.OV_WEBHOOK_PATH || '/webhooks/openvibe',
};
}
--function openDatabase(dbPath) {
-- if (dbPath !== ':memory:') fs.mkdirSync(path.dirname(dbPath), { recursive: true });
-- const db = new Database(dbPath);
-- db.pragma('journal_mode = WAL');
-- db.exec(`CREATE TABLE IF NOT EXISTS received_events (
-- event_id TEXT PRIMARY KEY,
-- event_type TEXT NOT NULL,
-- source TEXT NOT NULL,
-- seq INTEGER,
-- subject TEXT,
-- received_at TEXT NOT NULL
++/** The database and its two tables: the inbox's receipts and the app's own row per event. */
++async function openDatabase(config) {
++ let db;
++ if (config.databaseUrl) db = createDb({ url: config.databaseUrl, service: 'webhook-consumer' });
++ else {
++ if (config.dataDir !== 'memory') fs.mkdirSync(config.dataDir, { recursive: true });
++ db = createDb({ pglite: config.dataDir === 'memory' ? true : config.dataDir, service: 'webhook-consumer' });
++ }
++ await db.query(inboxSchema());
++ await db.query(`CREATE TABLE IF NOT EXISTS received_events (
++ id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
++ event_id text NOT NULL UNIQUE,
++ event_type text NOT NULL,
++ source text NOT NULL,
++ subject text,
++ received_at timestamptz NOT NULL DEFAULT now()
)`);
return db;
}
/**
-- * createConsumer(config, { db, handle, log })
-- * handle(event, { seq, attempt }) runs inside the inbox transaction and must be synchronous
-- * (better-sqlite3). Put side effects that need the network in your own outbox table instead.
++ * createConsumer(config, { db, handle, log }) db: from openDatabase(config)
++ * handle(event, { attempt }, t) runs inside the inbox transaction (t, the transaction handle: write with it and the
++ * write commits with the receipt). Put side effects that need the network in your own outbox table instead.
*/
--function createConsumer(config, { db = openDatabase(config.dbPath), handle = () => {}, log = console } = {}) {
-- const inbox = createInbox(db);
-- inbox.ensureSchema();
-- const record = db.prepare('INSERT INTO received_events (event_id, event_type, source, seq, subject, received_at) VALUES (?, ?, ?, ?, ?, ?)');
++function createConsumer(config, { db, handle = () => {}, log = console } = {}) {
++ if (!db) throw new TypeError('createConsumer: pass { db } from openDatabase(config)');
++ const inbox = createPgInbox(db);
function verify(raw, headers) {
for (const secret of config.secrets) {
@@@ -77,20 +86,20 @@ function createConsumer(config, { db = openDatabase(config.dbPath), handle = ()
return null;
}
-- function receive(raw, headers) {
++ async function receive(raw, headers) {
const delivery = verify(raw, headers);
if (!delivery) return { status: 401, body: { error: 'bad_signature' } };
-- const { event, seq, attempt } = delivery;
++ const { event, attempt } = delivery;
if (!event || typeof event.event_id !== 'string' || typeof event.event_type !== 'string') return { status: 400, body: { error: 'bad_envelope' } };
// The header is informational; the signed body is the truth. They must agree.
const headerId = headers['x-openvibe-event-id'];
if (headerId && headerId !== event.event_id) return { status: 400, body: { error: 'event_id_mismatch' } };
-- const out = inbox.once(CONSUMER, event.event_id, () => {
-- record.run(event.event_id, event.event_type, String(event.source || ''), Number.isFinite(seq) ? seq : null,
-- event.subject ? `${event.subject.type}:${event.subject.id}` : null, new Date().toISOString());
-- return handle(event, { seq, attempt });
++ const out = await inbox.once(CONSUMER, event.event_id, async (t) => {
++ await t.exec(sql`INSERT INTO received_events (event_id, event_type, source, subject)
++ VALUES (${event.event_id}, ${event.event_type}, ${String(event.source || '')}, ${event.subject ? `${event.subject.type}:${event.subject.id}` : null})`);
++ return await handle(event, { attempt }, t);
});
-- log.log(`[webhook] ${event.event_type} ${event.event_id} seq=${seq} attempt=${attempt}${out.duplicate ? ' (duplicate, skipped)' : ''}`);
++ log.log(`[webhook] ${event.event_type} ${event.event_id} attempt=${attempt}${out.duplicate ? ' (duplicate, skipped)' : ''}`);
return { status: 200, body: { ok: true, duplicate: out.duplicate } };
}
@@@ -110,10 +119,10 @@ function createConsumer(config, { db = openDatabase(config.dbPath), handle = ()
if (size > MAX_BODY) { tooLarge = true; chunks.length = 0; return; }
chunks.push(c);
});
-- req.on('end', () => {
++ req.on('end', async () => {
if (tooLarge) return send(413, { error: 'too_large' });
try {
-- const out = receive(Buffer.concat(chunks), req.headers);
++ const out = await receive(Buffer.concat(chunks), req.headers);
send(out.status, out.body);
} catch (err) {
// No receipt was written: Events retries this delivery with backoff.
@@@ -129,12 +138,15 @@ function createConsumer(config, { db = openDatabase(config.dbPath), handle = ()
if (require.main === module) {
let config;
try { config = loadConfig(); } catch (err) { console.error(err.message); process.exit(2); }
-- const { server } = createConsumer(config, {
-- handle(event) {
-- // Your side effect goes here (synchronous, same transaction as the receipt).
-- },
-- });
-- server.listen(config.port, () => console.log(`webhook-consumer: POST http://localhost:${config.port}${config.path}`));
++ openDatabase(config).then((db) => {
++ const { server } = createConsumer(config, {
++ db,
++ async handle(event, meta, t) {
++ // Your side effect goes here: write with `t` and it commits with the receipt.
++ },
++ });
++ server.listen(config.port, () => console.log(`webhook-consumer: POST http://localhost:${config.port}${config.path}`));
++ }).catch((err) => { console.error(`webhook-consumer: ${err.message}`); process.exit(1); });
}
module.exports = { loadConfig, openDatabase, createConsumer, CONSUMER };
ddiff --git a/examples/webhook-consumer/test/smoke.test.js b/examples/webhook-consumer/test/smoke.test.js
iindex a1a911d..c90721b 100644
---- a/examples/webhook-consumer/test/smoke.test.js
++++ b/examples/webhook-consumer/test/smoke.test.js
@@@ -45,12 +45,13 @@ const ENDPOINT = 'https://hooks.example.com/webhooks/openvibe';
// 2. Run the consumer with that secret.
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'ov-webhook-'));
-- const config = loadConfig({ OV_WEBHOOK_SECRET: created.secret, OV_DB_PATH: path.join(dir, 'consumer.db') });
++ const config = loadConfig({ OV_WEBHOOK_SECRET: created.secret, OV_DATA_DIR: path.join(dir, 'pg') });
++ const db = await openDatabase(config);
const handled = [];
let failNext = false;
const logs = [];
const consumer = createConsumer(config, {
-- db: openDatabase(config.dbPath),
++ db,
handle(event) {
if (failNext) { failNext = false; throw new Error('downstream unavailable'); }
handled.push(event.event_id);
@@@ -95,7 +96,7 @@ const ENDPOINT = 'https://hooks.example.com/webhooks/openvibe';
round = await platform.deliverEvents({ fetch: worker });
assert.equal(round.failed, 1);
assert.equal(round.attempts[0].status, 500);
-- assert.equal(consumer.inbox.seen('webhook-consumer', e2.event_id), false);
++ assert.equal(await consumer.inbox.seen('webhook-consumer', e2.event_id), false);
round = await platform.deliverEvents({ fetch: worker });
assert.deepEqual([round.delivered, round.attempts[0].attempt], [1, 2]);
assert.deepEqual(handled, [e1.event_id, e2.event_id]);
@@@ -116,8 +117,8 @@ const ENDPOINT = 'https://hooks.example.com/webhooks/openvibe';
// Secret rotation: deliveries signed with the previous secret are accepted while it is configured.
consumer.server.close();
-- const rotated = createConsumer(loadConfig({ OV_WEBHOOK_SECRET: 'whsec_new_secret_after_rotation_0000000000', OV_WEBHOOK_SECRET_PREVIOUS: created.secret, OV_DB_PATH: config.dbPath }), {
-- db: consumer.db, handle: (event) => handled.push(event.event_id), log: { log() {}, error() {} },
++ const rotated = createConsumer(loadConfig({ OV_WEBHOOK_SECRET: 'whsec_new_secret_after_rotation_0000000000', OV_WEBHOOK_SECRET_PREVIOUS: created.secret, OV_DATA_DIR: config.dataDir }), {
++ db, handle: (event) => handled.push(event.event_id), log: { log() {}, error() {} },
});
await new Promise((res) => rotated.server.listen(0, '127.0.0.1', res));
local = `http://127.0.0.1:${rotated.server.address().port}/webhooks/openvibe`;
@@@ -130,7 +131,7 @@ const ENDPOINT = 'https://hooks.example.com/webhooks/openvibe';
assert.deepEqual(handled, [e1.event_id, e2.event_id, e3.event_id, e4.event_id]);
// The receipt and the app's own row were written together.
-- const rows = consumer.db.prepare('SELECT event_id FROM received_events ORDER BY seq').all().map((x) => x.event_id);
++ const rows = (await db.many('SELECT event_id FROM received_events ORDER BY id')).map((x) => x.event_id);
assert.deepEqual(rows, handled);
// Oversized bodies are refused before parsing.
@@@ -141,7 +142,7 @@ const ENDPOINT = 'https://hooks.example.com/webhooks/openvibe';
assert.ok(!logs.join('\n').includes(created.secret));
rotated.server.close();
-- consumer.db.close();
++ await db.close();
fs.rmSync(dir, { recursive: true, force: true });
console.log('webhook-consumer: ok');
})().catch((err) => { console.error(err); process.exit(1); });
ddiff --git a/package-lock.json b/package-lock.json
iindex d1dfffd..1af2731 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -112,16 +112,23 @@
},
"examples/webhook-consumer": {
"name": "openvibe-example-webhook-consumer",
-- "version": "0.2.0",
++ "version": "0.3.0",
"license": "MIT",
"dependencies": {
-- "better-sqlite3": "^11.10.0",
-- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.43.0"
++ "@electric-sql/pglite": "^0.5.8",
++ "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.43.0",
++ "pg": "^8.23.0"
},
"engines": {
"node": ">=22"
}
},
++ "node_modules/@electric-sql/pglite": {
++ "version": "0.5.8",
++ "resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.5.8.tgz",
++ "integrity": "sha512-n9tsbUOhwx2epK1V0ZG9Ar4SHWUju04dhmzZXiSBXwBoleOvIfals33NAaWgagQVAL4Rbvx/Ptsu3P+pA09f6Q==",
++ "license": "Apache-2.0"
++ },
"node_modules/ajv": {
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
@@@ -155,138 +162,6 @@
}
}
},
-- "node_modules/base64-js": {
-- "version": "1.5.1",
-- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
-- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
-- "funding": [
-- {
-- "type": "github",
-- "url": "https://github.com/sponsors/feross"
-- },
-- {
-- "type": "patreon",
-- "url": "https://www.patreon.com/feross"
-- },
-- {
-- "type": "consulting",
-- "url": "https://feross.org/support"
-- }
-- ],
-- "license": "MIT"
-- },
-- "node_modules/better-sqlite3": {
-- "version": "11.10.0",
-- "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.10.0.tgz",
-- "integrity": "sha512-EwhOpyXiOEL/lKzHz9AW1msWFNzGc/z+LzeB3/jnFJpxu+th2yqvzsSWas1v9jgs9+xiXJcD5A8CJxAG2TaghQ==",
-- "hasInstallScript": true,
-- "license": "MIT",
-- "dependencies": {
-- "bindings": "^1.5.0",
-- "prebuild-install": "^7.1.1"
-- }
-- },
-- "node_modules/bindings": {
-- "version": "1.5.0",
-- "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
-- "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
-- "license": "MIT",
-- "dependencies": {
-- "file-uri-to-path": "1.0.0"
-- }
-- },
-- "node_modules/bl": {
-- "version": "4.1.0",
-- "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
-- "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
-- "license": "MIT",
-- "dependencies": {
-- "buffer": "^5.5.0",
-- "inherits": "^2.0.4",
-- "readable-stream": "^3.4.0"
-- }
-- },
-- "node_modules/buffer": {
-- "version": "5.7.1",
-- "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
-- "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
-- "funding": [
-- {
-- "type": "github",
-- "url": "https://github.com/sponsors/feross"
-- },
-- {
-- "type": "patreon",
-- "url": "https://www.patreon.com/feross"
-- },
-- {
-- "type": "consulting",
-- "url": "https://feross.org/support"
-- }
-- ],
-- "license": "MIT",
-- "dependencies": {
-- "base64-js": "^1.3.1",
-- "ieee754": "^1.1.13"
-- }
-- },
-- "node_modules/chownr": {
-- "version": "1.1.4",
-- "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
-- "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
-- "license": "ISC"
-- },
-- "node_modules/decompress-response": {
-- "version": "6.0.0",
-- "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
-- "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
-- "license": "MIT",
-- "dependencies": {
-- "mimic-response": "^3.1.0"
-- },
-- "engines": {
-- "node": ">=10"
-- },
-- "funding": {
-- "url": "https://github.com/sponsors/sindresorhus"
-- }
-- },
-- "node_modules/deep-extend": {
-- "version": "0.6.0",
-- "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
-- "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
-- "license": "MIT",
-- "engines": {
-- "node": ">=4.0.0"
-- }
-- },
-- "node_modules/detect-libc": {
-- "version": "2.1.2",
-- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
-- "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
-- "license": "Apache-2.0",
-- "engines": {
-- "node": ">=8"
-- }
-- },
-- "node_modules/end-of-stream": {
-- "version": "1.4.5",
-- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
-- "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
-- "license": "MIT",
-- "dependencies": {
-- "once": "^1.4.0"
-- }
-- },
-- "node_modules/expand-template": {
-- "version": "2.0.3",
-- "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
-- "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
-- "license": "(MIT OR WTFPL)",
-- "engines": {
-- "node": ">=6"
-- }
-- },
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@@ -309,116 +184,12 @@
],
"license": "BSD-3-Clause"
},
-- "node_modules/file-uri-to-path": {
-- "version": "1.0.0",
-- "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
-- "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
-- "license": "MIT"
-- },
-- "node_modules/fs-constants": {
-- "version": "1.0.0",
-- "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
-- "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
-- "license": "MIT"
-- },
-- "node_modules/github-from-package": {
-- "version": "0.0.0",
-- "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
-- "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
-- "license": "MIT"
-- },
-- "node_modules/ieee754": {
-- "version": "1.2.1",
-- "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
-- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
-- "funding": [
-- {
-- "type": "github",
-- "url": "https://github.com/sponsors/feross"
-- },
-- {
-- "type": "patreon",
-- "url": "https://www.patreon.com/feross"
-- },
-- {
-- "type": "consulting",
-- "url": "https://feross.org/support"
-- }
-- ],
-- "license": "BSD-3-Clause"
-- },
-- "node_modules/inherits": {
-- "version": "2.0.4",
-- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-- "license": "ISC"
-- },
-- "node_modules/ini": {
-- "version": "1.3.8",
-- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
-- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
-- "license": "ISC"
-- },
"node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"license": "MIT"
},
-- "node_modules/mimic-response": {
-- "version": "3.1.0",
-- "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
-- "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
-- "license": "MIT",
-- "engines": {
-- "node": ">=10"
-- },
-- "funding": {
-- "url": "https://github.com/sponsors/sindresorhus"
-- }
-- },
-- "node_modules/minimist": {
-- "version": "1.2.8",
-- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
-- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
-- "license": "MIT",
-- "funding": {
-- "url": "https://github.com/sponsors/ljharb"
-- }
-- },
-- "node_modules/mkdirp-classic": {
-- "version": "0.5.3",
-- "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
-- "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
-- "license": "MIT"
-- },
-- "node_modules/napi-build-utils": {
-- "version": "2.0.0",
-- "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
-- "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
-- "license": "MIT"
-- },
-- "node_modules/node-abi": {
-- "version": "3.96.0",
-- "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.96.0.tgz",
-- "integrity": "sha512-rebQ/lz7i0EkoLzUVSrKRzA69zMkwLp95kKMWoMDkkM00Suxz0D7zEQPwRml5fQum24mj7bPvmlgLAmu2JCiYg==",
-- "license": "MIT",
-- "dependencies": {
-- "semver": "^7.3.5"
-- },
-- "engines": {
-- "node": ">=10"
-- }
-- },
-- "node_modules/once": {
-- "version": "1.4.0",
-- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
-- "license": "ISC",
-- "dependencies": {
-- "wrappy": "1"
-- }
-- },
"node_modules/openvibe-contracts": {
"version": "0.129.0",
"resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.129.0",
@@@ -500,227 +271,151 @@
}
}
},
-- "node_modules/prebuild-install": {
-- "version": "7.1.3",
-- "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
-- "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
-- "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.",
++ "node_modules/pg": {
++ "version": "8.23.1",
++ "resolved": "https://registry.npmjs.org/pg/-/pg-8.23.1.tgz",
++ "integrity": "sha512-aL96AHANtWjPLDOLqnhx+ngp9+UK7ETEU8VJrDCGvsSSi/mGLcWYsS6Herg7lmaBJe4uwrfqsa7gTEFaSizDoQ==",
"license": "MIT",
"dependencies": {
-- "detect-libc": "^2.0.0",
-- "expand-template": "^2.0.3",
-- "github-from-package": "0.0.0",
-- "minimist": "^1.2.3",
-- "mkdirp-classic": "^0.5.3",
-- "napi-build-utils": "^2.0.0",
-- "node-abi": "^3.3.0",
-- "pump": "^3.0.0",
-- "rc": "^1.2.7",
-- "simple-get": "^4.0.0",
-- "tar-fs": "^2.0.0",
-- "tunnel-agent": "^0.6.0"
-- },
-- "bin": {
-- "prebuild-install": "bin.js"
++ "pg-connection-string": "^2.14.1",
++ "pg-pool": "^3.14.0",
++ "pg-protocol": "^1.16.1",
++ "pg-types": "2.2.0",
++ "pgpass": "1.0.5"
},
"engines": {
-- "node": ">=10"
++ "node": ">= 16.0.0"
++ },
++ "optionalDependencies": {
++ "pg-cloudflare": "^1.4.1"
++ },
++ "peerDependencies": {
++ "pg-native": ">=3.0.1"
++ },
++ "peerDependenciesMeta": {
++ "pg-native": {
++ "optional": true
++ }
}
},
-- "node_modules/pump": {
-- "version": "3.0.4",
-- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
-- "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
++ "node_modules/pg-cloudflare": {
++ "version": "1.4.1",
++ "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.4.1.tgz",
++ "integrity": "sha512-6PQbsFWZcp9EmJEwy5cGQ2La+AMWpP46lgbb8X+U/XsHIUweYDNCpeuKck5RxL2MdVFi7krbbEi5nX4Zh7JhrQ==",
"license": "MIT",
-- "dependencies": {
-- "end-of-stream": "^1.1.0",
-- "once": "^1.3.1"
-- }
++ "optional": true
},
-- "node_modules/rc": {
-- "version": "1.2.8",
-- "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
-- "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
-- "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
-- "dependencies": {
-- "deep-extend": "^0.6.0",
-- "ini": "~1.3.0",
-- "minimist": "^1.2.0",
-- "strip-json-comments": "~2.0.1"
-- },
-- "bin": {
-- "rc": "cli.js"
-- }
++ "node_modules/pg-connection-string": {
++ "version": "2.14.1",
++ "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.14.1.tgz",
++ "integrity": "sha512-qR3kGNPBLpCNtz0evbKA0Y/MRFXwSSdT+pTJvYp/bXTcReZbvX1kzF0IyTc1QnxqF7AZbOeBhNL8R5mYQZV/MA==",
++ "license": "MIT"
},
-- "node_modules/readable-stream": {
-- "version": "3.6.2",
-- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
-- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
-- "license": "MIT",
-- "dependencies": {
-- "inherits": "^2.0.3",
-- "string_decoder": "^1.1.1",
-- "util-deprecate": "^1.0.1"
-- },
++ "node_modules/pg-int8": {
++ "version": "1.0.1",
++ "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
++ "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
++ "license": "ISC",
"engines": {
-- "node": ">= 6"
++ "node": ">=4.0.0"
}
},
-- "node_modules/require-from-string": {
-- "version": "2.0.2",
-- "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
-- "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
++ "node_modules/pg-pool": {
++ "version": "3.14.0",
++ "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.14.0.tgz",
++ "integrity": "sha512-gKtPkFdQPU3DksooVLi9LsjZxrsBUZIpa+7aVx+LV5pNh0KzP4Zleud2po+ConrxbuXGBJ6Hfer6hdgpIBpBaw==",
"license": "MIT",
-- "engines": {
-- "node": ">=0.10.0"
++ "peerDependencies": {
++ "pg": ">=8.0"
}
},
-- "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/pg-protocol": {
++ "version": "1.16.1",
++ "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.16.1.tgz",
++ "integrity": "sha512-p9VOFMiHB/ZbJATetbg+99PxssTVSQRnyuPSQ67mN1+1KBOjZaZ83ZQzltnxPhJwSsC3nwVjJ10DVJlerbFzLg==",
"license": "MIT"
},
-- "node_modules/semver": {
-- "version": "7.8.5",
-- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
-- "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
-- "license": "ISC",
-- "bin": {
-- "semver": "bin/semver.js"
++ "node_modules/pg-types": {
++ "version": "2.2.0",
++ "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
++ "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
++ "license": "MIT",
++ "dependencies": {
++ "pg-int8": "1.0.1",
++ "postgres-array": "~2.0.0",
++ "postgres-bytea": "~1.0.0",
++ "postgres-date": "~1.0.4",
++ "postgres-interval": "^1.1.0"
},
"engines": {
-- "node": ">=10"
++ "node": ">=4"
}
},
-- "node_modules/simple-concat": {
-- "version": "1.0.1",
-- "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
-- "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
-- "funding": [
-- {
-- "type": "github",
-- "url": "https://github.com/sponsors/feross"
-- },
-- {
-- "type": "patreon",
-- "url": "https://www.patreon.com/feross"
-- },
-- {
-- "type": "consulting",
-- "url": "https://feross.org/support"
-- }
-- ],
-- "license": "MIT"
-- },
-- "node_modules/simple-get": {
-- "version": "4.0.1",
-- "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
-- "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
-- "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/pgpass": {
++ "version": "1.0.5",
++ "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
++ "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
"license": "MIT",
"dependencies": {
-- "decompress-response": "^6.0.0",
-- "once": "^1.3.1",
-- "simple-concat": "^1.0.0"
++ "split2": "^4.1.0"
}
},
-- "node_modules/string_decoder": {
-- "version": "1.3.0",
-- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
-- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
++ "node_modules/postgres-array": {
++ "version": "2.0.0",
++ "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
++ "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
"license": "MIT",
-- "dependencies": {
-- "safe-buffer": "~5.2.0"
++ "engines": {
++ "node": ">=4"
}
},
-- "node_modules/strip-json-comments": {
-- "version": "2.0.1",
-- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
-- "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
++ "node_modules/postgres-bytea": {
++ "version": "1.0.1",
++ "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz",
++ "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
-- "node_modules/tar-fs": {
-- "version": "2.1.5",
-- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz",
-- "integrity": "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==",
++ "node_modules/postgres-date": {
++ "version": "1.0.7",
++ "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
++ "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
"license": "MIT",
-- "dependencies": {
-- "chownr": "^1.1.1",
-- "mkdirp-classic": "^0.5.2",
-- "pump": "^3.0.0",
-- "tar-stream": "^2.1.4"
++ "engines": {
++ "node": ">=0.10.0"
}
},
-- "node_modules/tar-stream": {
-- "version": "2.2.0",
-- "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
-- "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
++ "node_modules/postgres-interval": {
++ "version": "1.2.0",
++ "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
++ "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
"license": "MIT",
"dependencies": {
-- "bl": "^4.0.3",
-- "end-of-stream": "^1.4.1",
-- "fs-constants": "^1.0.0",
-- "inherits": "^2.0.3",
-- "readable-stream": "^3.1.1"
++ "xtend": "^4.0.0"
},
"engines": {
-- "node": ">=6"
++ "node": ">=0.10.0"
}
},
-- "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==",
-- "license": "Apache-2.0",
-- "dependencies": {
-- "safe-buffer": "^5.0.1"
-- },
++ "node_modules/require-from-string": {
++ "version": "2.0.2",
++ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
++ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
++ "license": "MIT",
"engines": {
-- "node": "*"
++ "node": ">=0.10.0"
}
},
-- "node_modules/util-deprecate": {
-- "version": "1.0.2",
-- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
-- "license": "MIT"
-- },
-- "node_modules/wrappy": {
-- "version": "1.0.2",
-- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
-- "license": "ISC"
++ "node_modules/split2": {
++ "version": "4.2.0",
++ "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
++ "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
++ "license": "ISC",
++ "engines": {
++ "node": ">= 10.x"
++ }
},
"node_modules/ws": {
"version": "8.21.3",
@@@ -743,6 +438,15 @@
"optional": true
}
}
++ },
++ "node_modules/xtend": {
++ "version": "4.0.2",
++ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
++ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
++ "license": "MIT",
++ "engines": {
++ "node": ">=0.4"
++ }
}
}
}